From 92904da31a99782cca5258b7d2539cc3755678dc Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Thu, 12 Sep 2024 16:36:34 +0200 Subject: [PATCH] add all project files --- Workspace_msvc/Workspace_msvc.sln | 60 + Workspace_msvc/common.vcxproj | 276 + Workspace_msvc/debug.vcxproj | 158 + Workspace_msvc/evs_dec.vcxproj | 297 + Workspace_msvc/evs_enc.vcxproj | 323 + lib_com/ACcontextMapping.c | 74 + lib_com/__zaloha/basop32.c | 2542 +++ lib_com/__zaloha/basop32.h | 139 + lib_com/__zaloha/basop_com_lpc.c | 239 + lib_com/__zaloha/basop_lsf_tools.c | 265 + lib_com/__zaloha/basop_mpy.c | 56 + lib_com/__zaloha/basop_mpy.h | 67 + lib_com/__zaloha/basop_proto_func.h | 39 + lib_com/__zaloha/basop_settings.h | 85 + lib_com/__zaloha/basop_tcx_utils.c | 406 + lib_com/__zaloha/basop_util.c | 1044 ++ lib_com/__zaloha/basop_util.h | 386 + lib_com/__zaloha/bastypes.h | 46 + lib_com/__zaloha/enh1632.c | 637 + lib_com/__zaloha/enh1632.h | 518 + lib_com/__zaloha/enh40.c | 1071 ++ lib_com/__zaloha/enh40.h | 383 + lib_com/__zaloha/move.h | 42 + lib_com/__zaloha/stl.h | 38 + lib_com/ari.c | 41 + lib_com/ari_hm.c | 277 + lib_com/arith_coder.c | 512 + lib_com/basop32.c | 3464 ++++ lib_com/basop32.h | 276 + lib_com/basop_com_lpc.c | 263 + lib_com/basop_lsf_tools.c | 313 + lib_com/basop_mpy.c | 92 + lib_com/basop_mpy.h | 100 + lib_com/basop_proto_func.h | 70 + lib_com/basop_settings.h | 110 + lib_com/basop_tcx_utils.c | 441 + lib_com/basop_util.c | 1112 ++ lib_com/basop_util.h | 418 + lib_com/bitalloc.c | 977 + lib_com/bitallocsum.c | 61 + lib_com/bits_alloc.c | 309 + lib_com/bitstream.c | 2264 +++ lib_com/calc_st_com.c | 274 + lib_com/cb_shape.c | 89 + lib_com/cldfb.c | 804 + lib_com/cng_exc.c | 558 + lib_com/cnst.h | 2005 ++ lib_com/codec_tcx_common.c | 174 + lib_com/core_com_config.c | 420 + lib_com/deemph.c | 38 + lib_com/delay_comp.c | 40 + lib_com/disclaimer.c | 19 + lib_com/dlpc_bfi.c | 49 + lib_com/edct.c | 194 + lib_com/enh1632.c | 710 + lib_com/enh1632.h | 538 + lib_com/enh40.c | 1395 ++ lib_com/enh40.h | 409 + lib_com/enhancer.c | 244 + lib_com/enr_1_az.c | 31 + lib_com/env_adj.c | 134 + lib_com/env_stab.c | 169 + lib_com/env_stab_trans.c | 124 + lib_com/est_tilt.c | 57 + lib_com/fd_cng_com.c | 1081 ++ lib_com/fft.c | 3619 ++++ lib_com/fft_cldfb.c | 1194 ++ lib_com/fft_rel.c | 267 + lib_com/fill_spectrum.c | 237 + lib_com/findpulse.c | 107 + lib_com/fine_gain_bits.c | 101 + lib_com/frame_ener.c | 97 + lib_com/g192.c | 255 + lib_com/g192.h | 66 + lib_com/get_gain.c | 38 + lib_com/gs_bitallocation.c | 452 + lib_com/gs_gains.c | 572 + lib_com/gs_inact_switching.c | 108 + lib_com/gs_noisefill.c | 687 + lib_com/gs_preech.c | 95 + lib_com/guided_plc_util.c | 302 + lib_com/hp50.c | 106 + lib_com/hq2_bit_alloc.c | 993 + lib_com/hq2_core_com.c | 553 + lib_com/hq2_noise_inject.c | 243 + lib_com/hq_bit_allocation.c | 190 + lib_com/hq_conf.c | 207 + lib_com/hq_tools.c | 1733 ++ lib_com/hvq_pvq_bitalloc.c | 157 + lib_com/ifft_rel.c | 256 + lib_com/igf_base.c | 641 + lib_com/index_pvq_opt.c | 1163 ++ lib_com/int_lsp.c | 140 + lib_com/interleave_spectrum.c | 163 + lib_com/interpol.c | 44 + lib_com/isf_dec_amr_wb.c | 254 + lib_com/lag_wind.c | 131 + lib_com/lerp.c | 143 + lib_com/limit_t0.c | 201 + lib_com/logqnorm.c | 164 + lib_com/longarith.c | 164 + lib_com/low_rate_band_att.c | 162 + lib_com/lpc_tools.c | 300 + lib_com/lsf_dec_bfi.c | 268 + lib_com/lsf_msvq_ma.c | 148 + lib_com/lsf_tools.c | 2343 +++ lib_com/lsp_conv_poly.c | 630 + lib_com/mime.h | 423 + lib_com/modif_fs.c | 858 + lib_com/move.h | 86 + lib_com/mslvq_com.c | 734 + lib_com/nelp.c | 121 + lib_com/options.h | 24 + lib_com/parameter_bitmaping.c | 173 + lib_com/phase_dispersion.c | 124 + lib_com/ppp.c | 84 + lib_com/pred_lt4.c | 126 + lib_com/preemph.c | 36 + lib_com/prot.h | 9773 ++++++++++ lib_com/pvq_com.c | 919 + lib_com/range_com.c | 77 + lib_com/re8_ppv.c | 179 + lib_com/re8_util.c | 401 + lib_com/realft.c | 165 + lib_com/recovernorm.c | 51 + lib_com/reordvct.c | 45 + lib_com/residu.c | 65 + lib_com/rom_com.c | 19153 ++++++++++++++++++++ lib_com/rom_com.h | 1230 ++ lib_com/stab_est.c | 198 + lib_com/stat_com.h | 643 + lib_com/stat_noise_uv_mod.c | 206 + lib_com/stl.h | 71 + lib_com/swb_bwe_com.c | 1518 ++ lib_com/swb_bwe_com_hr.c | 286 + lib_com/swb_bwe_com_lr.c | 2048 +++ lib_com/swb_tbe_com.c | 1736 ++ lib_com/syn_12k8.c | 36 + lib_com/syn_filt.c | 122 + lib_com/tcq_position_arith.c | 2022 +++ lib_com/tcx_ltp.c | 757 + lib_com/tcx_mdct.c | 137 + lib_com/tcx_mdct_window.c | 189 + lib_com/tcx_utils.c | 941 + lib_com/tec_com.c | 930 + lib_com/tns_base.c | 735 + lib_com/tools.c | 1479 ++ lib_com/trans_direct.c | 142 + lib_com/trans_inv.c | 862 + lib_com/typedef.h | 94 + lib_com/vlpc_2st_com.c | 58 + lib_com/weight.c | 335 + lib_com/weight_a.c | 74 + lib_com/wi.c | 2701 +++ lib_com/window.c | 40 + lib_com/window_ola.c | 436 + lib_com/wtda.c | 330 + lib_debug/wmc_auto.c | 2220 +++ lib_debug/wmc_auto.h | 1449 ++ lib_dec/ACcontextMapping_dec.c | 279 + lib_dec/EvsRXlib.c | 510 + lib_dec/EvsRXlib.h | 90 + lib_dec/FEC.c | 536 + lib_dec/FEC_HQ_core.c | 1452 ++ lib_dec/FEC_HQ_phase_ecu.c | 1761 ++ lib_dec/FEC_adapt_codebook.c | 462 + lib_dec/FEC_clas_estim.c | 796 + lib_dec/FEC_lsf_estim.c | 57 + lib_dec/FEC_pitch_estim.c | 57 + lib_dec/FEC_scale_syn.c | 409 + lib_dec/LD_music_post_filter.c | 702 + lib_dec/TonalComponentDetection.c | 777 + lib_dec/acelp_core_dec.c | 920 + lib_dec/acelp_core_switch_dec.c | 561 + lib_dec/amr_wb_dec.c | 867 + lib_dec/ari_dec.c | 640 + lib_dec/ari_hm_dec.c | 128 + lib_dec/arith_coder_dec.c | 185 + lib_dec/avq_dec.c | 221 + lib_dec/bass_psfilter.c | 471 + lib_dec/cng_dec.c | 714 + lib_dec/core_dec_init.c | 669 + lib_dec/core_dec_reconf.c | 151 + lib_dec/core_dec_switch.c | 179 + lib_dec/core_switching_dec.c | 825 + lib_dec/d_gain2p.c | 260 + lib_dec/dec2t32.c | 91 + lib_dec/dec4t64.c | 740 + lib_dec/dec_LPD.c | 783 + lib_dec/dec_ace.c | 550 + lib_dec/dec_acelp.c | 334 + lib_dec/dec_acelp_tcx_main.c | 443 + lib_dec/dec_amr_wb.c | 125 + lib_dec/dec_gen_voic.c | 268 + lib_dec/dec_higher_acelp.c | 169 + lib_dec/dec_nelp.c | 58 + lib_dec/dec_pit_exc.c | 197 + lib_dec/dec_post.c | 967 + lib_dec/dec_ppp.c | 70 + lib_dec/dec_prm.c | 962 + lib_dec/dec_tcx.c | 1337 ++ lib_dec/dec_tran.c | 167 + lib_dec/dec_uv.c | 83 + lib_dec/decision_matrix_dec.c | 526 + lib_dec/decoder.c | 244 + lib_dec/dlpc_avq.c | 247 + lib_dec/dlpc_stoch.c | 106 + lib_dec/er_dec_acelp.c | 693 + lib_dec/er_dec_tcx.c | 550 + lib_dec/er_scale_syn.c | 104 + lib_dec/er_sync_exc.c | 301 + lib_dec/er_util.c | 288 + lib_dec/evs_dec.c | 1041 ++ lib_dec/evs_rtp_payload.c | 240 + lib_dec/evs_rtp_payload.h | 173 + lib_dec/fd_cng_dec.c | 1136 ++ lib_dec/gain_dec.c | 653 + lib_dec/gaus_dec.c | 236 + lib_dec/gs_dec.c | 514 + lib_dec/gs_dec_amr_wb.c | 394 + lib_dec/hdecnrm.c | 367 + lib_dec/hf_synth.c | 1212 ++ lib_dec/hq_classifier_dec.c | 65 + lib_dec/hq_conf_fec.c | 37 + lib_dec/hq_core_dec.c | 365 + lib_dec/hq_env_dec.c | 167 + lib_dec/hq_hr_dec.c | 272 + lib_dec/hq_lr_dec.c | 1302 ++ lib_dec/igf_dec.c | 945 + lib_dec/igf_scf_dec.c | 327 + lib_dec/init_dec.c | 656 + lib_dec/inov_dec.c | 110 + lib_dec/io_dec.c | 435 + lib_dec/jbm_jb4_circularbuffer.c | 425 + lib_dec/jbm_jb4_circularbuffer.h | 51 + lib_dec/jbm_jb4_inputbuffer.c | 307 + lib_dec/jbm_jb4_inputbuffer.h | 48 + lib_dec/jbm_jb4_jmf.c | 264 + lib_dec/jbm_jb4_jmf.h | 42 + lib_dec/jbm_jb4sb.c | 1389 ++ lib_dec/jbm_jb4sb.h | 73 + lib_dec/jbm_pcmdsp_apa.c | 1303 ++ lib_dec/jbm_pcmdsp_apa.h | 105 + lib_dec/jbm_pcmdsp_fifo.c | 164 + lib_dec/jbm_pcmdsp_fifo.h | 44 + lib_dec/jbm_pcmdsp_similarityestimation.c | 102 + lib_dec/jbm_pcmdsp_similarityestimation.h | 120 + lib_dec/jbm_pcmdsp_window.c | 90 + lib_dec/jbm_pcmdsp_window.h | 35 + lib_dec/jbm_types.h | 70 + lib_dec/lead_deindexing.c | 251 + lib_dec/lp_exc_d.c | 78 + lib_dec/lsf_dec.c | 709 + lib_dec/lsf_msvq_ma_dec.c | 262 + lib_dec/nelp_dec.c | 184 + lib_dec/peak_vq_dec.c | 504 + lib_dec/pit_dec.c | 786 + lib_dec/pitch_extr.c | 299 + lib_dec/post_dec.c | 446 + lib_dec/ppp_dec.c | 77 + lib_dec/pvq_core_dec.c | 429 + lib_dec/pvq_decode.c | 75 + lib_dec/range_dec.c | 195 + lib_dec/re8_dec.c | 73 + lib_dec/rom_dec.c | 214 + lib_dec/rom_dec.h | 38 + lib_dec/rst_dec.c | 59 + lib_dec/rtpdump.c | 352 + lib_dec/rtpdump.h | 75 + lib_dec/stat_dec.h | 1017 ++ lib_dec/stat_noise_uv_dec.c | 76 + lib_dec/swb_bwe_dec.c | 665 + lib_dec/swb_bwe_dec_hr.c | 757 + lib_dec/swb_bwe_dec_lr.c | 279 + lib_dec/swb_tbe_dec.c | 2021 +++ lib_dec/syn_outp.c | 106 + lib_dec/tcq_core_dec.c | 451 + lib_dec/tcx_utils_dec.c | 251 + lib_dec/tns_base_dec.c | 72 + lib_dec/tonalMDCTconcealment.c | 706 + lib_dec/transition_dec.c | 744 + lib_dec/updt_dec.c | 586 + lib_dec/vlpc_1st_dec.c | 38 + lib_dec/vlpc_2st_dec.c | 43 + lib_dec/voiced_dec.c | 189 + lib_dec/voip_client.c | 365 + lib_dec/waveadjust_fec_dec.c | 785 + lib_enc/ACcontextMapping_enc.c | 637 + lib_enc/FEC_enc.c | 240 + lib_enc/SNR_calc.c | 195 + lib_enc/acelp_core_enc.c | 587 + lib_enc/acelp_core_switch_enc.c | 431 + lib_enc/acelp_enc_util.c | 48 + lib_enc/amr_wb_enc.c | 541 + lib_enc/analy_lp.c | 143 + lib_enc/analy_sp.c | 210 + lib_enc/ari_enc.c | 414 + lib_enc/ari_hm_enc.c | 590 + lib_enc/arith_coder_enc.c | 627 + lib_enc/avq_cod.c | 380 + lib_enc/bass_psfilter_enc.c | 225 + lib_enc/bw_detect.c | 506 + lib_enc/cng_enc.c | 1005 + lib_enc/cod2t32.c | 305 + lib_enc/cod4t64.c | 957 + lib_enc/cod_ace.c | 430 + lib_enc/cod_tcx.c | 1340 ++ lib_enc/cod_uv.c | 64 + lib_enc/comvad_decision.c | 827 + lib_enc/cor_shif.c | 37 + lib_enc/core_enc_2div.c | 229 + lib_enc/core_enc_init.c | 721 + lib_enc/core_enc_ol.c | 1213 ++ lib_enc/core_enc_reconf.c | 174 + lib_enc/core_enc_switch.c | 166 + lib_enc/core_enc_updt.c | 186 + lib_enc/core_switching_enc.c | 418 + lib_enc/corr_xh.c | 42 + lib_enc/decision_matrix_enc.c | 637 + lib_enc/detect_transient.c | 229 + lib_enc/diffcod.c | 125 + lib_enc/dtx.c | 665 + lib_enc/enc_acelp.c | 1458 ++ lib_enc/enc_acelp_tcx_main.c | 105 + lib_enc/enc_acelpx.c | 474 + lib_enc/enc_amr_wb.c | 199 + lib_enc/enc_gain.c | 233 + lib_enc/enc_gen_voic.c | 309 + lib_enc/enc_gen_voic_rf.c | 384 + lib_enc/enc_higher_acelp.c | 332 + lib_enc/enc_nelp.c | 114 + lib_enc/enc_pit_exc.c | 278 + lib_enc/enc_ppp.c | 166 + lib_enc/enc_prm.c | 769 + lib_enc/enc_tran.c | 315 + lib_enc/enc_uv.c | 109 + lib_enc/encoder.c | 229 + lib_enc/energy.c | 249 + lib_enc/eval_pit_contr.c | 318 + lib_enc/evs_enc.c | 704 + lib_enc/ext_sig_ana.c | 255 + lib_enc/fd_cng_enc.c | 749 + lib_enc/find_tar.c | 87 + lib_enc/find_tilt.c | 184 + lib_enc/find_uv.c | 414 + lib_enc/find_wsp.c | 62 + lib_enc/frame_spec_dif_cor_rate.c | 63 + lib_enc/gain_enc.c | 1014 ++ lib_enc/gaus_enc.c | 430 + lib_enc/gp_clip.c | 214 + lib_enc/gs_enc.c | 470 + lib_enc/guided_plc_enc.c | 368 + lib_enc/hf_cod_amrwb.c | 306 + lib_enc/hq_classifier_enc.c | 501 + lib_enc/hq_core_enc.c | 158 + lib_enc/hq_env_enc.c | 529 + lib_enc/hq_hr_enc.c | 197 + lib_enc/hq_lr_enc.c | 1688 ++ lib_enc/hvq_enc.c | 118 + lib_enc/igf_enc.c | 868 + lib_enc/igf_scf_enc.c | 363 + lib_enc/init_enc.c | 732 + lib_enc/inov_enc.c | 267 + lib_enc/io_enc.c | 1008 + lib_enc/isf_enc_amr_wb.c | 488 + lib_enc/lead_indexing.c | 177 + lib_enc/long_enr.c | 68 + lib_enc/lp_exc_e.c | 286 + lib_enc/lsf_enc.c | 1950 ++ lib_enc/lsf_msvq_ma_enc.c | 521 + lib_enc/ltd_stable.c | 100 + lib_enc/mdct_classifier.c | 245 + lib_enc/mdct_selector.c | 260 + lib_enc/mslvq_enc.c | 744 + lib_enc/multi_harm.c | 288 + lib_enc/nelp_enc.c | 409 + lib_enc/nois_est.c | 884 + lib_enc/noise_adjust.c | 82 + lib_enc/normalizecoefs.c | 38 + lib_enc/peak_vq_enc.c | 593 + lib_enc/pit_enc.c | 1320 ++ lib_enc/pitch_ol.c | 960 + lib_enc/pitch_ol2.c | 303 + lib_enc/plc_enc_ext.c | 110 + lib_enc/ppp_enc.c | 203 + lib_enc/pre_proc.c | 913 + lib_enc/pvq_core_enc.c | 511 + lib_enc/pvq_encode.c | 162 + lib_enc/q_gain2p.c | 368 + lib_enc/qlpc_avq.c | 330 + lib_enc/qlpc_stoch.c | 314 + lib_enc/range_enc.c | 290 + lib_enc/re8_cod.c | 55 + lib_enc/reordernorm.c | 58 + lib_enc/rom_enc.c | 703 + lib_enc/rom_enc.h | 148 + lib_enc/rst_enc.c | 59 + lib_enc/set_impulse.c | 302 + lib_enc/setmodeindex.c | 41 + lib_enc/sig_clas.c | 312 + lib_enc/spec_center.c | 62 + lib_enc/spec_flatness.c | 98 + lib_enc/speech_music_classif.c | 1900 ++ lib_enc/stat_enc.h | 1230 ++ lib_enc/stat_noise_uv_enc.c | 72 + lib_enc/subband_fft.c | 183 + lib_enc/swb_bwe_enc.c | 1728 ++ lib_enc/swb_bwe_enc_hr.c | 474 + lib_enc/swb_bwe_enc_lr.c | 673 + lib_enc/swb_pre_proc.c | 314 + lib_enc/swb_tbe_enc.c | 2044 +++ lib_enc/tcq_core_enc.c | 439 + lib_enc/tcx_ltp_enc.c | 421 + lib_enc/tcx_utils_enc.c | 1219 ++ lib_enc/tfa_enc.c | 68 + lib_enc/tns_base_enc.c | 315 + lib_enc/transient_detection.c | 600 + lib_enc/transition_enc.c | 978 + lib_enc/update_decision.c | 248 + lib_enc/updt_enc.c | 234 + lib_enc/updt_tar.c | 29 + lib_enc/vad.c | 1010 ++ lib_enc/vad_param_updt.c | 119 + lib_enc/vad_proc.c | 264 + lib_enc/vbr_average_rate.c | 167 + lib_enc/vlpc_1st_cod.c | 120 + lib_enc/vlpc_2st_cod.c | 116 + lib_enc/voiced_enc.c | 647 + lib_enc/waveadjust_fec_cod.c | 44 + 429 files changed, 225546 insertions(+) create mode 100644 Workspace_msvc/Workspace_msvc.sln create mode 100644 Workspace_msvc/common.vcxproj create mode 100644 Workspace_msvc/debug.vcxproj create mode 100644 Workspace_msvc/evs_dec.vcxproj create mode 100644 Workspace_msvc/evs_enc.vcxproj create mode 100644 lib_com/ACcontextMapping.c create mode 100644 lib_com/__zaloha/basop32.c create mode 100644 lib_com/__zaloha/basop32.h create mode 100644 lib_com/__zaloha/basop_com_lpc.c create mode 100644 lib_com/__zaloha/basop_lsf_tools.c create mode 100644 lib_com/__zaloha/basop_mpy.c create mode 100644 lib_com/__zaloha/basop_mpy.h create mode 100644 lib_com/__zaloha/basop_proto_func.h create mode 100644 lib_com/__zaloha/basop_settings.h create mode 100644 lib_com/__zaloha/basop_tcx_utils.c create mode 100644 lib_com/__zaloha/basop_util.c create mode 100644 lib_com/__zaloha/basop_util.h create mode 100644 lib_com/__zaloha/bastypes.h create mode 100644 lib_com/__zaloha/enh1632.c create mode 100644 lib_com/__zaloha/enh1632.h create mode 100644 lib_com/__zaloha/enh40.c create mode 100644 lib_com/__zaloha/enh40.h create mode 100644 lib_com/__zaloha/move.h create mode 100644 lib_com/__zaloha/stl.h 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/basop32.c create mode 100644 lib_com/basop32.h create mode 100644 lib_com/basop_com_lpc.c create mode 100644 lib_com/basop_lsf_tools.c create mode 100644 lib_com/basop_mpy.c create mode 100644 lib_com/basop_mpy.h create mode 100644 lib_com/basop_proto_func.h create mode 100644 lib_com/basop_settings.h create mode 100644 lib_com/basop_tcx_utils.c create mode 100644 lib_com/basop_util.c create mode 100644 lib_com/basop_util.h create mode 100644 lib_com/bitalloc.c create mode 100644 lib_com/bitallocsum.c create mode 100644 lib_com/bits_alloc.c create mode 100644 lib_com/bitstream.c create mode 100644 lib_com/calc_st_com.c create mode 100644 lib_com/cb_shape.c create mode 100644 lib_com/cldfb.c create mode 100644 lib_com/cng_exc.c create mode 100644 lib_com/cnst.h create mode 100644 lib_com/codec_tcx_common.c create mode 100644 lib_com/core_com_config.c create mode 100644 lib_com/deemph.c create mode 100644 lib_com/delay_comp.c create mode 100644 lib_com/disclaimer.c create mode 100644 lib_com/dlpc_bfi.c create mode 100644 lib_com/edct.c create mode 100644 lib_com/enh1632.c create mode 100644 lib_com/enh1632.h create mode 100644 lib_com/enh40.c create mode 100644 lib_com/enh40.h create mode 100644 lib_com/enhancer.c create mode 100644 lib_com/enr_1_az.c create mode 100644 lib_com/env_adj.c create mode 100644 lib_com/env_stab.c create mode 100644 lib_com/env_stab_trans.c create mode 100644 lib_com/est_tilt.c create mode 100644 lib_com/fd_cng_com.c create mode 100644 lib_com/fft.c create mode 100644 lib_com/fft_cldfb.c create mode 100644 lib_com/fft_rel.c create mode 100644 lib_com/fill_spectrum.c create mode 100644 lib_com/findpulse.c create mode 100644 lib_com/fine_gain_bits.c create mode 100644 lib_com/frame_ener.c create mode 100644 lib_com/g192.c create mode 100644 lib_com/g192.h create mode 100644 lib_com/get_gain.c create mode 100644 lib_com/gs_bitallocation.c create mode 100644 lib_com/gs_gains.c create mode 100644 lib_com/gs_inact_switching.c create mode 100644 lib_com/gs_noisefill.c create mode 100644 lib_com/gs_preech.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.c create mode 100644 lib_com/hq2_core_com.c create mode 100644 lib_com/hq2_noise_inject.c create mode 100644 lib_com/hq_bit_allocation.c create mode 100644 lib_com/hq_conf.c create mode 100644 lib_com/hq_tools.c create mode 100644 lib_com/hvq_pvq_bitalloc.c create mode 100644 lib_com/ifft_rel.c create mode 100644 lib_com/igf_base.c create mode 100644 lib_com/index_pvq_opt.c create mode 100644 lib_com/int_lsp.c create mode 100644 lib_com/interleave_spectrum.c create mode 100644 lib_com/interpol.c create mode 100644 lib_com/isf_dec_amr_wb.c create mode 100644 lib_com/lag_wind.c create mode 100644 lib_com/lerp.c create mode 100644 lib_com/limit_t0.c create mode 100644 lib_com/logqnorm.c create mode 100644 lib_com/longarith.c create mode 100644 lib_com/low_rate_band_att.c create mode 100644 lib_com/lpc_tools.c create mode 100644 lib_com/lsf_dec_bfi.c create mode 100644 lib_com/lsf_msvq_ma.c create mode 100644 lib_com/lsf_tools.c create mode 100644 lib_com/lsp_conv_poly.c create mode 100644 lib_com/mime.h create mode 100644 lib_com/modif_fs.c create mode 100644 lib_com/move.h create mode 100644 lib_com/mslvq_com.c create mode 100644 lib_com/nelp.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.c create mode 100644 lib_com/pred_lt4.c create mode 100644 lib_com/preemph.c create mode 100644 lib_com/prot.h create mode 100644 lib_com/pvq_com.c create mode 100644 lib_com/range_com.c create mode 100644 lib_com/re8_ppv.c create mode 100644 lib_com/re8_util.c create mode 100644 lib_com/realft.c create mode 100644 lib_com/recovernorm.c create mode 100644 lib_com/reordvct.c create mode 100644 lib_com/residu.c create mode 100644 lib_com/rom_com.c create mode 100644 lib_com/rom_com.h create mode 100644 lib_com/stab_est.c create mode 100644 lib_com/stat_com.h create mode 100644 lib_com/stat_noise_uv_mod.c create mode 100644 lib_com/stl.h create mode 100644 lib_com/swb_bwe_com.c create mode 100644 lib_com/swb_bwe_com_hr.c create mode 100644 lib_com/swb_bwe_com_lr.c create mode 100644 lib_com/swb_tbe_com.c create mode 100644 lib_com/syn_12k8.c create mode 100644 lib_com/syn_filt.c create mode 100644 lib_com/tcq_position_arith.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.c create mode 100644 lib_com/trans_direct.c create mode 100644 lib_com/trans_inv.c create mode 100644 lib_com/typedef.h create mode 100644 lib_com/vlpc_2st_com.c create mode 100644 lib_com/weight.c create mode 100644 lib_com/weight_a.c create mode 100644 lib_com/wi.c create mode 100644 lib_com/window.c create mode 100644 lib_com/window_ola.c create mode 100644 lib_com/wtda.c create mode 100644 lib_debug/wmc_auto.c create mode 100644 lib_debug/wmc_auto.h 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.c create mode 100644 lib_dec/FEC_HQ_core.c create mode 100644 lib_dec/FEC_HQ_phase_ecu.c create mode 100644 lib_dec/FEC_adapt_codebook.c create mode 100644 lib_dec/FEC_clas_estim.c create mode 100644 lib_dec/FEC_lsf_estim.c create mode 100644 lib_dec/FEC_pitch_estim.c create mode 100644 lib_dec/FEC_scale_syn.c create mode 100644 lib_dec/LD_music_post_filter.c create mode 100644 lib_dec/TonalComponentDetection.c create mode 100644 lib_dec/acelp_core_dec.c create mode 100644 lib_dec/acelp_core_switch_dec.c create mode 100644 lib_dec/amr_wb_dec.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.c create mode 100644 lib_dec/bass_psfilter.c create mode 100644 lib_dec/cng_dec.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.c create mode 100644 lib_dec/d_gain2p.c create mode 100644 lib_dec/dec2t32.c create mode 100644 lib_dec/dec4t64.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.c create mode 100644 lib_dec/dec_gen_voic.c create mode 100644 lib_dec/dec_higher_acelp.c create mode 100644 lib_dec/dec_nelp.c create mode 100644 lib_dec/dec_pit_exc.c create mode 100644 lib_dec/dec_post.c create mode 100644 lib_dec/dec_ppp.c create mode 100644 lib_dec/dec_prm.c create mode 100644 lib_dec/dec_tcx.c create mode 100644 lib_dec/dec_tran.c create mode 100644 lib_dec/dec_uv.c create mode 100644 lib_dec/decision_matrix_dec.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.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.c create mode 100644 lib_dec/gaus_dec.c create mode 100644 lib_dec/gs_dec.c create mode 100644 lib_dec/gs_dec_amr_wb.c create mode 100644 lib_dec/hdecnrm.c create mode 100644 lib_dec/hf_synth.c create mode 100644 lib_dec/hq_classifier_dec.c create mode 100644 lib_dec/hq_conf_fec.c create mode 100644 lib_dec/hq_core_dec.c create mode 100644 lib_dec/hq_env_dec.c create mode 100644 lib_dec/hq_hr_dec.c create mode 100644 lib_dec/hq_lr_dec.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.c create mode 100644 lib_dec/inov_dec.c create mode 100644 lib_dec/io_dec.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/jbm_types.h create mode 100644 lib_dec/lead_deindexing.c create mode 100644 lib_dec/lp_exc_d.c create mode 100644 lib_dec/lsf_dec.c create mode 100644 lib_dec/lsf_msvq_ma_dec.c create mode 100644 lib_dec/nelp_dec.c create mode 100644 lib_dec/peak_vq_dec.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.c create mode 100644 lib_dec/pvq_core_dec.c create mode 100644 lib_dec/pvq_decode.c create mode 100644 lib_dec/range_dec.c create mode 100644 lib_dec/re8_dec.c create mode 100644 lib_dec/rom_dec.c create mode 100644 lib_dec/rom_dec.h create mode 100644 lib_dec/rst_dec.c create mode 100644 lib_dec/rtpdump.c create mode 100644 lib_dec/rtpdump.h create mode 100644 lib_dec/stat_dec.h create mode 100644 lib_dec/stat_noise_uv_dec.c create mode 100644 lib_dec/swb_bwe_dec.c create mode 100644 lib_dec/swb_bwe_dec_hr.c create mode 100644 lib_dec/swb_bwe_dec_lr.c create mode 100644 lib_dec/swb_tbe_dec.c create mode 100644 lib_dec/syn_outp.c create mode 100644 lib_dec/tcq_core_dec.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.c create mode 100644 lib_dec/updt_dec.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.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.c create mode 100644 lib_enc/SNR_calc.c create mode 100644 lib_enc/acelp_core_enc.c create mode 100644 lib_enc/acelp_core_switch_enc.c create mode 100644 lib_enc/acelp_enc_util.c create mode 100644 lib_enc/amr_wb_enc.c create mode 100644 lib_enc/analy_lp.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.c create mode 100644 lib_enc/bass_psfilter_enc.c create mode 100644 lib_enc/bw_detect.c create mode 100644 lib_enc/cng_enc.c create mode 100644 lib_enc/cod2t32.c create mode 100644 lib_enc/cod4t64.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.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.c create mode 100644 lib_enc/corr_xh.c create mode 100644 lib_enc/decision_matrix_enc.c create mode 100644 lib_enc/detect_transient.c create mode 100644 lib_enc/diffcod.c create mode 100644 lib_enc/dtx.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.c create mode 100644 lib_enc/enc_gain.c create mode 100644 lib_enc/enc_gen_voic.c create mode 100644 lib_enc/enc_gen_voic_rf.c create mode 100644 lib_enc/enc_higher_acelp.c create mode 100644 lib_enc/enc_nelp.c create mode 100644 lib_enc/enc_pit_exc.c create mode 100644 lib_enc/enc_ppp.c create mode 100644 lib_enc/enc_prm.c create mode 100644 lib_enc/enc_tran.c create mode 100644 lib_enc/enc_uv.c create mode 100644 lib_enc/encoder.c create mode 100644 lib_enc/energy.c create mode 100644 lib_enc/eval_pit_contr.c create mode 100644 lib_enc/evs_enc.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.c create mode 100644 lib_enc/find_tilt.c create mode 100644 lib_enc/find_uv.c create mode 100644 lib_enc/find_wsp.c create mode 100644 lib_enc/frame_spec_dif_cor_rate.c create mode 100644 lib_enc/gain_enc.c create mode 100644 lib_enc/gaus_enc.c create mode 100644 lib_enc/gp_clip.c create mode 100644 lib_enc/gs_enc.c create mode 100644 lib_enc/guided_plc_enc.c create mode 100644 lib_enc/hf_cod_amrwb.c create mode 100644 lib_enc/hq_classifier_enc.c create mode 100644 lib_enc/hq_core_enc.c create mode 100644 lib_enc/hq_env_enc.c create mode 100644 lib_enc/hq_hr_enc.c create mode 100644 lib_enc/hq_lr_enc.c create mode 100644 lib_enc/hvq_enc.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.c create mode 100644 lib_enc/inov_enc.c create mode 100644 lib_enc/io_enc.c create mode 100644 lib_enc/isf_enc_amr_wb.c create mode 100644 lib_enc/lead_indexing.c create mode 100644 lib_enc/long_enr.c create mode 100644 lib_enc/lp_exc_e.c create mode 100644 lib_enc/lsf_enc.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.c create mode 100644 lib_enc/mdct_selector.c create mode 100644 lib_enc/mslvq_enc.c create mode 100644 lib_enc/multi_harm.c create mode 100644 lib_enc/nelp_enc.c create mode 100644 lib_enc/nois_est.c create mode 100644 lib_enc/noise_adjust.c create mode 100644 lib_enc/normalizecoefs.c create mode 100644 lib_enc/peak_vq_enc.c create mode 100644 lib_enc/pit_enc.c create mode 100644 lib_enc/pitch_ol.c create mode 100644 lib_enc/pitch_ol2.c create mode 100644 lib_enc/plc_enc_ext.c create mode 100644 lib_enc/ppp_enc.c create mode 100644 lib_enc/pre_proc.c create mode 100644 lib_enc/pvq_core_enc.c create mode 100644 lib_enc/pvq_encode.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.c create mode 100644 lib_enc/re8_cod.c create mode 100644 lib_enc/reordernorm.c create mode 100644 lib_enc/rom_enc.c create mode 100644 lib_enc/rom_enc.h create mode 100644 lib_enc/rst_enc.c create mode 100644 lib_enc/set_impulse.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.c create mode 100644 lib_enc/stat_enc.h create mode 100644 lib_enc/stat_noise_uv_enc.c create mode 100644 lib_enc/subband_fft.c create mode 100644 lib_enc/swb_bwe_enc.c create mode 100644 lib_enc/swb_bwe_enc_hr.c create mode 100644 lib_enc/swb_bwe_enc_lr.c create mode 100644 lib_enc/swb_pre_proc.c create mode 100644 lib_enc/swb_tbe_enc.c create mode 100644 lib_enc/tcq_core_enc.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.c create mode 100644 lib_enc/update_decision.c create mode 100644 lib_enc/updt_enc.c create mode 100644 lib_enc/updt_tar.c create mode 100644 lib_enc/vad.c create mode 100644 lib_enc/vad_param_updt.c create mode 100644 lib_enc/vad_proc.c create mode 100644 lib_enc/vbr_average_rate.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.c create mode 100644 lib_enc/waveadjust_fec_cod.c diff --git a/Workspace_msvc/Workspace_msvc.sln b/Workspace_msvc/Workspace_msvc.sln new file mode 100644 index 000000000..ab6915398 --- /dev/null +++ b/Workspace_msvc/Workspace_msvc.sln @@ -0,0 +1,60 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.33027.164 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "common.vcxproj", "{39EC200D-7795-4FF8-B214-B24EDA5526AE}" + ProjectSection(ProjectDependencies) = postProject + {54509728-928B-44D9-A118-A6F92F08B34F} = {54509728-928B-44D9-A118-A6F92F08B34F} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "evs_dec", "evs_dec.vcxproj", "{E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}" + ProjectSection(ProjectDependencies) = postProject + {54509728-928B-44D9-A118-A6F92F08B34F} = {54509728-928B-44D9-A118-A6F92F08B34F} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "evs_enc", "evs_enc.vcxproj", "{824DA4CF-06F0-45C9-929A-8792F0E19C3E}" + ProjectSection(ProjectDependencies) = postProject + {54509728-928B-44D9-A118-A6F92F08B34F} = {54509728-928B-44D9-A118-A6F92F08B34F} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "debug", "debug.vcxproj", "{54509728-928B-44D9-A118-A6F92F08B34F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + Unittests|Win32 = Unittests|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 + {39EC200D-7795-4FF8-B214-B24EDA5526AE}.Unittests|Win32.ActiveCfg = Release|Win32 + {39EC200D-7795-4FF8-B214-B24EDA5526AE}.Unittests|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 + {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}.Unittests|Win32.ActiveCfg = Release|Win32 + {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}.Unittests|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 + {824DA4CF-06F0-45C9-929A-8792F0E19C3E}.Unittests|Win32.ActiveCfg = Release|Win32 + {824DA4CF-06F0-45C9-929A-8792F0E19C3E}.Unittests|Win32.Build.0 = Release|Win32 + {54509728-928B-44D9-A118-A6F92F08B34F}.Debug|Win32.ActiveCfg = Debug|Win32 + {54509728-928B-44D9-A118-A6F92F08B34F}.Debug|Win32.Build.0 = Debug|Win32 + {54509728-928B-44D9-A118-A6F92F08B34F}.Release|Win32.ActiveCfg = Release|Win32 + {54509728-928B-44D9-A118-A6F92F08B34F}.Release|Win32.Build.0 = Release|Win32 + {54509728-928B-44D9-A118-A6F92F08B34F}.Unittests|Win32.ActiveCfg = Unittests|Win32 + {54509728-928B-44D9-A118-A6F92F08B34F}.Unittests|Win32.Build.0 = Unittests|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FE9056FB-CCA7-4E31-A173-2A2DEB724C18} + EndGlobalSection +EndGlobal diff --git a/Workspace_msvc/common.vcxproj b/Workspace_msvc/common.vcxproj new file mode 100644 index 000000000..f29349cae --- /dev/null +++ b/Workspace_msvc/common.vcxproj @@ -0,0 +1,276 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {39EC200D-7795-4FF8-B214-B24EDA5526AE} + common + 10.0 + + + + StaticLibrary + false + MultiByte + v142 + + + StaticLibrary + false + MultiByte + v142 + + + + + + + + + + + + + + + <_ProjectFileVersion>15.0.26228.10 + + + .\Debug_Common\ + .\Debug_Common\ + + + .\Release_Common\ + .\Release_Common\ + + + + + + + Disabled + ..\lib_enc;..\lib_dec;..\lib_com;..\lib_debug;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions) + + EnableFastChecks + MultiThreadedDebug + + + $(IntDir)commonlib.pdb + Level4 + true + OldStyle + Default + 4310;4244;%(DisableSpecificWarnings) + Column + + + _DEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + WS2_32.lib;%(AdditionalDependencies) + $(OutDir)$(ProjectName).lib + true + + + + + + + + MaxSpeed + AnySuitable + false + Neither + false + false + ..\lib_enc;..\lib_dec;..\lib_com;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + + Default + MultiThreaded + true + + + $(IntDir)commonlib.pdb + Level4 + true + + Default + 4100;4244;4310;%(DisableSpecificWarnings) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + WS2_32.lib;%(AdditionalDependencies) + $(OutDir)$(ProjectName).lib + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {54509728-928b-44d9-a118-a6f92f08b34f} + + + + + + + + + + + \ No newline at end of file diff --git a/Workspace_msvc/debug.vcxproj b/Workspace_msvc/debug.vcxproj new file mode 100644 index 000000000..8e23671bf --- /dev/null +++ b/Workspace_msvc/debug.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Unittests + Win32 + + + + {54509728-928B-44D9-A118-A6F92F08B34F} + debug + 10.0.17763.0 + + + + StaticLibrary + v141 + MultiByte + + + StaticLibrary + v142 + MultiByte + + + StaticLibrary + v142 + MultiByte + true + + + + + + + + + + + + + + + + <_ProjectFileVersion>15.0.27428.2015 + + + .\Debug_Debug\ + .\Debug_Debug\ + lib_debug + + + .\Debug_$(ProjectName)\ + .\Debug_$(ProjectName)\ + libivasdebug + + + .\Release_$(ProjectName)\ + .\Release_$(ProjectName)\ + libivasdebug + + + + + + + Disabled + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;$(Macros);%(PreprocessorDefinitions) + false + + EnableFastChecks + MultiThreadedDebug + false + $(IntDir)$(ProjectName).pdb + Level4 + OldStyle + Default + %(DisableSpecificWarnings) + + + $(OutDir)$(TargetName).lib + + + + + + + + + Disabled + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;$(Macros);%(PreprocessorDefinitions) + false + + + EnableFastChecks + MultiThreadedDebug + false + $(IntDir)$(ProjectName).pdb + Level4 + OldStyle + Default + %(DisableSpecificWarnings) + + + $(OutDir)$(TargetName).lib + + + + + + + + MaxSpeed + AnySuitable + false + false + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;$(Macros);%(PreprocessorDefinitions) + true + + Default + MultiThreaded + true + $(IntDir)$(ProjectName).pdb + Level4 + + Default + %(DisableSpecificWarnings) + + + $(OutDir)$(TargetName).lib + + + + + + + + + + + + + + + + + \ 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 000000000..03b5ef562 --- /dev/null +++ b/Workspace_msvc/evs_dec.vcxproj @@ -0,0 +1,297 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3} + evs_dec + 10.0 + + + + Application + false + MultiByte + v142 + + + Application + false + MultiByte + v142 + + + + + + + + + + + + + + + <_ProjectFileVersion>15.0.26228.10 + + + ..\ + .\Debug_Dec\ + false + false + EVS_dec + + + ..\ + .\Release_Dec\ + false + false + EVS_dec + + + + + + + .\Debug/vbr_dec.tlb + + + + Disabled + ..\lib_enc;..\lib_dec;..\lib_com;..\lib_debug;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions) + + EnableFastChecks + MultiThreadedDebug + false + + + $(IntDir)evs_dec.pdb + Level4 + true + OldStyle + Default + 4244;%(DisableSpecificWarnings) + + + _DEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + + + ..\EVS_dec.exe + true + + true + .\Debug/evs_dec.pdb + Console + false + + MachineX86 + + + + + .\Release/vbr_dec.tlb + + + + MaxSpeed + AnySuitable + false + Neither + false + false + ..\lib_enc;..\lib_dec;..\lib_com;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions) + true + + Default + MultiThreaded + true + false + + + $(IntDir)evs_dec.pdb + Level4 + true + + Default + 4100;4244;4310;%(DisableSpecificWarnings) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + ..\EVS_dec.exe + true + + false + .\Release/vbr_dec.pdb + Console + false + + MachineX86 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {39ec200d-7795-4ff8-b214-b24eda5526ae} + false + + + {54509728-928b-44d9-a118-a6f92f08b34f} + + + + + + + + + + + \ 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 000000000..c562f2430 --- /dev/null +++ b/Workspace_msvc/evs_enc.vcxproj @@ -0,0 +1,323 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {824DA4CF-06F0-45C9-929A-8792F0E19C3E} + evs_enc + 10.0 + + + + Application + false + MultiByte + v142 + + + Application + false + MultiByte + v142 + + + + + + + + + + + + + + + <_ProjectFileVersion>15.0.26228.10 + + + ..\ + .\Release_Enc\ + false + false + EVS_cod + + + ..\ + .\Debug_Enc\ + false + false + EVS_cod + + + + + + + .\Release/vbr_enc.tlb + + + + MaxSpeed + AnySuitable + false + Neither + false + false + ..\lib_enc;..\lib_dec;..\lib_com;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + + Default + MultiThreaded + true + Precise + false + + + $(IntDir)ens_enc.pdb + Level4 + true + + Default + 4100;4244;4310;%(DisableSpecificWarnings) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + ..\EVS_cod.exe + true + + false + .\Release/vbr_enc.pdb + Console + false + + MachineX86 + + + + + + + + .\Debug/vbr_enc.tlb + + + + Disabled + ..\lib_enc;..\lib_dec;..\lib_com;..\lib_debug;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions) + + EnableFastChecks + MultiThreadedDebug + false + + + $(IntDir)ens_enc.pdb + Level4 + true + OldStyle + Default + 4244;%(DisableSpecificWarnings) + false + + + + + _DEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + + + ..\EVS_cod.exe + true + + false + true + .\Debug/evs_enc.pdb + Console + + false + + MachineX86 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {39ec200d-7795-4ff8-b214-b24eda5526ae} + false + + + {54509728-928b-44d9-a118-a6f92f08b34f} + + + + + + + + + + + \ No newline at end of file diff --git a/lib_com/ACcontextMapping.c b/lib_com/ACcontextMapping.c new file mode 100644 index 000000000..f1989a09b --- /dev/null +++ b/lib_com/ACcontextMapping.c @@ -0,0 +1,74 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" + + +/*-------------------------------------------------------------------* +* get_next_coeff_mapped() +* +* +*-------------------------------------------------------------------*/ + +int get_next_coeff_mapped( /* o : index of next coefficient */ + int ii[2], /* i/o: coefficient indexes */ + int *pp, /* o : peak(1)/hole(0) indicator */ + int *idx, /* o : index in unmapped domain */ + CONTEXT_HM_CONFIG *hm_cfg /* i : HM configuration */ +) +{ + unsigned int p; + + p = (ii[1] - hm_cfg->numPeakIndices) & (hm_cfg->indexBuffer[ii[1]] - hm_cfg->indexBuffer[ii[0]]); + p >>= sizeof(p)*8-1; + *pp = p; + *idx = ii[p]; + ii[p]++; + + return hm_cfg->indexBuffer[*idx]; +} + + +/*-------------------------------------------------------------------* +* get_next_coeff_unmapped() +* +* +*-------------------------------------------------------------------*/ + +int get_next_coeff_unmapped(/* o : index of next coefficient */ + int *ii, /* i/o: coefficient indexes */ + int *idx /* o : index in unmapped domain */ +) +{ + *idx = *ii; + (*ii)++; + + return *idx; +} + +/*-------------------------------------------------------------------* +* update_mixed_context() +* +* +*-------------------------------------------------------------------*/ + +int update_mixed_context( + int ctx, + int a +) +{ + int t; + + t = 1-13 + (a & ~1)*((a>>2)+1); + + if (t > 0) + { + t = min((a>>3), 2); + } + + return (ctx & 0xf) * 16 + t + 13; +} diff --git a/lib_com/__zaloha/basop32.c b/lib_com/__zaloha/basop32.c new file mode 100644 index 000000000..124cf7239 --- /dev/null +++ b/lib_com/__zaloha/basop32.c @@ -0,0 +1,2542 @@ + +/* 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. | + | | + | | + | | + | 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 | + |___________________________________________________________________________| +*/ +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include +#include +#include "stl.h" +#include "wmc_auto.h" + +#define WMC_TOOL_SKIP + +/*___________________________________________________________________________ + | | + | Local Functions | + |___________________________________________________________________________| +*/ +static Word16 saturate (Word32 L_var1); + + +/*___________________________________________________________________________ + | | + | Constants and Globals | + |___________________________________________________________________________| +*/ +Flag Overflow = 0; +Flag Carry = 0; + + +/*___________________________________________________________________________ + | | + | Functions | + |___________________________________________________________________________| +*/ + +#define PRINT_STACK_ID_ALL "*" + + + +/*___________________________________________________________________________ + | | + | 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); + } + + BASOP_CHECK(); + + 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); + + + 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); + + + 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; + } + } + + BASOP_CHECK(); + + + 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); + } + 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); + } + } + + BASOP_CHECK(); + + + 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); + } + else + { + if (var2 >= 15) + { + var_out = (var1 < 0) ? -1 : 0; + } + else + { + if (var1 < 0) + { + var_out = ~((~var1) >> var2); + } + else + { + var_out = var1 >> var2; + } + } + } + + BASOP_CHECK(); + + + 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); + + + 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; + } + + BASOP_CHECK(); + + + 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; + + + BASOP_CHECK(); + + + 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); + + BASOP_CHECK(); + + + 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; + + BASOP_CHECK(); + + + 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; + + BASOP_SATURATE_WARNING_OFF + L_rounded = L_add (L_var1, (Word32) 0x00008000L); + BASOP_SATURATE_WARNING_ON + var_out = extract_h (L_rounded); + + BASOP_CHECK(); + + + 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); + + BASOP_CHECK(); + + + 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); + + BASOP_CHECK(); + + + 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); + + /* BASOP_CHECK(); Do not check for overflow here, function produces the carry bit instead */ + + + 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); + + /* BASOP_CHECK(); Do not check for overflow here, function produces the carry bit instead */ + + + 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; + } + } + + BASOP_CHECK(); + + + 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; + } + } + + BASOP_CHECK(); + + + 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; + } + + /* BASOP_CHECK(); Do not check for overflow here, function produces the carry bit instead */ + + + 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); + } + 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; + } + } + + /* BASOP_CHECK(); Do not check for overflow here, function produces the carry bit instead */ + + + 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; + + + BASOP_CHECK(); + + + 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); + + + 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); + } + 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; + } + } + + BASOP_CHECK(); + + + 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); + } + 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; + } + } + } + + BASOP_CHECK(); + + + 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 (var2 > 0) + { + if ((var1 & ((Word16) 1 << (var2 - 1))) != 0) + { + var_out++; + } + } + } + + BASOP_CHECK(); + + + 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); + + BASOP_CHECK(); + + + 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); + + BASOP_CHECK(); + + + 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; + + BASOP_CHECK(); + + + 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; + + BASOP_CHECK(); + + + 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 (var2 > 0) + { + if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0) + { + L_var_out++; + } + } + } + + BASOP_CHECK(); + + + 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; + } + } + + BASOP_CHECK(); + + + 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; + } + + BASOP_CHECK(); + + + 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; + } + } + } + + BASOP_CHECK(); + + + 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 in ", var1, var2); printStack(); */ + char text[60]; + sprintf (text, "Division Error var1=%d var2=%d in ", var1, var2); + abort(); /* exit (0); */ + } + if (var2 == 0) + { + /* printf ("Division by 0, Fatal error in "); printStack(); */ + 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); + + 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); + } + } + } + } + + BASOP_CHECK(); + + + 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; + } + } + } + + BASOP_CHECK(); + + + 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) ) ; + + BASOP_CHECK(); + + + 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 ( den == (Word16) 0 ) + { + /* printf("Division by 0 in div_l, Fatal error in "); printStack(); */ + exit(-1); + } + + if ( (L_num < (Word32) 0) || (den < (Word16) 0) ) + { + /* printf("Division Error in div_l, Fatal error in "); printStack(); */ + exit(-1); + } + + L_den = L_deposit_h( den ) ; + + if ( L_num >= L_den ) + { + + + BASOP_CHECK(); + return MAX_16 ; + } + else + { + L_num = L_shr(L_num, (Word16)1) ; + L_den = L_shr(L_den, (Word16)1); + for(iteration=(Word16)0; iteration< (Word16)15; iteration++) + { + var_out = shl( var_out, (Word16)1); + L_num = L_shl( L_num, (Word16)1); + if (L_num >= L_den) + { + L_num = L_sub(L_num,L_den); + var_out = add(var_out, (Word16)1); + } + } + + + BASOP_CHECK(); + + 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; + 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; + + BASOP_CHECK(); + + + 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); + + BASOP_CHECK(); + + + 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); + + BASOP_CHECK(); + + + return(L_var_out); +} + + +/* end of file */ diff --git a/lib_com/__zaloha/basop32.h b/lib_com/__zaloha/basop32.h new file mode 100644 index 000000000..f8126e961 --- /dev/null +++ b/lib_com/__zaloha/basop32.h @@ -0,0 +1,139 @@ +/* + =========================================================================== + 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 + + 13 Mar 12 Add Overflow2 flag for additional overflow checking. + ============================================================================ +*/ + + +#ifndef _BASIC_OP_H +#define _BASIC_OP_H + +/* #define BASOP_OVERFLOW2 */ + +/*___________________________________________________________________________ + | | + | Constants and Globals | + |___________________________________________________________________________| +*/ +extern Flag Overflow, Overflow2; +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 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/lib_com/__zaloha/basop_com_lpc.c b/lib_com/__zaloha/basop_com_lpc.c new file mode 100644 index 000000000..30075a1a7 --- /dev/null +++ b/lib_com/__zaloha/basop_com_lpc.c @@ -0,0 +1,239 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "wmc_auto.h" +#include +#include +#include +#include +#include "typedef.h" +#include "basop_proto_func.h" +#include "cnst.h" + +#include "basop_util.h" +#include "stl.h" + +#define WMC_TOOL_SKIP + +#define UNROLL_CHEBYSHEV_INNER_LOOP +#define NC_MAX 8 +#define GUESS_TBL_SZ 256 + +#define Madd_32_16(accu, x, y) L_add(accu, Mpy_32_16(x, y)) +#define Msub_32_16(accu, x, y) L_sub(accu, Mpy_32_16(x, y)) + + +/* + * weight_a + * + * Parameters: + * a I: LP filter coefficients Q12 + * ap O: weighted LP filter coefficients Q12 + * gamma I: weighting factor Q15 + * + * Function: + * Weighting of LP filter coefficients, ap[i] = a[i] * (gamma^i). + * + * Returns: + * void + */ +void basop_weight_a(const Word16 *a, Word16 *ap, const Word16 gamma) +{ + Word16 i, fac; + Word32 Amax; + Word16 shift; + + + + fac = gamma; + Amax = L_mult( 16384, a[0] ); + FOR (i = 1; i < M; i++) + { + Amax = L_max( Amax, L_abs( L_mult0( fac, a[i] ) ) ); + fac = mult_r( fac, gamma ); + } + Amax = L_max( Amax, L_abs( L_mult0( fac, a[M] ) ) ); + shift = norm_l( Amax ); + fac = gamma; + ap[0] = shl( a[0], sub(shift,1) ); + move16(); + FOR (i = 1; i < M; i++) + { + ap[i] = round_fx(L_shl(L_mult0(a[i], fac),shift)); + move16(); + fac = mult_r( fac, gamma ); + } + ap[M] = round_fx(L_shl(L_mult0(a[M], fac),shift)); + move16(); + + + return; +} + +/* + * weight_a_inv + * + * Parameters: + * a I: LP filter coefficients Q12 + * ap O: weighted LP filter coefficients Q12 + * inv_gamma I: inverse weighting factor Q14 + * + * Function: + * Weighting of LP filter coefficients, ap[i] = a[i] * (inv_gamma^i). + * + * Returns: + * void + */ +void basop_weight_a_inv(const Word16 *a, Word16 *ap, const Word16 inv_gamma) +{ + Word16 i; + static const Word16 inv_gamma_tab_12k8[16] = { 17809, 19357, 21041, 22870, 24859, 27020, 29370, 31924, /* Q14 */ + 17350, 18859, 20499, 22281, 24219, 26325, 28614, 31102 + }; /* Q13 */ + static const Word16 inv_gamma_tab_16k[16] = { 17430, 18542, 19726, 20985, 22324, 23749, 25265, 26878, /* Q14 */ + 14297, 15209, 16180, 17213, 18312, 19480, 20724, 22047 + }; /* Q13 */ + const Word16 *inv_gamma_tab; + Word32 L_tmp; + Word32 Amax; + Word16 shift; + + + IF (inv_gamma == 16384) + { + FOR (i = 0; i <= M; i++) + { + ap[i] = a[i]; + move16(); + } + return; + } + + assert( inv_gamma==GAMMA1_INV || inv_gamma==GAMMA16k_INV ); + + inv_gamma_tab = inv_gamma_tab_12k8; + move16(); + if (sub(inv_gamma,GAMMA16k_INV) == 0) + { + inv_gamma_tab = inv_gamma_tab_16k; + move16(); + } + + Amax = L_mult( 16384, a[0] ); + FOR (i = 1; i < 9; i++) + { + Amax = L_max( Amax, L_abs( L_mult( a[i], inv_gamma_tab[i-1] ) ) ); + } + FOR (i = 9; i < 17; i++) + { + Amax = L_max( Amax, L_abs( L_shl( L_mult( a[i], inv_gamma_tab[i-1] ), 1 ) ) ); + } + shift = norm_l( Amax ); + ap[0] = shl( a[0], sub(shift,1) ); + move16(); + FOR (i = 1; i < 9; i++) + { + L_tmp = L_mult( a[i], inv_gamma_tab[i-1] ); + ap[i] = round_fx( L_shl( L_tmp, shift ) ); + move16(); + } + shift = add(shift,1); + FOR (i = 9; i < 17; i++) + { + L_tmp = L_mult( a[i], inv_gamma_tab[i-1] ); + ap[i] = round_fx( L_shl( L_tmp, shift ) ); + move16(); + } + + + return; +} + +/* + * basop_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 + * + * Function: + * Modified LP filter by adding 1st order pre-premphasis, Ap(z)=A(z).(1-gamma.z^(-1)) + * + * Returns: + * void + */ +void basop_E_LPC_a_add_tilt(const Word16 *a, Word16 *ap, Word16 gamma) +{ + 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 ) ); + move16(); + } + ap[M+1] = round_fx( L_shl( Atmp[M+1], shift ) ); + move16(); + + return; +} + + + +static Word16 xsf_to_xsp(Word16 xsf) +{ + /* xsp = cos(xsf * 3.1415/6400); */ + return getCosWord16R2(xsf); +} + +/* + * lsf2lsp + * + * Parameters: + * lsf I: lsf[m] normalized (range: 0 <= val <= 0.5) x2.56 + * lsp O: lsp[m] (range: -1 <= val < 1) Q15 + * + * Function: + * Transformation lsf to lsp + * + * LSF are line spectral pair in frequency domain (0 to 6400). + * LSP are line spectral pair in cosine domain (-1 to 1). + * + * Returns: + * void + */ +void basop_lsf2lsp(const Word16 lsf[], Word16 lsp[]) +{ + Word16 i; + + + + /* convert ISFs to the cosine domain */ + FOR (i = 0; i < M; i++) + { + *lsp++ = xsf_to_xsp(*lsf++); + move16(); + } + + + return; +} diff --git a/lib_com/__zaloha/basop_lsf_tools.c b/lib_com/__zaloha/basop_lsf_tools.c new file mode 100644 index 000000000..bbb190850 --- /dev/null +++ b/lib_com/__zaloha/basop_lsf_tools.c @@ -0,0 +1,265 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + + +#include "wmc_auto.h" +#include +#include +#include +#include "basop_proto_func.h" +#include "control.h" +#include "basop_util.h" + +#define WMC_TOOL_SKIP + +#define NC_MAX 8 + +static Word16 E_LPC_f_lsp_pol_get(const Word16 lsp[], Word32 f[], const Word16 n, const Word16 past_Ovf, const Word16 isMODE1); + + +/* + * E_LPC_f_lsp_a_conversion + * + * Parameters: + * lsp I: Line spectral pairs Q15 + * a O: Predictor coefficients (order = m) Qx (The Q factor of the output to be deduced from a(0)) + * m I: order of LP filter + * + * Function: + * Convert ISPs to predictor coefficients a[] + * + * Returns: + * void + */ +void basop_E_LPC_f_lsp_a_conversion(const Word16 *lsp, Word16 *a, const Word16 m) +{ + Word16 i, j, k; + Word32 f1[NC_MAX+1], f2[NC_MAX+1]; + Word16 nc; + Word32 t0; + Word16 Ovf, Ovf2; + + + /*-----------------------------------------------------* + * Find the polynomials F1(z) and F2(z) * + *-----------------------------------------------------*/ + + nc = shr(m, 1); + + assert(m == 16 || m == 10); + + Ovf = 0; + move16(); + Ovf = E_LPC_f_lsp_pol_get(&lsp[0], f1, nc, Ovf, 1); + Ovf2 = E_LPC_f_lsp_pol_get(&lsp[1], f2, nc, Ovf, 1); + IF(sub(Ovf2,Ovf) !=0) + { + /* to ensure similar scaling for f1 and f2 in case + an overflow would be detected only in f2, + but this case never happen on my dtb */ + E_LPC_f_lsp_pol_get(&lsp[0], f1, nc, s_max(Ovf2,Ovf), 1); + } + /*-----------------------------------------------------* + * Multiply F1(z) by (1+z^-1) and F2(z) by (1-z^-1) * + *-----------------------------------------------------*/ + /*modification*/ + k = sub(nc,1); + FOR (i = 0; i <= k; i++) + { + f1[nc-i] = L_add(f1[nc-i],f1[nc-i-1]); + move32(); + f2[nc-i] = L_sub(f2[nc-i],f2[nc-i-1]); + move32(); + } + + /*-----------------------------------------------------* + * A(z) = (F1(z)+F2(z))/2 * + * F1(z) is symmetric and F2(z) is antisymmetric * + *-----------------------------------------------------*/ + + t0 = L_deposit_l(0); + FOR (i = 1; i <= nc; i++) + { + t0 = L_max( t0, L_abs(L_add(f1[i], f2[i])) ); + t0 = L_max( t0, L_abs(L_sub(f1[i], f2[i])) ); + } + k = s_min( norm_l(t0), 6 ); + a[0] = shl( 256, k ); + move16(); + test(); + IF( Ovf || Ovf2) + { + a[0] = shl( 256, sub(k,Ovf) ); + move16(); + } + j = m; + FOR (i = 1; i <= nc; i++) + { + /* a[i] = 0.5*(f1[i] + f2[i]) */ + t0 = L_add(f1[i],f2[i]); + t0 = L_shl(t0, k); + a[i] = round_fx(t0); /* from Q23 to Qx and * 0.5 */ + + /* a[j] = 0.5*(f1[i] - f2[i]) */ + t0 = L_sub(f1[i],f2[i]); + t0 = L_shl(t0, k); + a[j] = round_fx(t0); /* from Q23 to Qx and * 0.5 */ + j--; + } + + return; +} + + +/*--------------------------------------------------------------------------- +* procedure reorder_lsf() +* +* To make sure that the lsfs are properly ordered and to keep a certain +* minimum distance between consecutive lsfs. +*--------------------------------------------------------------------------*/ +void basop_reorder_lsf( + 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 i, lsf_min, n_m_1; + Word16 lsf_max; + + lsf_min = min_dist; + move16(); + + /*-----------------------------------------------------------------------* + * Verify the LSF ordering and minimum GAP + *-----------------------------------------------------------------------*/ + + FOR (i = 0; i < n; i++) + { + if (sub(lsf[i], lsf_min) < 0) + { + lsf[i] = lsf_min; + move16(); + } + lsf_min = add(lsf[i], min_dist); + } + + /*-----------------------------------------------------------------------* + * Reverify the LSF ordering and minimum GAP in the reverse order (security) + *-----------------------------------------------------------------------*/ + lsf_max = round_fx(L_sub(L_shr(L_mult0(extract_l(L_shr(fs,1)), 1311),9-16), L_deposit_h(min_dist))); /* Q0 + Q9 , 1311 is 2.56 in Q9 */ + n_m_1 = sub(n,1); + IF (sub(lsf[n_m_1], lsf_max) > 0) /* If danger of unstable filter in case of resonance in HF */ + { + FOR (i = n_m_1; i >= 0; i--) /* Reverify the minimum LSF gap in the reverse direction */ + { + if (sub(lsf[i], lsf_max) > 0) + { + lsf[i] = lsf_max; + move16(); + } + lsf_max = sub(lsf[i], min_dist); + } + } +} + + +/* + * 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 * + *-----------------------------------------------------------* + */ +static +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(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(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; +} diff --git a/lib_com/__zaloha/basop_mpy.c b/lib_com/__zaloha/basop_mpy.c new file mode 100644 index 000000000..bf5ae96d2 --- /dev/null +++ b/lib_com/__zaloha/basop_mpy.c @@ -0,0 +1,56 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + + +#include "wmc_auto.h" +#include "basop_mpy.h" +#include "options.h" + +#define WMC_TOOL_SKIP + +Word32 Mpy_32_16_1(Word32 x, Word16 y) +{ + Word32 mh; + UWord16 ml; + + Mpy_32_16_ss(x, y, &mh, &ml); + + return (mh); +} + +Word32 Mpy_32_16(Word32 x, Word16 y) +{ + Word32 mh; + UWord16 ml; + + Mpy_32_16_ss(x, y, &mh, &ml); + + return (mh); +} + +Word32 Mpy_32_16_r(Word32 x, Word16 y) +{ + Word32 mh; + UWord16 ml; + + Mpy_32_16_ss(x, y, &mh, &ml); + + if(s_and(ml, -32768 /* 0x8000 */)) + { + mh = L_add(mh, 1); + } + + return (mh); +} + + +Word32 Mpy_32_32(Word32 x, Word32 y) +{ + Word32 mh; + UWord32 ml; + + Mpy_32_32_ss(x, y, &mh, &ml); + + return (mh); +} diff --git a/lib_com/__zaloha/basop_mpy.h b/lib_com/__zaloha/basop_mpy.h new file mode 100644 index 000000000..be62d6aa4 --- /dev/null +++ b/lib_com/__zaloha/basop_mpy.h @@ -0,0 +1,67 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#ifndef __BASOP_MPY_H +#define __BASOP_MPY_H + +#include "stl.h" +#include "options.h" + +/** + * \brief 32*16 Bit fractional Multiplication using 40 bit OPS + * Performs a multiplication of a 32-bit variable x by + * a 16-bit variable y, returning a 32-bit value. + * + * \param[i] x + * \param[i] y + * + * \return x*y + */ +Word32 Mpy_32_16_1(Word32 x, + Word16 y); + + +/** + * \brief 32*16 Bit fractional Multiplication using 40 bit OPS + * Performs a multiplication of a 32-bit variable x by + * a 16-bit variable y, returning a 32-bit value. + * + * \param[i] x + * \param[i] y + * + * \return x*y + */ +Word32 Mpy_32_16(Word32 x, + Word16 y); + + +/** + * \brief 32*16 Bit fractional Multiplication using 40 bit OPS + * Performs a multiplication of a 32-bit variable x by + * a 16-bit variable y including rounding, returning a 32-bit value. + * + * \param[i] x + * \param[i] y + * + * \return x*y + */ +Word32 Mpy_32_16_r(Word32 x, Word16 y); + + +/** + * \brief 32*32 Bit fractional Multiplication using 40 bit OPS + * + * Performs a multiplication of a 32-bit variable x by + * a 32-bit variable y, returning a 32-bit value. + * + * \param[i] x + * \param[i] y + * + * \return x*y + */ + +Word32 Mpy_32_32(Word32 x, + Word32 y); + +#endif /* __BASOP_SETTINGS_H */ diff --git a/lib_com/__zaloha/basop_proto_func.h b/lib_com/__zaloha/basop_proto_func.h new file mode 100644 index 000000000..804b8d750 --- /dev/null +++ b/lib_com/__zaloha/basop_proto_func.h @@ -0,0 +1,39 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#ifndef BASOP_PROTO_FUNC_H +#define BASOP_PROTO_FUNC_H + +#include "stl.h" +#include "basop_util.h" + + +/* tcx_lpc_cdk.h */ +#define LSF_GAP_VAL(x) (Word16)((x)*2.0f*1.28f) +#define LSFM(x) FL2WORD16_SCALE(x*1.28, 15-1) /* 14Q1*1.28 */ + +/* cnst.h */ +#define GAMMA1_INV 17809 /* weighting factor (numerator) default:0.92 (1Q14format) */ +#define GAMMA16k_INV 17430 /* weighting factor (numerator) default:0.94 (1Q14format) */ +#define FS_2 16384 /* isf max value (Use in reorder_fx.c) */ +#define INT_FS_FX 12800 /* internal sampling frequency */ + +void basop_lsp2a_stab(const Word16 *lsp, Word16 *a); +void basop_lsf2lsp(const Word16 lsf[], Word16 lsp[]); +void basop_weight_a(const Word16 *a, Word16 *ap, const Word16 gamma); +void basop_weight_a_inv(const Word16 *a, Word16 *ap, const Word16 inv_gamma); +void basop_E_LPC_a_add_tilt(const Word16 *a, Word16 *ap, Word16 gamma); +void basop_reorder_lsf(Word16 *lsf, const Word16 min_dist, const Word16 n, const Word32 fs); +void basop_E_LPC_f_lsp_a_conversion(const Word16 *lsp, Word16 *a, const Word16 m); + +/* tcx_utils.c */ +void basop_lpc2mdct(Word16 *lpcCoeffs, Word16 lpcOrder, + Word16 *mdct_gains, Word16 *mdct_gains_exp, + Word16 *mdct_inv_gains, Word16 *mdct_inv_gains_exp); + +void basop_PsychAdaptLowFreqDeemph(Word32 x[], const Word16 lpcGains[], const Word16 lpcGains_e[], Word16 lf_deemph_factors[]); +void basop_mdct_noiseShaping_interp(Word32 x[], Word16 lg, Word16 gains[], Word16 gains_exp[]); + + +#endif diff --git a/lib_com/__zaloha/basop_settings.h b/lib_com/__zaloha/basop_settings.h new file mode 100644 index 000000000..62f706e10 --- /dev/null +++ b/lib_com/__zaloha/basop_settings.h @@ -0,0 +1,85 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#ifndef __BASOP_SETTINGS_H +#define __BASOP_SETTINGS_H + +#include "stl.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 float < 1 to Word32 fixed point with saturation and rounding +*/ +#define FL2WORD32(val) \ +(Word32)( ( (val) >= 0) ? \ +((( (double)(val) * (WORD32_FIX_SCALE) + 0.5 ) >= (double)(MAXVAL_WORD32) ) ? (_LONG)(MAXVAL_WORD32) : (_LONG)( (double)(val) * (double)(WORD32_FIX_SCALE) + 0.5)) : \ +((( (double)(val) * (WORD32_FIX_SCALE) - 0.5) <= (double)(MINVAL_WORD32) ) ? (_LONG)(MINVAL_WORD32) : (_LONG)( (double)(val) * (double)(WORD32_FIX_SCALE) - 0.5)) ) + +/*! + \def Macro converts a float < 1 to Word16 fixed point with saturation and rounding +*/ +#define FL2WORD16(val) \ +(Word16)( ( (val) >= 0) ? \ +((( (double)(val) * (WORD16_FIX_SCALE) + 0.5 ) >= (double)(MAXVAL_WORD16) ) ? (_LONG)(MAXVAL_WORD16) : (_LONG)( (double)(val) * (double)(WORD16_FIX_SCALE) + 0.5)) : \ +((( (double)(val) * (WORD16_FIX_SCALE) - 0.5) <= (double)(MINVAL_WORD16) ) ? (_LONG)(MINVAL_WORD16) : (_LONG)( (double)(val) * (double)(WORD16_FIX_SCALE) - 0.5)) ) + +/*! + \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) ) + +/*! + \def Macro converts a Word32 fixed point < 1 to float shifts result left by scale +*/ +#define WORD322FL_SCALE(x,scale) ( ((float)((_LONG)(x))) / (((_INT64)1<<(WORD32_BITS-1 - (scale)))) ) + +/*! + \def Macro converts a float < 1 to Word32 fixed point with saturation and rounding, shifts result right by scale +*/ +/* Note: Both x and scale must be constants at compile time, scale must be in range -31..31 */ +#define FL2WORD32_SCALE(x,scale) FL2WORD32((double)(x) *(((_INT64)1<<(WORD32_BITS-1 - (scale)))) / ((_INT64)1<<(WORD32_BITS-1))) + +/*! + \def Macro converts a Word16 fixed point < 1 to float shifts result left by scale +*/ +#define WORD162FL_SCALE(x,scale) ( ((float)((_LONG)(x))) / (((_INT64)1<<(WORD16_BITS-1 - (scale)))) ) + +/*! + \def Macro converts a float < 1 to Word16 fixed point with saturation and rounding, shifts result right by scale +*/ +/* Note: At compile time, x must be a float constant and scale must be an integer constant in range -15..15 */ +#define FL2WORD16_SCALE(x,scale) FL2WORD16((float)(x) *(((_INT64)1<<(WORD16_BITS-1 - (scale)))) / ((_INT64)1<<(WORD16_BITS-1))) + + +/* Word16 Packed Type */ +typedef struct +{ + struct + { + Word16 re; + Word16 im; + } v; +} PWord16; + +#endif /* __BASOP_SETTINGS_H */ diff --git a/lib_com/__zaloha/basop_tcx_utils.c b/lib_com/__zaloha/basop_tcx_utils.c new file mode 100644 index 000000000..92bb558cb --- /dev/null +++ b/lib_com/__zaloha/basop_tcx_utils.c @@ -0,0 +1,406 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "options.h" +#include "cnst.h" +#include "basop_proto_func.h" +#include "stl.h" +#include "prot.h" +#include "rom_com.h" +#include "wmc_auto.h" + +#define WMC_TOOL_SKIP + +/* compare two positive normalized 16 bit mantissa/exponent values */ +/* return value: positive if first value greater, negative if second value greater, zero if equal */ +static 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; +} + +void basop_lpc2mdct(Word16 *lpcCoeffs, Word16 lpcOrder, + Word16 *mdct_gains, Word16 *mdct_gains_exp, + Word16 *mdct_inv_gains, Word16 *mdct_inv_gains_exp) +{ + Word32 RealData[FDNS_NPTS]; + Word32 ImagData[FDNS_NPTS]; + Word16 i, j, k, step, scale, s, tmp16; + Word16 g, g_e, ig, ig_e; + Word32 tmp32; + const PWord16 *ptwiddle; + + + + /* short-cut, to avoid calling of BASOP_getTables() */ + ptwiddle = SineTable512_fx; + step = 8; + + /*ODFT*/ + assert(lpcOrder < FDNS_NPTS); + + /* pre-twiddle */ + FOR (i=0; i<=lpcOrder; i++) + { + RealData[i] = L_mult(lpcCoeffs[i], ptwiddle->v.re); + move32(); + ImagData[i] = 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, FL2WORD16(0.375f)), g, FL2WORD16(0.625f)); + x[i] = L_shl(Mpy_32_16(x[i], tmp), e); + move32(); + + tmp = mac_r(L_mult(pg, FL2WORD16(0.125f)), g, FL2WORD16(0.875f)); + x[i+1] = L_shl(Mpy_32_16(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, FL2WORD16(0.875f)), ng, FL2WORD16(0.125f)); + x[i+2] = L_shl(Mpy_32_16(x[i+2], tmp), e); + move32(); + + tmp = mac_r(L_mult(g, FL2WORD16(0.625f)), ng, FL2WORD16(0.375f)); + x[i+3] = L_shl(Mpy_32_16(x[i+3], tmp), e); + move32(); + + jp = j; + move16(); + j = jn; + move16(); + jn = s_min(add(jn, 1), FDNS_NPTS-1); + } + } + ELSE IF (sub(k, 5) == 0) + { + 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, FL2WORD16(0.40f)), g, FL2WORD16(0.60f)); + x[i] = L_shl(Mpy_32_16(x[i], tmp), e); + move32(); + + tmp = mac_r(L_mult(pg, FL2WORD16(0.20f)), g, FL2WORD16(0.80f)); + x[i+1] = L_shl(Mpy_32_16(x[i+1], tmp), e); + move32(); + + + x[i+2] = L_shl(Mpy_32_16(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, FL2WORD16(0.80f)), ng, FL2WORD16(0.20f)); + x[i+3] = L_shl(Mpy_32_16(x[i+3], tmp), e); + move32(); + + tmp = mac_r(L_mult(g, FL2WORD16(0.60f)), ng, FL2WORD16(0.40f)); + x[i+4] = L_shl(Mpy_32_16(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(*x, *gains), *gains_exp); + move32(); + x++; + } + + gains++; + gains_exp++; + } + } + } + +} + + +void basop_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(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); + } + } + +} diff --git a/lib_com/__zaloha/basop_util.c b/lib_com/__zaloha/basop_util.c new file mode 100644 index 000000000..71edca7bd --- /dev/null +++ b/lib_com/__zaloha/basop_util.c @@ -0,0 +1,1044 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "wmc_auto.h" +#include +#include +#include "options.h" +#include "basop_util.h" +#include "rom_com.h" +#include "basop_settings.h" +#include "basop_mpy.h" +#include "control.h" +#include "cnst.h" + +#define WMC_TOOL_SKIP + + +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 < FL2WORD32(-31.0/64.0) ) + { + return 0; + } + test(); + if ( (L_sub(x,FL2WORD32(31.0/64.0)) >= 0) || (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(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); +} + + +/* local function for Sqrt16 */ +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; +} + + +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 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 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 = L_add(0, 0); + x_min = L_add(0, 0); + 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 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 set_val_Word16(Word16 X[], const Word16 val, Word16 n) +{ + Word16 i; + + + FOR (i = 0; i < n; i++) + { + X[i] = val; + move16(); + } + + + return; +} + +void set_val_Word32(Word32 X[], const Word32 val, Word16 n) +{ + Word16 i; + + + FOR (i = 0; i < n; i++) + { + X[i] = val; + move32(); + } + + + return; +} + +Word16 mult0 ( Word16 x, Word16 y) +{ + return extract_l(L_mult0(x,y)); +} + + +#define SINETAB SineTable512_fx +#define LD 9 + +/* + * Calculates coarse lookup values for sine/cosine and residual angle. + * \param x angle in radians with exponent = 2 or as radix 2 with exponent = 0. + * \param scale shall always be 2 + * \param sine pointer to where the sine lookup value is stored into + * \param cosine pointer to where the cosine lookup value is stored into + * \param flag_radix2 flag indicating radix 2 angle if non-zero. + */ +static Word16 fixp_sin_cos_residual_16(Word16 x, const Word16 scale, Word16 *sine, Word16 *cosine, Word8 flag_radix2) +{ + Word16 residual; + Word16 s; + Word16 ssign; + Word16 csign; + Word16 tmp, cl = 0, sl = 0; + const Word16 shift = 15-LD-1-scale; + + if (flag_radix2 == 0) + { + x = mult_r(x, FL2WORD16(1.0/EVS_PI)); + } + s = shr(x, shift); + + residual = s_and(x, (1< x */ + s = add(sub(norm_s(y), norm_s(x)), 1); + s = s_max(s, 0); + + BASOP_SATURATE_WARNING_OFF + y = shl(y, s); + BASOP_SATURATE_WARNING_ON + + /* divide and shift */ + y = shr(div_s(x, y), sub(15, s)); + + + return y; +} + +Word32 BASOP_util_Pow2( + const Word32 exp_m, const Word16 exp_e, + Word16 *result_e +) +{ + static const Word16 pow2Coeff[8] = + { + FL2WORD16(0.693147180559945309417232121458177), /* ln(2)^1 /1! */ + FL2WORD16(0.240226506959100712333551263163332), /* ln(2)^2 /2! */ + FL2WORD16(0.0555041086648215799531422637686218), /* ln(2)^3 /3! */ + FL2WORD16(0.00961812910762847716197907157365887), /* ln(2)^4 /4! */ + FL2WORD16(0.00133335581464284434234122219879962), /* ln(2)^5 /5! */ + FL2WORD16(1.54035303933816099544370973327423e-4), /* ln(2)^6 /6! */ + FL2WORD16(1.52527338040598402800254390120096e-5), /* ln(2)^7 /7! */ + FL2WORD16(1.32154867901443094884037582282884e-6) /* ln(2)^8 /8! */ + }; + + Word32 frac_part = 0, tmp_frac, result_m; + Word16 int_part = 0; + + 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,FL2WORD32(0.5))) >= 0) + { + int_part = add(int_part, 1); + frac_part = L_sub(tmp_frac,FL2WORD32(0.5)); + } + ELSE IF( (tmp_frac = L_add(frac_part,FL2WORD32(0.5))) < 0) + { + int_part = sub(int_part, 1); + frac_part = L_add(tmp_frac,FL2WORD32(0.5)); + } + + /* 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(FL2WORD32(1.0/2.0),L_shr(Mpy_32_16(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(p, pow2Coeff[i]), 1)); + p = Mpy_32_32(p, frac_part); + } + result_m = L_add(result_m, L_shr(Mpy_32_16(p, pow2Coeff[i]), 1)); + } + *result_e = int_part; + move16(); + + return result_m; +} + +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 ) + { + *s = 0; + move16(); + + 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; +} + + +static 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] */ +static 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 +}; + +Word32 Pow2( /* (o) Q0 : result (range: 0<=val<=0x7fffffff) */ + Word16 exponant, /* (i) Q0 : Integer part. (range: 0<=val<=30) */ + Word16 fraction /* (i) Q15 : Fractional 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: Log2_norm() + * + * 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 + * + *************************************************************************/ + +static const Word32 L_table[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 +}; + +static const Word16 table_diff[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 +}; + +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; + + + 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[i], table_diff[i], a);/* table[i] << 16 - diff*a*2 */ + + + return y; +} + + +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; +} + +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 = add(b_e,0); + + if (!b_m) + b_e = add(a_e,0); + + 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 = add(0,0); + if (L_tmp != 0) + a_e = sub(a_e,shift); + *ptr_e = a_e; + + return (L_tmp); +} + +static 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] */ +static 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 +}; +static const Word16 shift[] = {9,10}; +Word32 Isqrt_lc1( + 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[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; +} + + +static 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 +}; + +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); + +} diff --git a/lib_com/__zaloha/basop_util.h b/lib_com/__zaloha/basop_util.h new file mode 100644 index 000000000..7d0797bbe --- /dev/null +++ b/lib_com/__zaloha/basop_util.h @@ -0,0 +1,386 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#ifndef __BASOP_UTIL_H__ +#define __BASOP_UTIL_H__ + +#include "basop_settings.h" +#include "typedef.h" +#include "basop32.h" +#include "basop_mpy.h" + + +#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)) + +#ifndef CHEAP_NORM_SIZE +#define CHEAP_NORM_SIZE 161 +#endif + +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 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 */ +); + +/*****************************************************************************/ +/*! + \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 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 Binary logarithm with 7 iterations + + \param x + + \return log2(x)/64 + */ +/************************************************************************/ +Word32 BASOP_Util_Log2(Word32 x); + + + +/****************************************************************************/ +/*! + \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 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 Binary logarithm with 5 iterations + * + * \param[i] val + * + * \return basop_log2(val)/128 + */ +/************************************************************************/ +Word32 BASOP_Util_log2_i5(Word32 val); + +/************************************************************************/ +/*! + \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); + + +/****************************************************************************/ +/*! + \brief Sets Array Word16 arg1 to value Word16 arg2 for Word16 arg3 elements +*/ +void set_val_Word16( Word16 X[], /*!< Address of array */ + const Word16 val, /*!< Value to copy into array */ + Word16 n); /*!< Number of elements to process */ + + +/****************************************************************************/ +/*! + \brief Sets Array Word32 arg1 to value Word32 arg2 for Word16 arg3 elements +*/ +void set_val_Word32( Word32 X[], /*!< Address of array */ + const Word32 val, /*!< Value to copy into array */ + Word16 n); /*!< Number of elements to process */ + +/****************************************************************************/ +/*! + \brief Does a multiplication of Word16 input values + + \return z16 = x16 * y16 +*/ +Word16 mult0 ( Word16 x, /*!< i : Multiplier */ + Word16 y); /*!< i : Multiplicand */ + +/** + * \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 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 return 2 ^ (exp * 2^exp_e) + * \param exp_m mantissa of the exponent to 2.0f + * \param exp_e exponent of the exponent to 2.0f + * \param result_e pointer to a INT where the exponent of the result will be stored into + * \return mantissa of the result + */ +Word32 BASOP_util_Pow2( + const Word32 exp_m, const Word16 exp_e, + Word16 *result_e +); + + +Word32 Isqrt_lc1( + Word32 frac, /* (i) Q31: normalized value (1.0 < frac <= 0.5) */ + Word16 * exp /* (i/o) : exponent (value = frac x 2^exponent) */ +); + +/*****************************************************************************/ +/*! + + \brief Calculates pow(2,x) + ___________________________________________________________________________ + | | + | Function Name : Pow2() | + | | + | L_x = pow(2.0, exponant.fraction) (exponent = interger part) | + | = pow(2.0, 0.fraction) << exponent | + |---------------------------------------------------------------------------| + | 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) */ +); + +/************************************************************************* + * + * FUNCTION: Log2_norm() + * + * 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) */ +); + +/************************************************************************* + * + * FUNCTION: BASOP_Util_fPow() + */ +/** + * \brief BASOP_Util_fPow + * + * PURPOSE: Computes pow(base_m, base_e, exp_m, exp_e), where base_m and base_e + * specify the base, and exp_m and exp_e specify the exponent. + * The result is returned in a mantissa and exponent representation. + * + * DESCRIPTION: + * The function BASOP_Util_fPow(L_x) calculates the power function by + * calculating 2 ^ (log2(base)*exp) + * + * \param base_m mantissa of base + * \param base_e exponent of base + * \param exp_m mantissa of exponent + * \param exp_e exponent of exponent + * \param result_e pointer to exponent of result + * \return Word32 mantissa of result + * + *************************************************************************/ + +Word32 BASOP_Util_fPow( /* (o) : mantissa of result */ + Word32 base_m, Word16 base_e, /* (i) : input value for base (mantissa and exponent) */ + Word32 exp_m, Word16 exp_e, /* (i) : input value for exponent (mantissa and exponent) */ + Word16 *result_e /* (o) : output pointer to exponent of result */ +); + +/*!********************************************************************** + \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 Accumulates multiplications + + Accumulates the elementwise multiplications of Word32 Array X with Word16 Array Y + pointed to by arg1 and arg2 with specified headroom. Length of to be multiplied arrays is arg3, + headroom with has to be taken into account is specified in arg4 + + \return Word32 result of accumulated multiplications over Word32 array arg1 and Word16 array arg2 and Word16 pointer + to exponent correction factor which needs to be added to the exponent of the result vector +*/ +Word32 dotWord32_16_guards(const Word32 * X, const Word16 * Y, Word16 n, Word16 hr, Word16 * shift); + + + +Word32 Sqrt_l(Word32 L_x, Word16 *exp); + +#endif /* __BASOP_UTIL_H__ */ diff --git a/lib_com/__zaloha/bastypes.h b/lib_com/__zaloha/bastypes.h new file mode 100644 index 000000000..e88b8484b --- /dev/null +++ b/lib_com/__zaloha/bastypes.h @@ -0,0 +1,46 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#ifndef __BASTYPES_H +#define __BASTYPES_H + +typedef unsigned char BYTE; +typedef unsigned short WORD; +#if defined(__alpha__) || defined(__alpha) || defined(__sgi) +typedef unsigned int DWORD; /* long is 64 bits on these machines */ +#else +typedef unsigned long DWORD; +#endif + +typedef int BOOL; +typedef signed int INT; +typedef signed long LONG; +typedef unsigned long ULONG; +typedef unsigned int UINT; +typedef float FLOAT; +typedef double DOUBLE; +typedef unsigned char UCHAR; +typedef char CHAR; + +/* from uld_types.h: */ +typedef short SHORT; +typedef unsigned short USHORT; +typedef long int LINT; +typedef unsigned long int ULINT; + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#define INVALID_HANDLE NULL + +#endif diff --git a/lib_com/__zaloha/enh1632.c b/lib_com/__zaloha/enh1632.c new file mode 100644 index 000000000..8e031d5f2 --- /dev/null +++ b/lib_com/__zaloha/enh1632.c @@ -0,0 +1,637 @@ + +/* + =========================================================================== + 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" +#include "wmc_auto.h" + +/***************************************************************************** + * + * 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); + } + else + { + if( var2 == 0 || var1 == 0) + { + var_out = var1; + } + else if( var2 >= 16) + { + var_out = 0; + } + else + { + var_out = var1 << var2; + } + } + + BASOP_CHECK(); + + + 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); + } + 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); + } + } + + BASOP_CHECK(); + + + 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); + } + 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; + } + } + + BASOP_CHECK(); + + + 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); + } + 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); + } + } + + BASOP_CHECK(); + + + 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); + } + else + { + var2 = -var2; + var_out = shr_r( var1, var2); + } + + + 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); + } + else + { + var2 = -var2; + var_out = L_shr_r( L_var1, var2); + } + + + 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)); + + + 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)); + + + 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)); + + + 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))); + + + return( L_var_out); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/* end of file */ diff --git a/lib_com/__zaloha/enh1632.h b/lib_com/__zaloha/enh1632.h new file mode 100644 index 000000000..33a772702 --- /dev/null +++ b/lib_com/__zaloha/enh1632.h @@ -0,0 +1,518 @@ +/* + =========================================================================== + 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" + + +/***************************************************************************** + * + * 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; + + + 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; + + + 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; + + + 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; + + + 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; + + + 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; + + + 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; + + + 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; + + + 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; + + + 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; + + + return( L_var_out); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#endif /*_ENH1632_H*/ + +/* end of file */ diff --git a/lib_com/__zaloha/enh40.c b/lib_com/__zaloha/enh40.c new file mode 100644 index 000000000..bc5c9970a --- /dev/null +++ b/lib_com/__zaloha/enh40.c @@ -0,0 +1,1071 @@ + +/* + =========================================================================== + 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" +#include "wmc_auto.h" + +#ifdef _MSC_VER +#pragma warning( disable : 4310 ) +#endif + +/***************************************************************************** + * + * 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; + +#if defined(_MSC_VER) && (_MSC_VER <= 1200) + L40_constant = L40_set( 0xc000000000); +#else + L40_constant = L40_set( 0xc000000000LL); +#endif + + if( var2 < 0) + { + var2 = -var2; + L40_var_out = L40_shr( L40_var1, var2); + } + + else + { + L40_var_out = L40_var1; + + for ( ; var2 > 0; var2--) + { +#if defined(_MSC_VER) && (_MSC_VER <= 1200) + if( L40_var_out > 0x003fffffffff) +#else + if( L40_var_out > 0x003fffffffffLL) +#endif + { + Overflow = 1; + exit(1); + /* L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out); */ + } + + else if ( L40_var_out < L40_constant) + { + Overflow = 1; + exit(2); + /* L40_var_out = L40_UNDERFLOW_OCCURED( L40_var_out); */ + } + + else + { + L40_var_out = L40_var_out << 1; + } + } + } + + BASOP_CHECK(); + + + 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); + } + else + { + L40_var_out = L40_var1 >> var2; + + } + + + 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); + + 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 defined(_MSC_VER) && (_MSC_VER <= 1200) + if( ((( L40_var1 & 0x8000000000) >> 39) != 0) + && ((( L40_var2 & 0x8000000000) >> 39) != 0) + && ((( L40_var_out & 0x8000000000) >> 39) == 0)) + { + Overflow = 1; + exit(2); + /* 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)) + { + Overflow = 1; + exit(1); + /* L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out); */ + } +#else + if( ((( L40_var1 & 0x8000000000LL) >> 39) != 0) + && ((( L40_var2 & 0x8000000000LL) >> 39) != 0) + && ((( L40_var_out & 0x8000000000LL) >> 39) == 0)) + { + Overflow = 1; + exit(2); + /* L40_var_out = L40_UNDERFLOW_OCCURED( L40_var_out); */ + + } + else if( (((L40_var1 & 0x8000000000LL) >> 39) == 0) + && (((L40_var2 & 0x8000000000LL) >> 39) == 0) + && (((L40_var_out & 0x8000000000LL) >> 39) != 0)) + { + Overflow = 1; + exit(1); + /* L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out); */ + } +#endif + + BASOP_CHECK(); + + + 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 defined(_MSC_VER) && (_MSC_VER <= 1200) + if( (((L40_var1 & 0x8000000000) >> 39) != 0) + && (((L40_var2 & 0x8000000000) >> 39) == 0) + && (((L40_var_out & 0x8000000000) >> 39) == 0)) + { + Overflow = 1; + exit(2); + /* 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)) + { + Overflow = 1; + exit(1); + /* L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out); */ + } +#else + if( (((L40_var1 & 0x8000000000LL) >> 39) != 0) + && (((L40_var2 & 0x8000000000LL) >> 39) == 0) + && (((L40_var_out & 0x8000000000LL) >> 39) == 0)) + { + Overflow = 1; + exit(2); + /* L40_var_out = L40_UNDERFLOW_OCCURED( L40_var_out); */ + + } + else if( (((L40_var1 & 0x8000000000LL) >> 39) == 0) + && (((L40_var2 & 0x8000000000LL) >> 39) != 0) + && (((L40_var_out & 0x8000000000LL) >> 39) != 0)) + { + Overflow = 1; + exit(1); + /* L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out); */ + } +#endif + + BASOP_CHECK(); + + + 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); + } + else + { + L40_var_out = L40_var1; + } + + + 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; + + + 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; + + + 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); + + BASOP_CHECK(); + + + 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); + } + + + 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); + } + + + 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); + } + else + { + if( var2 >= 40) + L40_var_out = 0x0000000000; + else + { + L40_var_out = L40_var1 << var2; + } + L40_var_out = L40_set( L40_var_out); + } + + BASOP_CHECK(); + + + 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); + } + else + { + if( var2 >= 40) + L40_var_out = 0x0000000000; + else + { +#if defined(_MSC_VER) && (_MSC_VER <= 1200) + L40_var_out = (L40_var1 & 0xffffffffff) >> var2; +#else + L40_var_out = (L40_var1 & 0xffffffffffLL) >> var2; +#endif + } + } + + BASOP_CHECK(); + + + 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++; + } + + while( (L40_var1 < ( Word32)0x80000000L) + || (L40_var1 > ( Word32)0x7fffffffL)) + { + + L40_var1 = L40_shl( L40_var1, -1); + var_out--; + } + } + + + 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( var2 > 0) + { + if( ( L40_var1 & (( Word40) 1 << (var2 - 1))) != 0) + { + /* below line can not generate overflows on 40-bit */ + L40_var_out++; + } + } + } + + BASOP_CHECK(); + + + 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); + } + else + { + var2 = -var2; + L40_var_out = L40_shr_r ( L40_var1, var2); + } + + + return( L40_var_out); +} + + +/* end of file */ diff --git a/lib_com/__zaloha/enh40.h b/lib_com/__zaloha/enh40.h new file mode 100644 index 000000000..bc13eda04 --- /dev/null +++ b/lib_com/__zaloha/enh40.h @@ -0,0 +1,383 @@ +/* + =========================================================================== + 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 _MSC_VER +#define MAX_40 (0x0000007fffffffff) +#define MIN_40 (0xffffff8000000000) +#endif /* ifdef _MSC_VER */ + + + +#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); + + + +/*#ifdef _MSC_VER*/ +static __inline Word40 L40_set( Word40 L40_var1) +{ + Word40 L40_var_out; + +#if defined(_MSC_VER) && (_MSC_VER <= 1200) + L40_var_out = L40_var1 & 0x000000ffffffffff; + + if( L40_var1 & 0x8000000000) + L40_var_out = L40_var_out | 0xffffff0000000000; +#else + L40_var_out = L40_var1 & 0x000000ffffffffffLL; + + if( L40_var1 & 0x8000000000LL) + L40_var_out = L40_var_out | 0xffffff0000000000LL; +#endif + + + return( L40_var_out); +} +/*#endif*/ /* ifdef _MSC_VER */ + + + +static __inline UWord16 Extract40_H( Word40 L40_var1) +{ + UWord16 var_out; + + var_out = ( UWord16)( L40_var1 >> 16); + + + return( var_out); +} + + +static __inline UWord16 Extract40_L( Word40 L40_var1) +{ + UWord16 var_out; + + var_out = ( UWord16)( L40_var1); + + + return( var_out); +} + + +static __inline UWord32 L_Extract40( Word40 L40_var1) +{ + UWord32 L_var_out; + + L_var_out = ( UWord32) L40_var1; + + + return(L_var_out); +} + + +static __inline Word40 L40_deposit_h( Word16 var1) +{ + Word40 L40_var_out; + + L40_var_out = (( Word40) var1) << 16; + +#if defined(_MSC_VER) && (_MSC_VER <= 1200) + if( var1 & 0x8000) + { + L40_var_out = L40_set( L40_var_out | 0xff00000000); +#else + if( var1 & 0x8000) + { + L40_var_out = L40_set( L40_var_out | 0xff00000000LL); +#endif + } + + + return( L40_var_out); +} + + +static __inline Word40 L40_deposit_l( Word16 var1) +{ + Word40 L40_var_out; + + L40_var_out = var1; + +#if defined(_MSC_VER) && (_MSC_VER <= 1200) + if( var1 & 0x8000) + { + L40_var_out = L40_set( L40_var_out | 0xffffff0000); +#else + if( var1 & 0x8000) + { + L40_var_out = L40_set( L40_var_out | 0xffffff0000LL); +#endif + } + + + return( L40_var_out); +} + + +static __inline Word40 L40_deposit32( Word32 L_var1) +{ + Word40 L40_var_out; + + L40_var_out = ( Word40) L_var1; + +#if defined(_MSC_VER) && (_MSC_VER <= 1200) + if( L_var1 & 0x80000000) + { + L40_var_out = L40_set( L40_var_out | 0xff00000000); +#else + if( L_var1 & 0x80000000) + { + L40_var_out = L40_set( L40_var_out | 0xff00000000LL); +#endif + } + + + return( L40_var_out); +} + + + + + + + + +static __inline Word40 L40_round( Word40 L40_var1) +{ + Word40 L40_var_out; + Word40 L40_constant; + +#if defined(_MSC_VER) && (_MSC_VER <= 1200) + L40_constant = L40_set( 0xffffff0000); +#else + L40_constant = L40_set( 0xffffff0000LL); +#endif + + L40_var_out = L40_add( 0x8000, L40_var1); + L40_var_out = L40_var_out & L40_constant; + + + return( L40_var_out); +} + + +static __inline Word16 round40( Word40 L40_var1) +{ + Word16 var_out; + + var_out = extract_h( L_saturate40( L40_round( L40_var1))); + + + return( var_out); +} + + +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; + + + return( L40_var_out); +} + + + + + + + + + + + + +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); + + + return( L40_var_out); +} + + + + + + +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); + + + return( var_out); +} + + + + + + +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); + + + return( L40_var_out); +} + + + + + + +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); + + + return( var_out); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#endif /*_ENH40_H*/ + + +/* end of file */ + + diff --git a/lib_com/__zaloha/move.h b/lib_com/__zaloha/move.h new file mode 100644 index 000000000..d9d2040f1 --- /dev/null +++ b/lib_com/__zaloha/move.h @@ -0,0 +1,42 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#ifndef _MOVE_H +#define _MOVE_H + +/* BASOP -> FLC brigde: data move counting */ + +#include "stl.h" + +static __inline void move16( void) +{ +} + +static __inline void move32( void) +{ +} + +static __inline void test( void) +{ +} + +static __inline void logic16( void) +{ +} + +static __inline void logic32( void) +{ +} + + +/*-------- legacy ----------*/ +#define data_move() move16() +#define L_data_move() move32() +#define data_move_external() move16() +#define compare_zero() test() +/*-------- end legacy ----------*/ + +#define cast16 move16 + +#endif /* _MOVE_H */ diff --git a/lib_com/__zaloha/stl.h b/lib_com/__zaloha/stl.h new file mode 100644 index 000000000..4b66f442e --- /dev/null +++ b/lib_com/__zaloha/stl.h @@ -0,0 +1,38 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ +/* + =========================================================================== + 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 "typedef.h" +#include "basop32.h" +#include "move.h" +#include "control.h" +#include "enh1632.h" +#include "enh40.h" + +#endif /* ifndef _STL_H */ + + +/* end of file */ diff --git a/lib_com/ari.c b/lib_com/ari.c new file mode 100644 index 000000000..af9ea44d4 --- /dev/null +++ b/lib_com/ari.c @@ -0,0 +1,41 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "cnst.h" +#include "prot.h" +#include "stat_com.h" +#include "assert.h" +#include "basop_util.h" + +#ifndef int32 +#define int32 int +#endif + +#define WMC_TOOL_SKIP + + +/*--------------------------------------------------------------- + Ari 14 bits common routines + -------------------------------------------------------------*/ + +/** + * \brief Integer Multiply + * + * \param[i] r + * \param[i] c + * + * \return r*c + */ +long mul_sbc_14bits(long r,long c) +{ + long temp; + /*function in line*/ + temp = (((int32) r)*((int32) c))>>stat_bitsnew; + return temp; + + /*function in line*/ +} diff --git a/lib_com/ari_hm.c b/lib_com/ari_hm.c new file mode 100644 index 000000000..961a0f923 --- /dev/null +++ b/lib_com/ari_hm.c @@ -0,0 +1,277 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include +#include "cnst.h" +#include "stl.h" +#include "basop_util.h" +#include "prot.h" +#include "rom_com.h" +#include "options.h" +#include "wmc_auto.h" + + +/*-------------------------------------------------------------------* + * UnmapIndex() + * + * + *-------------------------------------------------------------------*/ + +void UnmapIndex( + int PeriodicityIndex, + int Bandwidth, + short LtpPitchLag, + int SmallerLags, + int *FractionalResolution, + int *Lag) +{ + if ((LtpPitchLag > 0) && (PeriodicityIndex & kLtpHmFlag)) + { + int LtpPitchIndex, Multiplier; + LtpPitchIndex = PeriodicityIndex >> 9; + Multiplier = PeriodicityIndex & 0xff; + assert(0 <= LtpPitchIndex && LtpPitchIndex <= 16); + assert(1 <= Multiplier && Multiplier <= (1 << NumRatioBits[Bandwidth][LtpPitchIndex])); + *FractionalResolution = kLtpHmFractionalResolution; + *Lag = (LtpPitchLag * (int)(4 * Ratios[Bandwidth][LtpPitchIndex][Multiplier-1])) >> 2; + } + else + { + if (PeriodicityIndex < 16) + { + *FractionalResolution = 3; + *Lag = PeriodicityIndex + GET_ADJ(0, 6); + } + else if (PeriodicityIndex < 80) + { + *FractionalResolution = 4; + *Lag = PeriodicityIndex + GET_ADJ(16, 8); + } + else if (PeriodicityIndex < 208) + { + *FractionalResolution = 3; + *Lag = PeriodicityIndex + GET_ADJ(80, 12); + } + else if (PeriodicityIndex < 224 || SmallerLags) + { + *FractionalResolution = 1; + *Lag = PeriodicityIndex + GET_ADJ(208, 28); + } + else + { + *FractionalResolution = 0; + *Lag = PeriodicityIndex + GET_ADJ(224, 188); + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * ConfigureContextHm() + * + * + *-------------------------------------------------------------------*/ + +void ConfigureContextHm( + int NumCoeffs, /* (I) Number of coefficients */ + int TargetBits, /* (I) Target bit budget (excl. Done flag) */ + int PeriodicityIndex, /* (I) Pitch related index */ + short LtpPitchLag, /* (I) TCX-LTP pitch in F.D. */ + CONTEXT_HM_CONFIG *hm_cfg /* (O) Context-based harmonic model configuration */ +) +{ + int Bandwidth, SmallerLags; + int i, Limit, Lag; + int j, Index, FractionalResolution; + int *tmp; + + Bandwidth = 0; + if (NumCoeffs >= 256) + { + Bandwidth = 1; + } + + SmallerLags = 0; + + if (TargetBits <= kSmallerLagsTargetBitsThreshold || Bandwidth == 0) + { + SmallerLags = 1; + } + + UnmapIndex(PeriodicityIndex, Bandwidth, LtpPitchLag, SmallerLags, &FractionalResolution, &Lag ); + + /* Set up and fill peakIndices */ + hm_cfg->peakIndices = hm_cfg->indexBuffer; + tmp = hm_cfg->peakIndices; + Limit = (NumCoeffs - 1) << FractionalResolution; + + for (i=Lag; i> FractionalResolution; + *tmp++ = Index - 1; + *tmp++ = Index; + *tmp++ = Index + 1; + } + hm_cfg->numPeakIndices = tmp - hm_cfg->indexBuffer; + + /* Set up and fill holeIndices */ + hm_cfg->holeIndices = hm_cfg->indexBuffer + hm_cfg->numPeakIndices; + tmp = hm_cfg->holeIndices; + Index = 0; + + for (j=0; jnumPeakIndices; j+=3) + { + for (; IndexpeakIndices[j]; ++Index) + { + *tmp++ = Index; + } + Index += 3; /* Skip the peak */ + } + + for (; IndexnumHoleIndices = tmp - hm_cfg->holeIndices; + /* Add extremal element signaling the end of the buffer */ + *tmp++ = NumCoeffs; + + return; +} + + +/*-------------------------------------------------------------------* + * CountIndexBits() + * + * + *-------------------------------------------------------------------*/ + +int CountIndexBits( + int Bandwidth, + int PeriodicityIndex) +{ + + if (PeriodicityIndex & kLtpHmFlag) + { + int LtpPitchIndex = PeriodicityIndex >> 9; + return NumRatioBits[Bandwidth][LtpPitchIndex]; + } + return 8; +} + +#define WMC_TOOL_SKIP + +#ifndef ANALYSIS_TOOL +/*-------------------------------------------------------------------* + * tcx_hm_render() + * + * + *-------------------------------------------------------------------*/ + +int tcx_hm_render( + int lag, /* i: pitch lag */ + int fract_res, /* i: fractional resolution of the lag */ + float LtpGain, /* i: LTP gain */ + Word16 p[] /* o: harmonic model (Q13) */ +) +{ + int k; + Word32 f0, tmp32; + Word16 height, PeakDeviation, tmp; + + /* Set up overall shape */ + (void)LtpGain; + + f0 = L_shl(lag, sub(15, fract_res)); /* Q15 */ + + tmp32 = Mpy_32_16(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(tmp32, 26214)); + height = round_fx(tmp32); /* Q13 */ + + tmp32 = Mpy_32_16(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( sub(13915,PeakDeviation) > 0 ) + { + /* A bit error was encountered */ + return 1; + } + ELSE + { + tmp = div_s(13915, PeakDeviation); + tmp = mult_r(tmp, tmp); /* Q15 */ + } + + /* Render the prototype peak */ + p[kTcxHmParabolaHalfWidth] = height; + + for (k=1; k<=kTcxHmParabolaHalfWidth; ++k) + { + p[kTcxHmParabolaHalfWidth+k] = round_fx(Mpy_32_16(BASOP_Util_InvLog2(L_shl(L_mult0(mult0(negate(k),k), tmp),10)), height)); + } + /* Mirror */ + for (k=-kTcxHmParabolaHalfWidth; k<0; ++k) + { + p[kTcxHmParabolaHalfWidth+k] = p[kTcxHmParabolaHalfWidth-k]; + } + + return 0; +} + + +/*-------------------------------------------------------------------* + * tcx_hm_modify_envelope() + * + * + *-------------------------------------------------------------------*/ + +void tcx_hm_modify_envelope( + Word16 gain, /* i: HM gain (Q11) */ + int lag, + int fract_res, + Word16 p[], /* i: harmonic model (Q13) */ + Word32 env[], /* i/o: envelope (Q16) */ + int L_frame /* i: number of spectral lines */ +) +{ + int k; + int h, x; + Word16 inv_shape[2*kTcxHmParabolaHalfWidth+1]; /* Q15 */ + + if (gain == 0) + { + return; + } + + for (k=0; k<2*kTcxHmParabolaHalfWidth+1; ++k) + { + inv_shape[k] = div_s(512, add(512, round_fx(L_mult(gain, p[k])))); + } + + h = 1; + k = lag >> fract_res; + + while (k <= L_frame + kTcxHmParabolaHalfWidth - 1) + { + + for (x=max(0, k-kTcxHmParabolaHalfWidth); x<=min(k+kTcxHmParabolaHalfWidth, L_frame-1); ++x) + { + env[x] = Mpy_32_16(env[x], inv_shape[x-k+kTcxHmParabolaHalfWidth]); + } + ++h; + k = (h * lag) >> fract_res; + } + + return; +} +#endif /* ANALYSIS_TOOL */ + +#undef WMC_TOOL_SKIP diff --git a/lib_com/arith_coder.c b/lib_com/arith_coder.c new file mode 100644 index 000000000..684d20b4b --- /dev/null +++ b/lib_com/arith_coder.c @@ -0,0 +1,512 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "basop_util.h" +#include "basop_proto_func.h" + + +#define WMC_TOOL_SKIP + + +/*-------------------------------------------------------* + * expfp() + * + * Fixed point implementation of exp() + *-------------------------------------------------------*/ + +Word16 expfp( /* o: Q15 */ + Word16 x, /* i: mantissa Q15-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_negate(L_shl(L_deposit_h(x), sub(x_e, 15))); + + /* 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(y, 24109); /* exp(-1) in -1Q16 */ + if (b1 != 0) y = Mpy_32_16(y, 17739); /* exp(-2) in -2Q17 */ + if (b2 != 0) y = Mpy_32_16(y, 19205); /* exp(-4) in -5Q20 */ + if (b3 != 0) y = Mpy_32_16(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); + move16(); + } + + return round_fx(L_shl(y, 15)); +} + + +/*-------------------------------------------------------* + * powfp_odd2() + * + * 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(); + + return; +} + + +/*------------------------------------------------------------------------ + * 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 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(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(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(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, FL2WORD16(0.357f)); + 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, FL2WORD16_SCALE(2.71828183f, 2)), 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(FL2WORD16(0.15f), 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(a, FL2WORD16(-4.0f*0.035f)), a_e, &tmp2)); + + IF( tmp <= 0 ) + { + tmp = 0; + + FOR( k=0; k 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(s, FL2WORD16_SCALE(5.436564f * 1.4142f, 3)); /* Q13 */ + bits = add(bits, sub(17, norm_l(L_tmp))); + } + } + + IF (sub(bits, target_bits) <= 0) + { + /* 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(FL2WORD16_SCALE(1.05f, 1), 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(); + + FOR( k=0; k 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 */ + basop_weight_a(A_ind, tmpA, gamma_w); + basop_lpc2mdct(tmpA, M, NULL, NULL, gainlpc, gainlpc_e); + + /* Add pre-emphasis tilt to LPC envelope, transform LPC into MDCT gains */ + basop_weight_a_inv(A_ind, signal_env, gamma_uw); + basop_E_LPC_a_add_tilt(signal_env, tmpA, preemph_fac); + basop_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 */ + FOR (k = 0; k < L_frame; k++) + { + env[k] = 0x10000; + move32(); + } + + basop_PsychAdaptLowFreqDeemph(env, gainlpc, gainlpc_e, NULL); + + /* Scale from FDNS_NPTS to L_frame and multiply LFE gains */ + basop_mdct_noiseShaping_interp(env, L_frame, signal_env, signal_env_e); + + FOR (k=L_frame; k +#include +#include "stl.h" +#ifdef BASOP_NOGLOB +#include +#endif /* BASOP_NOGLOB */ + +#define WMC_TOOL_SKIP + +#ifdef _MSC_VER +#pragma warning( disable : 4310 ) +#endif + +/*___________________________________________________________________________ + | | + | Local Functions | + |___________________________________________________________________________| +*/ +#ifdef BASOP_NOGLOB +static Word16 saturate_o( Word32 L_var1, Flag *Overflow ); +#endif /* BASOP_NOGLOB */ +static Word16 saturate( Word32 L_var1 ); + + +/*___________________________________________________________________________ + | | + | Constants and Globals | + |___________________________________________________________________________| +*/ +#ifndef BASOP_NOGLOB +Flag Overflow = 0; +Flag Carry = 0; + +#else /* BASOP_NOGLOB */ +/* +Flag BASOP_Overflow = 0; +Flag BASOP_Carry = 0; +*/ +#endif /* BASOP_NOGLOB */ + +/*___________________________________________________________________________ + | | + | Functions | + |___________________________________________________________________________| +*/ + +#define PRINT_STACK_ID_ALL "*" + + +/*___________________________________________________________________________ + | | + | 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. | + |___________________________________________________________________________| +*/ +#ifndef BASOP_NOGLOB +static Word16 saturate( Word32 L_var1 ) +#else /* BASOP_NOGLOB */ +static Word16 saturate_o( Word32 L_var1, Flag *Overflow ) +#endif /* BASOP_NOGLOB */ +{ + Word16 var_out; + + if ( L_var1 > 0X00007fffL ) + { +#ifndef BASOP_NOGLOB + Overflow = 1; +#else /* BASOP_NOGLOB */ + *Overflow = 1; +#endif /* BASOP_NOGLOB */ + var_out = MAX_16; + } + else if ( L_var1 < (Word32) 0xffff8000L ) + { +#ifndef BASOP_NOGLOB + Overflow = 1; +#else /* BASOP_NOGLOB */ + *Overflow = 1; +#endif /* BASOP_NOGLOB */ + var_out = MIN_16; + } + else + { + var_out = extract_l( L_var1 ); +#ifdef WMOPS + multiCounter[currCounter].extract_l--; +#endif + } + + BASOP_CHECK(); + + return ( var_out ); +} + +#ifdef BASOP_NOGLOB +static Word16 saturate( Word32 L_var1 ) +{ + Word16 var_out; + + if ( L_var1 > 0X00007fffL ) + { + assert( 0 ); + var_out = MAX_16; + } + else if ( L_var1 < (Word32) 0xffff8000L ) + { + assert( 0 ); + var_out = MIN_16; + } + else + { + var_out = extract_l( L_var1 ); +#ifdef WMOPS + multiCounter[currCounter].extract_l--; +#endif + } + + BASOP_CHECK(); + + return ( var_out ); +} +#endif /* BASOP_NOGLOB */ + +/*___________________________________________________________________________ + | | + | 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. | + |___________________________________________________________________________| +*/ +#ifdef BASOP_NOGLOB +Word16 add_o( Word16 var1, Word16 var2, Flag *Overflow ) +{ + Word16 var_out; + Word32 L_sum; + + L_sum = (Word32) var1 + var2; + var_out = saturate_o( L_sum, Overflow ); + +#ifdef WMOPS + multiCounter[currCounter].add++; +#endif + return ( var_out ); +} + +#endif /* BASOP_NOGLOB */ +Word16 add( Word16 var1, Word16 var2 ) +{ + Word16 var_out; + Word32 L_sum; + + L_sum = (Word32) var1 + var2; + var_out = saturate( L_sum ); + +#ifdef 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. | + |___________________________________________________________________________| +*/ +#ifdef BASOP_NOGLOB +Word16 sub_o( Word16 var1, Word16 var2, Flag *Overflow ) +{ + Word16 var_out; + Word32 L_diff; + + L_diff = (Word32) var1 - var2; + var_out = saturate_o( L_diff, Overflow ); + +#ifdef WMOPS + multiCounter[currCounter].sub++; +#endif + return ( var_out ); +} + +#endif /* BASOP_NOGLOB */ +Word16 sub( Word16 var1, Word16 var2 ) +{ + Word16 var_out; + Word32 L_diff; + + L_diff = (Word32) var1 - var2; + var_out = saturate( L_diff ); + +#ifdef 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; + } + } + +#ifdef WMOPS + multiCounter[currCounter].abs_s++; +#endif + BASOP_CHECK(); + + + 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. | + |___________________________________________________________________________| +*/ +#ifndef BASOP_NOGLOB +Word16 shl( Word16 var1, Word16 var2 ) +#else /* BASOP_NOGLOB */ +Word16 shl_o( Word16 var1, Word16 var2, Flag *Overflow ) +#endif /* BASOP_NOGLOB */ +{ + Word16 var_out; + Word32 result; + + if ( var2 < 0 ) + { + if ( var2 < -16 ) + var2 = -16; + var2 = -var2; + var_out = shr( var1, var2 ); + +#ifdef WMOPS + multiCounter[currCounter].shr--; +#endif + } + else + { + result = (Word32) var1 * ( (Word32) 1 << var2 ); + + if ( ( var2 > 15 && var1 != 0 ) || ( result != (Word32) ( (Word16) result ) ) ) + { +#ifndef BASOP_NOGLOB + Overflow = 1; +#else /* BASOP_NOGLOB */ + *Overflow = 1; +#endif /* BASOP_NOGLOB */ + var_out = ( var1 > 0 ) ? MAX_16 : MIN_16; + } + else + { + var_out = extract_l( result ); + +#ifdef WMOPS + multiCounter[currCounter].extract_l--; +#endif + } + } + +#ifdef WMOPS + multiCounter[currCounter].shl++; +#endif + + BASOP_CHECK(); + + + return ( var_out ); +} + +#ifdef BASOP_NOGLOB +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 ); + +#ifdef WMOPS + multiCounter[currCounter].shr--; +#endif + } + else + { + result = (Word32) var1 * ( (Word32) 1 << var2 ); + + if ( ( var2 > 15 && var1 != 0 ) || ( result != (Word32) ( (Word16) result ) ) ) + { + assert( 0 ); + var_out = ( var1 > 0 ) ? MAX_16 : MIN_16; + } + else + { + var_out = extract_l( result ); + +#ifdef WMOPS + multiCounter[currCounter].extract_l--; +#endif + } + } + +#ifdef WMOPS + multiCounter[currCounter].shl++; +#endif + BASOP_CHECK(); + + + return ( var_out ); +} +#endif /* BASOP_NOGLOB */ + +/*___________________________________________________________________________ + | | + | 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 ) + { +#ifdef BASOP_NOGLOB + assert( 0 ); +#endif /* BASOP_NOGLOB */ + if ( var2 < -16 ) + var2 = -16; + var2 = -var2; + var_out = shl( var1, var2 ); + +#ifdef 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; + } + } + } + +#ifdef WMOPS + multiCounter[currCounter].shr++; +#endif + + BASOP_CHECK(); + + + 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. | + |___________________________________________________________________________| +*/ +#ifdef BASOP_NOGLOB +Word16 mult_o( Word16 var1, Word16 var2, Flag *Overflow ) +{ + 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_o( L_product, Overflow ); + +#ifdef WMOPS + multiCounter[currCounter].mult++; +#endif + + return ( var_out ); +} + +#endif /* BASOP_NOGLOB */ +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 ); + +#ifdef 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. | + |___________________________________________________________________________| +*/ +#ifndef BASOP_NOGLOB +Word32 L_mult( Word16 var1, Word16 var2 ) +#else /* BASOP_NOGLOB */ +Word32 L_mult_o( Word16 var1, Word16 var2, Flag *Overflow ) +#endif /* BASOP_NOGLOB */ +{ + Word32 L_var_out; + + L_var_out = (Word32) var1 * (Word32) var2; + + if ( L_var_out != (Word32) 0x40000000L ) + { + L_var_out *= 2; + } + else + { +#ifndef BASOP_NOGLOB + Overflow = 1; +#else /* BASOP_NOGLOB */ + *Overflow = 1; +#endif /* BASOP_NOGLOB */ + L_var_out = MAX_32; + } + +#ifdef WMOPS + multiCounter[currCounter].L_mult++; +#endif + + BASOP_CHECK(); + + return ( L_var_out ); +} + +#ifdef BASOP_NOGLOB +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 + { + assert( 0 ); + L_var_out = MAX_32; + } + +#ifdef WMOPS + multiCounter[currCounter].L_mult++; +#endif + + BASOP_CHECK(); + + return ( L_var_out ); +} +#endif /* BASOP_NOGLOB */ + +/*___________________________________________________________________________ + | | + | 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; + + +#ifdef WMOPS + multiCounter[currCounter].negate++; +#endif + + BASOP_CHECK(); + + + 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 ); + +#ifdef WMOPS + multiCounter[currCounter].extract_h++; +#endif + + BASOP_CHECK(); + + + 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; + +#ifdef WMOPS + multiCounter[currCounter].extract_l++; +#endif + + BASOP_CHECK(); + + + 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. | + |___________________________________________________________________________| +*/ +#ifdef BASOP_NOGLOB +Word16 round_fx_o( Word32 L_var1, Flag *Overflow ) +{ + Word16 var_out; + Word32 L_rounded; + + BASOP_SATURATE_WARNING_OFF + L_rounded = L_add_o( L_var1, (Word32) 0x00008000L, Overflow ); + BASOP_SATURATE_WARNING_ON + var_out = extract_h( L_rounded ); + +#ifdef WMOPS + multiCounter[currCounter].L_add--; + multiCounter[currCounter].extract_h--; + multiCounter[currCounter].round++; +#endif + + BASOP_CHECK(); + + return ( var_out ); +} + +#endif /* BASOP_NOGLOB */ +Word16 round_fx( Word32 L_var1 ) +{ + Word16 var_out; + Word32 L_rounded; + + BASOP_SATURATE_WARNING_OFF + L_rounded = L_add( L_var1, (Word32) 0x00008000L ); + BASOP_SATURATE_WARNING_ON + var_out = extract_h( L_rounded ); + +#ifdef WMOPS + multiCounter[currCounter].L_add--; + multiCounter[currCounter].extract_h--; + multiCounter[currCounter].round++; +#endif + BASOP_CHECK(); + + 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. | + |___________________________________________________________________________| +*/ +#ifdef BASOP_NOGLOB +Word32 L_mac_o( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow ) +{ + Word32 L_var_out; + Word32 L_product; + + L_product = L_mult_o( var1, var2, Overflow ); + L_var_out = L_add_o( L_var3, L_product, Overflow ); + +#ifdef WMOPS + multiCounter[currCounter].L_mult--; + multiCounter[currCounter].L_add--; + multiCounter[currCounter].L_mac++; +#endif + + return ( L_var_out ); +} + +#endif /* BASOP_NOGLOB */ +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 ); + +#ifdef WMOPS + multiCounter[currCounter].L_mult--; + multiCounter[currCounter].L_add--; + multiCounter[currCounter].L_mac++; +#endif + BASOP_CHECK(); + + 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. | + |___________________________________________________________________________| +*/ +#ifdef BASOP_NOGLOB +Word32 L_msu_o( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow ) +{ + Word32 L_var_out; + Word32 L_product; + + L_product = L_mult_o( var1, var2, Overflow ); + L_var_out = L_sub_o( L_var3, L_product, Overflow ); + +#ifdef WMOPS + multiCounter[currCounter].L_mult--; + multiCounter[currCounter].L_sub--; + multiCounter[currCounter].L_msu++; +#endif + + return ( L_var_out ); +} + +#endif /* BASOP_NOGLOB */ +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 ); + +#ifdef WMOPS + multiCounter[currCounter].L_mult--; + multiCounter[currCounter].L_sub--; + multiCounter[currCounter].L_msu++; +#endif + BASOP_CHECK(); + + 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 : | + | | +#ifndef BASOP_NOGLOB + | In some cases the Carry flag has to be cleared or set before using | +#else + | In some cases the BASOP_Carry flag has to be cleared or set before using | +#endif + | operators which take into account its value. | + |___________________________________________________________________________| +*/ +#ifndef BASOP_NOGLOB +Word32 L_macNs( Word32 L_var3, Word16 var1, Word16 var2 ) +#else /* BASOP_NOGLOB */ +Word32 DEPR_L_macNs( Word32 L_var3, Word16 var1, Word16 var2, Flag *Carry ) +#endif /* BASOP_NOGLOB */ +{ + Word32 L_var_out; + + L_var_out = L_mult( var1, var2 ); +#ifndef BASOP_NOGLOB + L_var_out = L_add_c( L_var3, L_var_out ); +#else /* BASOP_NOGLOB */ + L_var_out = DEPR_L_add_c( L_var3, L_var_out, Carry ); +#endif /* BASOP_NOGLOB */ + +#ifdef WMOPS + multiCounter[currCounter].L_mult--; + multiCounter[currCounter].L_add_c--; + multiCounter[currCounter].L_macNs++; +#endif + + /* BASOP_CHECK(); Do not check for overflow here, function produces the carry bit instead */ + + + 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 : | + | | +#ifndef BASOP_NOGLOB + | In some cases the Carry flag has to be cleared or set before using | +#else + | In some cases the BASOP_Carry flag has to be cleared or set before using | +#endif + | operators which take into account its value. | + |___________________________________________________________________________| +*/ +#ifndef BASOP_NOGLOB +Word32 L_msuNs( Word32 L_var3, Word16 var1, Word16 var2 ) +#else /* BASOP_NOGLOB */ +Word32 DEPR_L_msuNs( Word32 L_var3, Word16 var1, Word16 var2, Flag *Carry ) +#endif /* BASOP_NOGLOB */ +{ + Word32 L_var_out; + + L_var_out = L_mult( var1, var2 ); +#ifndef BASOP_NOGLOB + L_var_out = L_sub_c( L_var3, L_var_out ); +#else /* BASOP_NOGLOB */ + L_var_out = DEPR_L_sub_c( L_var3, L_var_out, Carry ); +#endif /* BASOP_NOGLOB */ + +#ifdef WMOPS + multiCounter[currCounter].L_mult--; + multiCounter[currCounter].L_sub_c--; + multiCounter[currCounter].L_msuNs++; +#endif + + /* BASOP_CHECK(); Do not check for overflow here, function produces the carry bit instead */ + + 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. | + |___________________________________________________________________________| +*/ +#ifndef BASOP_NOGLOB +Word32 L_add( Word32 L_var1, Word32 L_var2 ) +#else /* BASOP_NOGLOB */ +Word32 L_add_o( Word32 L_var1, Word32 L_var2, Flag *Overflow ) +#endif /* BASOP_NOGLOB */ +{ + 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; +#ifndef BASOP_NOGLOB + Overflow = 1; +#else /* BASOP_NOGLOB */ + *Overflow = 1; +#endif /* BASOP_NOGLOB */ + } + } + +#ifdef WMOPS + multiCounter[currCounter].L_add++; +#endif + + BASOP_CHECK(); + + + return ( L_var_out ); +} + +#ifdef BASOP_NOGLOB +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; + assert( 0 ); + } + } + +#ifdef WMOPS + multiCounter[currCounter].L_add++; +#endif + return ( L_var_out ); +} +#endif /* BASOP_NOGLOB */ + +/*___________________________________________________________________________ + | | + | 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. | + |___________________________________________________________________________| +*/ +#ifndef BASOP_NOGLOB +Word32 L_sub( Word32 L_var1, Word32 L_var2 ) +#else /* BASOP_NOGLOB */ +Word32 L_sub_o( Word32 L_var1, Word32 L_var2, Flag *Overflow ) +#endif /* BASOP_NOGLOB */ +{ + 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; +#ifndef BASOP_NOGLOB + Overflow = 1; +#else /* BASOP_NOGLOB */ + *Overflow = 1; +#endif /* BASOP_NOGLOB */ + } + } + +#ifdef WMOPS + multiCounter[currCounter].L_sub++; +#endif + + BASOP_CHECK(); + + return ( L_var_out ); +} + +#ifdef BASOP_NOGLOB +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; + assert( 0 ); + } + } + +#ifdef WMOPS + multiCounter[currCounter].L_sub++; +#endif + BASOP_CHECK(); + + return ( L_var_out ); +} +#endif /* BASOP_NOGLOB */ + +/*___________________________________________________________________________ + | | + | Function Name : L_add_c | + | | + | Purpose : | + | | + | Performs 32 bits addition of the two 32 bits variables (L_var1+L_var2+C)| +#ifndef BASOP_NOGLOB + | with carry. No saturation. Generate carry and Overflow values. The car- | +#else + | with carry. No saturation. Generate carry and BASOP_Overflow values. The car- | +#endif + | 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 : | + | | +#ifndef BASOP_NOGLOB + | In some cases the Carry flag has to be cleared or set before using | +#else + | In some cases the BASOP_Carry flag has to be cleared or set before using | +#endif + | operators which take into account its value. | + |___________________________________________________________________________| +*/ +#ifndef BASOP_NOGLOB +Word32 L_add_c( Word32 L_var1, Word32 L_var2 ) +#else /* BASOP_NOGLOB */ +Word32 DEPR_L_add_c( Word32 L_var1, Word32 L_var2, Flag *Carry ) +#endif /* BASOP_NOGLOB */ +{ + Word32 L_var_out; + Word32 L_test; + Flag carry_int = 0; + +#ifndef BASOP_NOGLOB + L_var_out = L_var1 + L_var2 + Carry; +#else /* BASOP_NOGLOB */ + L_var_out = L_var1 + L_var2 + *Carry; +#endif /* BASOP_NOGLOB */ + + L_test = L_var1 + L_var2; + + if ( ( L_var1 > 0 ) && ( L_var2 > 0 ) && ( L_test < 0 ) ) + { +#ifndef BASOP_NOGLOB + Overflow = 1; +#endif /* ! BASOP_NOGLOB */ + carry_int = 0; + } + else + { + if ( ( L_var1 < 0 ) && ( L_var2 < 0 ) ) + { + if ( L_test >= 0 ) + { +#ifndef BASOP_NOGLOB + Overflow = 1; +#endif /* ! BASOP_NOGLOB */ + carry_int = 1; + } + else + { +#ifndef BASOP_NOGLOB + Overflow = 0; +#endif /* ! BASOP_NOGLOB */ + carry_int = 1; + } + } + else + { + if ( ( ( L_var1 ^ L_var2 ) < 0 ) && ( L_test >= 0 ) ) + { +#ifndef BASOP_NOGLOB + Overflow = 0; +#endif /* ! BASOP_NOGLOB */ + carry_int = 1; + } + else + { +#ifndef BASOP_NOGLOB + Overflow = 0; +#endif /* ! BASOP_NOGLOB */ + carry_int = 0; + } + } + } + +#ifndef BASOP_NOGLOB + if ( Carry ) +#else /* BASOP_NOGLOB */ + if ( *Carry ) +#endif /* BASOP_NOGLOB */ + { + if ( L_test == MAX_32 ) + { +#ifndef BASOP_NOGLOB + Overflow = 1; + Carry = carry_int; +#else /* BASOP_NOGLOB */ + *Carry = carry_int; +#endif /* BASOP_NOGLOB */ + } + else + { + if ( L_test == (Word32) 0xFFFFFFFFL ) + { +#ifndef BASOP_NOGLOB + Carry = 1; +#else /* BASOP_NOGLOB */ + *Carry = 1; +#endif /* BASOP_NOGLOB */ + } + else + { +#ifndef BASOP_NOGLOB + Carry = carry_int; +#else /* BASOP_NOGLOB */ + *Carry = carry_int; +#endif /* BASOP_NOGLOB */ + } + } + } + else + { +#ifndef BASOP_NOGLOB + Carry = carry_int; +#else /* BASOP_NOGLOB */ + *Carry = carry_int; +#endif /* BASOP_NOGLOB */ + } + +#ifdef WMOPS + multiCounter[currCounter].L_add_c++; +#endif + + /* BASOP_CHECK(); Do not check for overflow here, function produces the carry bit instead */ + + + return ( L_var_out ); +} + + +/*___________________________________________________________________________ + | | + | Function Name : L_sub_c | + | | + | Purpose : | + | | + | Performs 32 bits subtraction of the two 32 bits variables with carry | +#ifndef BASOP_NOGLOB + | (borrow) : L_var1-L_var2-C. No saturation. Generate carry and Overflow | +#else + | (borrow) : L_var1-L_var2-C. No saturation. Generate carry and BASOP_Overflow | +#endif + | 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 : | + | | +#ifndef BASOP_NOGLOB + | In some cases the Carry flag has to be cleared or set before using | +#else + | In some cases the BASOP_Carry flag has to be cleared or set before using | +#endif + | operators which take into account its value. | + |___________________________________________________________________________| +*/ +#ifndef BASOP_NOGLOB +Word32 L_sub_c( Word32 L_var1, Word32 L_var2 ) +#else /* BASOP_NOGLOB */ +Word32 DEPR_L_sub_c( Word32 L_var1, Word32 L_var2, Flag *Carry ) +#endif /* BASOP_NOGLOB */ +{ + Word32 L_var_out; + Word32 L_test; + Flag carry_int = 0; + +#ifndef BASOP_NOGLOB + if ( Carry ) +#else /* BASOP_NOGLOB */ + if ( *Carry ) +#endif /* BASOP_NOGLOB */ + { +#ifndef BASOP_NOGLOB + Carry = 0; +#else /* BASOP_NOGLOB */ + *Carry = 0; +#endif /* BASOP_NOGLOB */ + if ( L_var2 != MIN_32 ) + { +#ifndef BASOP_NOGLOB + L_var_out = L_add_c( L_var1, -L_var2 ); +#else /* BASOP_NOGLOB */ + L_var_out = DEPR_L_add_c( L_var1, -L_var2, Carry ); +#endif /* BASOP_NOGLOB */ +#ifdef WMOPS + multiCounter[currCounter].L_add_c--; +#endif + } + else + { + L_var_out = L_var1 - L_var2; + if ( L_var1 > 0L ) + { +#ifndef BASOP_NOGLOB + Overflow = 1; + Carry = 0; +#else /* BASOP_NOGLOB */ + *Carry = 0; +#endif /* BASOP_NOGLOB */ + } + } + } + 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 ) ) + { +#ifndef BASOP_NOGLOB + Overflow = 1; +#endif /* ! BASOP_NOGLOB */ + carry_int = 0; + } + else if ( ( L_test > 0 ) && ( L_var1 < 0 ) && ( L_var2 > 0 ) ) + { +#ifndef BASOP_NOGLOB + Overflow = 1; +#endif /* ! BASOP_NOGLOB */ + carry_int = 1; + } + else if ( ( L_test > 0 ) && ( ( L_var1 ^ L_var2 ) > 0 ) ) + { +#ifndef BASOP_NOGLOB + Overflow = 0; +#endif /* ! BASOP_NOGLOB */ + carry_int = 1; + } + if ( L_test == MIN_32 ) + { +#ifndef BASOP_NOGLOB + Overflow = 1; + Carry = carry_int; +#else /* BASOP_NOGLOB */ + *Carry = carry_int; +#endif /* BASOP_NOGLOB */ + } + else + { +#ifndef BASOP_NOGLOB + Carry = carry_int; +#else /* BASOP_NOGLOB */ + *Carry = carry_int; +#endif /* BASOP_NOGLOB */ + } + } + +#ifdef WMOPS + multiCounter[currCounter].L_sub_c++; +#endif + + /* BASOP_CHECK(); Do not check for overflow here, function produces the carry bit instead */ + + + 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; + + +#ifdef WMOPS + multiCounter[currCounter].L_negate++; +#endif + + BASOP_CHECK(); + + 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. | + |___________________________________________________________________________| +*/ +#ifdef BASOP_NOGLOB +Word16 mult_ro( Word16 var1, Word16 var2, Flag *Overflow ) +{ + 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_o( L_product_arr, Overflow ); + +#ifdef WMOPS + multiCounter[currCounter].mult_r++; +#endif + + return ( var_out ); +} + +#endif /* BASOP_NOGLOB */ +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 ); + +#ifdef 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. | + |___________________________________________________________________________| +*/ +#ifndef BASOP_NOGLOB +Word32 L_shl( Word32 L_var1, Word16 var2 ) +#else /* BASOP_NOGLOB */ +Word32 L_shl_o( Word32 L_var1, Word16 var2, Flag *Overflow ) +#endif /* BASOP_NOGLOB */ +{ + + Word32 L_var_out = 0L; + + if ( var2 <= 0 ) + { + if ( var2 < -32 ) + var2 = -32; + var2 = -var2; + L_var_out = L_shr( L_var1, var2 ); +#ifdef WMOPS + multiCounter[currCounter].L_shr--; +#endif + } + else + { + for ( ; var2 > 0; var2-- ) + { + if ( L_var1 > (Word32) 0X3fffffffL ) + { +#ifndef BASOP_NOGLOB + Overflow = 1; +#else /* BASOP_NOGLOB */ + *Overflow = 1; +#endif /* BASOP_NOGLOB */ + L_var_out = MAX_32; + break; + } + else + { + if ( L_var1 < (Word32) 0xc0000000L ) + { +#ifndef BASOP_NOGLOB + Overflow = 1; +#else /* BASOP_NOGLOB */ + *Overflow = 1; +#endif /* BASOP_NOGLOB */ + L_var_out = MIN_32; + break; + } + } + L_var1 *= 2; + L_var_out = L_var1; + } + } + +#ifdef WMOPS + multiCounter[currCounter].L_shl++; +#endif + + BASOP_CHECK(); + + + return ( L_var_out ); +} + +#ifdef BASOP_NOGLOB +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 ); +#ifdef WMOPS + multiCounter[currCounter].L_shr--; +#endif + } + else + { + for ( ; var2 > 0; var2-- ) + { + if ( L_var1 > (Word32) 0X3fffffffL ) + { + assert( 0 ); + L_var_out = MAX_32; + break; + } + else + { + if ( L_var1 < (Word32) 0xc0000000L ) + { + assert( 0 ); + L_var_out = MIN_32; + break; + } + } + L_var1 *= 2; + L_var_out = L_var1; + } + } + +#ifdef WMOPS + multiCounter[currCounter].L_shl++; +#endif + BASOP_CHECK(); + + + return ( L_var_out ); +} +#endif /* BASOP_NOGLOB */ + +/*___________________________________________________________________________ + | | + | 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. | + |___________________________________________________________________________| +*/ +#ifdef BASOP_NOGLOB +Word32 L_shr_o( Word32 L_var1, Word16 var2, Flag *Overflow ) +{ + Word32 L_var_out; + + if ( var2 < 0 ) + { + if ( var2 < -32 ) + var2 = -32; + var2 = -var2; + L_var_out = L_shl_o( L_var1, var2, Overflow ); +#ifdef 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; + } + } + } + +#ifdef WMOPS + multiCounter[currCounter].L_shr++; +#endif + + BASOP_CHECK(); + + + return ( L_var_out ); +} + +#endif /* BASOP_NOGLOB */ +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 ); +#ifdef 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; + } + } + } + +#ifdef WMOPS + multiCounter[currCounter].L_shr++; +#endif + BASOP_CHECK(); + + + 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 ); + +#ifdef WMOPS + multiCounter[currCounter].shr--; +#endif + if ( var2 > 0 ) + { + if ( ( var1 & ( (Word16) 1 << ( var2 - 1 ) ) ) != 0 ) + { + var_out++; + } + } + } + +#ifdef WMOPS + multiCounter[currCounter].shr_r++; +#endif + + BASOP_CHECK(); + + 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. | + |___________________________________________________________________________| +*/ +#ifdef BASOP_NOGLOB +Word16 mac_ro( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow ) +{ + Word16 var_out; + + L_var3 = L_mac_o( L_var3, var1, var2, Overflow ); + L_var3 = L_add_o( L_var3, (Word32) 0x00008000L, Overflow ); + var_out = extract_h( L_var3 ); + +#ifdef WMOPS + multiCounter[currCounter].L_mac--; + multiCounter[currCounter].L_add--; + multiCounter[currCounter].extract_h--; + multiCounter[currCounter].mac_r++; +#endif + + BASOP_CHECK(); + + + return ( var_out ); +} + +#endif /* BASOP_NOGLOB */ +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 ); + +#ifdef WMOPS + multiCounter[currCounter].L_mac--; + multiCounter[currCounter].L_add--; + multiCounter[currCounter].extract_h--; + multiCounter[currCounter].mac_r++; +#endif + + BASOP_CHECK(); + + + 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. | + |___________________________________________________________________________| +*/ +#ifdef BASOP_NOGLOB +Word16 msu_ro( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow ) +{ + Word16 var_out; + + L_var3 = L_msu_o( L_var3, var1, var2, Overflow ); + L_var3 = L_add_o( L_var3, (Word32) 0x00008000L, Overflow ); + var_out = extract_h( L_var3 ); + +#ifdef WMOPS + multiCounter[currCounter].L_msu--; + multiCounter[currCounter].L_add--; + multiCounter[currCounter].extract_h--; + multiCounter[currCounter].msu_r++; +#endif + BASOP_CHECK(); + + return ( var_out ); +} + +#endif /* BASOP_NOGLOB */ +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 ); + +#ifdef WMOPS + multiCounter[currCounter].L_msu--; + multiCounter[currCounter].L_add--; + multiCounter[currCounter].extract_h--; + multiCounter[currCounter].msu_r++; +#endif + BASOP_CHECK(); + + 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; + +#ifdef WMOPS + multiCounter[currCounter].L_deposit_h++; +#endif + + BASOP_CHECK(); + + + 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; + +#ifdef WMOPS + multiCounter[currCounter].L_deposit_l++; +#endif + + BASOP_CHECK(); + + + 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 ); + +#ifdef WMOPS + multiCounter[currCounter].L_shr--; +#endif + if ( var2 > 0 ) + { + if ( ( L_var1 & ( (Word32) 1 << ( var2 - 1 ) ) ) != 0 ) + { + L_var_out++; + } + } + } + +#ifdef WMOPS + multiCounter[currCounter].L_shr_r++; +#endif + + BASOP_CHECK(); + + + 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; + } + } + +#ifdef WMOPS + multiCounter[currCounter].L_abs++; +#endif + + BASOP_CHECK(); + + + 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. | + |___________________________________________________________________________| +*/ +#ifndef BASOP_NOGLOB +Word32 L_sat( Word32 L_var1 ) +#else /* BASOP_NOGLOB */ +Word32 DEPR_L_sat_co( Word32 L_var1, Flag Overflow, Flag Carry ) +#endif /* BASOP_NOGLOB */ +{ + Word32 L_var_out; + + L_var_out = L_var1; + + if ( Overflow ) + { + + if ( Carry ) + { + L_var_out = MIN_32; + } + else + { + L_var_out = MAX_32; + } +#ifndef BASOP_NOGLOB + + Carry = 0; + Overflow = 0; +#endif /* ! BASOP_NOGLOB */ + } + +#ifdef WMOPS + multiCounter[currCounter].L_sat++; +#endif + + BASOP_CHECK(); + + + 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; + } + } + } + +#ifdef WMOPS + multiCounter[currCounter].norm_s++; +#endif + + BASOP_CHECK(); + + + 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 in ", var1, var2); printStack(); */ + char text[60]; + sprintf( text, "Division Error var1=%d var2=%d in ", var1, var2 ); + abort(); /* exit (0); */ + } + if ( var2 == 0 ) + { + /* printf ("Division by 0, Fatal error in "); printStack(); */ + 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 ); + +#ifdef 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 ); +#ifdef WMOPS + multiCounter[currCounter].L_sub--; + multiCounter[currCounter].add--; +#endif + } + } + } + } + +#ifdef WMOPS + multiCounter[currCounter].div_s++; +#endif + + BASOP_CHECK(); + + + 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; + } + } + } + +#ifdef WMOPS + multiCounter[currCounter].norm_l++; +#endif + + BASOP_CHECK(); + + + 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. | + | | + |___________________________________________________________________________| +*/ +#ifdef BASOP_NOGLOB +Word32 L_mls_o( Word32 Lv, Word16 v, Flag *Overflow ) +{ + Word32 Temp; + + Temp = Lv & (Word32) 0x0000ffff; + Temp = Temp * (Word32) v; + Temp = L_shr( Temp, (Word16) 15 ); + Temp = L_mac_o( Temp, v, extract_h( Lv ), Overflow ); + +#ifdef WMOPS + multiCounter[currCounter].L_shr--; + multiCounter[currCounter].L_mac--; + multiCounter[currCounter].extract_h--; + multiCounter[currCounter].L_mls++; +#endif + + BASOP_CHECK(); + + return Temp; +} + +#endif /* BASOP_NOGLOB */ +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 ) ); + +#ifdef WMOPS + multiCounter[currCounter].L_shr--; + multiCounter[currCounter].L_mac--; + multiCounter[currCounter].extract_h--; + multiCounter[currCounter].L_mls++; +#endif + + BASOP_CHECK(); + + 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; + +#ifdef WMOPS + multiCounter[currCounter].div_l++; +#endif + + if ( den == (Word16) 0 ) + { + /* printf("Division by 0 in div_l, Fatal error in "); printStack(); */ + exit( -1 ); + } + + if ( ( L_num < (Word32) 0 ) || ( den < (Word16) 0 ) ) + { + /* printf("Division Error in div_l, Fatal error in "); printStack(); */ + exit( -1 ); + } + + L_den = L_deposit_h( den ); +#ifdef WMOPS + multiCounter[currCounter].L_deposit_h--; +#endif + + if ( L_num >= L_den ) + { + + + BASOP_CHECK(); + return MAX_16; + } + else + { + L_num = L_shr( L_num, (Word16) 1 ); + L_den = L_shr( L_den, (Word16) 1 ); +#ifdef 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 ); +#ifdef 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 ); +#ifdef WMOPS + multiCounter[currCounter].L_sub--; + multiCounter[currCounter].add--; +#endif + } + } + + + BASOP_CHECK(); + + 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. | +|___________________________________________________________________________| +*/ +#ifndef BASOP_NOGLOB +Word16 i_mult( Word16 a, Word16 b ) +#else /* BASOP_NOGLOB */ +Word16 DEPR_i_mult( Word16 a, Word16 b ) +#endif /* BASOP_NOGLOB */ +{ +#ifdef ORIGINAL_G7231 + return a * b; +#else + Word32 /*register*/ c = a * b; +#ifdef 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; + +#ifdef 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. + |___________________________________________________________________________ +*/ +#ifdef BASOP_NOGLOB +Word32 L_mac0_o( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow ) +{ + Word32 L_var_out; + Word32 L_product; + + L_product = L_mult0( var1, var2 ); + L_var_out = L_add_o( L_var3, L_product, Overflow ); + +#ifdef WMOPS + multiCounter[currCounter].L_mac0++; + multiCounter[currCounter].L_mult0--; + multiCounter[currCounter].L_add--; +#endif + + BASOP_CHECK(); + + return ( L_var_out ); +} + +#endif /* BASOP_NOGLOB */ +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 ); + +#ifdef WMOPS + multiCounter[currCounter].L_mac0++; + multiCounter[currCounter].L_mult0--; + multiCounter[currCounter].L_add--; +#endif + + BASOP_CHECK(); + + + 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. + |___________________________________________________________________________ +*/ +#ifdef BASOP_NOGLOB +Word32 L_msu0_o( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow ) +{ + Word32 L_var_out; + Word32 L_product; + + L_product = L_mult0( var1, var2 ); + L_var_out = L_sub_o( L_var3, L_product, Overflow ); + +#ifdef WMOPS + multiCounter[currCounter].L_msu0++; + multiCounter[currCounter].L_mult0--; + multiCounter[currCounter].L_sub--; +#endif + + BASOP_CHECK(); + + return ( L_var_out ); +} + +#endif /* BASOP_NOGLOB */ +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 ); + +#ifdef WMOPS + multiCounter[currCounter].L_msu0++; + multiCounter[currCounter].L_mult0--; + multiCounter[currCounter].L_sub--; +#endif + + BASOP_CHECK(); + + + return ( L_var_out ); +} + +#undef WMC_TOOL_SKIP diff --git a/lib_com/basop32.h b/lib_com/basop32.h new file mode 100644 index 000000000..376ac8c78 --- /dev/null +++ b/lib_com/basop32.h @@ -0,0 +1,276 @@ +/****************************************************************************************************** + + (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +/* + =========================================================================== + 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 + + 13 Mar 12 Add Overflow2 flag for additional overflow checking. + ============================================================================ +*/ + + +#ifndef _BASIC_OP_H +#define _BASIC_OP_H + +#include "typedef.h" +#define BASOP_OVERFLOW2 + +/*___________________________________________________________________________ + | | + | Constants and Globals | + |___________________________________________________________________________| +*/ +#ifndef BASOP_NOGLOB +extern Flag Overflow, Overflow2; +extern Flag Carry; + +#else /* BASOP_NOGLOB */ +/* DISABLED TO AVOID GLOBAL VARIABLES */ +/* +extern Flag BASOP_Overflow, BASOP_Overflow2; +extern Flag BASOP_Carry; +*/ +#endif /* BASOP_NOGLOB */ +#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 | + |___________________________________________________________________________| +*/ + +#ifndef BASOP_NOGLOB +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 */ +#else /* BASOP_NOGLOB */ +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 DEPR_L_macNs( Word32 L_var3, Word16 var1, Word16 var2, Flag *Carry ); /* Mac without + sat, 1 */ +#endif /* BASOP_NOGLOB */ + +#ifndef BASOP_NOGLOB +Word32 L_msuNs( Word32 L_var3, Word16 var1, Word16 var2 ); /* Msu without + sat, 1 */ +#else /* BASOP_NOGLOB */ +Word32 DEPR_L_msuNs( Word32 L_var3, Word16 var1, Word16 var2, Flag *Carry ); /* Msu without + sat, 1 */ +#endif /* BASOP_NOGLOB */ +#ifndef BASOP_NOGLOB +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 */ +#else /* BASOP_NOGLOB */ +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 DEPR_L_add_c( Word32 L_var1, Word32 L_var2, Flag *Carry ); /* Long add with c, 2 */ +Word32 DEPR_L_sub_c( Word32 L_var1, Word32 L_var2, Flag *Carry ); /* 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 */ +#endif /* BASOP_NOGLOB */ + +#ifndef BASOP_NOGLOB +Word16 mac_r( Word32 L_var3, Word16 var1, Word16 var2 ); /* Mac with + rounding, 1 */ +#else /* BASOP_NOGLOB */ +Word16 mac_r( Word32 L_var3, Word16 var1, Word16 var2 ); /* Mac with + rounding, 1 */ +#endif /* BASOP_NOGLOB */ +#ifndef BASOP_NOGLOB +Word16 msu_r( Word32 L_var3, Word16 var1, Word16 var2 ); /* Msu with + rounding, 1 */ +#else /* BASOP_NOGLOB */ +Word16 msu_r( Word32 L_var3, Word16 var1, Word16 var2 ); /* Msu with + rounding, 1 */ +#endif /* BASOP_NOGLOB */ +#ifndef BASOP_NOGLOB +Word32 L_deposit_h( Word16 var1 ); /* 16 bit var1 -> MSB, 1 */ +Word32 L_deposit_l( Word16 var1 ); /* 16 bit var1 -> LSB, 1 */ +#else /* BASOP_NOGLOB */ +Word32 L_deposit_h( Word16 var1 ); /* 16 bit var1 -> MSB, 1 */ +Word32 L_deposit_l( Word16 var1 ); /* 16 bit var1 -> LSB, 1 */ +#endif /* BASOP_NOGLOB */ + +#ifndef BASOP_NOGLOB +Word32 L_shr_r( Word32 L_var1, Word16 var2 ); /* Long shift right with + round, 3 */ +#else /* BASOP_NOGLOB */ +Word32 L_shr_r( Word32 L_var1, Word16 var2 ); /* Long shift right with + round, 3 */ +#endif /* BASOP_NOGLOB */ +#ifndef BASOP_NOGLOB +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 */ +#else /* BASOP_NOGLOB */ +Word32 L_abs( Word32 L_var1 ); /* Long abs, 1 */ +Word32 DEPR_L_sat_co( Word32 L_var1, Flag Overflow, Flag Carry ); /* 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 */ +#endif /* BASOP_NOGLOB */ + + +/* + * Additional G.723.1 operators + */ +#ifndef BASOP_NOGLOB +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 */ +#else /* BASOP_NOGLOB */ +Word32 L_mls( Word32, Word16 ); /* Weight FFS; currently assigned 5 */ +Word16 div_l( Word32, Word16 ); /* Weight FFS; currently assigned 32 */ +Word16 DEPR_i_mult( Word16 a, Word16 b ); /* Weight FFS; currently assigned 3 */ +#endif /* BASOP_NOGLOB */ + +/* + * New shiftless operators, not used in G.729/G.723.1 + */ +Word32 L_mult0( Word16 v1, Word16 v2 ); /* 32-bit Multiply w/o shift 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 */ +#ifdef BASOP_NOGLOB + +/* + * Overflowing operators + */ +Word16 add_o( Word16 var1, Word16 var2, Flag *Overflow ); +Word16 sub_o( Word16 var1, Word16 var2, Flag *Overflow ); +Word16 shl_o( Word16 var1, Word16 var2, Flag *Overflow ); +Word16 mult_o( Word16 var1, Word16 var2, Flag *Overflow ); +Word32 L_mult_o( Word16 var1, Word16 var2, Flag *Overflow ); +Word16 round_fx_o( Word32 L_var1, Flag *Overflow ); +Word32 L_mac_o( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow ); +Word32 L_msu_o( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow ); +Word32 L_add_o( Word32 L_var1, Word32 L_var2, Flag *Overflow ); +Word32 L_sub_o( Word32 L_var1, Word32 L_var2, Flag *Overflow ); +Word32 L_shr_o( Word32 L_var1, Word16 var2, Flag *Overflow ); +Word32 L_shl_o( Word32 L_var1, Word16 var2, Flag *Overflow ); +Word32 L_mls_o( Word32 Lv, Word16 v, Flag *Overflow ); +Word32 L_mac0_o( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow ); +Word32 L_msu0_o( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow ); +Word16 mult_ro( Word16 var1, Word16 var2, Flag *Overflow ); +Word16 mac_ro( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow ); +Word16 msu_ro( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow ); +#endif /* BASOP_NOGLOB */ + + +#endif /* ifndef _BASIC_OP_H */ + + +/* end of file */ diff --git a/lib_com/basop_com_lpc.c b/lib_com/basop_com_lpc.c new file mode 100644 index 000000000..abdd1f4a6 --- /dev/null +++ b/lib_com/basop_com_lpc.c @@ -0,0 +1,263 @@ +/****************************************************************************************************** + + (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include +#include "options.h" +#include "typedef.h" +#include "basop_proto_func.h" +#include "cnst.h" +#include "basop_util.h" +#include "stl.h" + +#define WMC_TOOL_SKIP + +#define UNROLL_CHEBYSHEV_INNER_LOOP +#define NC_MAX 8 +#define GUESS_TBL_SZ 256 + +#define Madd_32_16( accu, x, y ) L_add( accu, Mpy_32_16( x, y ) ) +#define Msub_32_16( accu, x, y ) L_sub( accu, Mpy_32_16( x, y ) ) + + +/* + * weight_a + * + * Parameters: + * a I: LP filter coefficients Q12 + * ap O: weighted LP filter coefficients Q12 + * gamma I: weighting factor Q15 + * + * Function: + * Weighting of LP filter coefficients, ap[i] = a[i] * (gamma^i). + * + * Returns: + * void + */ +void basop_weight_a( const Word16 *a, Word16 *ap, const Word16 gamma ) +{ + Word16 i, fac; + Word32 Amax; + Word16 shift; + + + fac = gamma; + Amax = L_mult( 16384, a[0] ); + FOR( i = 1; i < M; i++ ) + { + Amax = L_max( Amax, L_abs( L_mult0( fac, a[i] ) ) ); + fac = mult_r( fac, gamma ); + } + Amax = L_max( Amax, L_abs( L_mult0( fac, a[M] ) ) ); + shift = norm_l( Amax ); + fac = gamma; + ap[0] = shl( a[0], sub( shift, 1 ) ); + move16(); + FOR( i = 1; i < M; i++ ) + { + ap[i] = round_fx( L_shl( L_mult0( a[i], fac ), shift ) ); + move16(); + fac = mult_r( fac, gamma ); + } + ap[M] = round_fx( L_shl( L_mult0( a[M], fac ), shift ) ); + move16(); + + + return; +} + +/* + * weight_a_inv + * + * Parameters: + * a I: LP filter coefficients Q12 + * ap O: weighted LP filter coefficients Q12 + * inv_gamma I: inverse weighting factor Q14 + * + * Function: + * Weighting of LP filter coefficients, ap[i] = a[i] * (inv_gamma^i). + * + * Returns: + * void + */ +void basop_weight_a_inv( const Word16 *a, Word16 *ap, const Word16 inv_gamma ) +{ + Word16 i; + static const Word16 inv_gamma_tab_12k8[16] = { 17809, 19357, 21041, 22870, 24859, 27020, 29370, 31924, /* Q14 */ + 17350, 18859, 20499, 22281, 24219, 26325, 28614, 31102 }; /* Q13 */ + static const Word16 inv_gamma_tab_16k[16] = { 17430, 18542, 19726, 20985, 22324, 23749, 25265, 26878, /* Q14 */ + 14297, 15209, 16180, 17213, 18312, 19480, 20724, 22047 }; /* Q13 */ + const Word16 *inv_gamma_tab; + Word32 L_tmp; + Word32 Amax; + Word16 shift; + + + IF( inv_gamma == 16384 ) + { + FOR( i = 0; i <= M; i++ ) + { + ap[i] = a[i]; + move16(); + } + return; + } + + assert( inv_gamma == GAMMA1_INV || inv_gamma == GAMMA16k_INV ); + + inv_gamma_tab = inv_gamma_tab_12k8; + move16(); + if ( sub( inv_gamma, GAMMA16k_INV ) == 0 ) + { + inv_gamma_tab = inv_gamma_tab_16k; + move16(); + } + + Amax = L_mult( 16384, a[0] ); + FOR( i = 1; i < 9; i++ ) + { + Amax = L_max( Amax, L_abs( L_mult( a[i], inv_gamma_tab[i - 1] ) ) ); + } + FOR( i = 9; i < 17; i++ ) + { + Amax = L_max( Amax, L_abs( L_shl( L_mult( a[i], inv_gamma_tab[i - 1] ), 1 ) ) ); + } + shift = norm_l( Amax ); + ap[0] = shl( a[0], sub( shift, 1 ) ); + move16(); + FOR( i = 1; i < 9; i++ ) + { + L_tmp = L_mult( a[i], inv_gamma_tab[i - 1] ); + ap[i] = round_fx( L_shl( L_tmp, shift ) ); + move16(); + } + shift = add( shift, 1 ); + FOR( i = 9; i < 17; i++ ) + { + L_tmp = L_mult( a[i], inv_gamma_tab[i - 1] ); + ap[i] = round_fx( L_shl( L_tmp, shift ) ); + move16(); + } + + + return; +} + +/* + * basop_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 + * + * Function: + * Modified LP filter by adding 1st order pre-premphasis, Ap(z)=A(z).(1-gamma.z^(-1)) + * + * Returns: + * void + */ +void basop_E_LPC_a_add_tilt( const Word16 *a, Word16 *ap, Word16 gamma ) +{ + 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 ) ); + move16(); + } + ap[M + 1] = round_fx( L_shl( Atmp[M + 1], shift ) ); + move16(); + + return; +} + + +static Word16 xsf_to_xsp( Word16 xsf ) +{ + /* xsp = cos(xsf * 3.1415/6400); */ + return getCosWord16R2( xsf ); +} + +/* + * lsf2lsp + * + * Parameters: + * lsf I: lsf[m] normalized (range: 0 <= val <= 0.5) x2.56 + * lsp O: lsp[m] (range: -1 <= val < 1) Q15 + * + * Function: + * Transformation lsf to lsp + * + * LSF are line spectral pair in frequency domain (0 to 6400). + * LSP are line spectral pair in cosine domain (-1 to 1). + * + * Returns: + * void + */ +void basop_lsf2lsp( const Word16 lsf[], Word16 lsp[] ) +{ + Word16 i; + + + /* convert ISFs to the cosine domain */ + FOR( i = 0; i < M; i++ ) + { + *lsp++ = xsf_to_xsp( *lsf++ ); + move16(); + } + + + return; +} + +#undef WMC_TOOL_SKIP diff --git a/lib_com/basop_lsf_tools.c b/lib_com/basop_lsf_tools.c new file mode 100644 index 000000000..bf1555a82 --- /dev/null +++ b/lib_com/basop_lsf_tools.c @@ -0,0 +1,313 @@ +/****************************************************************************************************** + + (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include +#include "options.h" +#include "basop_proto_func.h" +#include "basop_util.h" + +#define WMC_TOOL_SKIP + +#define NC_MAX 8 + +static Word16 E_LPC_f_lsp_pol_get( const Word16 lsp[], Word32 f[], const Word16 n, const Word16 past_Ovf, const Word16 isMODE1 ); + + +/* + * E_LPC_f_lsp_a_conversion + * + * Parameters: + * lsp I: Line spectral pairs Q15 + * a O: Predictor coefficients (order = m) Qx (The Q factor of the output to be deduced from a(0)) + * m I: order of LP filter + * + * Function: + * Convert ISPs to predictor coefficients a[] + * + * Returns: + * void + */ +void basop_E_LPC_f_lsp_a_conversion( + const Word16 *lsp, + Word16 *a, + const Word16 m ) +{ + Word16 i, j, k; + Word32 f1[NC_MAX + 1], f2[NC_MAX + 1]; + Word16 nc; + Word32 t0; + Word16 Ovf, Ovf2; + + + /*-----------------------------------------------------* + * Find the polynomials F1(z) and F2(z) * + *-----------------------------------------------------*/ + + nc = shr( m, 1 ); + + assert( m == 16 || m == 10 ); + + Ovf = 0; + move16(); + Ovf = E_LPC_f_lsp_pol_get( &lsp[0], f1, nc, Ovf, 1 ); + Ovf2 = E_LPC_f_lsp_pol_get( &lsp[1], f2, nc, Ovf, 1 ); + IF( sub( Ovf2, Ovf ) != 0 ) + { + /* to ensure similar scaling for f1 and f2 in case + an overflow would be detected only in f2, + but this case never happen on my dtb */ + E_LPC_f_lsp_pol_get( &lsp[0], f1, nc, s_max( Ovf2, Ovf ), 1 ); + } + /*-----------------------------------------------------* + * Multiply F1(z) by (1+z^-1) and F2(z) by (1-z^-1) * + *-----------------------------------------------------*/ + /*modification*/ + k = sub( nc, 1 ); + FOR( i = 0; i <= k; i++ ) + { + f1[nc - i] = L_add( f1[nc - i], f1[nc - i - 1] ); + move32(); + f2[nc - i] = L_sub( f2[nc - i], f2[nc - i - 1] ); + move32(); + } + + /*-----------------------------------------------------* + * A(z) = (F1(z)+F2(z))/2 * + * F1(z) is symmetric and F2(z) is antisymmetric * + *-----------------------------------------------------*/ + + t0 = L_deposit_l( 0 ); + FOR( i = 1; i <= nc; i++ ) + { + t0 = L_max( t0, L_abs( L_add( f1[i], f2[i] ) ) ); + t0 = L_max( t0, L_abs( L_sub( f1[i], f2[i] ) ) ); + } + k = s_min( norm_l( t0 ), 6 ); + a[0] = shl( 256, k ); + move16(); + test(); + IF( Ovf || Ovf2 ) + { + a[0] = shl( 256, sub( k, Ovf ) ); + move16(); + } + j = m; + FOR( i = 1; i <= nc; i++ ) + { + /* a[i] = 0.5*(f1[i] + f2[i]) */ + t0 = L_add( f1[i], f2[i] ); + t0 = L_shl( t0, k ); + a[i] = round_fx( t0 ); /* from Q23 to Qx and * 0.5 */ + + /* a[j] = 0.5*(f1[i] - f2[i]) */ + t0 = L_sub( f1[i], f2[i] ); + t0 = L_shl( t0, k ); + a[j] = round_fx( t0 ); /* from Q23 to Qx and * 0.5 */ + j--; + } + + return; +} + + +/*--------------------------------------------------------------------------- + * procedure reorder_lsf() + * + * To make sure that the lsfs are properly ordered and to keep a certain + * minimum distance between consecutive lsfs. + *--------------------------------------------------------------------------*/ +void basop_reorder_lsf( + 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 i, lsf_min, n_m_1; + Word16 lsf_max; + + lsf_min = min_dist; + move16(); + + /*-----------------------------------------------------------------------* + * Verify the LSF ordering and minimum GAP + *-----------------------------------------------------------------------*/ + + FOR( i = 0; i < n; i++ ) + { + if ( sub( lsf[i], lsf_min ) < 0 ) + { + lsf[i] = lsf_min; + move16(); + } + lsf_min = add( lsf[i], min_dist ); + } + + /*-----------------------------------------------------------------------* + * Reverify the LSF ordering and minimum GAP in the reverse order (security) + *-----------------------------------------------------------------------*/ + + lsf_max = round_fx( L_sub( L_shr( L_mult0( extract_l( L_shr( Fs, 1 ) ), 1311 ), 9 - 16 ), L_deposit_h( min_dist ) ) ); /* Q0 + Q9 , 1311 is 2.56 in Q9 */ + + n_m_1 = sub( n, 1 ); + IF( sub( lsf[n_m_1], lsf_max ) > 0 ) /* If danger of unstable filter in case of resonance in HF */ + { + FOR( i = n_m_1; i >= 0; i-- ) /* Reverify the minimum LSF gap in the reverse direction */ + { + if ( sub( lsf[i], lsf_max ) > 0 ) + { + lsf[i] = lsf_max; + move16(); + } + lsf_max = sub( lsf[i], min_dist ); + } + } + + return; +} + + +/* + * 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 * + *-----------------------------------------------------------* + */ +static 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; +#ifdef BASOP_NOGLOB + Flag Overflow; +#endif /* BASOP_NOGLOB */ + + + 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( 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( f[j - 1], b ), 1 ) ) ); + } + move32(); + f[1] = L_add( f[1], b32 ); + } + + + test(); + IF( Overflow > 0 && isMODE1 ) + { +#ifdef BASOP_NOGLOB + assert( 0 ); +#endif /* BASOP_NOGLOB */ + /* 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; +} + +#undef WMC_TOOL_SKIP diff --git a/lib_com/basop_mpy.c b/lib_com/basop_mpy.c new file mode 100644 index 000000000..17c5347d0 --- /dev/null +++ b/lib_com/basop_mpy.c @@ -0,0 +1,92 @@ +/****************************************************************************************************** + + (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "basop_mpy.h" +#include +#include "options.h" +#ifdef DEBUGGING +#include "debug.h" +#endif + +#define WMC_TOOL_SKIP + +Word32 Mpy_32_16_1( Word32 x, Word16 y ) +{ + Word32 mh; + UWord16 ml; + + Mpy_32_16_ss( x, y, &mh, &ml ); + + return ( mh ); +} + +Word32 Mpy_32_16( Word32 x, Word16 y ) +{ + Word32 mh; + UWord16 ml; + + Mpy_32_16_ss( x, y, &mh, &ml ); + + return ( mh ); +} + +Word32 Mpy_32_16_r( Word32 x, Word16 y ) +{ + Word32 mh; + UWord16 ml; + + Mpy_32_16_ss( x, y, &mh, &ml ); + + if ( s_and( ml, -32768 /* 0x8000 */ ) ) + { + mh = L_add( mh, 1 ); + } + + return ( mh ); +} + + +Word32 Mpy_32_32( Word32 x, Word32 y ) +{ + Word32 mh; + UWord32 ml; + + Mpy_32_32_ss( x, y, &mh, &ml ); + + return ( mh ); +} + +#undef WMC_TOOL_SKIP diff --git a/lib_com/basop_mpy.h b/lib_com/basop_mpy.h new file mode 100644 index 000000000..726bf7ed3 --- /dev/null +++ b/lib_com/basop_mpy.h @@ -0,0 +1,100 @@ +/****************************************************************************************************** + + (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#ifndef __BASOP_MPY_H +#define __BASOP_MPY_H + +#include "stl.h" +#include +#include "options.h" +#ifdef DEBUGGING +#include "debug.h" +#endif + +/** + * \brief 32*16 Bit fractional Multiplication using 40 bit OPS + * Performs a multiplication of a 32-bit variable x by + * a 16-bit variable y, returning a 32-bit value. + * + * \param[i] x + * \param[i] y + * + * \return x*y + */ +Word32 Mpy_32_16_1( Word32 x, Word16 y ); + + +/** + * \brief 32*16 Bit fractional Multiplication using 40 bit OPS + * Performs a multiplication of a 32-bit variable x by + * a 16-bit variable y, returning a 32-bit value. + * + * \param[i] x + * \param[i] y + * + * \return x*y + */ +Word32 Mpy_32_16( Word32 x, Word16 y ); + + +/** + * \brief 32*16 Bit fractional Multiplication using 40 bit OPS + * Performs a multiplication of a 32-bit variable x by + * a 16-bit variable y including rounding, returning a 32-bit value. + * + * \param[i] x + * \param[i] y + * + * \return x*y + */ +Word32 Mpy_32_16_r( Word32 x, Word16 y ); + + +/** + * \brief 32*32 Bit fractional Multiplication using 40 bit OPS + * + * Performs a multiplication of a 32-bit variable x by + * a 32-bit variable y, returning a 32-bit value. + * + * \param[i] x + * \param[i] y + * + * \return x*y + */ + +Word32 Mpy_32_32( Word32 x, Word32 y ); + +#endif /* __BASOP_SETTINGS_H */ diff --git a/lib_com/basop_proto_func.h b/lib_com/basop_proto_func.h new file mode 100644 index 000000000..d8b9768a1 --- /dev/null +++ b/lib_com/basop_proto_func.h @@ -0,0 +1,70 @@ +/****************************************************************************************************** + + (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#ifndef BASOP_PROTO_FUNC_H +#define BASOP_PROTO_FUNC_H + +#include +#include "options.h" +#include "stl.h" +#include "basop_util.h" + + +/* tcx_lpc_cdk.h */ +#define LSF_GAP_VAL( x ) ( Word16 )( (x) *2.0f * 1.28f ) +#define LSFM( x ) FL2WORD16_SCALE( x * 1.28, 15 - 1 ) /* 14Q1*1.28 */ + +/* cnst.h */ +#define GAMMA1_INV 17809 /* weighting factor (numerator) default:0.92 (1Q14format) */ +#define GAMMA16k_INV 17430 /* weighting factor (numerator) default:0.94 (1Q14format) */ +#define INT_FS_FX 12800 /* internal sampling frequency */ + +void basop_lsp2a_stab( const Word16 *lsp, Word16 *a ); +void basop_lsf2lsp( const Word16 lsf[], Word16 lsp[] ); +void basop_weight_a( const Word16 *a, Word16 *ap, const Word16 gamma ); +void basop_weight_a_inv( const Word16 *a, Word16 *ap, const Word16 inv_gamma ); +void basop_E_LPC_a_add_tilt( const Word16 *a, Word16 *ap, Word16 gamma ); +void basop_reorder_lsf( Word16 *lsf, const Word16 min_dist, const Word16 n, const Word32 Fs ); +void basop_E_LPC_f_lsp_a_conversion( const Word16 *lsp, Word16 *a, const Word16 m ); + +/* tcx_utils.c */ +void basop_lpc2mdct( Word16 *lpcCoeffs, Word16 lpcOrder, Word16 *mdct_gains, Word16 *mdct_gains_exp, Word16 *mdct_inv_gains, Word16 *mdct_inv_gains_exp ); + +void basop_PsychAdaptLowFreqDeemph( Word32 x[], const Word16 lpcGains[], const Word16 lpcGains_e[], Word16 lf_deemph_factors[] ); +void basop_mdct_noiseShaping_interp( Word32 x[], Word16 lg, Word16 gains[], Word16 gains_exp[] ); + + +#endif diff --git a/lib_com/basop_settings.h b/lib_com/basop_settings.h new file mode 100644 index 000000000..59d871029 --- /dev/null +++ b/lib_com/basop_settings.h @@ -0,0 +1,110 @@ +/****************************************************************************************************** + + (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#ifndef __BASOP_SETTINGS_H +#define __BASOP_SETTINGS_H + +#include +#include "options.h" +#include "stl.h" +#include "basop_mpy.h" + +#define WORD32_BITS 32 +#define MAXVAL_WORD32 ( (int32_t) 0x7FFFFFFF ) +#define MINVAL_WORD32 ( (int32_t) 0x80000000 ) +#define WORD32_FIX_SCALE ( (int64_t) ( 1 ) << ( WORD32_BITS - 1 ) ) + +#define WORD16_BITS 16 +#define MAXVAL_WORD16 ( ( (int32_t) 0x7FFFFFFF ) >> 16 ) +#define MINVAL_WORD16 ( ( (int32_t) 0x80000000 ) >> 16 ) +#define WORD16_FIX_SCALE ( (int64_t) ( 1 ) << ( WORD16_BITS - 1 ) ) + +#ifdef _MSC_VER +#pragma warning( disable : 4310 ) +#endif + +/*! + \def Macro converts a float < 1 to Word32 fixed point with saturation and rounding +*/ +#define FL2WORD32( val ) \ + ( Word32 )( ( ( val ) >= 0 ) ? ( ( ( (double) ( val ) * ( WORD32_FIX_SCALE ) + 0.5 ) >= (double) ( MAXVAL_WORD32 ) ) ? (int32_t) ( MAXVAL_WORD32 ) : (int32_t) ( (double) ( val ) * (double) ( WORD32_FIX_SCALE ) + 0.5 ) ) : ( ( ( (double) ( val ) * (WORD32_FIX_SCALE) -0.5 ) <= (double) ( MINVAL_WORD32 ) ) ? (int32_t) ( MINVAL_WORD32 ) : (int32_t) ( (double) ( val ) * (double) (WORD32_FIX_SCALE) -0.5 ) ) ) + +/*! + \def Macro converts a float < 1 to Word16 fixed point with saturation and rounding +*/ +#define FL2WORD16( val ) \ + ( Word16 )( ( ( val ) >= 0 ) ? ( ( ( (double) ( val ) * ( WORD16_FIX_SCALE ) + 0.5 ) >= (double) ( MAXVAL_WORD16 ) ) ? (int32_t) ( MAXVAL_WORD16 ) : (int32_t) ( (double) ( val ) * (double) ( WORD16_FIX_SCALE ) + 0.5 ) ) : ( ( ( (double) ( val ) * (WORD16_FIX_SCALE) -0.5 ) <= (double) ( MINVAL_WORD16 ) ) ? (int32_t) ( MINVAL_WORD16 ) : (int32_t) ( (double) ( val ) * (double) (WORD16_FIX_SCALE) -0.5 ) ) ) + +/*! + \def Macro converts a Word32 fixed point to Word16 fixed point <1 with saturation +*/ +#define WORD322WORD16( val ) \ + ( ( ( ( ( ( val ) >> ( WORD32_BITS - WORD16_BITS - 1 ) ) + 1 ) > ( ( (int32_t) 1 << WORD16_BITS ) - 1 ) ) && ( (int32_t) ( val ) > 0 ) ) ? (Word16) (int16_t) ( ( (int32_t) 1 << ( WORD16_BITS - 1 ) ) - 1 ) : (Word16) (int16_t) ( ( ( ( val ) >> ( WORD32_BITS - WORD16_BITS - 1 ) ) + 1 ) >> 1 ) ) + +/*! + \def Macro converts a Word32 fixed point < 1 to float shifts result left by scale +*/ +#define WORD322FL_SCALE( x, scale ) ( ( (float) ( (int32_t) ( x ) ) ) / ( (int64_t) 1 << ( WORD32_BITS - 1 - ( scale ) ) ) ) + +/*! + \def Macro converts a float < 1 to Word32 fixed point with saturation and rounding, shifts result right by scale +*/ +/* Note: Both x and scale must be constants at compile time, scale must be in range -31..31 */ +#define FL2WORD32_SCALE( x, scale ) FL2WORD32( (double) ( x ) * ( (int64_t) 1 << ( WORD32_BITS - 1 - ( scale ) ) ) / ( (int64_t) 1 << ( WORD32_BITS - 1 ) ) ) + +/*! + \def Macro converts a Word16 fixed point < 1 to float shifts result left by scale +*/ +#define WORD162FL_SCALE( x, scale ) ( ( (float) ( (int32_t) ( x ) ) ) / ( (int64_t) 1 << ( WORD16_BITS - 1 - ( scale ) ) ) ) + +/*! + \def Macro converts a float < 1 to Word16 fixed point with saturation and rounding, shifts result right by scale +*/ +/* Note: At compile time, x must be a float constant and scale must be an integer constant in range -15..15 */ +#define FL2WORD16_SCALE( x, scale ) FL2WORD16( (float) ( x ) * ( (int64_t) 1 << ( WORD16_BITS - 1 - ( scale ) ) ) / ( (int64_t) 1 << ( WORD16_BITS - 1 ) ) ) + + +/* Word16 Packed Type */ +typedef struct +{ + struct + { + Word16 re; + Word16 im; + } v; +} PWord16; + +#endif /* __BASOP_SETTINGS_H */ diff --git a/lib_com/basop_tcx_utils.c b/lib_com/basop_tcx_utils.c new file mode 100644 index 000000000..660f4ece5 --- /dev/null +++ b/lib_com/basop_tcx_utils.c @@ -0,0 +1,441 @@ +/****************************************************************************************************** + + (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include +#include "options.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "cnst.h" +#include "basop_proto_func.h" +#include "stl.h" +#include "prot.h" +#include "rom_com.h" + +#define WMC_TOOL_SKIP + +/* compare two positive normalized 16 bit mantissa/exponent values */ +/* return value: positive if first value greater, negative if second value greater, zero if equal */ +static 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; +} + +void basop_lpc2mdct( Word16 *lpcCoeffs, Word16 lpcOrder, Word16 *mdct_gains, Word16 *mdct_gains_exp, Word16 *mdct_inv_gains, Word16 *mdct_inv_gains_exp ) +{ + Word32 RealData[FDNS_NPTS]; + Word32 ImagData[FDNS_NPTS]; + Word16 i, j, k, step, scale, s, tmp16; + Word16 g, g_e, ig, ig_e; + Word32 tmp32; + const PWord16 *ptwiddle; + + + /* short-cut, to avoid calling of BASOP_getTables() */ + ptwiddle = SineTable512_fx; + step = 8; + + /*ODFT*/ + assert( lpcOrder < FDNS_NPTS ); + + /* pre-twiddle */ + FOR( i = 0; i <= lpcOrder; i++ ) + { + RealData[i] = L_mult( lpcCoeffs[i], ptwiddle->v.re ); + move32(); + ImagData[i] = L_negate( L_mult( lpcCoeffs[i], ptwiddle->v.im ) ); + move32(); + ptwiddle += step; + } + + /* zero padding */ + FOR( ; i < FDNS_NPTS; i++ ) + { + RealData[i] = 0; + move32(); + ImagData[i] = 0; + move32(); + } + + /* half length FFT */ + scale = add( norm_s( lpcCoeffs[0] ), 1 ); + move16(); + BASOP_cfft( RealData, ImagData, 1, &scale ); /* sizeOfFft == FDNS_NPTS == 8 */ + + + /*Get amplitude*/ + j = FDNS_NPTS - 1; + k = 0; + move16(); + + FOR( i = 0; i < FDNS_NPTS / 2; i++ ) + { + s = sub( norm_l( L_max( L_abs( RealData[i] ), L_abs( ImagData[i] ) ) ), 1 ); + + tmp16 = extract_h( L_shl( RealData[i], s ) ); + tmp32 = L_mult( tmp16, tmp16 ); + + tmp16 = extract_h( L_shl( ImagData[i], s ) ); + tmp16 = mac_r( tmp32, tmp16, tmp16 ); + + s = shl( sub( scale, s ), 1 ); + + if ( tmp16 == 0 ) + { + s = -16; + move16(); + } + if ( tmp16 == 0 ) + { + tmp16 = 1; + move16(); + } + + BASOP_Util_Sqrt_InvSqrt_MantExp( tmp16, s, &g, &g_e, &ig, &ig_e ); + + if ( mdct_gains != NULL ) + { + mdct_gains[k] = g; + move16(); + } + + if ( mdct_gains_exp != NULL ) + { + mdct_gains_exp[k] = g_e; + move16(); + } + + if ( mdct_inv_gains != NULL ) + { + mdct_inv_gains[k] = ig; + move16(); + } + + if ( mdct_inv_gains_exp != NULL ) + { + mdct_inv_gains_exp[k] = ig_e; + move16(); + } + + k = add( k, 1 ); + + + s = sub( norm_l( L_max( L_abs( RealData[j] ), L_abs( ImagData[j] ) ) ), 1 ); + + tmp16 = extract_h( L_shl( RealData[j], s ) ); + tmp32 = L_mult( tmp16, tmp16 ); + + tmp16 = extract_h( L_shl( ImagData[j], s ) ); + tmp16 = mac_r( tmp32, tmp16, tmp16 ); + + s = shl( sub( scale, s ), 1 ); + + if ( tmp16 == 0 ) + { + s = -16; + move16(); + } + if ( tmp16 == 0 ) + { + tmp16 = 1; + move16(); + } + + BASOP_Util_Sqrt_InvSqrt_MantExp( tmp16, s, &g, &g_e, &ig, &ig_e ); + + if ( mdct_gains != NULL ) + { + mdct_gains[k] = g; + move16(); + } + + if ( mdct_gains_exp != NULL ) + { + mdct_gains_exp[k] = g_e; + move16(); + } + + if ( mdct_inv_gains != NULL ) + { + mdct_inv_gains[k] = ig; + move16(); + } + + if ( mdct_inv_gains_exp != NULL ) + { + mdct_inv_gains_exp[k] = ig_e; + move16(); + } + + j = sub( j, 1 ); + k = add( k, 1 ); + } +} + + +void basop_mdct_noiseShaping_interp( Word32 x[], Word16 lg, Word16 gains[], Word16 gains_exp[] ) +{ + Word16 i, j, jp, jn, k, l; + Word16 g, pg, ng, e, tmp; + + + assert( lg % FDNS_NPTS == 0 ); + k = shr( lg, 6 ); /* FDNS_NPTS = 64 */ + + IF( gains != NULL ) + { + /* Linear interpolation */ + IF( sub( k, 4 ) == 0 ) + { + jp = 0; + move16(); + j = 0; + move16(); + jn = 1; + move16(); + + FOR( i = 0; i < lg; i += 4 ) + { + 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, FL2WORD16( 0.375f ) ), g, FL2WORD16( 0.625f ) ); + x[i] = L_shl( Mpy_32_16( x[i], tmp ), e ); + move32(); + + tmp = mac_r( L_mult( pg, FL2WORD16( 0.125f ) ), g, FL2WORD16( 0.875f ) ); + x[i + 1] = L_shl( Mpy_32_16( 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, FL2WORD16( 0.875f ) ), ng, FL2WORD16( 0.125f ) ); + x[i + 2] = L_shl( Mpy_32_16( x[i + 2], tmp ), e ); + move32(); + + tmp = mac_r( L_mult( g, FL2WORD16( 0.625f ) ), ng, FL2WORD16( 0.375f ) ); + x[i + 3] = L_shl( Mpy_32_16( x[i + 3], tmp ), e ); + move32(); + + jp = j; + move16(); + j = jn; + move16(); + jn = s_min( add( jn, 1 ), FDNS_NPTS - 1 ); + } + } + ELSE IF( sub( k, 5 ) == 0 ) + { + 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, FL2WORD16( 0.40f ) ), g, FL2WORD16( 0.60f ) ); + x[i] = L_shl( Mpy_32_16( x[i], tmp ), e ); + move32(); + + tmp = mac_r( L_mult( pg, FL2WORD16( 0.20f ) ), g, FL2WORD16( 0.80f ) ); + x[i + 1] = L_shl( Mpy_32_16( x[i + 1], tmp ), e ); + move32(); + + + x[i + 2] = L_shl( Mpy_32_16( 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, FL2WORD16( 0.80f ) ), ng, FL2WORD16( 0.20f ) ); + x[i + 3] = L_shl( Mpy_32_16( x[i + 3], tmp ), e ); + move32(); + + tmp = mac_r( L_mult( g, FL2WORD16( 0.60f ) ), ng, FL2WORD16( 0.40f ) ); + x[i + 4] = L_shl( Mpy_32_16( 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( *x, *gains ), *gains_exp ); + move32(); + x++; + } + + gains++; + gains_exp++; + } + } + } +} + + +void basop_PsychAdaptLowFreqDeemph( Word32 x[], const Word16 lpcGains[], const Word16 lpcGains_e[], Word16 lf_deemph_factors[] ) +{ + Word16 i; + Word16 max_val, max_e, fac, min_val, min_e, tmp, tmp_e; + Word32 L_tmp; + + + assert( lpcGains[0] >= 0x4000 ); + + max_val = lpcGains[0]; + move16(); + max_e = lpcGains_e[0]; + move16(); + min_val = 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_val, min_e ) < 0 ) + { + min_val = lpcGains[i]; + move16(); + min_e = lpcGains_e[i]; + move16(); + } + + IF( compMantExp16Unorm( lpcGains[i], lpcGains_e[i], max_val, max_e ) > 0 ) + { + max_val = lpcGains[i]; + move16(); + max_e = lpcGains_e[i]; + move16(); + } + } + + min_e = add( min_e, 5 ); /* min *= 32.0f; */ + + test(); + IF( ( compMantExp16Unorm( max_val, max_e, min_val, min_e ) < 0 ) && ( min_val > 0 ) ) + { + /* fac = tmp = (float)pow(max / min, 0.0078125f); */ + tmp_e = min_e; + move16(); + tmp = Inv16( min_val, &tmp_e ); + L_tmp = L_shl( L_mult( tmp, max_val ), 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( 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 ); + } + } +} + +#undef WMC_TOOL_SKIP diff --git a/lib_com/basop_util.c b/lib_com/basop_util.c new file mode 100644 index 000000000..d73334902 --- /dev/null +++ b/lib_com/basop_util.c @@ -0,0 +1,1112 @@ +/****************************************************************************************************** + + (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include +#include "options.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "basop_util.h" +#include "rom_com.h" +#include "basop_settings.h" +#include "basop_mpy.h" +#include "stl.h" +#include "cnst.h" + +#define WMC_TOOL_SKIP + +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 < FL2WORD32( -31.0 / 64.0 ) ) + { + return 0; + } + test(); + if ( ( L_sub( x, FL2WORD32( 31.0 / 64.0 ) ) >= 0 ) || ( 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( 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 ); +} + + +/* local function for Sqrt16 */ +static Word16 Sqrt16_common( + Word16 m, + Word16 e ) +{ + Word16 index, frac; +#ifdef BASOP_NOGLOB + Flag Overflow; +#endif /* BASOP_NOGLOB */ + + 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; +#ifndef BASOP_NOGLOB + m = mac_r( SqrtTable[index], SqrtDiffTable[index], frac ); +#else /* BASOP_NOGLOB */ + m = mac_ro( SqrtTable[index], SqrtDiffTable[index], frac, &Overflow ); +#endif /* BASOP_NOGLOB */ + BASOP_SATURATE_WARNING_ON; + } + + /* handle odd exponents */ + if ( s_and( e, 1 ) != 0 ) + m = mult_r( 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 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 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 +*/ + +/*! r: measured headroom in range [0..31], 0 if all x[i] == 0 */ +Word16 getScaleFactor32( + 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 = L_add( 0, 0 ); + x_min = L_add( 0, 0 ); + 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 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 set_val_Word16( + Word16 X[], + const Word16 val, + Word16 n ) +{ + Word16 i; + + + FOR( i = 0; i < n; i++ ) + { + X[i] = val; + move16(); + } + + + return; +} + +void set_val_Word32( + Word32 X[], + const Word32 val, + Word16 n ) +{ + Word16 i; + + + FOR( i = 0; i < n; i++ ) + { + X[i] = val; + move32(); + } + + + return; +} + +Word16 mult0( + Word16 x, + Word16 y ) +{ + return extract_l( L_mult0( x, y ) ); +} + + +#define SINETAB SineTable512_fx +#define LD 9 + +/* + * Calculates coarse lookup values for sine/cosine and residual angle. + * \param x angle in radians with exponent = 2 or as radix 2 with exponent = 0. + * \param scale shall always be 2 + * \param sine pointer to where the sine lookup value is stored into + * \param cosine pointer to where the cosine lookup value is stored into + * \param flag_radix2 flag indicating radix 2 angle if non-zero. + */ +static Word16 fixp_sin_cos_residual_16( + Word16 x, + const Word16 scale, + Word16 *sine, + Word16 *cosine, + Word8 flag_radix2 ) +{ + Word16 residual; + Word16 s; + Word16 ssign; + Word16 csign; + Word16 tmp, cl = 0, sl = 0; + const Word16 shift = 15 - LD - 1 - scale; + + if ( flag_radix2 == 0 ) + { + x = mult_r( x, FL2WORD16( 1.0 / EVS_PI ) ); + } + s = shr( x, shift ); + + residual = s_and( x, ( 1 << shift ) - 1 ); + /* We assume "2+scale" is a constant */ + residual = shl( residual, 2 + scale ); + residual = mult_r( residual, FL2WORD16( EVS_PI / 4.0 ) ); + + /* Sine sign symmetry */ + ssign = s_and( s, ( 1 << LD ) << 1 ); + + /* Cosine sign symmetry */ + csign = s_and( add( s, ( 1 << LD ) ), ( 1 << LD ) << 1 ); + + /* Modulo EVS_PI */ + s = s_and( s, ( 2 << LD ) - 1 ); + + /* EVS_PI/2 symmetry */ + s = s_min( s, sub( 2 << LD, s ) ); + + { + tmp = s_min( sub( 1 << LD, s ), s ); + s = sub( tmp, s ); + + if ( !s ) + { + move16(); + sl = SINETAB[tmp].v.im; + } + if ( !s ) + { + move16(); + cl = SINETAB[tmp].v.re; + } + if ( s ) + { + move16(); + sl = SINETAB[tmp].v.re; + } + if ( s ) + { + move16(); + cl = SINETAB[tmp].v.im; + } + + if ( ssign ) + { + sl = negate( sl ); + } + if ( csign ) + { + cl = negate( cl ); + } + + move16(); + move16(); + *sine = sl; + *cosine = cl; + } + + return residual; +} + + +Word16 getCosWord16R2( + Word16 theta ) +{ + Word16 result, residual, sine, cosine; + + residual = fixp_sin_cos_residual_16( theta, 1, &sine, &cosine, 1 ); + /* This negation prevents the subsequent addition from overflow */ + /* The negation cannot overflow, sine is in range [0x0..0x7FFF] */ + BASOP_SATURATE_WARNING_OFF + sine = negate( sine ); + result = msu_r( L_mult( sine, residual ), cosine, -32768 ); + BASOP_SATURATE_WARNING_ON + + return result; +} + + +Word16 idiv1616U( + Word16 x, + Word16 y ) +{ + Word16 s; + Word16 tmp; + + /* make y > x */ + s = add( sub( norm_s( y ), norm_s( x ) ), 1 ); + s = s_max( s, 0 ); + + BASOP_SATURATE_WARNING_OFF + y = shl( y, s ); + BASOP_SATURATE_WARNING_ON + + /* divide and shift */ + tmp = div_s( x, y ); + y = shr( tmp, sub( 15, s ) ); + + return y; +} + +Word32 BASOP_util_Pow2( + const Word32 exp_m, + const Word16 exp_e, + Word16 *result_e ) +{ + static const Word16 pow2Coeff[8] = { + FL2WORD16( 0.693147180559945309417232121458177 ), /* ln(2)^1 /1! */ + FL2WORD16( 0.240226506959100712333551263163332 ), /* ln(2)^2 /2! */ + FL2WORD16( 0.0555041086648215799531422637686218 ), /* ln(2)^3 /3! */ + FL2WORD16( 0.00961812910762847716197907157365887 ), /* ln(2)^4 /4! */ + FL2WORD16( 0.00133335581464284434234122219879962 ), /* ln(2)^5 /5! */ + FL2WORD16( 1.54035303933816099544370973327423e-4 ), /* ln(2)^6 /6! */ + FL2WORD16( 1.52527338040598402800254390120096e-5 ), /* ln(2)^7 /7! */ + FL2WORD16( 1.32154867901443094884037582282884e-6 ) /* ln(2)^8 /8! */ + }; + + Word32 frac_part = 0, tmp_frac, result_m; + Word16 int_part = 0; + + 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, FL2WORD32( 0.5 ) ) ) >= 0 ) + { + int_part = add( int_part, 1 ); + frac_part = L_sub( tmp_frac, FL2WORD32( 0.5 ) ); + } + ELSE IF( ( tmp_frac = L_add( frac_part, FL2WORD32( 0.5 ) ) ) < 0 ) + { + int_part = sub( int_part, 1 ); + frac_part = L_add( tmp_frac, FL2WORD32( 0.5 ) ); + } + + /* 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( FL2WORD32( 1.0 / 2.0 ), L_shr( Mpy_32_16( 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( p, pow2Coeff[i] ), 1 ) ); + p = Mpy_32_32( p, frac_part ); + } + result_m = L_add( result_m, L_shr( Mpy_32_16( p, pow2Coeff[i] ), 1 ) ); + } + *result_e = int_part; + move16(); + + return result_m; +} + +/*! r: result of division x/y, not normalized */ +Word16 BASOP_Util_Divide3216_Scale( + 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 ) + { + *s = 0; + move16(); + + 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; +} + + +static 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] */ +static 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 +}; + +Word32 Pow2( /* o Q0 : result (range: 0<=val<=0x7fffffff) */ + Word16 exponant, /* i Q0 : Integer part. (range: 0<=val<=30) */ + Word16 fraction /* i Q15 : Fractional 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: Log2_norm() + * + * 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 + * + *************************************************************************/ + +static const Word32 L_table[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 +}; + +static const Word16 table_diff[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 +}; + +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; + + + 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[i], table_diff[i], a ); /* table[i] << 16 - diff*a*2 */ + + + return y; +} + + +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; +} + +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 = add( b_e, 0 ); + + if ( !b_m ) + b_e = add( a_e, 0 ); + + 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 = add( 0, 0 ); + if ( L_tmp != 0 ) + a_e = sub( a_e, shift ); + *ptr_e = a_e; + + return ( L_tmp ); +} + +static 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] */ +static 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 +}; + +static const Word16 shift[] = { 9, 10 }; + +Word32 Isqrt_lc1( + 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[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; +} + +static 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 +}; + +/*! r: output value, Q31 */ +Word32 Sqrt_l( + 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 ); + } + +#if 0 /* original version creates an overflow warning */ + e = s_and(norm_l(L_x), 0xFFFE); /* get next lower EVEN norm. exp */ +#else + e = s_and( norm_l( L_x ), 0x7FFE ); /* get next lower EVEN norm. exp */ +#endif + 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 ); +} + +#undef WMC_TOOL_SKIP diff --git a/lib_com/basop_util.h b/lib_com/basop_util.h new file mode 100644 index 000000000..0a20e526f --- /dev/null +++ b/lib_com/basop_util.h @@ -0,0 +1,418 @@ +/****************************************************************************************************** + + (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#ifndef __BASOP_UTIL_H__ +#define __BASOP_UTIL_H__ + +#include +#include "options.h" +#include "basop_settings.h" +#include "typedef.h" +#include "basop32.h" +#include "basop_mpy.h" + + +#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 ) ) + +#ifndef CHEAP_NORM_SIZE +#define CHEAP_NORM_SIZE 161 +#endif + +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 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 */ +); + +/*****************************************************************************/ +/*! + \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 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 +*/ + +/*! r: measured headroom in range [0..31], 0 if all x[i] == 0 */ +Word16 getScaleFactor32( + const Word32 *x, /* i : array containing 32-bit data */ + const Word16 len_x ); /* i : length of the array to scan */ + +/************************************************************************/ +/*! + \brief Binary logarithm with 7 iterations + + \param x + + \return log2(x)/64 + */ +/************************************************************************/ +Word32 BASOP_Util_Log2( Word32 x ); + + +/****************************************************************************/ +/*! + \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 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 Binary logarithm with 5 iterations + * + * \param[i] val + * + * \return basop_log2(val)/128 + */ +/************************************************************************/ +Word32 BASOP_Util_log2_i5( Word32 val ); + +/************************************************************************/ +/*! + \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 ); + + +/****************************************************************************/ +/*! + \brief Sets Array Word16 arg1 to value Word16 arg2 for Word16 arg3 elements +*/ +void set_val_Word16( Word16 X[], /*!< Address of array */ + const Word16 val, /*!< Value to copy into array */ + Word16 n ); /*!< Number of elements to process */ + + +/****************************************************************************/ +/*! + \brief Sets Array Word32 arg1 to value Word32 arg2 for Word16 arg3 elements +*/ +void set_val_Word32( Word32 X[], /*!< Address of array */ + const Word32 val, /*!< Value to copy into array */ + Word16 n ); /*!< Number of elements to process */ + +/****************************************************************************/ +/*! + \brief Does a multiplication of Word16 input values + + \return z16 = x16 * y16 +*/ +Word16 mult0( Word16 x, /* i : Multiplier */ + Word16 y ); /* i : Multiplicand */ + +/** + * \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 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 return 2 ^ (exp * 2^exp_e) + * \param exp_m mantissa of the exponent to 2.0f + * \param exp_e exponent of the exponent to 2.0f + * \param result_e pointer to a INT where the exponent of the result will be stored into + * \return mantissa of the result + */ +Word32 BASOP_util_Pow2( + const Word32 exp_m, + const Word16 exp_e, + Word16 *result_e ); + + +Word32 Isqrt_lc1( + Word32 frac, /* i : Q31: normalized value (1.0 < frac <= 0.5) */ + Word16 *exp /* i/o: exponent (value = frac x 2^exponent) */ +); + +/*****************************************************************************/ +/*! + + \brief Calculates pow(2,x) + ___________________________________________________________________________ + | | + | Function Name : Pow2() | + | | + | L_x = pow(2.0, exponant.fraction) (exponent = interger part) | + | = pow(2.0, 0.fraction) << exponent | + |---------------------------------------------------------------------------| + | 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) */ +); + +/************************************************************************* + * + * FUNCTION: Log2_norm() + * + * 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) */ +); + +/************************************************************************* + * + * FUNCTION: BASOP_Util_fPow() + */ +/** + * \brief BASOP_Util_fPow + * + * PURPOSE: Computes pow(base_m, base_e, exp_m, exp_e), where base_m and base_e + * specify the base, and exp_m and exp_e specify the exponent. + * The result is returned in a mantissa and exponent representation. + * + * DESCRIPTION: + * The function BASOP_Util_fPow(L_x) calculates the power function by + * calculating 2 ^ (log2(base)*exp) + * + * \param base_m mantissa of base + * \param base_e exponent of base + * \param exp_m mantissa of exponent + * \param exp_e exponent of exponent + * \param result_e pointer to exponent of result + * \return Word32 mantissa of result + * + *************************************************************************/ + +Word32 BASOP_Util_fPow( /* o : mantissa of result */ + Word32 base_m, + Word16 base_e, /* i : input value for base (mantissa and exponent) */ + Word32 exp_m, + Word16 exp_e, /* i : input value for exponent (mantissa and exponent) */ + Word16 *result_e /* o : output pointer to exponent of result */ +); + +/*!********************************************************************** + \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 Accumulates multiplications + + Accumulates the elementwise multiplications of Word32 Array X with Word16 Array Y + pointed to by arg1 and arg2 with specified headroom. Length of to be multiplied arrays is arg3, + headroom with has to be taken into account is specified in arg4 + + \return Word32 result of accumulated multiplications over Word32 array arg1 and Word16 array arg2 and Word16 pointer + to exponent correction factor which needs to be added to the exponent of the result vector +*/ +Word32 dotWord32_16_guards( const Word32 *X, const Word16 *Y, Word16 n, Word16 hr, Word16 *shift ); + +Word32 Sqrt_l( Word32 L_x, Word16 *exp ); + +#endif /* __BASOP_UTIL_H__ */ diff --git a/lib_com/bitalloc.c b/lib_com/bitalloc.c new file mode 100644 index 000000000..91a9782ec --- /dev/null +++ b/lib_com/bitalloc.c @@ -0,0 +1,977 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" +#include "basop_util.h" +#include "basop_proto_func.h" + + +/*-------------------------------------------------------------------------- + * bitalloc() + * + * Adaptive bit allocation for 20kHz audio codec + *--------------------------------------------------------------------------*/ + +void bitalloc ( + short *y, /* i : reordered norm of sub-vectors */ + short *idx, /* i : reordered sub-vector indices */ + short sum, /* i : number of available bits */ + short N, /* i : number of norms */ + short K, /* i : maximum number of bits per dimension */ + short *r, /* o : bit-allacation vector */ + const short *sfmsize, /* i : band length */ + const short hqswb_clas /* i : signal classification flag */ +) +{ + short i, j, k, n, m, v, im; + short diff, temp; + short fac; + short ii; + short SFM_thr = SFM_G1G2; + + N -= 1; + + if ( hqswb_clas == HQ_HARMONIC ) + { + SFM_thr = 22; + } + + fac = 3; + K -= 2; + im = 1; + diff = sum; + n = sum >> 3; + for ( i=0; i= sfmsize[j] && r[j] < K ) + { + y[k] -= fac; + r[j]++; + if ( r[j] >= K ) + { + y[k] = MIN16B; + } + sum -= sfmsize[j]; + } + else + { + y[k] = MIN16B; + k++; + if ( k == im && im < N ) + { + im++; + } + } + + if ( sum < WID_G1 || diff == sum ) + { + break; + } + + diff = sum; + v = N - 1; + + if (k > v) + { + for ( ii=0; ii<=N; ii++ ) + { + if ( y[ii] > MIN16B ) + { + if( ii < N ) + { + im = ii + 1; + } + + break; + } + } + } + } + + if ( sum >= WID_G2) + { + for (i=0; i<=N; i++) + { + j = idx[i]; + if ( j >= SFM_G1 && j < SFM_thr && r[j] == 0 ) + { + r[j] = 1; + sum -= WID_G2; + if ( sum < WID_G2 ) + { + break; + } + } + } + } + + if ( sum >= WID_G2 ) + { + for (i=0; i<=N; i++) + { + j = idx[i]; + if ( j >= SFM_G1 && j < SFM_thr && r[j] == 1 ) + { + r[j] = 2; + sum -= WID_G2; + if ( sum < WID_G2 ) + { + break; + } + } + } + } + + if ( sum >= WID_G1 ) + { + for (i=0; i<=N; i++) + { + j = idx[i]; + if ( j < SFM_G1 && r[j] == 0 ) + { + r[j] = 1; + sum -= WID_G1; + if ( sum < WID_G1 ) + { + break; + } + } + } + } + + if ( sum >= WID_G1 ) + { + for (i=0; i<=N; i++) + { + j = idx[i]; + if ( j < SFM_G1 && r[j] == 1 ) + { + r[j] = 2; + sum -= WID_G1; + if ( sum < WID_G1 ) + { + break; + } + } + } + } + + return; +} + +#define WMC_TOOL_SKIP + +/*-------------------------------------------------------------------* + * BitAllocF() + * + * Fractional bit allocation + *-------------------------------------------------------------------*/ + +short BitAllocF ( + short *y, /* i : norm of sub-vectors */ + long bit_rate, /* i : bitrate */ + short B, /* i : number of available bits */ + short N, /* i : number of sub-vectors */ + short *R, /* o : bit-allocation indicator */ + short *Rsubband, /* o : sub-band bit-allocation vector (Q3) */ + const short hqswb_clas, /* i : hq swb class */ + const short num_env_bands /* i : Number sub bands to be encoded for HQ_SWB_BWE */ +) +{ + Word16 fac; + Word16 i, n, Nmin, Bits, bs, low_rate = 0; + + Word16 m_fx; + Word32 t_fx, B_fx; + Word32 L_tmp1, L_tmp2; + Word16 tmp, exp1, exp2; + Word32 Rsubband_w32_fx[NB_SFM]; /* Q15 */ + Word16 B_w16_fx; + + set_i( Rsubband_w32_fx, 0, NB_SFM); + + fac = 3; + if (L_sub(bit_rate, 32000) < 0) + { + bs = 2; + } + else + { + bs = 3; + } + low_rate = 1; + + Nmin = N; + if ( sub(Nmin,SFM_N) > 0) + { + Nmin = SFM_N; + } + + /* Initial bits distribution */ + if (sub(hqswb_clas , HQ_GEN_SWB) == 0 || sub(hqswb_clas , HQ_GEN_FB) == 0) + { + /* Initial bits distribution */ + L_tmp1 = 0; + m_fx = 0; + for ( i = 0; i < num_env_bands ; i++) + { + L_tmp1 = L_mac0(L_tmp1, Nb[i], y[i]); + } + L_tmp1 = L_msu0(L_tmp1, fac, B); + + t_fx = 0; + n = 0; + tmp = add(band_end_HQ[num_env_bands-1], shl(band_end_HQ[num_env_bands-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[num_env_bands-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]); + Rsubband_w32_fx[i] = Mpy_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] = 0; + move32(); + } + } + } + else + { + /* Initial bits distribution */ + L_tmp1 = 0; + m_fx = 0; + 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 = 0; + n = 0; + 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]); + Rsubband_w32_fx[i] = Mpy_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] = 0; + move32(); + } + } + } + + /* Distribute the remaining bits to subbands with non-zero bits */ + B_fx = L_shl(B, 15); + WHILE (L_sub(L_shr(L_add(t_fx, 16384), 15) , B) != 0) + { + 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 = 0; + n = 0; + 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] = 0; + move32(); + } + } + } + } + Bits = B; + + /* Impose bit-constraints to subbands with less than minimum bits*/ + t_fx = 0; + n = 0; + for ( i = 0; i < N; i++) + { + if (Rsubband_w32_fx[i] > 0) + { + test(); + test(); + if ((L_sub(Rsubband_w32_fx[i] , L_shl(add(bs, LNb[i]), 15)) <0) && (sub(low_rate,1) == 0)) + { + Rsubband_w32_fx[i] = 0; + move32(); + } + else if ( L_sub(Rsubband_w32_fx[i] , L_shl(Nb[i], 15)) <=0) + { + 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 (L_sub(L_shr(L_add(t_fx, 16384), 15) ,B) != 0) + { + 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 = 0; + n = 0; + for( i = 0; i < N; i++) + { + if (L_sub(Rsubband_w32_fx[i] , L_shl(Nb[i], 15)) > 0) + { + Rsubband_w32_fx[i] = L_msu(Rsubband_w32_fx[i], m_fx, Nb[i]); + if (L_sub(Rsubband_w32_fx[i] ,L_shl(Nb[i], 15)) > 0) + { + 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] = 0; + move32(); + if ( B >= 0) + { + BREAK; + } + } + } + BREAK; + } + } + + /* fine redistribution of over-allocated or under-allocated bits */ + tmp = 0; + for ( i = 0; i < N; i++) + { + Rsubband[i] = extract_l(L_shr(Rsubband_w32_fx[i], 12)); + tmp = add(tmp, Rsubband[i]); + } + + B = Bits; + B_w16_fx = shl(B, 3); + if (sub(tmp ,B_w16_fx)>0) + { + tmp = sub(tmp, B_w16_fx); + for ( i = 0; i < N; i++) + { + if (sub(Rsubband[i], add(shl(Nb[i], 3), tmp)) >= 0) + { + Rsubband[i] = sub(Rsubband[i], tmp); + BREAK; + } + } + } + else + { + tmp = sub(tmp, B_w16_fx); + for ( i = 0; i < N; i++) + { + if (Rsubband[i] > 0) + { + Rsubband[i] = sub(Rsubband[i], tmp); + BREAK; + } + } + } + + /* Calculate total used bits and initialize R to be used for Noise Filling */ + tmp = 0; + for ( i = 0; i < N; i++) + { + tmp = add(tmp, Rsubband[i]); + R[i] = shr(Rsubband[i], 3); + } + + 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; + UWord32 lo; + + /* initialization for bit allocation in one group*/ + tmp = 6554; + move16(); /*Q15 1/5 */ + IF(sub(thr,5) == 0) + { + tmp = 6554; + move16(); /*Q15 1/5 */ + } + IF(sub(thr,6) == 0) + { + tmp = 5462; + move16();/*Q15 1/6 */ + } + IF(sub(thr,7) == 0) + { + 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(y_index, band_num, index); + /* norm vector modification */ + + factor_fx = div_s(1, band_num);/*Q15 */ + IF ( sub(thr,5) > 0 ) + { + 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 ( sub(shl(bit_band,7),tmp) >= 0 ) + { + 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] = 0; + move32();/*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); + Mpy_32_32_ss(Bits_avg_fx,L_tmp,&L_tmp,&lo); + + R_temp_fx[k] = L_shl(L_tmp,sub(exp,2)); + move32();/*Q21 */ + } + } + + L_tmp = L_shl(L_deposit_l(thr),21);/*Q21 */ + IF ( L_sub(R_temp_fx[i],L_tmp) < 0 ) + { + R_temp_fx[i] = 0; + move32(); + 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] = 0; + move32(); + } + + 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] = 0; + move32();/*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); + Mpy_32_32_ss(Bits_avg_fx,L_tmp,&L_tmp,&lo); + 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 (L_sub(R_temp_fx[k],L_tmp) < 0) + { + FOR(m = k; m < i; m++) + { + norm_sum = sub(norm_sum,y_index[m]); + R_temp_fx[m] = 0; + move32();/*Q21 */ + } + i = k; + BREAK; + } + ELSE + { + R_sum_fx = L_add(R_sum_fx,R_temp_fx[k]); + } + } + IF (L_sub(R_sum_fx,R_sum_org_fx) == 0) + { + 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 + *-------------------------------------------------------------------*/ + +short BitAllocWB ( + short *y, /* i : norm of sub-vectors */ + short B, /* i : number of available bits */ + short N, /* i : number of sub-vectors */ + short *R, /* o : bit-allocation indicator */ + short *Rsubband /* 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; + Word32 L_tmp,L_tmp1; + Word32 Rsubband_buf[NB_SFM]; + UWord16 lo; + + BANDS = N; + move16(); + IF( sub(BANDS,SFM_N) > 0) + { + 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; + FOR ( j = 0; j < SFM_G1; j++ ) + { + IF ( y[j] > 0 ) + { + Rsum_sub_fx[0] = add(Rsum_sub_fx[0],y[j]); + 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; + move32(); + FOR ( j = SFM_G1; j < SFM_G1G2; j++ ) + { + IF ( y[j] > 0 ) + { + Rsum_sub_fx[1] = add(Rsum_sub_fx[1],y[j]); + 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[2] = add(Rsum_sub_fx[2],y[j]); + 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 */ + + IF ( L_sub(R_diff_32_fx[0],393216) < 0 && L_sub(R_diff_32_fx[1],245760) < 0 ) + { + 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 */ + Mpy_32_16_ss(L_tmp1,tmp,&L_tmp,&lo); + B1 = extract_h(L_shl(L_tmp,add(exp,1)));/*Q0 */ + IF(L_sub(L_tmp1,L_mult(B1,Rsum_fx)) > 0 && L_sub(L_tmp1,L_mult(add(B1,1),Rsum_fx)) >= 0) + { + B1 = add(B1,1); + } + L_tmp1 = L_mult(B,Rsum_sub_fx[1]);/*Q1 */ + Mpy_32_16_ss(L_tmp1,tmp,&L_tmp,&lo); + B2 = extract_h(L_shl(L_tmp,add(exp,1)));/*Q0 */ + IF(L_sub(L_tmp1,L_mult(B2,Rsum_fx)) > 0 && L_sub(L_tmp1,L_mult(add(B2,1),Rsum_fx)) >= 0) + { + B2 = add(B2,1); + } + L_tmp1 = L_mult(B,Rsum_sub_fx[2]);/*Q1 */ + Mpy_32_16_ss(L_tmp1,tmp,&L_tmp,&lo); + B3 = extract_h(L_shl(L_tmp,add(exp,1)));/*Q0 */ + IF(L_sub(L_tmp1,L_mult(B3,Rsum_fx)) > 0 && L_sub(L_tmp1,L_mult(add(B3,1),Rsum_fx)) >= 0) + { + B3 = add(B3,1); + } + } + IF ( L_sub(Ravg_sub_32_fx[2],786432) > 0 ) + { + B_saved = 0; + move16(); + IF ( sub(B1,288) > 0 ) + { + B_saved = sub(B1,288); + B1 = 288; + move16(); + } + + IF ( sub(B2,256) > 0 ) + { + tmp = sub(B2,256); + B_saved = add(B_saved,tmp); + B2 = 256; + move16(); + } + + IF ( sub(B3,96) > 0 ) + { + tmp = sub(B3,96); + B_saved = add(B_saved,tmp); + B3 = 96; + move16(); + } + + IF ( B_saved > 0 ) + { + IF ( sub(B1,288) == 0 ) + { + 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 ( sub(B2,256) == 0 ) + { + 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 */ + Mpy_32_16_ss(L_tmp1,tmp,&L_tmp,&lo); + B1 = extract_h(L_shl(L_tmp,add(exp,1)));/*Q0 */ + IF(L_sub(L_tmp1,L_mult(B1,Rsum_fx)) > 0 && L_sub(L_tmp1,L_mult(add(B1,1),Rsum_fx)) >= 0) + { + B1 = add(B1,1); + } + Mpy_32_16_ss(1975684956,shl(B,5),&L_tmp1,&lo); + Mpy_32_16_ss(L_tmp1,shl(Rsum_sub_fx[1],7),&L_tmp1,&lo); + Mpy_32_16_ss(L_tmp1,tmp,&L_tmp,&lo); + B2 = extract_h(L_shl(L_tmp,sub(exp,11)));/*Q0 */ + IF(L_sub(L_tmp1,L_shl(L_mult(B2,Rsum_fx),12)) > 0 && L_sub(L_add(L_tmp1,2),L_shl(L_mult(add(B2,1),Rsum_fx),12)) >= 0) + { + B2 = add(B2,1); + } + tmp = sub(B,B1); + B3 = sub(tmp,B2); + } + } + } + + IF ( sub(Rsum_sub_fx[2],3) < 0 ) + { + 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[i] = extract_l(L_shr(Rsubband_buf[i], 18)); + move16(); + } + + /* Calcuate total used bits and initialize R to be used for Noise Filling */ + L_tmp = 0; + move32(); + 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; +} + +#undef WMC_TOOL_SKIP diff --git a/lib_com/bitallocsum.c b/lib_com/bitallocsum.c new file mode 100644 index 000000000..8ff41e2a2 --- /dev/null +++ b/lib_com/bitallocsum.c @@ -0,0 +1,61 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" + + +/*-------------------------------------------------------------------------- + * bitallocsum() + * + * Calculate the total number of bits allocated over frame + *--------------------------------------------------------------------------*/ + +void bitallocsum( + short *R, /* i : bit-allocation vector */ + const short nb_sfm, /* i : number of sub-vectors */ + short *sum, /* o : total number of bits allocated */ + short *Rsubband, /* o : rate per subband (Q3) */ + const short v, /* i : bit rate */ + const short length, /* i : length of spectrum (32 or 48 kHz samplerate) */ + const short *sfmsize /* i : band length */ +) +{ + short i; + short total, tmp; + short diff; + + total = 0; + for (i = 0; i < nb_sfm; i++) + { + tmp = R[i] * sfmsize[i]; + Rsubband[i] = tmp*8; + total += tmp; + } + *sum = total; + + if ( length <= L_FRAME32k ) + { + diff = v - *sum; + i = 0; + while ( diff > 0 ) + { + if ( R[i] > 0 ) + { + Rsubband[i] += 8; + diff -= 1; + *sum += 1; + } + i++; + if ( i >= nb_sfm ) + { + i = 0; + } + } + } + + return; +} diff --git a/lib_com/bits_alloc.c b/lib_com/bits_alloc.c new file mode 100644 index 000000000..f1dabff4f --- /dev/null +++ b/lib_com/bits_alloc.c @@ -0,0 +1,309 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include "options.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* +* Local function +*--------------------------------------------------------------------*/ + +static int BITS_ALLOC_adjust_acelp_fixed_cdk( int bits_frame, int *fixed_cdk_index, int nb_subfr ); + + +/*-------------------------------------------------------------------* +* BITS_ALLOC_init_config_acelp() +* +* initial configuration for Mode 2 ACELP +*--------------------------------------------------------------------*/ + +void BITS_ALLOC_init_config_acelp( + int bit_rate, + int narrowBand, + int nb_subfr, + ACELP_config *acelp_cfg /*o: configuration structure of ACELP*/ +) +{ + short rate_mode_index; + + if( bit_rate <= ACELP_9k60 ) + { + rate_mode_index=0; + } + else + { + rate_mode_index=1; + } + + acelp_cfg->mode_index=rate_mode_index; + + /*LPC: midLpc should be swithced off?*/ + acelp_cfg->midLpc_enable = 1; + + /*ACELP ICB config*/ + if( (rate_mode_index==0) || (narrowBand==1) ) + { + acelp_cfg->pre_emphasis = 1; + acelp_cfg->formant_enh = 1; + acelp_cfg->formant_enh_num = FORMANT_SHARPENING_G1; + acelp_cfg->formant_enh_den = FORMANT_SHARPENING_G2; + acelp_cfg->formant_tilt = 0; + acelp_cfg->voice_tilt = 0; + } + else + { + acelp_cfg->pre_emphasis = 0; + acelp_cfg->formant_enh = 1; + acelp_cfg->formant_enh_num = FORMANT_SHARPENING_G1; + acelp_cfg->formant_enh_den = FORMANT_SHARPENING_G2; + acelp_cfg->formant_tilt = 1; + acelp_cfg->voice_tilt = 1; + } + + /*Wide band @ 16kHz*/ + if ( nb_subfr == NB_SUBFR16k ) + { + acelp_cfg->pre_emphasis = 1; + acelp_cfg->formant_enh = 1; + acelp_cfg->formant_enh_num = FORMANT_SHARPENING_G1_16k; + acelp_cfg->formant_enh_den = FORMANT_SHARPENING_G2_16k; + acelp_cfg->formant_tilt = 0; + acelp_cfg->voice_tilt = 2; + } + + return; +} + +/*-------------------------------------------------------------------* +* BITS_ALLOC_config_acelp() +* +* configure all Mode 2 ACELP modes and allocate the bits +*--------------------------------------------------------------------*/ + +int BITS_ALLOC_config_acelp( + const int bits_frame, /* i : remaining bit budget for the frame */ + const short coder_type, /* i : acelp extended mode index */ + ACELP_config *acelp_cfg, /* i/o: configuration structure of ACELP */ + const short narrowBand, /* i : narrowband flag */ + const short nb_subfr /* i : number of subframes */ +) +{ + short mode_index; + short band_index; + short i; + short remaining_bits, bits; + + /*Sanity check*/ + + mode_index = acelp_cfg->mode_index; + band_index = (narrowBand==0); + bits = 0; + + if ( band_index==0 ) + { + if(coder_type == INACTIVE) + { + acelp_cfg->formant_enh = 0; + } + else + { + acelp_cfg->formant_enh = 1; + } + } + + if( band_index==1 && nb_subfr == NB_SUBFR ) + { + + if( coder_type == INACTIVE) + { + acelp_cfg->pre_emphasis = 0; + acelp_cfg->formant_enh = 0; + acelp_cfg->formant_enh_num = FORMANT_SHARPENING_G1_16k; + acelp_cfg->formant_tilt = 1; + acelp_cfg->voice_tilt = 1; + } + else + { + acelp_cfg->pre_emphasis = 1; + acelp_cfg->formant_enh = 1; + acelp_cfg->formant_enh_num = FORMANT_SHARPENING_G1; + acelp_cfg->formant_tilt = 0; + acelp_cfg->voice_tilt = 0; + } + } + + if( coder_type == UNVOICED ) + { + if( ACELP_GAINS_MODE[mode_index][band_index][coder_type]==6 ) + { + acelp_cfg->pitch_sharpening = 0; + acelp_cfg->phase_scrambling = 1; + } + else + { + acelp_cfg->pitch_sharpening = 0; + acelp_cfg->phase_scrambling = 0; + } + } + else + { + acelp_cfg->pitch_sharpening = 1; + acelp_cfg->phase_scrambling = 0; + } + + if( coder_type > ACELP_MODE_MAX ) + { + /* keep pitch sharpening for RF_ALLPRED mode */ + acelp_cfg->pitch_sharpening = 0; + acelp_cfg->phase_scrambling = 0; + } + + /*Allocate bits and different modes*/ + acelp_cfg->bpf_mode=ACELP_BPF_MODE[mode_index][band_index][coder_type]; + bits+=ACELP_BPF_BITS[acelp_cfg->bpf_mode]; + + acelp_cfg->nrg_mode=ACELP_NRG_MODE[mode_index][band_index][coder_type]; + acelp_cfg->nrg_bits=ACELP_NRG_BITS[acelp_cfg->nrg_mode]; + bits+=acelp_cfg->nrg_bits; + + acelp_cfg->ltp_mode=ACELP_LTP_MODE[mode_index][band_index][coder_type]; + acelp_cfg->ltp_bits=0; + acelp_cfg->ltf_mode=ACELP_LTF_MODE[mode_index][band_index][coder_type]; + acelp_cfg->ltf_bits=ACELP_LTF_BITS[acelp_cfg->ltf_mode]; + + if( nb_subfr == NB_SUBFR16k && acelp_cfg->ltf_bits == 4 ) + { + acelp_cfg->ltf_bits++; + } + bits+=acelp_cfg->ltf_bits; + + + for ( i=0; igains_mode[i] = ACELP_GAINS_MODE[mode_index][band_index][coder_type]; + + /* skip subframe 1, 3 gain encoding, and use from subframe 0, and 3, respectively */ + if(coder_type >= ACELP_MODE_MAX && (i == 1 || i == 3)) + { + acelp_cfg->gains_mode[i] = 0; + } + + bits += ACELP_GAINS_BITS[acelp_cfg->gains_mode[i]]; + bits += ACELP_LTP_BITS_SFR[acelp_cfg->ltp_mode][i]; + acelp_cfg->ltp_bits += ACELP_LTP_BITS_SFR[acelp_cfg->ltp_mode][i]; + } + + /*Innovation*/ + if( bits_frame < bits ) + { + printf("\nWarning: bits per frame too low\n"); + return -1; + } + + if( coder_type == RF_ALLPRED ) + { + set_i(acelp_cfg->fixed_cdk_index, -1, nb_subfr); + } + else if ( coder_type == RF_GENPRED ) + { + acelp_cfg->fixed_cdk_index[0] = 0; /* 7 bits */ + acelp_cfg->fixed_cdk_index[1] = -1; + acelp_cfg->fixed_cdk_index[2] = 0; /* 7 bits */ + acelp_cfg->fixed_cdk_index[3] = -1; + acelp_cfg->fixed_cdk_index[4] = -1; + bits += 14; + } + else if( coder_type == RF_NOPRED ) + { + set_i(acelp_cfg->fixed_cdk_index, 0, nb_subfr); + bits += 28; + } + else + { + bits += BITS_ALLOC_adjust_acelp_fixed_cdk(bits_frame - bits, acelp_cfg->fixed_cdk_index, nb_subfr ); + } + + remaining_bits = bits_frame-bits; + + /*Sanity check*/ + if( remaining_bits < 0 ) + { + bits = -1; + } + + + return( bits ); +} + +/*-------------------------------------------------------------------* +* BITS_ALLOC_adjust_acelp_fixed_cdk() +* +* +*--------------------------------------------------------------------*/ + +static int BITS_ALLOC_adjust_acelp_fixed_cdk( + int bits_frame, /*i: bit budget*/ + int *fixed_cdk_index, + int nb_subfr +) +{ + int bits_subframe2; + int sfr, k, bitsused, bits_currsubframe; + + bits_subframe2 = bits_frame; + + if( bits_subframe2 < ACELP_FIXED_CDK_BITS(0)*nb_subfr ) + { + return(bits_frame+1 ); /* Not enough bits for lowest mode. -> trigger alarm*/ + } + + /* search cdk-index for first subframe */ + for (k=0; k bits_subframe2) + { + k--; /* previous mode did not exceed bit-budget */ + break; + } + } + + if( ACELP_FIXED_CDK_BITS(k)*nb_subfr > bits_subframe2 ) + { + k--; /* previous mode did not exceed bit-budget */ + } + fixed_cdk_index[0] = k; + bitsused = ACELP_FIXED_CDK_BITS(k); + + for (sfr=1; sfr < nb_subfr; sfr++) + { + bits_currsubframe = (sfr*bits_subframe2 + bits_subframe2) - bitsused*nb_subfr; + + /* try increasing mode while below threshold */ + while ( (k < ACELP_FIXED_CDK_NB-1) && (ACELP_FIXED_CDK_BITS(k+1)*nb_subfr <= bits_currsubframe) ) + { + k++; + } + + /* try decreasing mode until below threshold */ + while (ACELP_FIXED_CDK_BITS(k)*nb_subfr > bits_currsubframe) + { + k--; + if ( k == 0 ) + { + break; + } + } + + /* store mode */ + fixed_cdk_index[sfr] = k; + bitsused += ACELP_FIXED_CDK_BITS(k); + } + + return bitsused; +} diff --git a/lib_com/bitstream.c b/lib_com/bitstream.c new file mode 100644 index 000000000..ce3b2fe0f --- /dev/null +++ b/lib_com/bitstream.c @@ -0,0 +1,2264 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "stat_enc.h" +#include "stat_dec.h" +#include "rom_com.h" +#include "mime.h" + + + + +/*-------------------------------------------------------------------* +* 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; + } + 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; + 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; + } + return rate2AMRWB_IOmode(rate); +} + +/*-------------------------------------------------------------------* + * push_indice() + * + * Push a new indice into the buffer + *-------------------------------------------------------------------*/ + +void push_indice( + Encoder_State *st, /* i/o: encoder state structure */ + short id, /* i : ID of the indice */ + unsigned short value, /* i : value of the quantized indice */ + short nb_bits /* i : number of bits used to quantize the indice */ +) +{ + short i; + + + if ( st->last_ind == id ) + { + /* indice with the same name as the previous one */ + i = st->next_ind; + } + else + { + /* new indice - find an empty slot in the list */ + i = id; + while (st->ind_list[i].nb_bits != -1) + { + i++; + } + } + + /* store the new indice in the list */ + st->ind_list[i].value = value; + st->ind_list[i].nb_bits = nb_bits; + + /* updates */ + st->next_ind = i + 1; + st->last_ind = id; + st->nb_bits_tot += nb_bits; + + return; +} + +/*-------------------------------------------------------------------* + * push_next_indice() + * + * Push a new indice into the buffer at the next position + *-------------------------------------------------------------------*/ + +void push_next_indice( + Encoder_State *st, /* i/o: encoder state structure */ + unsigned short value, /* i : value of the quantized indice */ + short nb_bits /* i : number of bits used to quantize the indice */ +) +{ + + /* store the values in the list */ + st->ind_list[st->next_ind].value = value; + st->ind_list[st->next_ind].nb_bits = nb_bits; + st->next_ind++; + + /* update the total number of bits already written */ + st->nb_bits_tot += nb_bits; + + return; +} + +/*-------------------------------------------------------------------* + * push_next_bits() + * Push a bit buffer into the buffer at the next position + *-------------------------------------------------------------------*/ + +void push_next_bits( + Encoder_State *st, /* i/o: encoder state structure */ + int bits[], /* i : bit buffer to pack, sequence of single bits */ + short nb_bits /* i : number of bits to pack */ +) +{ + unsigned short code; + int i, nb_bits_m15; + Indice *ptr; + + ptr = &st->ind_list[st->next_ind]; + nb_bits_m15 = nb_bits - 15; + + for (i=0; ivalue = code; + ptr->nb_bits = 16; + ++ptr; + } + for (; ivalue = bits[i]; + ptr->nb_bits = 1; + ++ptr; + } + st->next_ind = (int)(ptr - st->ind_list); + st->nb_bits_tot = st->nb_bits_tot + nb_bits; +} + +/*-------------------------------------------------------------------* + * get_next_indice() + * + * Get the next indice from the buffer + *-------------------------------------------------------------------*/ + +unsigned short get_next_indice( /* o : value of the indice */ + Decoder_State *st, /* i/o: decoder state structure */ + short nb_bits /* i : number of bits that were used to quantize the indice */ +) +{ + unsigned short value; + short i; + + assert(nb_bits <= 16); + + /* detect corrupted bitstream */ + if( st->next_bit_pos + nb_bits > st->total_brate/50 ) + { + st->BER_detect = 1; + return(0); + } + + value = 0; + for (i = 0; i < nb_bits; i++) + { + value <<= 1; + value += st->bit_stream[st->next_bit_pos+i]; + } + + /* update the position in the bitstream */ + st->next_bit_pos += nb_bits; + + return value; +} + +/*-------------------------------------------------------------------* + * get_next_indice_1() + * + * Get the next 1-bit indice from the buffer + *-------------------------------------------------------------------*/ + +unsigned short get_next_indice_1( /* o : value of the indice */ + Decoder_State *st /* i/o: decoder state structure */ +) +{ + + /* detect corrupted bitstream */ + if( + ( st->next_bit_pos + 1 > st->total_brate/50 && st->codec_mode == MODE1 ) || + ( (st->next_bit_pos + 1 > st->total_brate/50 + (2*8) ) && st->codec_mode == MODE2 ) /* add two zero bytes for arithmetic coder flush */ + ) + { + st->BER_detect = 1; + return(0); + } + + return st->bit_stream[st->next_bit_pos++]; +} + +/*-------------------------------------------------------------------* + * get_next_indice_tmp() + * + * update the total number of bits and the position in the bitstream + *-------------------------------------------------------------------*/ + +void get_next_indice_tmp( + Decoder_State *st, /* o : decoder state structure */ + short nb_bits /* i : number of bits that were used to quantize the indice */ +) +{ + /* update the position in the bitstream */ + st->next_bit_pos += nb_bits; + +} + +/*-------------------------------------------------------------------* + * get_indice() + * + * Get indice at specific position in the buffer + *-------------------------------------------------------------------*/ + +unsigned short get_indice( /* o : value of the indice */ + Decoder_State *st, /* i/o: decoder state structure */ + short pos, /* i : absolute position in the bitstream (update after the read) */ + short nb_bits /* i : number of bits that were used to quantize the indice */ +) +{ + unsigned short value; + int i; + + assert(nb_bits <= 16); + + /* detect corrupted bitstream */ + if( pos + nb_bits > st->total_brate/50 ) + { + st->BER_detect = 1; + return(0); + } + + value = 0; + for (i = 0; i < nb_bits; i++) + { + value <<= 1; + value += st->bit_stream[pos+i]; + } + + return value; +} + +/*-------------------------------------------------------------------* + * get_indice_1() + * + * Get a 1-bit indice at specific position in the buffer + *-------------------------------------------------------------------*/ + +unsigned short get_indice_1( /* o : value of the indice */ + Decoder_State *st, /* i/o: decoder state structure */ + short pos /* i : absolute position in the bitstream (update after the read) */ +) +{ + /* detect corrupted bitstream */ + if( pos+1 > st->total_brate/50 ) + { + st->BER_detect = 1; + return(0); + } + + return st->bit_stream[pos]; +} + +/*-------------------------------------------------------------------* + * reset_indices_enc() + * + * Reset the buffer of encoder indices + *-------------------------------------------------------------------*/ + +void reset_indices_enc( + Encoder_State *st +) +{ + short i; + + st->nb_bits_tot = 0; + st->next_ind = 0; + st->last_ind = -1; + + for (i=0; iind_list[i].nb_bits = -1; + } + + return; +} + +/*-------------------------------------------------------------------* + * reset_indices_dec() + * + * Reset the buffer of decoder indices + *-------------------------------------------------------------------*/ + +void reset_indices_dec( + Decoder_State *st +) +{ + st->next_bit_pos = 0; + + return; +} + +/*-------------------------------------------------------------------* +* write_indices() +* +* Write the buffer of indices to a file +*-------------------------------------------------------------------*/ + +void write_indices( + Encoder_State *st, /* 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] */ +) +{ + short i, k; + unsigned short stream[2+MAX_BITS_PER_FRAME], *pt_stream; + int mask; + short value, nb_bits; + UWord8 header; + + if( st->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++ = SYNC_GOOD_FRAME; + *pt_stream++ = st->nb_bits_tot; + + /*----------------------------------------------------------------* + * Bitstream packing (conversion of individual indices into a serial stream) + * Writing the serial stream into file + * Clearing of indices + *----------------------------------------------------------------*/ + + for (i=0; iind_list[i].value; + nb_bits = st->ind_list[i].nb_bits; + if (nb_bits != -1) + { + /* mask from MSB to LSB */ + mask = 1 << (nb_bits - 1); + + /* write bit by bit */ + for (k=0; k < nb_bits; k++) + { + if ( 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->Opt_AMR_WB << 5 | st->Opt_AMR_WB << 4 | rate2EVSmode(st->nb_bits_tot * 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[i].nb_bits = -1; + } + + if( st->bitstreamformat == G192 ) + { + /* write the serial stream into file */ + fwrite( stream, sizeof(unsigned short), 2+stream[1], file ); + } + + + /* reset index pointers */ + st->nb_bits_tot = 0; + st->next_ind = 0; + st->last_ind = -1; + + return; +} + +/*-------------------------------------------------------------------* + * indices_to_serial() + * + * pack indices into serialized payload format + *-------------------------------------------------------------------*/ + +void indices_to_serial( + const Encoder_State *st, /* 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->Opt_AMR_WB ) + { + cmi = rate2EVSmode(st->total_brate); + core_mode = rate2EVSmode(st->nb_bits_tot * 50); + + j=0; + for (i=0; iind_list[i].nb_bits != -1) + { + /* mask from MSB to LSB */ + mask = 1 << (st->ind_list[i].nb_bits - 1); + + /* temporarily save bit */ + for (k=0; k < st->ind_list[i].nb_bits; k++) + { + amrwb_bits[j++] = (st->ind_list[i].value & mask) > 0; + mask >>= 1; + } + } + } + } + + *pFrame_size = st->nb_bits_tot; + + /*----------------------------------------------------------------* + * Bitstream packing (conversion of individual indices into a serial stream) + *----------------------------------------------------------------*/ + j=0; + for (i=0; iind_list[i].nb_bits != -1) + { + /* mask from MSB to LSB */ + mask = 1 << (st->ind_list[i].nb_bits - 1); + + /* write bit by bit */ + for (k=0; k < st->ind_list[i].nb_bits; k++) + { + if (st->Opt_AMR_WB ) + { + pack_bit(amrwb_bits[sort_ptr[core_mode][j++]], &pt_pFrame, &omask); + } + else + { + pack_bit(st->ind_list[i].value & mask, &pt_pFrame, &omask); + j++; + } + mask >>= 1; + } + } + } + + if ( st->Opt_AMR_WB && core_mode == AMRWB_IO_SID) /* SID frame */ + { + /* 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); + } + } + + return; +} + +/*-------------------------------------------------------------------* + * indices_to_serial_generic() + * + * pack indices into serialized payload format + *-------------------------------------------------------------------*/ + +void indices_to_serial_generic( + const Indice *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 = 0; + + omask = (0x80 >> (*pFrame_size & 0x7)); + pt_pFrame += *pFrame_size >> 3; + + /*----------------------------------------------------------------* + * Bitstream packing (conversion of individual indices into a serial stream) + *----------------------------------------------------------------*/ + j=0; + for (i=0; i>= 1; + } + nb_bits_tot += ind_list[i].nb_bits; + } + } + + *pFrame_size += nb_bits_tot; + + return; +} + +/*-------------------------------------------------------------------* + * decoder_selectCodec() + * + * + *-------------------------------------------------------------------*/ + +static void decoder_selectCodec( + Decoder_State *st, /* i/o: decoder state structure */ + const long total_brate, /* i : total bitrate */ + const short bit0 /* i : first bit */ +) +{ + /* set the AMR-WB IO flag */ + if( total_brate == SID_1k75 || + total_brate == ACELP_6k60 || total_brate == ACELP_8k85 || total_brate == ACELP_12k65 || + total_brate == ACELP_14k25 || total_brate == ACELP_15k85 || total_brate == ACELP_18k25 || + total_brate == ACELP_19k85 || total_brate == ACELP_23k05 || total_brate == ACELP_23k85 ) + { + st->Opt_AMR_WB = 1; + } + else if ( total_brate != FRAME_NO_DATA ) + { + st->Opt_AMR_WB = 0; + } + + if ( st->Opt_AMR_WB ) + { + st->codec_mode = MODE1; + } + else + { + switch ( total_brate ) + { + case 0: + st->codec_mode = st->last_codec_mode; + break; + case 2400: + st->codec_mode = st->last_codec_mode; + break; + case 2800: + st->codec_mode = MODE1; + break; + case 7200: + st->codec_mode = MODE1; + break; + case 8000: + st->codec_mode = MODE1; + break; + case 9600: + st->codec_mode = MODE2; + break; + case 13200: + st->codec_mode = MODE1; + break; + case 16400: + st->codec_mode = MODE2; + break; + case 24400: + st->codec_mode = MODE2; + break; + case 32000: + st->codec_mode = MODE1; + break; + case 48000: + st->codec_mode = MODE2; + break; + case 64000: + st->codec_mode = MODE1; + break; + case 96000: + st->codec_mode = MODE2; + break; + case 128000: + st->codec_mode = MODE2; + 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 = 1; + break; + } + } + + if( st->ini_frame == 0 ) + { + if( st->codec_mode == -1 ) + { + st->codec_mode = MODE1; + } + st->last_codec_mode = st->codec_mode; + } + + /* set SID/CNG type */ + if( total_brate == SID_2k40 ) + { + if( bit0 == G192_BIN0 ) + { + st->cng_type = LP_CNG; + + /* force MODE1 when selecting LP_CNG */ + st->codec_mode = MODE1; + } + else + { + st->cng_type = FD_CNG; + if ( st->last_codec_mode == MODE2 && st->last_total_brate == ACELP_13k20 ) + { + st->codec_mode = MODE1; + } + } + st->last_cng_type = st->cng_type; /* CNG type switching at the first correctly received SID frame */ + } + + + return; +} + +/*-------------------------------------------------------------------* + * dec_prm_core() + * + * + *-------------------------------------------------------------------*/ + +void dec_prm_core( + Decoder_State *st +) +{ + int n, frame_size_index = -1; + + st->core = -1; + + if (st->total_brate == FRAME_NO_DATA) + { + st->m_frame_type = ZERO_FRAME; + } + else if (st->total_brate == SID_2k40) + { + st->m_frame_type = SID_FRAME; + } + else + { + st->m_frame_type = ACTIVE_FRAME; + for (n=0; ntotal_brate/50) + { + frame_size_index = n; + break; + } + } + + /* Get bandwidth mode */ + st->bwidth = get_next_indice(st, FrameSizeConfig[frame_size_index].bandwidth_bits); + st->bwidth += FrameSizeConfig[frame_size_index].bandwidth_min; + if (st->bwidth > FB) + { + st->bwidth = FB; + st->BER_detect = 1; + } + + if (st->bwidth > SWB && st->total_brate < ACELP_16k40) + { + st->bwidth = SWB; + st->BER_detect = 1; + } + /* Skip reserved bit */ + get_next_indice_tmp(st, FrameSizeConfig[frame_size_index].reserved_bits); + + if (get_next_indice_1(st)) /* TCX */ + { + if (get_next_indice_1(st)) + { + st->core = HQ_CORE; + } + else + { + st->core = TCX_20_CORE; + } + } + else /* ACELP */ + { + st->core = ACELP_CORE; + } + } + + return; +} + +/*-----------------------------------------------------------------* + * decision_matrix_core_dec() + * + * Read core mode signalling bits from the bitstream + * Set st->core, and st->bwidth if signalled together with the core. + *-----------------------------------------------------------------*/ + +static void decision_matrix_core_dec( + Decoder_State *st /* i/o: decoder state structure */ +) +{ + short start_idx; + long ind; + short nBits; + + assert(st->bfi != 1); + + st->core = -1; + st->bwidth = -1; + + if ( st->total_brate == FRAME_NO_DATA || st->total_brate == SID_2k40 ) + { + st->core = ACELP_CORE; + } + /* SC-VBR */ + else if ( st->total_brate == PPP_NELP_2k80 ) + { + st->core = ACELP_CORE; + return; + } + + /*---------------------------------------------------------------------* + * ACELP/HQ core selection + *---------------------------------------------------------------------*/ + + if ( st->total_brate < ACELP_24k40 ) + { + st->core = ACELP_CORE; + } + else if ( st->total_brate >= ACELP_24k40 && st->total_brate <= ACELP_64k ) + { + /* read the ACELP/HQ core selection bit */ + st->core = ((short) get_next_indice( st, 1 ))*HQ_CORE; + } + else + { + st->core = HQ_CORE; + } + + /*-----------------------------------------------------------------* + * Read ACELP signalling bits from the bitstream + *-----------------------------------------------------------------*/ + + if ( st->core == ACELP_CORE ) + { + /* find the section in the ACELP signalling table corresponding to bitrate */ + start_idx = 0; + while ( acelp_sig_tbl[start_idx] != st->total_brate ) + { + start_idx++; + } + + /* skip the bitrate */ + start_idx += 1; + + /* retrieve the number of bits */ + nBits = (short) acelp_sig_tbl[start_idx++]; + + /* retrieve the signalling indice */ + ind = acelp_sig_tbl[start_idx + get_next_indice( st, nBits )]; + st->bwidth = (ind >> 3) & 0x7; + + /* convert signalling indice into signalling information */ + if ( (ind & 0x7) == LR_MDCT ) + { + st->core = HQ_CORE; + } + } + + /*-----------------------------------------------------------------* + * Read HQ signalling bits from the bitstream + * Set HQ core type + *-----------------------------------------------------------------*/ + + if ( st->core == HQ_CORE ) + { + /* read the HQ/TCX core switching flag */ + if ( get_next_indice( st, 1 ) ) + { + st->core = TCX_20_CORE; + } + + /* For TCX: read/set band-width (needed for different I/O sampling rate support) */ + if( st->core == TCX_20_CORE && st->total_brate > ACELP_16k40 ) + { + ind = get_next_indice( st, 2 ); + + if( ind == 0 ) + { + st->bwidth = NB; + } + else if( ind == 1 ) + { + st->bwidth = WB; + } + else if( ind == 2 ) + { + st->bwidth = SWB; + } + else + { + st->bwidth = FB; + } + } + } + + return; +} + +/*-------------------------------------------------------------------* + * mdct_switching_dec() + * + * Set up MDCT core switching if indicated in the bit stream + *-------------------------------------------------------------------*/ + +static void mdct_switching_dec( + Decoder_State *st /* i/o: decoder state structure */ +) +{ + if (st->Opt_AMR_WB) + { + return; + } + + if (st->total_brate == ACELP_13k20 || st->total_brate == ACELP_32k) + { + st->mdct_sw_enable = MODE1; + } + else if (ACELP_16k40 <= st->total_brate && st->total_brate <= ACELP_24k40) + { + st->mdct_sw_enable = MODE2; + } + + if ( st->codec_mode == MODE1 && st->mdct_sw_enable == MODE1 ) + { + /* Read ahead core mode signaling */ + short next_bit_pos_save = st->next_bit_pos; + short core_save = st->core; + short bwidth_save = st->bwidth; + + decision_matrix_core_dec(st); /* sets st->core */ + + if (st->core == TCX_20_CORE) + { + /* Trigger TCX */ + st->codec_mode = MODE2; + st->mdct_sw = MODE1; + } + else + { + /* Rewind bitstream */ + st->next_bit_pos = next_bit_pos_save; + if (st->bfi) + { + st->core = core_save; + st->bwidth = bwidth_save; + } + } + } + else if (st->codec_mode == MODE2 && st->mdct_sw_enable == MODE2) + { + /* Read ahead core mode signaling */ + short next_bit_pos_save = st->next_bit_pos; + short core_save = st->core; + short bwidth_save = st->bwidth; + + dec_prm_core(st); /* sets st->core */ + + if (st->core == HQ_CORE) + { + /* Trigger HQ_CORE */ + st->codec_mode = MODE1; + st->mdct_sw = MODE2; + } + else + { + /* Rewind bitstream */ + st->next_bit_pos = next_bit_pos_save; + if (st->bfi) + { + st->core = core_save; + } + + /* always reset bwidth, to not interfere with BER logic */ + st->bwidth = bwidth_save; + } + } + + return; +} + + + +/*-------------------------------------------------------------------* + * read_indices() + * + * Read indices from an ITU-T G.192 bitstream to the buffer + * Simulate packet losses by inserting frame erasures + *-------------------------------------------------------------------*/ + +short read_indices( /* o : 1 = reading OK, 0 = problem */ + Decoder_State *st, /* i/o: decoder state structure */ + FILE *file, /* i : bitstream file */ + const short rew_flag /* i : rewind flag (rewind file after reading)*/ +) +{ + short k; + unsigned short utmp, stream[2+MAX_BITS_PER_FRAME], *pt_stream; + unsigned short *bit_stream_ptr; + unsigned short num_bits; + long total_brate; + short curr_ft_good_sp, curr_ft_bad_sp; + short g192_sid_first,sid_upd_bad, sid_update; + short speech_bad, speech_lost; + unsigned short num_bits_read; + + st->bfi = 0; + st->BER_detect = 0; + st->mdct_sw_enable = 0; + st->mdct_sw = 0; + reset_indices_dec( 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 ( utmp == SYNC_BAD_FRAME ) + { + st->bfi = 1; + } + + + + else + { + st->bfi = 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 (%ld) in the G.192 frame ! Exiting ! \n", total_brate); + exit(-1); + } + pt_stream = stream; + num_bits_read = (unsigned short) 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 || 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 == 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 == 0 ) + { + sid_update = 1; + } + else + { + sid_upd_bad = 1; /* this frame type may happen in ETSI/3GPP CS cases , a corrupt sid frames */ + } + } + /* 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 */ + short sum = 0; + for (k = 0; k < num_bits; ++k) + { + sum += (pt_stream[k] == G192_BIN1);/* check of 35 zeroes */ + } + if( sum == 0 ) + { /* all zeros */ + sid_upd_bad = 1; /* initial signal as corrupt (BER likely) */ + } + } + + /* 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 frames triggers SID_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 == AMR_WB_CORE && st->prev_ft_speech && total_brate == FRAME_NO_DATA && st->bfi == 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 != 0 ) /* CS-type of CRC failure frame */ + { + speech_bad = 1; /* initial ft assumption, CNG_state decides what to do */ + } + + speech_lost = 0; + if( total_brate == 0 && st->bfi != 0 ) /* unsent NO_DATA or stolen NO_DATA/signaling frame */ + { + speech_lost = 1; /* initial ft 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 != 0 ) + { + /* We were in CNG synthesis */ + if( curr_ft_good_sp != 0 ) + { + /* only a good speech frame makes you leave CNG synthesis */ + st->CNG = 0; + } + } + else + { + /* We were in SPEECH synthesis */ + /* only a received/detected SID frame can make the decoder enter into CNG synthsis */ + if( g192_sid_first || sid_update || sid_upd_bad ) + { + st->CNG = 1; + } + } + + /* set bfi, total_brate pair for proper decoding */ + /* handle the G.192 _simulated_ untransmitted NO_DATA frame, setting for decoder SPEECH synthesis */ + if ( (st->CNG==0) && (total_brate==0 && st->bfi == 0 ) ) + { + st->bfi= 1; /* SPEECH PLC code will now become active as in a real system */ + /* total_brate= 0 */ + } + + /* handle bad/lost speech frame(and CS bad sid frame) in the decoders CNG synthesis settings pair (total_brate, bfi) */ + if( ((st->CNG != 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 = 0; /* bfi=0 needed to activate CNG code */ + total_brate = 0; + } + /* update for next frame's G.192 file format's odd SID_FIRST detection (primarily for AMRWBIO) */ + st->prev_ft_speech = ((curr_ft_good_sp != 0) || (curr_ft_bad_sp != 0)); + + /* st->total brate= total_brate ; updated in a good frame below */ + } /* rew_flag */ + + if ( st->bfi == 0 && !rew_flag ) + { + /* select Mode 1 or Mode 2 */ + decoder_selectCodec( st, total_brate, *pt_stream ); + } + + /* 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 = total_brate; + return 1; + } + + /* GOOD frame */ + if ( st->bfi == 0 ) + { + /* GOOD frame - convert ITU-T G.192 words to short values */ + bit_stream_ptr = st->bit_stream; + + for ( k = 0; k < (short)num_bits; ++k ) + { + *bit_stream_ptr++ = (*pt_stream++ == G192_BIN1); + } + + /* add two zero bytes for arithmetic coder flush */ + for (k=0; k<8*2; ++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 = 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 *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( total_brate > SID_2k40 ) + { + if( st->bfi != 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 = 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 == 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 ) + { + 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==0 ) || /* switch to AMRWBIO */ + (isAMRWB_IOmode != 1 && st->Opt_AMR_WB==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==1); /* bfi stays 1 */ + } + + if( total_brate > SID_2k40 && st->bfi == 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 != 0 ) + { + /* We were in CNG synthesis */ + if( curr_ft_good_sp != 0 ) + { + /* only a good speech frame makes decoder leave CNG synthesis */ + st->CNG = 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 = 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 == 0) && ( no_data != 0 ) ) + { + /* treat no_data received in speech synthesis as SP_LOST frames, SPEECH PLC code will now become active */ + st->bfi = 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 != 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 = 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 == 1 && st->ini_frame == 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 = init_rate; /* not updated on bfi as decoderSelectCodec is not called below */ + st->core_brate = 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 *st, + Word32 *total_brate, + Word16 sti +) +{ + Word16 k, sum = 0; + + 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 |= st->bit_stream[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 */ + for (k = 0; k < 35; k++) + { + sum += st->bit_stream[k]; /* check of 35 zeroes */ + } + + if ( sum == 0 ) + { + st->bfi = 1; /* eventually becomes SID_UPD_BAD */ + } + } +} + + +/*-------------------------------------------------------------------* + * read_indices_mime() + * + * Read indices from MIME formatted bitstream to the buffer + *-------------------------------------------------------------------*/ + +Word16 read_indices_mime( /* o : 1 = reading OK, 0 = problem */ + Decoder_State *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; + Word16 speech_lost = 0, no_data = 0; + Word16 num_bytes_read; + + st->BER_detect = 0; + st->bfi = 0; + st->mdct_sw_enable = 0; + st->mdct_sw = 0; + reset_indices_dec( st ); + + /* read the FT Header field from the bitstream */ + /* read the FT header */ + 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 = !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 = !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; + } + + num_bits = (Word16)(total_brate/50); + 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; + } + + /* 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 */ + if ( rew_flag ) + { + + st->total_brate = total_brate; + /* select MODE1 or MODE2 */ + if( st->bfi == 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; + for( k=0; kbit_stream[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: these cmi bits are unpacked for demo purposes; they are actually not needed */ + 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 == 0 ) + { + /* select MODE1 or MODE2 in MIME */ + + decoder_selectCodec( st, total_brate, *st->bit_stream ? 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 = total_brate; + mdct_switching_dec(st); + } + /* else{ bfi stay in past synthesis mode(SP,CNG) } */ + + return 1; +} + + + +/*-------------------------------------------------------------------* +* get_rfFrameType() +* +* Extract the rf frame type +*-------------------------------------------------------------------*/ + +static void get_rfFrameType( + Decoder_State *st, /* i : decoder state structure */ + short *rf_frame_type /* o : RF frame type */ +) +{ + short num_bits; + num_bits = st->total_brate/50; + + if( st->rf_flag == 1) + { + /* the last three bits in a packet is the RF frame type */ + *rf_frame_type = get_indice( st, num_bits - 3, 3 ); + } + else + { + *rf_frame_type = 0; + } + + return; +} + +/*-------------------------------------------------------------------* +* get_rfFlag() +* +* Check if rf flag is present in the bitstream +*-------------------------------------------------------------------*/ + +static void get_rfFlag( + Decoder_State *st, /* i: decoder state structure */ + short *rf_flag, /* o : check for the RF flag */ + short *nBits, + long *ind +) +{ + short start_idx, nBits_tmp; + long ind_tmp; + + /* Init */ + *rf_flag = 0; + + /* check for rf_flag in the packet and extract the rf_frame_type and rf_fec_offset */ + if( st->total_brate == ACELP_13k20 && (st->bfi == FRAMEMODE_NORMAL || st->bfi == FRAMEMODE_FUTURE) ) + { + /* find the section in the ACELP signalling table corresponding to bitrate */ + start_idx = 0; + while ( acelp_sig_tbl[start_idx] != st->total_brate ) + { + start_idx++; + assert((start_idx < MAX_ACELP_SIG) && "ERROR: start_idx larger than acelp_sig_tbl[].\n"); + } + + /* skip the bitrate */ + start_idx += 1; + + /* retrieve the number of bits */ + nBits_tmp = (short) acelp_sig_tbl[start_idx++]; + + /* retrieve the signalling indice */ + ind_tmp = acelp_sig_tbl[start_idx + get_indice( st, 0, nBits_tmp )]; + + /* convert signalling indice into RF flag. */ + *rf_flag = (ind_tmp >> 7) & 0x1; + + if( ind ) + { + *ind = ind_tmp; + } + + if( nBits ) + { + *nBits = nBits_tmp; + } + } + + return; +} + +/*-------------------------------------------------------------------* +* get_rf_fec_offset() +* +* Extract the FEC offset +*-------------------------------------------------------------------*/ + +static void get_rf_fec_offset( + Decoder_State *st, /* i : decoder state structure */ + short *rf_fec_offset /* o : RF fec offset */ +) +{ + short num_bits, tmp; + num_bits = st->total_brate/50; + + if( st->rf_flag == 1) + { + /* the two bits before the rf frame type contains the fec offset */ + tmp = get_indice( st, num_bits - 5, 2 ); + + if (tmp == 0) + { + *rf_fec_offset = 2; + } + else + { + *rf_fec_offset = 2*tmp + 1; + } + + } + else + { + *rf_fec_offset = 0; + } + + return; +} + +/*-------------------------------------------------------------------* +* get_rfTargetBits() +* +* Return the number of RF target bits +*-------------------------------------------------------------------*/ + +static void get_rfTargetBits( + short rf_frame_type, /* i : RF frame type */ + short *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; + } + + return; +} + +/*-------------------------------------------------------------------* +* berCheck() +* +* Check for bit errors in channel aware signalling. +*-------------------------------------------------------------------*/ + +static void berCheck( + Decoder_State *st, /* i/o: decoder state structure */ + short *coder_type /* i/o: coder type */ +) +{ + /* In case of RF flag = 1, and valid RF packet with primary and partial copy */ + if( st->bwidth == NB || st->bwidth == FB || *coder_type >= TRANSITION ) + { + if( st->use_partial_copy == 1 ) + { + st->use_partial_copy = 0; + } + + st->bfi = 1; + st->bwidth = st->last_bwidth; + st->BER_detect = 1; + *coder_type = GENERIC; + } + + return; +} + +/*-------------------------------------------------------------------* + * getPartialCopyInfo() + * + * Check if the frame includes a partial copy for channel aware processing. + *-------------------------------------------------------------------*/ + +void getPartialCopyInfo( + Decoder_State *st, /* i/o: decoder state structure */ + short *coder_type, + short *sharpFlag +) +{ + short nBits = 0; + long ind = 0; + + /* 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( st->rf_flag == 1 ) + { + *coder_type = ind & 0x7; + st->bwidth = (ind >> 3) & 0x7; + *sharpFlag = (ind >> 6) & 0x1; + st->codec_mode = MODE2; + get_rfTargetBits( st->rf_frame_type, &(st->rf_target_bits) ); + + if( st->bfi == FRAMEMODE_FUTURE ) + { + st->use_partial_copy = 1; + /* now set the frame mode to normal mode */ + if(st->rf_frame_type >= RF_TCXFD && st->rf_frame_type <= RF_TCXTD2) + { + st->bfi = 1; + st->core = 1; + } + else + { + st->bfi = FRAMEMODE_NORMAL; + st->core = 0; + } + } + + /* check for bit errors */ + berCheck( st, coder_type ); + + get_next_indice_tmp(st, nBits); + } + + return; +} + +/*-------------------------------------------------------------------* + * get_NextCoderType() + * + * Extract the coder type of next frame + *-------------------------------------------------------------------*/ + +void get_NextCoderType( + unsigned char *bitsteam, /* i : bitstream */ + short *next_coder_type /* o : next coder type */ +) +{ + short k; + short start_idx; + char bit_stream[ACELP_13k20/50]; + long tmp; + short nBits_tmp; + + + for( k = 0; k < ACELP_13k20/50; k++ ) + { + bit_stream[k] = (bitsteam[k / 8] >> (7 - (k % 8))) & 0x1; + } + start_idx = 0; + while ( acelp_sig_tbl[start_idx] != ACELP_13k20 ) + { + start_idx++; + assert((start_idx < MAX_ACELP_SIG) && "ERROR: start_idx larger than acelp_sig_tbl[].\n"); + } + + /* skip the bitrate */ + start_idx += 1; + + tmp = 0; + nBits_tmp = (short) acelp_sig_tbl[start_idx++]; + for (k = 0; k < nBits_tmp; k++) + { + tmp <<= 1; + tmp += bit_stream[k]; + } + + /* retrieve the signalling indice */ + *next_coder_type = acelp_sig_tbl[start_idx + tmp] & 0x7; + + return; +} + +/*-------------------------------------------------------------------* + * read_indices_from_djb() + * + * Read indices from the de-jitter buffer payload (works also for AMR-WB IO mode) + *-------------------------------------------------------------------*/ +void read_indices_from_djb( + Decoder_State *st, /* i/o: decoder state structure */ + unsigned char *pt_stream, /* i : bitstream file */ + int num_bits, /* i : input frame length in bits */ + Word16 isAMRWB_IOmode, + Word16 core_mode, + Word16 qbit, + short partialframe, /* i : partial frame information */ + short next_coder_type /* i : next coder type information */ +) +{ + int k; + UWord8 mask = 0x80; + Word16 no_data = 0; + Word16 sti = -1; + unsigned short *bit_stream_ptr; + Word32 total_brate; + short speech_lost = 0; + + st->bfi = 0; + st->BER_detect = 0; + st->mdct_sw_enable = 0; + st->mdct_sw = 0; + reset_indices_dec(st); + + st->bfi = !qbit; + total_brate = (Word32)(num_bits) * 50; + + if( num_bits == 0 ) /* guess type of missing frame for SP_LOST and NO_DATA */ + { + speech_lost = st->CNG == 0; + no_data = st->CNG != 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 = 2; + } + + /* unpack speech data */ + bit_stream_ptr = st->bit_stream; + /* 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[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 set inside */ + + if ( st->bfi != 1 ) + { + /* select Mode 1 or Mode 2 */ + decoder_selectCodec( st, total_brate, *st->bit_stream ? 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 = total_brate; + + mdct_switching_dec(st); + } + + return; +} + +/*-------------------------------------------------------------------* + * get_indice_preview() + * + * Indices preview to parse for the presence of partial copy + *-------------------------------------------------------------------*/ +static unsigned short get_indice_preview( + unsigned char *bitstream, + int bitstreamSize, + short pos, + short nb_bits +) +{ + unsigned short value; + int i; + unsigned short bitstreamShort[MAX_BITS_PER_FRAME+16]; + unsigned short *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 <<= 1; + value += bitstreamShort[pos+i]; + } + return value; +} + +/*-------------------------------------------------------------------* + * evs_dec_previewFrame() + * + * Signalling index preview + *-------------------------------------------------------------------*/ +void evs_dec_previewFrame( + unsigned char *bitstream, + int bitstreamSize, + short *partialCopyFrameType, + short *partialCopyOffset +) +{ + long total_brate; + short start_idx, nBits; + long ind; + short rf_flag; + + rf_flag = 0; + *partialCopyFrameType = 0; + *partialCopyOffset = 0; + total_brate = bitstreamSize * 50; + + if( total_brate == ACELP_13k20 ) + { + /* find the section in the ACELP signalling table corresponding to bitrate */ + start_idx = 0; + while ( acelp_sig_tbl[start_idx] != total_brate ) + { + start_idx++; + assert((start_idx < MAX_ACELP_SIG) && "ERROR: start_idx larger than acelp_sig_tbl[].\n"); + } + + /* skip the bitrate */ + start_idx += 1; + /* retrieve the number of bits */ + nBits = (short) 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 = (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 (ind == 1) + { + *partialCopyOffset = 3; + } + else if (ind == 2) + { + *partialCopyOffset = 5; + } + else if (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 ); + } + } + + return; +} diff --git a/lib_com/calc_st_com.c b/lib_com/calc_st_com.c new file mode 100644 index 000000000..38d48af8e --- /dev/null +++ b/lib_com/calc_st_com.c @@ -0,0 +1,274 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" + + + +/*---------------------------------------------------------------------------- + * calc_rc0_h() + * + * computes 1st parcor from composed filter impulse response + *---------------------------------------------------------------------------*/ + +static void calc_rc0_h( + const float *h, /* i : impulse response of composed filter */ + float *rc0 /* o : 1st parcor */ +) +{ + float acf0, acf1; + float temp, temp2; + const float *ptrs; + int i; + + /* computation of the autocorrelation function acf */ + temp = (float) 0.; + for (i = 0; i < LONG_H_ST; i++) + { + temp += h[i] * h[i]; + } + acf0 = temp; + + temp = (float) 0.; + ptrs = h; + for (i = 0; i < LONG_H_ST - 1; i++) + { + temp2 = *ptrs++; + temp += temp2 * (*ptrs); + } + acf1 = temp; + + /* Initialisation of the calculation */ + if (acf0 == (float) 0.) + { + *rc0 = (float) 0.; + return; + } + + /* Compute 1st parcor */ + if (acf0 < (float) fabs (acf1)) + { + *rc0 = (float) 0.0; + return; + } + *rc0 = -acf1 / acf0; + + return; +} + + +/*---------------------------------------------------------------------------- + * 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 + *---------------------------------------------------------------------------- */ + +void calc_st_filt( + const float *apond2, /* i : coefficients of numerator */ + const float *apond1, /* i : coefficients of denominator */ + float *parcor0, /* o : 1st parcor calcul. on composed filter */ + float *sig_ltp_ptr, /* i/o: input of 1/A(gamma1) : scaled by 1/g0 */ + float *mem_zero, /* i/o: All zero memory */ + const short L_subfr, /* i : the length of subframe */ + const short extl /* i : extension layer info */ + +) +{ + float h[LONG_H_ST]; + float g0, temp; + int i; + + /* compute i.r. of composed filter apond2 / apond1 */ + if( extl == SWB_TBE ) + { + syn_filt( apond1, LPC_SHB_ORDER, apond2, h, LONG_H_ST, mem_zero, 0 ); + } + else + { + syn_filt( apond1, M, apond2, h, LONG_H_ST, mem_zero, 0 ); + } + + /* compute 1st parcor */ + calc_rc0_h( h, parcor0 ); + + /* compute g0 */ + g0 = (float) 0.; + for (i = 0; i < LONG_H_ST; i++) + { + g0 += (float) fabs (h[i]); + } + + /* Scale signal input of 1/A(gamma1) */ + if (g0 > (float) 1.) + { + temp = (float) 1. / g0; + + for (i = 0; i < L_subfr; i++) + { + sig_ltp_ptr[i] = sig_ltp_ptr[i] * temp; + } + } + + 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( + const float *sig_in, /* i : signal (beginning at sample -1) */ + float *sig_out, /* o : output signal */ + const float parcor0, /* i : parcor0 (mu = parcor0 * gamma3) */ + const short L_subfr, /* i : the length of subframe */ + const short extl /* i : extension layer info */ +) +{ + short n; + float mu, ga, temp; + const float *ptrs; + + if( extl == SWB_TBE ) + { + if(parcor0 > 0.0f) + { + mu = parcor0 * GAMMA3_PLUS_WB; + } + else + { + mu = parcor0 * GAMMA3_MINUS_WB; + } + } + else + { + if (parcor0 > 0.0f) + { + mu = parcor0 * GAMMA3_PLUS; + } + else + { + mu = parcor0 * GAMMA3_MINUS; + } + } + + ga = (float) 1. / ((float) 1. - (float) fabs (mu)); + + ptrs = sig_in; /* points on sig_in(-1) */ + + for (n = 0; n < L_subfr; n++) + { + temp = mu * (*ptrs++); + temp += (*ptrs); + sig_out[n] = ga * temp; + } + + 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 float *sig_in, /* i : postfilter input signal */ + float *sig_out, /* i/o: postfilter output signal */ + float *gain_prec, /* i/o: last value of gain for subframe */ + const short L_subfr, /* i : the length of subframe */ + const short extl /* i : extension layer info */ +) +{ + int i; + float gain_in, gain_out; + float g0, gain; + float agc_fac1_para = 0.0f; + float agc_fac_para = 0.0f; + + if( extl == SWB_TBE ) + { + agc_fac1_para = AGC_FAC1_WB; + agc_fac_para = AGC_FAC_WB; + } + else + { + agc_fac1_para = AGC_FAC1; + agc_fac_para = AGC_FAC; + } + + /* compute input gain */ + gain_in = (float) 0.; + for (i = 0; i < L_subfr; i++) + { + gain_in += (float) fabs (sig_in[i]); + } + + if ( gain_in == 0.0f ) + { + g0 = 0.0f; + } + else + { + /* Compute output gain */ + gain_out = 0.0f; + for (i = 0; i < L_subfr; i++) + { + gain_out += (float) fabs (sig_out[i]); + } + + if (gain_out == 0.0f) + { + *gain_prec = 0.0f; + return; + } + + g0 = gain_in / gain_out; + g0 *= agc_fac1_para; + } + + /* compute gain(n) = AGC_FAC gain(n-1) + (1-AGC_FAC)gain_in/gain_out */ + /* sig_out(n) = gain(n) sig_out(n) */ + gain = *gain_prec; + for (i = 0; i < L_subfr; i++) + { + gain *= agc_fac_para; + gain += g0; + sig_out[i] *= gain; + } + + *gain_prec = gain; + + return; +} + +void blend_subfr2( float *sigIn1, float *sigIn2, float *sigOut) +{ + + float fac1 = 1.f - (1.f / L_SUBFR); + float fac2 = 0.f + (1.f / L_SUBFR); + float step = 1.f / (L_SUBFR/2); + int i; + + for(i=0; i +#include "wmc_auto.h" +#include +#include "stat_dec.h" +#include "prot.h" +#include "rom_com.h" +#include "string.h" +#include + +#if defined __ICL +#define restrict __restrict +#else +#define restrict +#endif + +#ifdef _MSC_VER +#pragma warning(disable : 4305) /* disable truncation from double to float warning (VC++)*/ +#endif + + +/*-------------------------------------------------------------------* + * local prototypes + *--------------------------------------------------------------------*/ + +static void cldfb_init_proto_and_twiddles(HANDLE_CLDFB_FILTER_BANK hs); + +static float GetEnergyCldfb( float *energyValuesSum, float *energyLookahead, float **realValues, float **imagValues, + int numberBands, int numberCols, HANDLE_TEC_ENC hTecEnc ); + +/*-------------------------------------------------------------------* + * cplxMult() + * + * Conduct complex multiplication + *--------------------------------------------------------------------*/ +static void cplxMult( + float *yr, /* o : real output */ + float *yi, /* o : imag output */ + float xr, /* i : real input 1*/ + float xi, /* i : imag input 1*/ + float cr, /* i : real input 1*/ + float ci /* i : imag input 1*/ +) +{ + *yr = xr*cr - xi*ci; + *yi = xr*ci + xi*cr; + + return; +} + + +/*-------------------------------------------------------------------* + * cldfbAnalysis() + * + * Conduct multple overlap cmplex low delay MDCT + *--------------------------------------------------------------------*/ +void cldfbAnalysis( + const float *timeIn, /* i : time buffer */ + float **realBuffer, /* o : real value buffer */ + float **imagBuffer, /* o : imag value buffer */ + int samplesToProcess, /* i : samples to process */ + HANDLE_CLDFB_FILTER_BANK h_cldfb /* i : filterbank state */ +) +{ + short i, k; + short L2, M1, M2, M4; + short no_col = h_cldfb->no_col; + + float r1, r2, rr12, ir12; + float i1, i2, ri12, ii12; + float rBuffer[2*CLDFB_NO_CHANNELS_MAX]; + float iBuffer[2*CLDFB_NO_CHANNELS_MAX]; + const float *rot_vctr_re; + const float *rot_vctr_im; + const float *ptr_pf; + float *timeBuffer = h_cldfb->cldfb_state; + int offset = h_cldfb->p_filter_length - h_cldfb->no_channels; + int frameSize = h_cldfb->no_channels * h_cldfb->no_col; + + /* prepare input buffer */ + mvr2r( timeBuffer + frameSize, timeBuffer, offset ); + + if( samplesToProcess > -1 ) + { + mvr2r( timeIn, timeBuffer + offset, samplesToProcess ); + set_f( timeBuffer+offset+samplesToProcess, 0.0f, (frameSize-samplesToProcess) ); + } + else + { + mvr2r( timeIn, timeBuffer + offset, frameSize ); + } + + /* only process needed cols */ + if( samplesToProcess > -1 ) + { + no_col = min(no_col, (samplesToProcess + h_cldfb->no_channels - 1) / h_cldfb->no_channels); + } + + M1 = h_cldfb->no_channels; + M2 = M1 >> 1; + M4 = M1 >> 2; + L2 = M1 << 1; + + if( M2 & 1 ) + { + M4 += 1; + } + + rot_vctr_re = h_cldfb->rot_vec_ana_re; + rot_vctr_im = h_cldfb->rot_vec_ana_im; + + ptr_pf = h_cldfb->p_filter; + + for( i = 0; i < no_col; i++ ) + { + for (k=0; k < M4; k++ ) + { + /* prototype filter */ + r1 = 0 - ptr_pf[(L2-M2-1-(2*k) + 0 * L2)] * timeBuffer[L2-M2-1-(2*k) + 0 * L2]; + r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 1 * L2)] * timeBuffer[L2-M2-1-(2*k) + 1 * L2]; + r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 2 * L2)] * timeBuffer[L2-M2-1-(2*k) + 2 * L2]; + r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 3 * L2)] * timeBuffer[L2-M2-1-(2*k) + 3 * L2]; + r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 4 * L2)] * timeBuffer[L2-M2-1-(2*k) + 4 * L2]; + + r2 = 0 - ptr_pf[(L2-M2+(2*k) + 0 * L2)] * timeBuffer[L2-M2+(2*k) + 0 * L2]; + r2 = r2 - ptr_pf[(L2-M2+(2*k) + 1 * L2)] * timeBuffer[L2-M2+(2*k) + 1 * L2]; + r2 = r2 - ptr_pf[(L2-M2+(2*k) + 2 * L2)] * timeBuffer[L2-M2+(2*k) + 2 * L2]; + r2 = r2 - ptr_pf[(L2-M2+(2*k) + 3 * L2)] * timeBuffer[L2-M2+(2*k) + 3 * L2]; + r2 = r2 - ptr_pf[(L2-M2+(2*k) + 4 * L2)] * timeBuffer[L2-M2+(2*k) + 4 * L2]; + + i1 = 0 - ptr_pf[(L2-3*M2+(2*k) + 0 * L2)] * timeBuffer[L2-3*M2+(2*k) + 0 * L2]; + i1 = i1 - ptr_pf[(L2-3*M2+(2*k) + 1 * L2)] * timeBuffer[L2-3*M2+(2*k) + 1 * L2]; + i1 = i1 - ptr_pf[(L2-3*M2+(2*k) + 2 * L2)] * timeBuffer[L2-3*M2+(2*k) + 2 * L2]; + i1 = i1 - ptr_pf[(L2-3*M2+(2*k) + 3 * L2)] * timeBuffer[L2-3*M2+(2*k) + 3 * L2]; + i1 = i1 - ptr_pf[(L2-3*M2+(2*k) + 4 * L2)] * timeBuffer[L2-3*M2+(2*k) + 4 * L2]; + + i2 = 0 - ptr_pf[(L2-3*M2-1-(2*k) + 0 * L2)] * timeBuffer[L2-3*M2-1-(2*k) + 0 * L2]; + i2 = i2 - ptr_pf[(L2-3*M2-1-(2*k) + 1 * L2)] * timeBuffer[L2-3*M2-1-(2*k) + 1 * L2]; + i2 = i2 - ptr_pf[(L2-3*M2-1-(2*k) + 2 * L2)] * timeBuffer[L2-3*M2-1-(2*k) + 2 * L2]; + i2 = i2 - ptr_pf[(L2-3*M2-1-(2*k) + 3 * L2)] * timeBuffer[L2-3*M2-1-(2*k) + 3 * L2]; + i2 = i2 - ptr_pf[(L2-3*M2-1-(2*k) + 4 * L2)] * timeBuffer[L2-3*M2-1-(2*k) + 4 * L2]; + + /* folding + pre modulation of DST IV */ + rr12 = r1 - r2; + ri12 = -i1 - i2; + cplxMult(&rBuffer[2*k],&rBuffer[2*k+1],rr12,ri12,rot_vctr_re[k],rot_vctr_im[k]); + + /* folding + pre modulation of DCT IV */ + ir12 = r1 + r2; + ii12 = i1 - i2; + cplxMult(&iBuffer[2*k],&iBuffer[2*k+1],ir12,ii12,rot_vctr_re[k],rot_vctr_im[k]); + } + + for (k=M4; k < M2; k++) + { + /* prototype filter */ + r1 = 0 - ptr_pf[(L2-M2-1-(2*k) + 0 * L2)] * timeBuffer[L2-M2-1-(2*k) + 0 * L2]; + r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 1 * L2)] * timeBuffer[L2-M2-1-(2*k) + 1 * L2]; + r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 2 * L2)] * timeBuffer[L2-M2-1-(2*k) + 2 * L2]; + r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 3 * L2)] * timeBuffer[L2-M2-1-(2*k) + 3 * L2]; + r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 4 * L2)] * timeBuffer[L2-M2-1-(2*k) + 4 * L2]; + + r2 = 0 - ptr_pf[(L2-5*M2+(2*k) + 0 * L2)] * timeBuffer[L2-5*M2+(2*k) + 0 * L2]; + r2 = r2 - ptr_pf[(L2-5*M2+(2*k) + 1 * L2)] * timeBuffer[L2-5*M2+(2*k) + 1 * L2]; + r2 = r2 - ptr_pf[(L2-5*M2+(2*k) + 2 * L2)] * timeBuffer[L2-5*M2+(2*k) + 2 * L2]; + r2 = r2 - ptr_pf[(L2-5*M2+(2*k) + 3 * L2)] * timeBuffer[L2-5*M2+(2*k) + 3 * L2]; + r2 = r2 - ptr_pf[(L2-5*M2+(2*k) + 4 * L2)] * timeBuffer[L2-5*M2+(2*k) + 4 * L2]; + + i1 = 0 - ptr_pf[(L2+M2-1-(2*k) + 0 * L2)] * timeBuffer[L2+M2-1-(2*k) + 0 * L2]; + i1 = i1 - ptr_pf[(L2+M2-1-(2*k) + 1 * L2)] * timeBuffer[L2+M2-1-(2*k) + 1 * L2]; + i1 = i1 - ptr_pf[(L2+M2-1-(2*k) + 2 * L2)] * timeBuffer[L2+M2-1-(2*k) + 2 * L2]; + i1 = i1 - ptr_pf[(L2+M2-1-(2*k) + 3 * L2)] * timeBuffer[L2+M2-1-(2*k) + 3 * L2]; + i1 = i1 - ptr_pf[(L2+M2-1-(2*k) + 4 * L2)] * timeBuffer[L2+M2-1-(2*k) + 4 * L2]; + + i2 = 0 - ptr_pf[(L2-3*M2+(2*k) + 0 * L2)] * timeBuffer[L2-3*M2+(2*k) + 0 * L2]; + i2 = i2 - ptr_pf[(L2-3*M2+(2*k) + 1 * L2)] * timeBuffer[L2-3*M2+(2*k) + 1 * L2]; + i2 = i2 - ptr_pf[(L2-3*M2+(2*k) + 2 * L2)] * timeBuffer[L2-3*M2+(2*k) + 2 * L2]; + i2 = i2 - ptr_pf[(L2-3*M2+(2*k) + 3 * L2)] * timeBuffer[L2-3*M2+(2*k) + 3 * L2]; + i2 = i2 - ptr_pf[(L2-3*M2+(2*k) + 4 * L2)] * timeBuffer[L2-3*M2+(2*k) + 4 * L2]; + + /* folding + pre modulation of DST IV */ + rr12 = r1 + r2; + ri12 = i1 - i2; + cplxMult(&rBuffer[2*k],&rBuffer[2*k+1],rr12,ri12,rot_vctr_re[k],rot_vctr_im[k]); + + /* folding + pre modulation of DCT IV */ + ir12 = r1 - r2; + ii12 = i1 + i2; + cplxMult(&iBuffer[2*k],&iBuffer[2*k+1],ir12,ii12,rot_vctr_re[k],rot_vctr_im[k]); + } + + /* FFT of DST IV */ + fft_cldfb(rBuffer, M2); + + /* post modulation of DST IV */ + for (k=0; k < M2; k++) + { + cplxMult(&realBuffer[i][M1-1-(2*k)],&realBuffer[i][2*k],rBuffer[2*k],rBuffer[2*k+1],rot_vctr_re[k],rot_vctr_im[k]); + } + + /* FFT of DCT IV */ + fft_cldfb(iBuffer, M2); + + /* post modulation of DCT IV */ + for (k=0; k < M2; k++) + { + /* do it inplace */ + cplxMult(&imagBuffer[i][2*k],&imagBuffer[i][M1-1-(2*k)],iBuffer[2*k],iBuffer[2*k+1],rot_vctr_re[k],rot_vctr_im[k]); + } + + timeBuffer += L2 * 5; + timeBuffer += h_cldfb->no_channels - h_cldfb->p_filter_length; + } + + return; +} + + +/*-------------------------------------------------------------------* + * cldfbSynthesis() + * + * Conduct inverse multple overlap cmplex low delay MDCT + *--------------------------------------------------------------------*/ +void cldfbSynthesis( + float **realBuffer, /* i : real values */ + float **imagBuffer, /* i : imag values */ + float *timeOut, /* o : output time domain samples */ + int samplesToProcess, /* i : number of processed samples */ + HANDLE_CLDFB_FILTER_BANK h_cldfb /* i : filter bank state */ +) +{ + int i; + int k; + int L2; + int M1; + int M2; + int M41; + int M42; + int Mz; + + float rBuffer[2*CLDFB_NO_CHANNELS_MAX]; + float iBuffer[2*CLDFB_NO_CHANNELS_MAX]; + const float *rot_vctr_re; + const float *rot_vctr_im; + float rr12, ir12; + float ri12, ii12; + + float *synthesisBuffer; + float new_samples[2*CLDFB_NO_CHANNELS_MAX]; + + float *ptr_time_out; + const float *p_filter; + + float accu0, accu1, accu2, accu3, accu4; + int no_col = h_cldfb->no_col; + + M1 = h_cldfb->no_channels; + L2 = M1 << 1; + M2 = M1 >> 1; + M41 = M2>>1; + M42 = M2-M41; + Mz = M1 - h_cldfb->bandsToZero; + + /* only process needed cols */ + if(samplesToProcess > -1) + { + no_col = min(no_col, (samplesToProcess + h_cldfb->no_channels - 1) / h_cldfb->no_channels); + } + + rot_vctr_re = h_cldfb->rot_vec_syn_re; + rot_vctr_im = h_cldfb->rot_vec_syn_im; + + synthesisBuffer = h_cldfb->cldfb_state; + p_filter = h_cldfb->p_filter; + ptr_time_out = timeOut; + + mvr2r( synthesisBuffer, synthesisBuffer + M1 * h_cldfb->no_col, h_cldfb->p_filter_length ); + + synthesisBuffer += M1 * h_cldfb->no_col; + + for (k=0; k < no_col; k++) + { + for (i=Mz; i < M1; i++) + { + realBuffer[k][i] = 0.0f; + imagBuffer[k][i] = 0.0f; + } + + for (i=0; i < M2; i++) + { + /* pre modulation of DST IV */ + cplxMult(&rBuffer[2*i], &rBuffer[2*i+1], realBuffer[k][2*i], realBuffer[k][M1-1-2*i], rot_vctr_re[i], rot_vctr_im[i]); + + /* pre modulation of DCT IV */ + cplxMult(&iBuffer[2*i], &iBuffer[2*i+1],-imagBuffer[k][2*i], imagBuffer[k][M1-1-2*i], rot_vctr_re[i], rot_vctr_im[i]); + } + + /* FFT of DST IV */ + fft_cldfb(rBuffer, M2); + + /* FFT of DCT IV */ + fft_cldfb(iBuffer, M2); + + /* folding */ + for (i=0; ino_col = CLDFB_NO_COL_MAX; + h_cldfb->bandsToZero = 0; + h_cldfb->nab = 0; + + h_cldfb->no_channels = samplerate * INV_CLDFB_BANDWIDTH + 0.5f; + h_cldfb->p_filter_length = 10*h_cldfb->no_channels; + + cldfb_init_proto_and_twiddles (h_cldfb); + + h_cldfb->scale = 0.f; + for ( k=0; kp_filter_length; k++ ) + { + h_cldfb->scale += h_cldfb->p_filter[k] * h_cldfb->p_filter[k]; + } + + h_cldfb->scale *= (float)(6400/h_cldfb->no_channels); + h_cldfb->scale = (float)sqrt( h_cldfb->scale ); + + return; +} + +/*-------------------------------------------------------------------* + * openClfdb() + * + * open and configures a CLDFB handle + *--------------------------------------------------------------------*/ +int openCldfb( + HANDLE_CLDFB_FILTER_BANK *h_cldfb, /* i/o : filter bank handle */ + CLDFB_TYPE type, /* i : analysis or synthesis */ + int samplerate /* i : max samplerate to oeprate */ +) +{ + HANDLE_CLDFB_FILTER_BANK hs; + short buf_len; + + hs = (HANDLE_CLDFB_FILTER_BANK) calloc(1, sizeof (CLDFB_FILTER_BANK)); + if( hs == NULL ) + { + return (1); + } + + hs->type = type; + + configureCldfb (hs, samplerate); + hs->memory = NULL; + hs->memory_length = 0; + + if (type == CLDFB_ANALYSIS) + { + short timeOffset = hs->p_filter_length - hs->no_channels; + buf_len = (hs->no_channels*hs->no_col+timeOffset); + } + else + { + buf_len = (hs->p_filter_length + hs->no_channels*hs->no_col); + } + + hs->cldfb_state = (float *) calloc( buf_len, sizeof (float)); + if (hs->cldfb_state == NULL) + { + return (1); + } + + set_f(hs->cldfb_state, 0.0f, buf_len); + + *h_cldfb = hs; + + return (0); +} + + +/*-------------------------------------------------------------------* +* resampleCldfb() +* +* Change sample rate of filter bank +*--------------------------------------------------------------------*/ +void resampleCldfb( + HANDLE_CLDFB_FILTER_BANK hs, + int newSamplerate +) +{ + short timeOffset, newframeSize; + + /* keep old parameters before switching*/ + int timeOffsetold = hs->p_filter_length - hs->no_channels; + int old_no_channels = hs->no_channels; + + /* new settings */ + configureCldfb (hs, newSamplerate); + timeOffset = hs->p_filter_length - hs->no_channels; + newframeSize = hs->no_channels * hs->no_col; + + /*low complexity-resampling only stored previous samples that are needed for next frame modulation */ + lerp(hs->cldfb_state+(old_no_channels*hs->no_col),hs->cldfb_state+(old_no_channels*hs->no_col),timeOffset, timeOffsetold); + mvr2r(hs->cldfb_state+(old_no_channels*hs->no_col),hs->cldfb_state+newframeSize,timeOffset); + + return; +} + +/*-------------------------------------------------------------------* +* analysisCLDFBEncoder() +* +* Encoder CLDFB analysis + energy stage +*--------------------------------------------------------------------*/ + +void analysisCldfbEncoder( + Encoder_State *st, /* i/o: encoder state structure */ + const float *timeIn, + int samplesToProcess, + float realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + float imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + float *ppBuf_Ener +) +{ + short i; + float *ppBuf_Real[CLDFB_NO_COL_MAX]; + float *ppBuf_Imag[CLDFB_NO_COL_MAX]; + + for( i=0; icldfbAnaEnc ); + + st->currEnergyHF = GetEnergyCldfb( ppBuf_Ener, &st->currEnergyLookAhead, ppBuf_Real, ppBuf_Imag, + st->cldfbAnaEnc->no_channels, st->cldfbAnaEnc->no_col, &(st->tecEnc) ); + + return; +} + +/*-------------------------------------------------------------------* +* GetEnergyCldfb() +* +* Conduct energy from complex data +*--------------------------------------------------------------------*/ +static float GetEnergyCldfb( + float *energyValuesSum,/*!< the result of the operation */ + float *energyLookahead, /*!< the result in the core look-ahead slot */ + float **realValues, /*!< the real part of the subsamples */ + float **imagValues, /*!< the imaginary part of the subsamples */ + int numberBands, /*!< number of bands */ + int numberCols, /*!< number of subsamples */ + HANDLE_TEC_ENC hTecEnc +) +{ + short j, k; + float energyValues[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + short numLookahead = 1; + + for (k = 0; k < numberCols; k++) + { + for (j = 0; j < numberBands; j++) + { + energyValues[k][j] = realValues[k][j] * realValues[k][j] + + imagValues[k][j] * imagValues[k][j]; + } + } + + if(numberBands >= freqTable[1]) + { + float *tempEnergyValuesArry[CLDFB_NO_COL_MAX]; + + assert(numberCols == CLDFB_NO_COL_MAX); + for (j=0; jloBuffer, hTecEnc->hiTempEnv ); + } + + for (j = 0; j < numberBands; j++) + { + energyValuesSum[j]=0; + for (k = 0; k < CLDFB_NO_COL_MAX; k++) + { + energyValuesSum[j] += energyValues[k][j]; + } + } + + if (numberBands > 20) + { + float energyHF = *energyLookahead; /* energy above 8 kHz */ + numberCols -= numLookahead; + *energyLookahead = 6.1e-5f; /* process look-ahead region */ + + for (j = 20; j < min(40, numberBands); j++) + { + energyHF += energyValuesSum[j]; + + for (k = numberCols; k < CLDFB_NO_COL_MAX; k++) + { + energyHF -= energyValues[k][j]; + *energyLookahead += energyValues[k][j]; + } + } + + return energyHF * OUTMAX_SQ_INV; + } + + return 65535.0f; +} + + +/*-------------------------------------------------------------------* +* GetEnergyCldfb() +* +* Remove handle +*--------------------------------------------------------------------*/ +void deleteCldfb( + HANDLE_CLDFB_FILTER_BANK * h_cldfb +) +{ + HANDLE_CLDFB_FILTER_BANK hs = *h_cldfb; + + if (hs) + { + if (hs->cldfb_state) + { + free(hs->cldfb_state); + } + free(hs); + *h_cldfb = NULL; + } + + return; +} + + +/*-------------------------------------------------------------------* +* cldfb_init_proto_and_twiddles() +* +* Initializes rom pointer +*--------------------------------------------------------------------*/ +static void cldfb_init_proto_and_twiddles( + HANDLE_CLDFB_FILTER_BANK hs +) +{ + + /*find appropriate set of rotVecs*/ + switch(hs->no_channels) + { + case 10: + hs->rot_vec_ana_re = rot_vec_ana_re_L10; + hs->rot_vec_ana_im = rot_vec_ana_im_L10; + hs->rot_vec_syn_re = rot_vec_syn_re_L10; + hs->rot_vec_syn_im = rot_vec_syn_im_L10; + hs->p_filter = CLDFB80_10; + break; + + case 16: + hs->rot_vec_ana_re = rot_vec_ana_re_L16; + hs->rot_vec_ana_im = rot_vec_ana_im_L16; + hs->rot_vec_syn_re = rot_vec_syn_re_L16; + hs->rot_vec_syn_im = rot_vec_syn_im_L16; + hs->p_filter = CLDFB80_16; + break; + + case 20: + hs->rot_vec_ana_re = rot_vec_ana_re_L20; + hs->rot_vec_ana_im = rot_vec_ana_im_L20; + hs->rot_vec_syn_re = rot_vec_syn_re_L20; + hs->rot_vec_syn_im = rot_vec_syn_im_L20; + hs->p_filter = CLDFB80_20; + break; + + case 30: + hs->rot_vec_ana_re = rot_vec_ana_re_L30; + hs->rot_vec_ana_im = rot_vec_ana_im_L30; + hs->rot_vec_syn_re = rot_vec_syn_re_L30; + hs->rot_vec_syn_im = rot_vec_syn_im_L30; + hs->p_filter = CLDFB80_30; + break; + + case 32: + hs->rot_vec_ana_re = rot_vec_ana_re_L32; + hs->rot_vec_ana_im = rot_vec_ana_im_L32; + hs->rot_vec_syn_re = rot_vec_syn_re_L32; + hs->rot_vec_syn_im = rot_vec_syn_im_L32; + hs->p_filter = CLDFB80_32; + break; + + case 40: + hs->rot_vec_ana_re = rot_vec_ana_re_L40; + hs->rot_vec_ana_im = rot_vec_ana_im_L40; + hs->rot_vec_syn_re = rot_vec_syn_re_L40; + hs->rot_vec_syn_im = rot_vec_syn_im_L40; + hs->p_filter = CLDFB80_40; + break; + + case 60: + hs->rot_vec_ana_re = rot_vec_ana_re_L60; + hs->rot_vec_ana_im = rot_vec_ana_im_L60; + hs->rot_vec_syn_re = rot_vec_syn_re_L60; + hs->rot_vec_syn_im = rot_vec_syn_im_L60; + hs->p_filter = CLDFB80_60; + break; + + } + + return; +} + + +/*-------------------------------------------------------------------* +* cldfb_save_memory() +* +* Save the memory of filter; to be restored with cldfb_restore_memory() +*--------------------------------------------------------------------*/ +int cldfb_save_memory( + HANDLE_CLDFB_FILTER_BANK hs /* i/o: cldfb handle */ +) +{ + unsigned int offset = hs->p_filter_length - hs->no_channels; + unsigned int frameSize = hs->no_channels * hs->no_col; + + if (hs->memory != NULL || hs->memory_length!=0) + { + /* memory already stored; Free memory first */ + return 1; + } + + + if (hs->type == CLDFB_ANALYSIS) + { + hs->memory_length = offset + frameSize; + } + else + { + hs->memory_length = hs->p_filter_length; + } + + hs->memory = (float *) calloc( hs->memory_length, sizeof (float)); + if (hs->memory == NULL) + { + /* memory cannot be allocated */ + return (1); + } + + /* save the memory */ + mvr2r (hs->cldfb_state, hs->memory, hs->memory_length); + + return 0; +} + + +/*-------------------------------------------------------------------* +* cldfb_restore_memory() +* +* Restores the memory of filter; memory to be save by cldfb_save_memory() +*--------------------------------------------------------------------*/ +int cldfb_restore_memory( + HANDLE_CLDFB_FILTER_BANK hs /* i/o: cldfb handle */ +) +{ + unsigned int offset = hs->p_filter_length - hs->no_channels; + unsigned int frameSize = hs->no_channels * hs->no_col; + unsigned int size; + + if (hs->memory == NULL || hs->memory_length==0) + { + /* memory not allocated */ + return 1; + } + + if ( hs->type == CLDFB_ANALYSIS ) + { + size = offset + frameSize; + } + else + { + size = hs->p_filter_length; + } + + /* read the memory */ + mvr2r (hs->memory, hs->cldfb_state, hs->memory_length); + + /* adjust sample rate if it was changed in the meanwhile */ + if (hs->memory_length != size) + { + lerp(hs->cldfb_state, hs->cldfb_state, size, hs->memory_length); + } + + hs->memory_length = 0; + free(hs->memory); + hs->memory = NULL; + + return 0; +} + + +/*-------------------------------------------------------------------* +* cldfb_reset_memory() +* +* Resets the memory of filter. +*--------------------------------------------------------------------*/ +int cldfb_reset_memory( + HANDLE_CLDFB_FILTER_BANK hs /* i/o: cldfb handle */ +) +{ + unsigned int offset = hs->p_filter_length - hs->no_channels; + unsigned int frameSize = hs->no_channels * hs->no_col; + int memory_length; + + if (hs->type == CLDFB_ANALYSIS) + { + memory_length = offset + frameSize; + } + else + { + memory_length = hs->p_filter_length; + } + + /* save the memory */ + set_f (hs->cldfb_state, 0, memory_length); + + return 0; +} diff --git a/lib_com/cng_exc.c b/lib_com/cng_exc.c new file mode 100644 index 000000000..f193b861b --- /dev/null +++ b/lib_com/cng_exc.c @@ -0,0 +1,558 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ + +#define A2 0.2f +#define GAIN_VAR 0.000011f + +/*-------------------------------------------------------* + * CNG_exc() + * + * Comfort noise generation routine + *-------------------------------------------------------*/ + +void CNG_exc( + const long core_brate, /* i : core bitrate */ + const short L_frame, /* i : length of the frame */ + float *Enew, /* i/o: decoded SID energy */ + short *seed, /* i/o: random generator seed */ + float exc[], /* o : current non-enhanced excitation */ + float exc2[], /* o : current enhanced excitation */ + float *lp_ener, /* i/o: LP filtered E */ + const long last_core_brate, /* i : previous frame core bitrate */ + short *first_CNG, /* i/o: first CNG frame flag for energy init. */ + short *cng_ener_seed, /* i/o: random generator seed for CNG energy */ + float bwe_exc[], /* o : excitation for SWB TBE */ + const short allow_cn_step, /* i : allow CN step */ + short *last_allow_cn_step, /* i/o: last allow step */ + const short num_ho, /* i : number of selected hangover frames */ + float q_env[], + float *lp_env, + float *old_env, + float *exc_mem, + float *exc_mem1, + short *sid_bw, + short *cng_ener_seed1, + float exc3[], + short Opt_AMR_WB +) +{ + float enr; + short i; + float ener_lp; + short i_subfr; + short pit_max; + float ftmp; + float *ptR,*ptI; + float fft_io[L_FRAME16k]; + float itmp[129]; + float env[NUM_ENV_CNG]; + float enr1; + float denv[NUM_ENV_CNG]; + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + + if( L_frame == L_FRAME ) + { + pit_max = PIT_MAX; + } + else /* L_frame == L_FRAME16k */ + { + pit_max = PIT16k_MAX; + } + + /*---------------------------------------------------------------------* + * Initialization of CNG energy for the first CNG frame + *---------------------------------------------------------------------*/ + + if( *first_CNG == 0 ) + { + if( 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 */ + *Enew = dotp( exc-pit_max, exc-pit_max, pit_max ) / pit_max; + } + + *lp_ener = *Enew; + } + + /*---------------------------------------------------------------------* + * Update CNG energy + *---------------------------------------------------------------------*/ + + if( last_core_brate != SID_1k75 && last_core_brate != FRAME_NO_DATA && last_core_brate != SID_2k40 ) + { + /* Partially reset CNG energy after active speech period */ + if ( allow_cn_step == 0 && *last_allow_cn_step == 0 ) + { + if( num_ho < 3 || *Enew < 1.5f * *lp_ener ) + { + *lp_ener = 0.8f * *lp_ener + 0.2f * *Enew; + } + else + { + *lp_ener = 0.95f * *lp_ener + 0.05f * *Enew; + } + } + else + { + *lp_ener = *Enew; + *last_allow_cn_step = 0; + } + } + else + { + /* normal CNG update */ + if ( *last_allow_cn_step == 0 ) + { + *lp_ener = (float)(A2 **Enew + (1-A2) **lp_ener); + } + else + { + if ( core_brate == SID_1k75 || core_brate == SID_2k40 ) + { + *last_allow_cn_step = 0; + } + + *lp_ener = *Enew; + + } + } + + if ( allow_cn_step == 1 ) + { + *last_allow_cn_step = 1; + } + + /*---------------------------------------------------------------------* + * Generate white noise vector + *---------------------------------------------------------------------*/ + + for ( i=0; i 1 ) + { + enr = 1; + } + } + + for ( i=0; i 1 ) + { + enr = 1; + } + + ftmp = sqrt(enr); + for (i=0; i ACELP_13k20 ) + { + CNG_mode = 4; + } + else if( last_active_brate > ACELP_9k60 ) + { + CNG_mode = 3; + } + else if( last_active_brate > ACELP_8k00 ) + { + CNG_mode = 2; + } + else if( last_active_brate > ACELP_7k20 ) + { + CNG_mode = 1; + } + else + { + CNG_mode = 0; + } + + att = 1/pow(2,ENR_ATT[CNG_mode]); + + for ( i=0; i HO_HIST_SIZE) + { + *cng_buf_cnt = HO_HIST_SIZE; + } + mvr2r( exc2, &(cng_exc2_buf[(*ho_circ_ptr)*L_FFT]), L_FFT ); + cng_brate_buf[*ho_circ_ptr] = last_active_brate; + } + else + { + + /* calculate the spectrum of residual signal */ + mvr2r(exc2, fft_io, L_frame); + + fft_rel(fft_io, L_FFT, LOG2_L_FFT); + + ptR = &fft_io[1]; + ptI = &fft_io[L_FFT-1]; + for (i=0; i ACELP_13k20 ) + { + CNG_mode = 4; + } + else if( last_active_brate > ACELP_9k60 ) + { + CNG_mode = 3; + } + else if( last_active_brate > ACELP_8k00 ) + { + CNG_mode = 2; + } + else if( last_active_brate > ACELP_7k20 ) + { + CNG_mode = 1; + } + else + { + CNG_mode = 0; + } + + att = 1/pow(2,ENR_ATT[CNG_mode]); + + for ( i=0; i HO_HIST_SIZE ) + { + *ho_circ_size = HO_HIST_SIZE; + } + + return; +} diff --git a/lib_com/cnst.h b/lib_com/cnst.h new file mode 100644 index 000000000..21d2eaf9c --- /dev/null +++ b/lib_com/cnst.h @@ -0,0 +1,2005 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#ifndef CNST_H +#define CNST_H + +#include "options.h" + +/*----------------------------------------------------------------------------------* + * General constants + *----------------------------------------------------------------------------------*/ + +#define MODE1 1 +#define MODE2 2 + +#define EVS_PI 3.14159265358979323846264338327950288f + +#define PI2 (2*EVS_PI) +#define RANDOM_INITSEED 21845 /* Seed for random generators */ +#ifndef FLT_MIN +#define FLT_MIN (1.175494351e-38F) +#endif +#ifndef FLT_MAX +#define FLT_MAX (3.402823466e+38F) +#endif +#define TRUE 1 +#define FALSE 0 + + +#define MAX_FRAME_COUNTER 200 +#define MAX_BITS_PER_FRAME 2560 + +#define ENC 0 /* Index for "encoder" */ +#define DEC 1 /* Index for "decoder" */ + +#define NB 0 /* Indicator of 4 kHz bandwidth */ +#define WB 1 /* Indicator of 8 kHz bandwidth */ +#define SWB 2 /* Indicator of 14 kHz bandwidth */ +#define FB 3 /* Indicator of 20 kHz bandwidth */ + +/* Conversion of bandwidth string into numerical constant */ +#define CONV_BWIDTH(bw) ( !strcmp(bw, "NB") ? NB : !strcmp(bw, "WB") ? WB : !strcmp(bw, "SWB") ? SWB : !strcmp(bw, "FB") ? FB : -1) + +#define L_FRAME48k 960 /* Frame size in samples at 48kHz */ +#define L_FRAME32k 640 /* Frame size in samples at 32kHz */ +#define L_FRAME16k 320 /* Frame size in samples at 16kHz */ +#define L_FRAME8k 160 /* Frame size in samples at 8kHz */ + +/* Conversion of ns to samples for a given sampling frequency */ +#define NS2SA(fs,x) (short)((((long)(fs)/100L) * ((x)/100L)) / 100000L) + +#define SYNC_GOOD_FRAME (unsigned short) 0x6B21 /* synchronization word of a "good" frame */ +#define SYNC_BAD_FRAME (unsigned short) 0x6B20 /* synchronization word of a "bad" frame */ +#define G192_BIN0 (unsigned short) 0x007F /* binary "0" according to ITU-T G.192 */ +#define G192_BIN1 (unsigned short) 0x0081 /* binary "1" according to ITU-T G.192 */ + +#define ACTIVE_FRAME 0xFF +#define SID_FRAME 0xFA +#define ZERO_FRAME 0xF0 +#define FRAME_SIZE_NB 13 + +#define RATE_MODE_MAX 2 /* Number of rate mode */ +#define BANDWIDTH_MODE_MAX 2 /* Number of different bandwidth (NB/WB-FB) */ + +#define MIN_LOG_60dB 0.000001f +#define MIN_LOG_VAL_60dB -60.0f + +#define INV_LOG_2 1.442695040888963f /* 1/log(2) */ + + +/*----------------------------------------------------------------------------------* + * Layers + *----------------------------------------------------------------------------------*/ + +#define ACELP_CORE 0 /* ACELP core layer */ +#define TCX_20_CORE 1 /* TCX 20ms core layer */ +#define TCX_10_CORE 2 /* TCX 10ms core layer */ +#define HQ_CORE 3 /* HQ core layer */ +#define AMR_WB_CORE 4 /* AMR-WB IO core */ + + +#define WB_TBE 5 /* WB TBE layer (16/32/48kHz signals) */ +#define WB_BWE 6 /* WB BWE layer optimized for music (16/32/48kHz signals) */ + +#define SWB_CNG 7 /* SWB CNG layer (32/48kHz signals) */ +#define SWB_TBE 8 /* SWB TBE layer optimized for speech (32/48kHz signals) */ +#define SWB_BWE 9 /* SWB BWE layer optimized for music (32/48kHz signals) */ +#define SWB_BWE_HIGHRATE 10 /* SWB BWE layer optimized for highrate speech (32/48kHz) */ + +#define FB_TBE 11 /* FB TBE layer (48kHz signals) */ +#define FB_BWE 12 /* FB BWE layer optimized for music (48kHz) */ +#define FB_BWE_HIGHRATE 13 /* FB BWE layer optimized for highrate speech (48kHz) */ + +#define IGF_BWE 14 /* IGF layer for music (16.4 and 24.4kbps), 32kHz signals */ + +#define LP_CNG 0 /* LP-based CNG in DTX operation */ +#define FD_CNG 1 /* FD-based CNG in DTX operation */ + +/*----------------------------------------------------------------------------------* + * Bitrates + *----------------------------------------------------------------------------------*/ + +#define FRAME_NO_DATA 0 /* Frame with no data */ +#define SID_1k75 1750 /* SID at 1.75 kbps (used only in AMR-WB IO mode */ +#define SID_2k40 2400 /* SID at 2.40 kbps */ +#define PPP_NELP_2k80 2800 /* PPP and NELP at 2.80 kbps (used only for SC-VBR) */ +#define ACELP_5k90 5900 /* ACELP core layer at average bitrate of 5.90 kbps (used only in SC-VBR mode) */ +#define ACELP_6k60 6600 /* ACELP core layer at 6.60 kbps (used only in AMR-WB IO mode) */ +#define ACELP_7k20 7200 /* ACELP core layer at 7.20 kbps */ +#define ACELP_8k00 8000 /* ACELP core layer at 8 kbps */ +#define ACELP_8k85 8850 /* ACELP core layer at 8.85 kbps (used only in AMR-WB IO mode) */ +#define ACELP_9k60 9600 /* ACELP core layer at 9.60 kbps */ +#define ACELP_11k60 11600 /* ACELP core layer at 11.60 kbps (used for SWB TBE) */ +#define ACELP_12k15 12150 /* ACELP core layer at 12.15 kbps (used for WB TBE) */ +#define ACELP_12k65 12650 /* ACELP core layer at 12.65 kbps (used only in AMR-WB IO mode) */ +#define ACELP_12k85 12850 /* ACELP core layer at 12.85 kbps (used for WB BWE) */ +#define ACELP_13k20 13200 /* ACELP core layer at 13.20 kbps */ +#define ACELP_14k25 14250 /* ACELP core layer at 14.25 kbps (used only in AMR-WB IO mode) */ +#define ACELP_14k80 14800 /* ACELP core layer at 14.80 kbps (used only in core switching) */ +#define ACELP_15k85 15850 /* ACELP core layer at 15.85 kbps (used only in AMR-WB IO mode) */ +#define ACELP_16k40 16400 /* ACELP core layer at 16.40 kbps */ +#define ACELP_18k25 18250 /* ACELP core layer at 18.25 kbps (used only in AMR-WB IO mode) */ +#define ACELP_19k85 19850 /* ACELP core layer at 19.85 kbps (used only in AMR-WB IO mode) */ +#define ACELP_22k60 22600 /* ACELP core layer at 22.60 kbps (used only in core switching) */ +#define ACELP_23k05 23050 /* ACELP core layer at 23.05 kbps (used only in AMR-WB IO mode) */ +#define ACELP_23k85 23850 /* ACELP core layer at 23.85 kbps (used only in AMR-WB IO mode) */ +#define ACELP_24k40 24400 /* ACELP core layer at 24.40 kbps */ +#define ACELP_29k00 29000 /* ACELP core layer at 29.00 kbps (used for FB + SWB TBE) */ +#define ACELP_29k20 29200 /* ACELP core layer at 29.20 kbps (used for SWB TBE) */ +#define ACELP_30k20 30200 /* ACELP core layer at 30.20 kbps (used for FB + SWB BWE) */ +#define ACELP_30k40 30400 /* ACELP core layer at 30.40 kbps (used for SWB BWE) */ +#define ACELP_32k 32000 /* ACELP core layer at 32 kbps */ +#define ACELP_48k 48000 /* ACELP core layer at 48 kbps */ +#define ACELP_64k 64000 /* ACELP core layer at 64 kbps */ + +#define HQ_16k40 16400 /* HQ core at 16.4 kbps */ +#define HQ_13k20 13200 /* HQ core at 13.2 kbps */ +#define HQ_24k40 24400 /* HQ core at 24.4 kbps */ +#define HQ_32k 32000 /* HQ core at 32 kbps */ +#define HQ_48k 48000 /* HQ core at 48 kbps */ +#define HQ_64k 64000 /* HQ core at 64 kbps */ +#define HQ_96k 96000 /* HQ core at 96 kbps */ +#define HQ_128k 128000 /* HQ core at 128 kbps */ + +#define WB_TBE_0k35 350 /* WB TBE layer (used only at 9.6 kbps on top of ACELP@12k8 core for 16kHz signals) */ +#define WB_BWE_0k35 350 /* WB BWE layer (used only on top of ACELP@12k8 core for 16kHz signals) */ +#define WB_TBE_1k05 1050 /* WB TBE layer (used only on top of ACELP@12k8 core for 16kHz signals) */ +#define SWB_TBE_1k6 1600 /* SWB TBE layer */ +#define SWB_BWE_1k6 1600 /* SWB BWE layer */ +#define FB_TBE_1k8 1800 /* SWB+FB TBE layer (used only for 48kHz signals) */ +#define FB_BWE_1k8 1800 /* SWB+FB BWE layer (used only for 48kHz signals) */ +#define SWB_TBE_2k8 2800 /* SWB TBE layer @32kbps */ +#define FB_TBE_3k0 3000 /* SWB+FB TBE layer @32kbps (used only for 48kHz signals) */ +#define SWB_BWE_16k 16000 /* SWB BWE layer for highrate SWB speech */ + +#define SIZE_BRATE_TBL 11 + +#define BRATE2IDX(brate) ( brate == ACELP_7k20 ? 0: \ + brate == ACELP_8k00 ? 1 : \ + brate == ACELP_11k60 ? 2 : \ + brate == ACELP_12k15 ? 3 : \ + brate == ACELP_12k85 ? 4 : \ + brate == ACELP_13k20 ? 5 : \ + brate == ACELP_14k80 ? 6 : \ + brate == ACELP_16k40 ? 7 : \ + brate == ACELP_22k60 ? 8 : \ + brate == ACELP_24k40 ? 9 : \ + brate == ACELP_29k00 ? 10 : \ + brate == ACELP_29k20 ? 11 : \ + brate == ACELP_30k20 ? 12 : \ + brate == ACELP_30k40 ? 13 : \ + brate == ACELP_32k ? 14 : \ + brate == ACELP_48k ? 15 : \ + brate == ACELP_64k ? 16 : \ + brate == HQ_96k ? 17 : \ + brate == HQ_128k ? 18 : -1 ) + +#define BRATE2IDX16k( brate ) ( brate == ACELP_8k00 ? 0 : \ + brate == ACELP_14k80 || brate == ACELP_16k40? 1 : \ + brate == ACELP_22k60 ? 2 : \ + brate == ACELP_24k40 ? 3 : \ + brate == ACELP_29k00 ? 4 : \ + brate == ACELP_29k20 ? 5 : \ + brate == ACELP_30k20 ? 6 : \ + brate == ACELP_30k40 ? 7 : \ + brate == ACELP_32k ? 8 : \ + brate == ACELP_48k ? 9 : \ + brate == ACELP_64k ? 10: -1 ) + +/* Combine parameters into a single index (used to retrieve number of bits from bit allocation tables) */ +#define LSF_BIT_ALLOC_IDX(brate, ctype) ( 6*BRATE2IDX(brate) + (ctype) ) + +#define BIT_ALLOC_IDX(brate, ctype, sfrm, tc) \ + ( ( sfrm != -1 ? NB_SUBFR : 1 ) * \ + ( ( tc == -1 ? 4 : 10 ) * BRATE2IDX(brate) + (ctype == INACTIVE ? GENERIC : ctype) - 1 + (tc == -1 ? 0 : tc) ) + \ + ( sfrm != -1 ? sfrm/L_SUBFR : 0 ) ) + +#define BIT_ALLOC_IDX_16KHZ(brate, ctype, sfrm, tc) \ + ( ( sfrm > -1 ? NB_SUBFR16k : 1 ) * \ + ( ( tc == -1 ? 3 : 7 ) * BRATE2IDX16k(brate) + (ctype == TRANSITION ? 2 : (ctype == GENERIC ? 1 :0) ) + (tc == -1 ? 0 : tc) ) + \ + ( sfrm != -1 ? sfrm/L_SUBFR : 0 ) ) + +/* 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) ) + +#define MAX_ACELP_SIG 100 + +/*----------------------------------------------------------------------------------* + * Bitstream indices + *----------------------------------------------------------------------------------*/ +#define MAX_PVQ_PUSH_IND 320 /* Maximum number of (fwd+reverse) calls to push_indices for the PVQ_range encoder */ +enum +{ + IND_CORE, + IND_PPP_NELP_MODE, + IND_SID_TYPE, + IND_ACELP_16KHZ, + IND_ACELP_SIGNALLING, + IND_MDCT_CORE, + IND_BWE_FLAG, + IND_HQ_SWITCHING_FLG, + IND_LAST_L_FRAME, + IND_VAD_FLAG, + IND_HQ_BWIDTH, + IND_TC_SUBFR, + IND_LSF_PREDICTOR_SELECT_BIT = IND_TC_SUBFR + 4, + IND_LSF, + IND_MID_FRAME_LSF_INDEX = IND_LSF + 17, + + IND_ISF_0_0, + IND_ISF_0_1, + IND_ISF_0_2, + IND_ISF_0_3, + IND_ISF_0_4, + IND_ISF_1_0, + IND_ISF_1_1, + IND_ISF_1_2, + IND_ISF_1_3, + IND_ISF_1_4, + + IND_GSC_ATTACK, + IND_GSC_SWB_SPEECH, + IND_NOISE_LEVEL, + IND_HF_NOISE, + IND_PIT_CONTR_IDX, + IND_FEC_CLAS, + IND_FEC_ENR, + IND_FEC_POS, + IND_ES_PRED, + IND_HARM_FLAG_ACELP, + /* ------------- Loop for alg. codebook indices at 24.4 kbps (special case) -------------- */ + TAG_ALG_CDBK_4T64_24KBIT_START, + IND_ALG_CDBK_4T64_1_24KBIT = TAG_ALG_CDBK_4T64_24KBIT_START, + IND_ALG_CDBK_4T64_2_24KBIT = TAG_ALG_CDBK_4T64_24KBIT_START, + TAG_ALG_CDBK_4T64_24KBIT_END = TAG_ALG_CDBK_4T64_24KBIT_START + 40, + /* ------------------------------------------------ */ + + /* ------------- ACELP subframe loop -------------- */ + TAG_ACELP_SUBFR_LOOP_START, + IND_PITCH = TAG_ACELP_SUBFR_LOOP_START, + IND_LP_FILT_SELECT = TAG_ACELP_SUBFR_LOOP_START, + IND_ALG_CDBK_1T64 = TAG_ACELP_SUBFR_LOOP_START, + IND_ALG_CDBK_2T32 = TAG_ACELP_SUBFR_LOOP_START, + IND_ALG_CDBK_4T64 = TAG_ACELP_SUBFR_LOOP_START, + IND_ALG_CDBK_4T64_1 = TAG_ACELP_SUBFR_LOOP_START, + IND_ALG_CDBK_4T64_2 = TAG_ACELP_SUBFR_LOOP_START, + IND_ALG_CDBK_4T64_1BIT = TAG_ACELP_SUBFR_LOOP_START, + IND_GAUS_CDBK_INDEX = TAG_ACELP_SUBFR_LOOP_START, + IND_TILT_FACTOR = TAG_ACELP_SUBFR_LOOP_START, + IND_GAIN = TAG_ACELP_SUBFR_LOOP_START, + IND_GAIN_CODE = TAG_ACELP_SUBFR_LOOP_START, + IND_TC_IMP_SHAPE = TAG_ACELP_SUBFR_LOOP_START, + IND_TC_IMP_POS = TAG_ACELP_SUBFR_LOOP_START, + IND_TC_IMP_SIGN = TAG_ACELP_SUBFR_LOOP_START, + IND_TC_IMP_GAIN = TAG_ACELP_SUBFR_LOOP_START, + IND_GAIN_PIT = TAG_ACELP_SUBFR_LOOP_START, + IND_PIT_IDX = TAG_ACELP_SUBFR_LOOP_START, + IND_AVQ_GAIN = TAG_ACELP_SUBFR_LOOP_START, + IND_I = TAG_ACELP_SUBFR_LOOP_START, + IND_KV = TAG_ACELP_SUBFR_LOOP_START, + IND_NQ = TAG_ACELP_SUBFR_LOOP_START, + IND_HF_GAIN_MODIFICATION = TAG_ACELP_SUBFR_LOOP_START, + TAG_ACELP_SUBFR_LOOP_END = TAG_ACELP_SUBFR_LOOP_START + 300, + /* ------------------------------------------------ */ + + IND_MEAN_GAIN2, + IND_Y_GAIN_TMP = IND_MEAN_GAIN2 + 32, + IND_Y_GAIN_HF = IND_Y_GAIN_TMP + 32, + IND_HQ_VOICING_FLAG, + IND_HQ_SWB_CLAS, + IND_NF_IDX, + IND_LC_MODE, + IND_YNRM, + IND_HQ_SWB_EXC_SP_CLAS = IND_YNRM + 44, + IND_HQ_SWB_EXC_CLAS = IND_HQ_SWB_EXC_SP_CLAS, + IND_SWB_FENV_HQ = IND_HQ_SWB_EXC_CLAS, + IND_FB_FENV_HQ = IND_SWB_FENV_HQ + 5, + IND_DELTA_ENV_HQ = IND_FB_FENV_HQ + 5, + IND_HVQ_BWE_NL, + IND_NUM_PEAKS = IND_HVQ_BWE_NL + 2, + IND_POS_IDX, + IND_FLAGN = IND_POS_IDX + 280, + IND_PG_IDX, + IND_HVQ_PEAKS = IND_PG_IDX + 27, + IND_HVQ_NF_GAIN = IND_HVQ_PEAKS + 54, + IND_HQ2_SWB_CLAS = IND_HVQ_NF_GAIN + 2, + IND_HQ2_DENG_MODE, + IND_HQ2_DENG_8SMODE, + IND_HQ2_DENG_8SMODE_N0, + IND_HQ2_DENG_8SMODE_N1, + IND_HQ2_DENG_8SPOS, + IND_HQ2_DENG_8SDEPTH, + IND_HQ2_DENG_HMODE, + IND_HQ2_DIFF_ENERGY, + IND_HQ2_P2A_FLAGS = IND_HQ2_DIFF_ENERGY + 100, + IND_HQ2_LAST_BA_MAX_BAND = IND_HQ2_P2A_FLAGS + 60, + IND_RC_START = IND_HQ2_LAST_BA_MAX_BAND + 2, + IND_RC_END = IND_RC_START + MAX_PVQ_PUSH_IND , + IND_HVQ_PVQ_GAIN = IND_RC_END+1, + IND_NOISINESS = IND_HVQ_PVQ_GAIN + 8, + IND_ENERGY, + IND_CNG_HO, + IND_SID_BW, + IND_CNG_ENV1, + IND_WB_FENV, + IND_WB_CLASS, + IND_IG1, + IND_IG2A, + IND_IG2B, + IND_NELP_FID, + IND_DELTALAG, + IND_POWER, + IND_AMP0, + IND_AMP1, + IND_GLOBAL_ALIGNMENT, + IND_PVQ_FINE_GAIN, + IND_UV_FLAG, + IND_SHB_SUBGAIN = IND_PVQ_FINE_GAIN + 44, + IND_SHB_FRAMEGAIN, + IND_SHB_ENER_SF, + IND_SHB_RES_GS1, + IND_SHB_RES_GS2, + IND_SHB_RES_GS3, + IND_SHB_RES_GS4, + IND_SHB_RES_GS5, + IND_SHB_VF, + IND_SHB_LSF, + IND_SHB_MIRROR = IND_SHB_LSF + 5, + IND_SHB_GRID, + IND_SWB_CLASS, + IND_SWB_TENV, + IND_SWB_FENV = IND_SWB_TENV + 4, + IND_SHB_CNG_GAIN = IND_SWB_FENV + 4, + IND_DITHERING, + IND_FB_SLOPE, + + IND_HQ2_SPT_SHORTEN, + IND_HQ2_SUBBAND_TCQ, + IND_HQ2_SUBBAND_GAIN = IND_HQ2_SUBBAND_TCQ + 100, + IND_HQ2_DUMMY = IND_HQ2_SUBBAND_GAIN + 20, + + IND_LAGINDICES, + IND_NOISEG, + IND_AUDIO_GAIN, + IND_AUDIO_DELAY, + + /* ------------- HR SWB BWE loop -------------- */ + TAG_HR_BWE_LOOP_START = IND_AUDIO_DELAY + 4, + IND_HR_IS_TRANSIENT = TAG_HR_BWE_LOOP_START, + IND_HR_GAIN = TAG_HR_BWE_LOOP_START, + IND_HR_ENVELOPE = TAG_HR_BWE_LOOP_START, + IND_HR_HF_GAIN = TAG_HR_BWE_LOOP_START, + IND_I2 = TAG_HR_BWE_LOOP_START, + IND_KV2 = TAG_HR_BWE_LOOP_START, + IND_NQ2 = TAG_HR_BWE_LOOP_START, + TAG_HR_BWE_LOOP_END = TAG_HR_BWE_LOOP_START + 200, + /* ------------------------------------------------ */ + + IND_CORE_SWITCHING_CELP_SUBFRAME, + IND_CORE_SWITCHING_AUDIO_DELAY = IND_CORE_SWITCHING_CELP_SUBFRAME + 20, + IND_CORE_SWITCHING_AUDIO_GAIN, + + IND_UNUSED, + MAX_NUM_INDICES = IND_UNUSED + 127 +}; + +/*----------------------------------------------------------------------------------* + * Delays + *----------------------------------------------------------------------------------*/ + +#define FRAME_SIZE_NS 20000000L + +#define ACELP_LOOK_NS 8750000L +#define DELAY_FIR_RESAMPL_NS 937500L +#define DELAY_CLDFB_NS 1250000L + +#define DELAY_SWB_TBE_12k8_NS 1250000L +#define DELAY_SWB_TBE_16k_NS 1125000L +#define MAX_DELAY_TBE_NS 1312500L +#define DELAY_BWE_TOTAL_NS 2312500L +#define DELAY_FD_BWE_ENC_12k8_NS (DELAY_BWE_TOTAL_NS - (MAX_DELAY_TBE_NS - DELAY_SWB_TBE_12k8_NS)) +#define DELAY_FD_BWE_ENC_16k_NS (DELAY_BWE_TOTAL_NS - (MAX_DELAY_TBE_NS - DELAY_SWB_TBE_16k_NS)) +#define DELAY_FD_BWE_ENC_NS 2250000L + +#define L_LOOK_12k8 NS2SA(INT_FS_12k8, ACELP_LOOK_NS) /* look-ahead length at 12.8kHz */ +#define L_LOOK_16k NS2SA(INT_FS_16k, ACELP_LOOK_NS) /* look-ahead length at 16kHz */ + +/* core switching constants @16kHz */ +#define SWITCH_GAP_LENGTH_NS 6250000L /* lenght of ACELP->HQ 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 ) + *--------------------------------------------------*/ + +#define ACELP_MODE_MAX 4 +#define RF_MODE_MAX 4 + +/* 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 + + +/*--------------------------------------------------------------* + * Frame length constants in mode 2 + *---------------------------------------------------------------*/ + +#define ACELP_TCX_TRANS_NS 1250000 /* Duration of the ACELP->TCX overlap - 1.25 ms */ +#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 spectrum */ +#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 TCX/IGF coded lines */ +#define IGF_START_MN 164 /* MDCT lines not used by IGF*/ +#define IGF_START_MX 800 /* max. MDCT lines used by IGF*/ + +#define NUM_DCT_LENGTH 24 + +#define NB_DIV 2 /* number of division (frame) per 20ms frame */ +#define L_MDCT_HALF_OVLP_MAX (L_MDCT_OVLP_MAX/2) /* Size of the MDCT half overlap @ 48 kHz */ +#define L_MDCT_MIN_OVLP_MAX 60 /* Size of the MDCT minimal overlap @ 48 kHz - 1.25ms */ +#define L_MDCT_TRANS_OVLP_MAX NS2SA(48000, ACELP_TCX_TRANS_NS) /* Size of the ACELP->MDCT transition overlap - 1.25ms */ + +#define L_NEXT_MAX_16k NS2SA(16000, ACELP_LOOK_NS) /* 140 */ /* maximum encoder lookahead at 16kHz */ +#define L_NEXT_MAX_32k NS2SA(32000, ACELP_LOOK_NS) /* 280 */ /* maximum encoder lookahead at 32kHz */ +#define L_PAST_MAX_32k 360 /* maximum encoder past samples at 32kHz */ + +/*----------------------------------------------------------------------------------* + * ACELP core constants + *----------------------------------------------------------------------------------*/ + +#define SAFETY_NET 0 +#define MOVING_AVERAGE 1 +#define AUTO_REGRESSIVE 2 + +#define INT_FS_12k8 12800 /* internal sampling frequency */ +#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_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 @32kHz */ + +#define L_EXC_MEM L_FRAME16k /* length of memory of excitation signal @16kHz */ +#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 PLC in case of TCX->ACELP*/ +#define L_EXC (L_EXC_MEM + L_FRAME16k + 1) /* length of encoder excitation signal buffer @16kHz*/ +#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 @16kHz */ +#define L_WSP_MEM (PIT_MAX + L_INTERPOL) /* length of memory for weighted input signal @12.8kHz*/ +#define L_WSP (L_WSP_MEM + L_FRAME + L_LOOK_12k8) /* length of weighted input signal buffer @12.8kHz*/ + +#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 /* encoder synth memory */ +#define OLD_EXC_SIZE_DEC (3*L_FRAME_MAX/2+2*L_FIR_FER2) /*old excitation needed for decoder for PLC*/ + +#define TILT_CODE 0.3f /* ACELP code preemphasis factor */ + +#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 0.68f /* tilt factor (denominator) */ +#define M16k 20 /* order of the LP filter @ 16kHz */ +#define PIT_SHARP 0.85f /* pitch sharpening factor */ +#define PIT_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 0.0035f /* minimum allowable energy */ +#define STEP_DELTA 0.0625f /* quantization step for tilt compensation of gaussian cb. excitation */ +#define GAMMA_EV 0.92f /* weighting factor for core synthesis error weighting */ +#define FORMANT_SHARPENING_NOISE_THRESHOLD 21.0f /* lp_noise level above which formant sharpening is deactivated */ +#define BWD_N_BINS_MAX 13 +#define LP_NOISE_THRESH 20.f + +#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 /* Resampling - delay of the resampling low-pass filter @12.8kHz */ +#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, BFI */ +#define INV_CLDFB_BANDWIDTH (1.f/800.f) + +typedef enum +{ + CLDFB_ANALYSIS, + CLDFB_SYNTHESIS +} CLDFB_TYPE; + +#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_12k8/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 M_ALPHA 0.9f /* Multi-harm analysis - forgetting factor of LT correlation map */ +#define M_GAMMA 0.99f /* Multi-harm analysis - forgetting factor of active speech decision predictor */ +#define THR_CORR 56 /* Multi-harm analysis - starting threshold of multi-harm. correlation */ + +#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 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 GRID100_POINTS 100 /* LP analysis - number of points to evaluate Chebyshev polynomials */ + +#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 (PIT_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 */ + +#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_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 MAX_IDX_LEN 9 + +#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 0.9f /* CNG & DTX - CNG spectral envelope smoothing factor */ +#define STEP_AMR_WB_SID 2.625f /* CNG & DTX - CNG energy quantization step */ +#define HO_HIST_SIZE 8 /* CNG & DTX - maximal number of hangover frames used for averaging */ +#define NUM_ENV_CNG 20 +#define BUF_L_NRG 0.7f /* CNG & DTX - lower threshold factor for hangover updates */ +#define BUF_H_NRG 1.03f /* CNG & DTX - higher threshold factor for hangover updates */ + +#define BUF_DEC_RATE 25 /* CNG & DTX - buffer size decrease rate for active frames */ +#define STEP_SID 5.25f /* 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 UNKNOWN_NOISE 0 /* unknown noisy type */ +#define SILENCE 1 /* speech with high SNR */ +#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 /* number of spectral centroid */ +#define TONA_NUM 3 /* number of tonal */ +#define PRE_SNR_NUM 32 /* number of snr to calculate average SNR of all sub-bands */ +#define POWER_NUM 56 /* number of energy of several frames*/ +#define PRE_SPEC_DIF_NUM 56 /* number of energy of several frames*/ + +#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 START_NG 5 /* Stationary noise UV modification */ +#define FULL_NG 10 /* Stationary noise UV modification */ +#define ISP_SMOOTHING_QUANT_A1 0.9f /* Stationary noise UV modification */ + +#define FFT_15PONIT_WNK1 0.55901699f /* EDCT & EMDCT constants */ +#define FFT_15PONIT_WNK2 0.95105652f /* EDCT & EMDCT constants */ +#define FFT_15PONIT_WNK3 0.58778525f /* EDCT & EMDCT constants */ +#define FFT_15PONIT_WNK4 0.86602540f /* EDCT & EMDCT constants */ +#define FFT_15PONIT_WNK5 0.25000000f /* 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<= use MA-predictor */ + +#define NC16k (M16k/2) +#define NO_ITER 4 /* number of iterations for tracking the root */ +#define SPC 0.0234952f +#define SPC_plus SPC * 1.001f +#define ALPHA_SQ ((0.5f / PI2) * (0.5f / PI2)) + +#define NC M/2 +#define LSF_GAP 50.0f +#define LSF_BITS_CNG 29 + +#define MU_MA (1.0f/3.0f) /* original prediction factor (only for AMR-WB IO mode) */ +#define ISF_GAP 50 /* Minimum ISF separation for end-frame ISFs (only in AMR-WB IO mode) */ +#define LSF_GAP_MID 80.0f /* Minimum LSF separation for mid-frame LSFs */ +#define MODE1_LSF_GAP 70.0f /* Minimum LSF separation for end-frame ISFs */ +#define PREFERSFNET 1.05 +#define SFNETLOWLIMIT_WB 35000 /* new sampling rate dependent thresholds used in LSF codebook decision logic, WB case */ +#define SFNETLOWLIMIT_NB 38000 /* 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 */ +#define STREAKMULT 0.8f /* 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 80.0f + +#define MAX_VQ_STAGES 4 +#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 MIDLSF_NBITS 5 +#define ENDLSF_NBITS 31 + +#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 WB_LIMIT_LSF 6350 +#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-TCVQ */ +#define N_STAGE_VQ 8 +#define N_DIM 2 +#define NUM_SUBSET 8 +#define OP_LOOP_THR_HVO 3784536.3f /* 80% : Open-loop Threshold */ +#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 +#define ALDO_WINDOW 4 + +#define SWITCH_OVERLAP_8k 15 /* == NS2SA(8000, SWITCH_GAP_LENGTH_NS) - NS2SA(8000, 10000000.0f - N_ZERO_MDCT_NS) */ +#define SWITCH_GAP_LENGTH_8k 50 + +/*----------------------------------------------------------------------------------* + * 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 concealments */ +#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 0.75f /* FEC - weighting factor for LSF estimation in FER */ +#define STAB_FAC_LIMIT 0.25f /* 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 /* impulse response length for low- & high-pass filters in FER concealment */ +#define L_FIR_FER2 11 /* new filter tuning: 11*/ +#define MAX_UPD_CNT 5 /* FEC - maximum number of frames since last pitch update */ +#define ALPHA_S 0.6f /* FEC - damping factor for SIN_ONSET frames */ +#define ALPHA_V 1.0f /* FEC - damping factor for VOICED_CLAS frames */ +#define ALPHA_VT 0.4f /* FEC - damping factor for VOICED_TRANSITION frames */ +#define ALPHA_UT 0.8f /* FEC - damping factor for UNVOICED_TRANSITION frames */ +#define ALPHA_U 0.4f /* FEC - damping factor for UNVOICED_CLAS frames */ +#define ALPHA_UU 1.0f /* FEC - damping factor for UNVOICED_CLAS frames */ + +#define AGC 0.98f + +#define PLC_MIN_CNG_LEV 0.01f /* minimum background level */ +#define PLC_MIN_STAT_BUFF_SIZE 50 /* buffer size for minimum statistics */ +#define PLC_MIN_CNG_LEV 0.01f +#define G_LPC_RECOVERY_BITS 1 + +/*----------------------------------------------------------------------------------* + * Transition mode (TC) constants + *----------------------------------------------------------------------------------*/ + +/* Conversion of tc_subfr to index */ +#define TC_SUBFR2IDX(x) ( x == 0 ? 0 : \ + x == 1 ? 0 : \ + x == 2 ? 1 : \ + x == 3 ? 2 : \ + x == 4 ? 3 : \ + x == 64 ? 4 : \ + x == 128 ? 5 : \ + x == 192 ? 6 : \ + x == 256 ? 7 : 0 ) + +#define TC_SUBFR2IDX_16KHZ(x) ( x == 0 ? 0 : \ + x == 64 ? 1 : \ + x == 128 ? 2 : \ + x == 192 ? 3 : \ + x == 256 ? 4 : 0 ) + +#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_SPHERE 32 +#define NB_LEADER 36 +#define NB_LDQ4 27 +#define FAC_LOG2 3.321928095f + +#define NSV_MAX 34 /* maximal number of sub-vectors used by the AVQ */ + +/*----------------------------------------------------------------------------------* + * Arithmetic coder + *----------------------------------------------------------------------------------*/ + +#define A_THRES_SHIFT 2 +#define A_THRES (1<= 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 0.1f /* HF (noncoded) energy equalization limit 1, transient frames */ +#define BWE_HR_TRANS_EN_LIMIT2 0.3f /* HF (noncoded) energy equalization limit 2, transient frames */ +#define BWE_HR_TRANS_EN_LIMIT3 0.5f /* HF (noncoded) energy equalization limit 3, transient frames */ +#define BWE_HR_NONTRANS_EN_LIMIT1 0.5f /* HF (noncoded) energy equalization limit 1, non-transient frames */ +#define BWE_HR_NONTRANS_EN_LIMIT2 1.2f /* HF (noncoded) energy equalization limit 2, non-transient frames */ +#define BWE_HR_NONTRANS_EN_LIMIT3 0.8f /* HF (noncoded) energy equalization limit 3, non-transient frames */ + +/*----------------------------------------------------------------------------------* + * FD CNG + *----------------------------------------------------------------------------------*/ + +#define OUTMAX_INV 0.000030517578125f /* 1/2^15 */ +#define OUTMAX_SQ 1073741824.f /* 2^30 */ +#define OUTMAX_SQ_INV 0.00000000093132257461547852f /* 1/2^30 */ +#define DELTA (1e-20f) + +#define CLDFB_SCALING (1.5f) + +#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 MSALPHACORALPHA 0.7f +#define MSALPHACORMAX 0.3f +#define MSALPHAMAX 0.96f +#define MSALPHAHATMIN 0.05f /* It is used for all bands except the first one to get a stable bass */ +#define MSQEQINVMAX (1.f/5.f) +#define MSAV 2.12f +#define MSBETAMAX 0.8f +#define MSSNREXP (-0.02f/0.064f) + +#define NB_LAST_BAND_SCALE 0.8f +#define SWB_13k2_LAST_BAND_SCALE 0.8f + +#define CNG_LOG_SCALING 512.f /*2^9*/ + +#define M_MAX 32 +#define N_GAIN_MIN 4 +#define N_GAIN_MAX 17 + +#define CHEAP_NORM_SIZE 161 + +#define CNA_MAX_BRATE ACELP_13k20 + +/*----------------------------------------------------------------------------------* + * 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 THRESCRIT 0.5f /* NB post-filter - threshold LT pst switch off */ +#define AGC_FAC 0.9875f /* NB post-filter - gain adjustment factor */ +#define AGC_FAC1 (1.0f-AGC_FAC) /* NB post-filter - gain adjustment factor complement */ +#define LONG_H_ST 20 /* NB post-filter - impulse response length */ +#define POST_G1 0.75f /* NB post-filter - denominator weighting factor 12kbps */ +#define POST_G2 0.7f /* NB post-filter - numerator weighting factor 12kbps */ +#define GAMMA1_PST 0.7f /* denominator weighting factor */ +#define GAMMA2_PST 0.55f /* numerator weighting factor */ +#define GAMMA3_PLUS 0.2f /* NB post-filter - tilt weighting factor when k1>0 */ +#define GAMMA3_MINUS 0.9f /* NB post-filter - tilt weighting factor when k1<0 */ +#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 MIN_GPLT (1.0f/1.5f) /* NB post-filter - LT gain minimum */ +#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 POST_G1_MIN 0.65f +#define POST_G2_MIN 0.55f +#define POST_G1_NOIS 0.15f +#define POST_G2_NOIS 0.10f +#define BG1 (-0.01f) +#define BG2 (-0.05f) +#define CG1 0.9f +#define CG2 1.45f +#define C_LP_NOISE (0.1f/4.0f) +#define K_LP_NOISE 15.0f +#define LP_NOISE_THR 25.0f + +/*----------------------------------------------------------------------------------* + * Stability estimation + *----------------------------------------------------------------------------------*/ + +#define NB_BFI_THR 2 /* threshold for counter of last bad frames */ +#define MAX_LT 40 +#define INV_MAX_LT (1.0f/MAX_LT) + +#define TH_0_MIN 2.5f +#define TH_1_MIN 1.875f +#define TH_2_MIN 1.5625f +#define TH_3_MIN 1.3125f + +/*----------------------------------------------------------------------------------* + * 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 /* == (L_FFT/2-2)/3 */ + +#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 + +/*----------------------------------------------------------------------------------* + * LD music post-filter constants + *----------------------------------------------------------------------------------*/ + +#define TH_0_MIN2 1.875f +#define TH_1_MIN2 1.25f +#define TH_2_MIN2 0.9375f +#define TH_3_MIN2 0.625f + +#define DCT_L_POST 640 +#define OFFSET2 192 + +#define VOIC_BINS_HR 640 +#define BIN_16kdct (6400.0f/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 BIN_SIZE 25.0f +#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 + +/*----------------------------------------------------------------------------------* + * Core switching constants + *----------------------------------------------------------------------------------*/ + +#define SWITCH_MAX_GAP 360 /* 6.25 + 1.25 of filter mem max == NS2SA(48000, SWITCH_GAP_LENGTH_NS+DELAY_CLDFB_NS) */ + +/*----------------------------------------------------------------------------------* + * 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 INV_PREECHO_SMOOTH_LENP1 (1 / (PREECHO_SMOOTH_LEN + 1.0)); + +#define MAX16B 32767 +#define MIN16B (-32768) + +#define EPSILON 0.000000000000001f + +#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 2.5f +#define MINVALUEOFFIRSTGAIN -2.5f +#define NOOFGAINBITS1 6 + +#define AUDIODELAYBITS 6 +#define DELTAOFFIRSTGAIN (float)(MAXVALUEOFFIRSTGAIN - MINVALUEOFFIRSTGAIN) / (float)((1 << NOOFGAINBITS1) - 1) + +#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 ENV_SMOOTH_FAC 0.1f /* Smoothing factor for envelope stability measure */ +#define L_STAB_TBL 10 /* Number of elements in stability transition table */ +#define M_STAB_TBL_FX ((Word16)21068) /* Q13, 2.571756 */ +#define D_STAB_TBL_FX ((Word16) 845) /* Q13 0.1013138 */ +#define HALF_D_STAB_TBL_FX ((Word16) 422) /* Q13 0.1013138/2.0 */ +#define NUM_ENV_STAB_PLC_STATES 2 /* Number of states of markov model */ + +#define ATT_LIM_HANGOVER 150 /* Number of hangover frames for disabling stability dependent attenuation */ +#define DELTA_TH 5.0f /* Delta energy threshold for transient detection for envelope stability */ +#define ENERGY_TH 100.0f /* Energy threshold for transient detection */ +#define ENERGY_LT_BETA 0.93f /* Smoothing factor for long-term energy measure */ + +#define START_EXC 60 +#define L_HARMONIC_EXC 202 + +#define HQ_GENERIC_OFFSET 2 +#define HQ_GENERIC_END_FREQ 560 +#define HQ_GENERIC_END_FREQ_14P2KHZ 568 +#define HQ_GENERIC_END_FREQ_16P0KHZ 640 + +#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 LF_EMP_FAC 1.2f + +#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_E_PEAK_SMOOTH_FAC (0.3f) + +#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 0.9578f /* HVQ Classifier - Noise floor estimate weight 1 */ +#define HVQ_NF_WEIGHT2 0.6472f /* HVQ Classifier - Noise floor estimate weight 2 */ +#define HVQ_PE_WEIGHT1 0.42237f /* HVQ Classifier - Peak envelope estimate weight 1 */ +#define HVQ_PE_WEIGHT2 0.80285f /* HVQ Classifier - Peak envelope estimate weight 2 */ +#define HVQ_THR_POW 0.88f /* HVQ Classifier power factor for threshold calc */ +#define HVQ_SHARP_THRES 9 /* HVQ Classifier - Sharpness threshold */ + +#define HVQ_PA_FAC 0.7071f /* 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 16.0f /* HVQ Classifier - Sharpness threshold for band with medium sharpness */ +#define HVQ_PA_SHARP_THRES3 12.0f /* 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 0.95f +#define HVQ_BWE_WEIGHT2 0.2f +#define HVQ_NFPE_FACTOR 6.4f +#define HVQ_LB_NFPE_FACTOR 3.2f + +#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 DS_INDEX_LINEAR_END 21 +#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. */ +#define MAX_SRT_LEN NB_SFM_MAX /* Maximum length of input for srt_vec_ind() */ + +/* index_pvq constants */ +#define KMAX 512 +#define KMAX_NON_DIRECT 96 /* max K for non-direct indexing recursion rows */ +#define ODD_DIV_SIZE 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 QTCQ (0.2f) + +#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 + *----------------------------------------------------------------------------------*/ + +#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_14P2KHZ - 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_16P0KHZ - 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 (SWB_HIGHBAND_12KBPS/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 + +/* LRMDCT fix precision */ +#define SWB_BWE_LR_Qs 12 +#define SWB_BWE_LR_Qbe 14 +#define SWB_BWE_LR_QRk 16 + + +/*----------------------------------------------------------------------------------* + * FEC for HQ core + *----------------------------------------------------------------------------------*/ + +#define MAX_PGF 7 +#define MAX_ROW 2 + +#define MAX_SB_NB 3 + +#define NELP_LP_ORDER 8 +#define NUM_NELP_GAINS 10 + +#define MINIMUM_RATE_TO_ENCODE_VOICING_FLAG 45000 +#define FRAC_BWE_SMOOTH 2.0f /* >= 1 */ +#define FRAMECTTOSTART_MDCT 3 + +/*----------------------------------------------------------------------------------* + * Channel aware mode (FEC) + *----------------------------------------------------------------------------------*/ + +#define FEC_OFFSET 3 +#define MAX_RF_FEC_OFFSET 9 + + +/*----------------------------------------------------------------------------------* + * HQ FEC + *----------------------------------------------------------------------------------*/ + +#define POST_HQ_DELAY_NS DELAY_BWE_TOTAL_NS /* delay of post processing after core HQ coding */ +#define PH_ECU_ALDO_OLP2_NS (ACELP_LOOK_NS/2) /* half length of 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 ((L_PROT48k/48 - 20)*1000000-PH_ECU_LOOKAHEAD_NS) /* Number of nanoseconds memory for Phase ECU before the old_synthFB_fx pointer */ + +#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 L_PROT32k 1024 /* HQ phase ECU prototype frame length */ +#define MAX_PLOCS L_PROT48k/4+1 /* maximum number of spectral peaks to be searched */ +#define QUOT_LPR_LTR 4 +#define LGW_MAX 9 /* maximum number frequency group widths */ +#define BETA_MUTE_FAC_INI 0.5f /* initial noise attenuation factor */ +#define L_TRANA32k (L_PROT32k/QUOT_LPR_LTR) /* transient analysis frame length */ +#define L_TRANA16k (L_TRANA32k/2) +#define L_TRANA8k (L_TRANA32k/4) +#define L_PROT_HAMM_LEN2_48k NS2SA(48000,6000000L) +#define L_PROT_HAMM_LEN2_32k NS2SA(32000,6000000L) +#define L_PROT_HAMM_LEN2_16k NS2SA(16000,6000000L) +#define L_PROT48k L_PROT32k * 3/2 /* HQ phase ECU prototype frame length */ +#define L_PROT48k_2 L_PROT48k/2 +#define L_TRANA48k (L_PROT48k/QUOT_LPR_LTR) /* transient analysis frame length */ +#define PH_ECU_SPEC_SIZE L_PROT48k +#define T_SIN_PI_2 (PH_ECU_SPEC_SIZE/4) +#define HQ_FEC_SIGN_SFM 16 +#define OFF_FRAMES_LIMIT 30 /* HQ phase ECU, burst length for muting to zero */ +#define PH_ECU_MUTE_START 15 /* HQ phase ECU, burst length to start steep muting */ + +#define SCALE_DOWN_3dB 0.7071f +#define MAX_TILT 0.f +#define ED_THRES 1.0f + +#define ED_THRES_12P 0.032209f +#define ED_THRES_50P 0.159063f +#define ED_THRES_90P 0.532669 +#define MAXDELAY_FEC 224 + +#define RANDOM_START 1 +#define HQ_FEC_SIGN_THRES 6 +#define HQ_FEC_SIGN_THRES_TRANS 3 +#define HQ_FEC_BAND_SIZE 4 + + +/*--------------------------------------------------------------* + * Tonal MDCT PLC + *---------------------------------------------------------------*/ + +#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 ALLOWED_SIDE_LOBE_FLUCTUATION 3.0f /* 4.8 dB */ +#define LEVEL_ABOVE_ENVELOPE 7.59f /* 8.8 dB */ +#define UNREACHABLE_THRESHOLD 16.0f /* 12 dB Increase of LEVEL_ABOVE_ENVELOPE so that the threshold is not reached */ +#define SMALL_THRESHOLD 1.10f /* 0.41 dB Increase of LEVEL_ABOVE_ENVELOPE for the peak detection at a definitive peak in the estimated spectrum */ +#define BIG_THRESHOLD 1.5f /* 1.76 dB Increase of LEVEL_ABOVE_ENVELOPE for the peak detection at a probable peak in the estimated spectrum */ + +#define kSmallerLagsTargetBitsThreshold 150 +#define kCtxHmOlRSThr 2.6f + + +#define kTcxHmNumGainBits 2 /* Number of bits for the gain index */ +#define kTcxHmParabolaHalfWidth 4 /* Parabola half width */ +#define kLtpHmGainThr 0.46f /* Use the LTP pitch lag in the harmonic model? */ + +#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 VBR_ADR_MAX_TARGET 6.15f /* max target ADR for VBR. This rate is used in the closed loop rate control */ +#define PPP_LAG_THRLD 180 /* max lag allowed for PPP coding */ + +#define MAXLAG_WI (PPP_LAG_THRLD/2 + 12) /* Maximum lag used in waveform interpolation */ +#define MAX_LAG_PIT (PPP_LAG_THRLD + 21) /* Max possible pitch lag after adding delta lag */ + +/*----------------------------------------------------------------------------------* + * 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 */ + +/*----------------------------------------------------------------------------------* + * TEC/TFA + *----------------------------------------------------------------------------------*/ +#define DELAY_TEMP_ENV_BUFF_TEC 9 +#define EXT_DELAY_HI_TEMP_ENV 2 + + +/*----------------------------------------------------------------------------------* + * BASOP ROM Tables + *----------------------------------------------------------------------------------*/ + +#define LD_INT_TAB_LEN 120 +#define INV_TABLE_SIZE 256 +#define SQRT_TABLE_SIZE 256 + + +/*----------------------------------------------------------------------------------* + * Decoder modes + *----------------------------------------------------------------------------------*/ + + +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 +}; + +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 */ +}; + +enum +{ + G192, + MIME + , VOIP_G192_RTP + , VOIP_RTPDUMP +}; + +#endif /* CNST_H */ diff --git a/lib_com/codec_tcx_common.c b/lib_com/codec_tcx_common.c new file mode 100644 index 000000000..ac9cf85dc --- /dev/null +++ b/lib_com/codec_tcx_common.c @@ -0,0 +1,174 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "prot.h" +#include "options.h" + +/*-------------------------------------------------------------------* + * tcxGetNoiseFillingTilt() + * + * + *-------------------------------------------------------------------*/ + +int tcxGetNoiseFillingTilt( + float A[], + int L_frame, + int mode, + float *noiseTiltFactor +) +{ + int firstLine; + + if (mode) + { + firstLine = L_frame / 6; + *noiseTiltFactor = 0.5625f; + } + else + { + firstLine = L_frame / 8; + *noiseTiltFactor = get_gain( A+1, A, M, NULL ); + *noiseTiltFactor = min(1.0f, (*noiseTiltFactor) + 0.09375f); + } + + return firstLine; +} + +/*-------------------------------------------------------------------* + * tcxFormantEnhancement() + * + * + *-------------------------------------------------------------------*/ + +void tcxFormantEnhancement( + float xn_buf[], + float gainlpc[], + float spectrum[], + int L_frame +) +{ + int k; + int i, j, l = 0; + float fac, step; + + k = L_frame / FDNS_NPTS; + + /* Formant enhancement via square root of the LPC gains */ + xn_buf[0] = (float)sqrt(gainlpc[0]); + xn_buf[1] = (float)sqrt(gainlpc[1]); + fac = 1.0f / min(xn_buf[0], xn_buf[1]); + + for (i = 1; i < FDNS_NPTS - 1; i++) + { + xn_buf[i+1] = (float)sqrt(gainlpc[i+1]); + + if ((xn_buf[i-1] <= xn_buf[i]) && (xn_buf[i+1] <= xn_buf[i])) + { + step = max(xn_buf[i-1], xn_buf[i+1]); + step = (1.0f / step - fac) / (float)(i - l); + xn_buf[l] = 1.0f; + fac += step; + for (j = l + 1; j < i; j++) + { + xn_buf[j] = min(1.0f, xn_buf[j] * fac); + fac += step; + } + l = i; + } + } + + /* i = tcx_cfg->fdns_npts - 1; Completing changes to gains */ + step = min(xn_buf[i-1], xn_buf[i]); + step = (1.0f / step - fac) / (float)(i - l); + xn_buf[l] = 1.0f; + fac += step; + for (j = l + 1; j < i; j++) + { + xn_buf[j] = min(1.0f, xn_buf[j] * fac); + fac += step; + } + xn_buf[i] = 1.0f; + + /* Application of changed gains onto decoded MDCT lines */ + for (i = j = 0; i < L_frame; j++) + { + for (l = 0; l < k; i++, l++) + { + spectrum[i] *= xn_buf[j]; + } + } + + return; +} + +/*-------------------------------------------------------------------* + * tcxGetNoiseFillingTilt() + * + * + *-------------------------------------------------------------------*/ + +void tcxInvertWindowGrouping( + TCX_config *tcx_cfg, + float xn_buf[], + float spectrum[], + int L_frame, + int fUseTns, + int last_core, + int index, + int frame_cnt, + int bfi +) +{ + short i, w, t_integer; + int L_win, L_spec; + + if (frame_cnt && !bfi && last_core!=0) + { + /* fix sub-window overlap */ + tcx_cfg->tcx_last_overlap_mode = tcx_cfg->tcx_curr_overlap_mode; + } + + if (((!bfi) &&((tcx_cfg->tcx_last_overlap_mode != FULL_OVERLAP) || + ((tcx_cfg->tcx_curr_overlap_mode == FULL_OVERLAP) && (frame_cnt == 0) && (index == 0)))) + || + ((bfi) &&((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 */ + for (t_integer = w = 0; w < 2; w++) + { + for (i = w; i < L_frame; i += 2) + { + xn_buf[t_integer++] = spectrum[i]; + } + } + + mvr2r( xn_buf, spectrum, L_frame ); + + if( tcx_cfg->fIsTNSAllowed && !bfi && fUseTns ) + { + L_win = L_frame >> 1; + L_spec = tcx_cfg->tnsConfig[0][0].iFilterBorders[0]; + + /* rearrange LF sub-window lines prior to TNS synthesis filtering */ + if( L_spec < L_frame ) + { + mvr2r( spectrum+8, spectrum+16, L_spec/2-8 ); + mvr2r( spectrum+L_frame/2, spectrum+8, 8 ); + mvr2r( spectrum+L_frame/2+8, spectrum+L_spec/2+8, L_spec/2-8 ); + } + else + { + mvr2r( spectrum+8, xn_buf, L_win ); + mvr2r( xn_buf, spectrum+16, L_win-8 ); + mvr2r( xn_buf+L_win-8, spectrum+8, 8); + } + } + } + + return; +} diff --git a/lib_com/core_com_config.c b/lib_com/core_com_config.c new file mode 100644 index 000000000..8546169d8 --- /dev/null +++ b/lib_com/core_com_config.c @@ -0,0 +1,420 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include + +#include "options.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * getTcxonly() + * + * + *-------------------------------------------------------------------*/ + +short getTcxonly( + const int bitrate +) +{ + short tcxonly = 0; + + if( bitrate > ACELP_32k ) + { + tcxonly = 1; + } + + return tcxonly; +} + + +/*-------------------------------------------------------------------* + * getCtxHm() + * + * + *-------------------------------------------------------------------*/ + +short getCtxHm( + const int bitrate, + const short rf_flag +) +{ + short ctx_hm = 0; + if( (bitrate > LPC_SHAPED_ARI_MAX_RATE) && (bitrate <= 64000) && !rf_flag) + { + ctx_hm = 1; + } + + return ctx_hm; +} + +/*-------------------------------------------------------------------* + * getResq() + * + * + *-------------------------------------------------------------------*/ + +short getResq( + const int bitrate +) +{ + short resq = 0; + + if(bitrate <= HQ_64k) + { + resq = 1; + } + + return resq; +} + +/*-------------------------------------------------------------------* + * getTnsAllowed() + * + * + *-------------------------------------------------------------------*/ + +short getTnsAllowed( + const int bitrate, + const short igf +) +{ + short tnsAllowed = 0; + + if( igf ) + { + if( bitrate > HQ_16k40 ) + { + tnsAllowed = 1; + } + } + else if( bitrate > HQ_32k ) + { + tnsAllowed = 1; + } + + return tnsAllowed; +} + +/*-------------------------------------------------------------------* + * getRestrictedMode() + * + * + *-------------------------------------------------------------------*/ + +short getRestrictedMode( + const int bitrate, + const short Opt_AMR_WB +) +{ + short restrictedMode = 3; + + if ( !Opt_AMR_WB && (bitrate > HQ_32k) ) + { + restrictedMode = 6; + } + else if ( Opt_AMR_WB ) + { + restrictedMode = 1; + } + + return restrictedMode; +} + +/*-------------------------------------------------------------------* + * getMdctWindowLength() + * + * + *-------------------------------------------------------------------*/ + +short getMdctWindowLength( + const float fscale +) +{ + + short mdctWindowLength; + + mdctWindowLength = (L_LOOK_12k8 * fscale)/FSCALE_DENOM; + + return mdctWindowLength; +} + +/*-------------------------------------------------------------------* + * sr2fscale() + * + * + *-------------------------------------------------------------------*/ + +short sr2fscale( + const int sr +) +{ + + return (FSCALE_DENOM*sr)/12800; +} + +/*-------------------------------------------------------------------* + * getCoreSamplerateMode2() + * + * + *-------------------------------------------------------------------*/ + +int getCoreSamplerateMode2( + const int bitrate, + const int bandwidth, + const short rf_mode +) +{ + int sr_core = 0; + + if( bandwidth == NB ) + { + sr_core = 12800; + } + else if( (bandwidth == WB && bitrate < ACELP_13k20) || + (bandwidth == SWB && bitrate <= ACELP_13k20) || (rf_mode == 1) ) + { + sr_core = 12800; + } + else if( bandwidth == WB || (bandwidth == SWB && bitrate <= ACELP_32k) + || (bandwidth == FB && bitrate <= ACELP_32k) ) + { + sr_core = 16000; + } + else if( (bandwidth == SWB || bandwidth == FB) && bitrate <= HQ_64k) + { + sr_core = 25600; + } + else if( bandwidth == SWB || bandwidth == FB ) + { + sr_core = 32000; + } + + return sr_core; +} + +/*-------------------------------------------------------------------* + * getTcxBandwidth() + * + * + *-------------------------------------------------------------------*/ + +float getTcxBandwidth( + const int bandwidth +) +{ + float tcxBandwidth = 0.5f; + + if( bandwidth == NB ) + { + tcxBandwidth = 0.3125f; + } + + return tcxBandwidth; +} + +/*-------------------------------------------------------------------* + * getIgfPresent() + * + * + *-------------------------------------------------------------------*/ + +short getIgfPresent( + const int bitrate, + const int bandwidth, + const short rf_mode +) +{ + short igfPresent = 0; + + if( bandwidth == SWB && bitrate >= ACELP_9k60 && bitrate < HQ_64k ) + { + igfPresent = 1; + } + else if( bandwidth == FB && bitrate >= ACELP_16k40 ) + { + igfPresent = 1; + } + else if( bandwidth == WB && bitrate == ACELP_9k60 ) + { + igfPresent = 1; + } + if( ((bandwidth == WB) || (bandwidth == SWB)) && (rf_mode == 1) && (bitrate == ACELP_13k20) ) + { + igfPresent = 1; + } + + return igfPresent; +} + +/*-------------------------------------------------------------------* + * getCnaPresent() + * + * + *-------------------------------------------------------------------*/ + +short getCnaPresent( + const int bitrate, + const int bandwidth +) +{ + short flag_cna = 0; + + if( bandwidth == NB && bitrate <= ACELP_13k20 ) + { + flag_cna = 1; + } + + if( bandwidth == WB && bitrate <= ACELP_13k20 ) + { + flag_cna = 1; + } + + if( bandwidth == SWB && bitrate <= ACELP_13k20 ) + { + flag_cna = 1; + } + + return flag_cna; +} + +/*-------------------------------------------------------------------* + * getTcxLtp() + * + * + *-------------------------------------------------------------------*/ +short getTcxLtp( + const int sr_core +) +{ + short tcxltp = 0; + + if ( (sr_core <= 25600) ) + { + tcxltp = 1; + } + + return tcxltp; +} + +/*-------------------------------------------------------------------* + * initPitchLagParameters() + * + * + *-------------------------------------------------------------------*/ + +short initPitchLagParameters( + const int sr_core, + int *pit_min, + int *pit_fr1, + int *pit_fr1b, + int *pit_fr2, + int *pit_max +) +{ + + short pit_res_max; + + + if (sr_core==12800) + { + *pit_min = PIT_MIN_12k8; + *pit_max = PIT_MAX_12k8; + *pit_fr2 = PIT_FR2_12k8; + *pit_fr1 = PIT_FR1_12k8; + *pit_fr1b = PIT_FR1_8b_12k8; + pit_res_max = 4; + } + else if (sr_core==16000) + { + *pit_min = PIT_MIN_16k; + *pit_max = PIT16k_MAX; + *pit_fr2 = PIT_FR2_16k; + *pit_fr1 = PIT_FR1_16k; + *pit_fr1b = PIT_FR1_8b_16k; + pit_res_max = 6; + } + else if (sr_core==25600) + { + *pit_min = PIT_MIN_25k6; + *pit_max = PIT_MAX_25k6; + *pit_fr2 = PIT_FR2_25k6; + *pit_fr1 = PIT_FR1_25k6; + *pit_fr1b = PIT_FR1_8b_25k6; + pit_res_max = 4; + } + else /* sr_core==32000 */ + { + *pit_min = PIT_MIN_32k; + *pit_max = PIT_MAX_32k; + *pit_fr2 = PIT_FR2_32k; + *pit_fr1 = PIT_FR1_32k; + *pit_fr1b = PIT_FR1_8b_32k; + pit_res_max = 6; + } + + return pit_res_max; +} + +/*-------------------------------------------------------------------* + * getNumTcxCodedLines() + * + * + *-------------------------------------------------------------------*/ + +short getNumTcxCodedLines( + const short bwidth +) +{ + short tcx_coded_lines; + + switch (bwidth) + { + case NB: + tcx_coded_lines = 160; + break; + case WB: + tcx_coded_lines = 320; + break; + case SWB: + tcx_coded_lines = 640; + break; + case FB: + tcx_coded_lines = 960; + break; + default: + tcx_coded_lines = 0; + break; + } + + return tcx_coded_lines; +} + +/*-------------------------------------------------------------------* + * getTcxLpcShapedAri() + * + * + *-------------------------------------------------------------------*/ + +short getTcxLpcShapedAri( + const int total_brate, + const short bwidth, + const short rf_mode +) +{ + short tcx_lpc_shaped_ari = 0; + + (void) bwidth; + + if( total_brate <= LPC_SHAPED_ARI_MAX_RATE || rf_mode ) + { + tcx_lpc_shaped_ari = 1; + } + + return tcx_lpc_shaped_ari; +} diff --git a/lib_com/deemph.c b/lib_com/deemph.c new file mode 100644 index 000000000..9109ba2ab --- /dev/null +++ b/lib_com/deemph.c @@ -0,0 +1,38 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * deemph() + * + * Deemphasis: filtering through 1/(1-mu z^-1) + *-------------------------------------------------------------------*/ + +void deemph( + float *signal, /* i/o: signal */ + const float mu, /* i : deemphasis factor */ + const short L, /* i : vector size */ + float *mem /* i/o: memory (y[-1]) */ +) +{ + short i; + + signal[0] = signal[0] + mu * (*mem); + for (i=1; i -1e-10) ) + { + *mem = 0; + } + + return; +} diff --git a/lib_com/delay_comp.c b/lib_com/delay_comp.c new file mode 100644 index 000000000..ef5dd06fe --- /dev/null +++ b/lib_com/delay_comp.c @@ -0,0 +1,40 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "prot.h" + + +/*-------------------------------------------------------------------------- + * get_delay() + * + * Function returns various types of delays in the codec in ms. + *--------------------------------------------------------------------------*/ + +float get_delay( /* o : delay value in ms */ + const short what_delay, /* i : what delay? (ENC or DEC) */ + const int io_fs /* i : input/output sampling frequency */ +) +{ + float delay = 0; + + if( what_delay == ENC ) + { + delay = (DELAY_FIR_RESAMPL_NS + ACELP_LOOK_NS); + } + else + { + if( io_fs == 8000 ) + { + delay = DELAY_CLDFB_NS; + } + else + { + delay = DELAY_BWE_TOTAL_NS; + } + } + + return delay; +} diff --git a/lib_com/disclaimer.c b/lib_com/disclaimer.c new file mode 100644 index 000000000..7340db511 --- /dev/null +++ b/lib_com/disclaimer.c @@ -0,0 +1,19 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + + +#include "wmc_auto.h" +#include "options.h" +#include "prot.h" + +int print_disclaimer(FILE *fPtr) +{ + + fprintf(fPtr, "\n===========================================================================\n"); + fprintf(fPtr, " EVS Codec (Floating Point) 3GPP TS26.443 November 04, 2021.\n"); + fprintf(fPtr, " Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0\n"); + fprintf(fPtr, "===========================================================================\n\n\n"); + + return 0; +} diff --git a/lib_com/dlpc_bfi.c b/lib_com/dlpc_bfi.c new file mode 100644 index 000000000..9c7e0be31 --- /dev/null +++ b/lib_com/dlpc_bfi.c @@ -0,0 +1,49 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include "options.h" +#include "prot.h" +#include "rom_com.h" + + +/*---------------------------------------------------------------------* +* routine: dlpc_bfi() +* +* +*---------------------------------------------------------------------*/ + +void dlpc_bfi( + int L_frame, + float *lsf_q, /* o : quantized lsfs */ + const float *lsfold, /* i : past quantized lsf */ + const short last_good, /* i : last good received frame */ + const short nbLostCmpt, /* i : counter of consecutive bad frames */ + float mem_MA[], /* i/o: quantizer memory for MA model */ + float *mem_AR, /* i/o: quantizer memory for AR model */ + float *stab_fac, /* i : lsf stability factor */ + float *lsf_adaptive_mean,/* i : lsf adaptive mean, updated when BFI==0 */ + int numlpc, /* i : Number of division per superframe */ + float lsf_cng[], + int plcBackgroundNoiseUpdated, + float *lsf_q_cng, /* o : quantized lsfs of background noise */ + float *old_lsf_q_cng, /* o : old quantized lsfs for background noise */ + const float lsfBase[] /* i : base for differential lsf coding */ +) +{ + 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, 0 ); + + if( 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, 0 ); + } + + return; +} diff --git a/lib_com/edct.c b/lib_com/edct.c new file mode 100644 index 000000000..472f507d0 --- /dev/null +++ b/lib_com/edct.c @@ -0,0 +1,194 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +static float const * get_edct_table(short length) +{ + float const * edct_table = NULL; + switch (length) + { + case 1200: + edct_table = edct_table_600; + break; + case 960: + edct_table = edct_table_480; + break; + case 640: + edct_table = edct_table_320; + break; + case 320: + edct_table = edct_table_160; + break; + case 256: + edct_table = edct_table_128; + break; + case 240: + edct_table = edct_table_120; + break; + case 200: + edct_table = edct_table_100; + break; + case 160: + edct_table = edct_table_80; + break; + case 40: + edct_table = edct_table_20; + break; + case 800: + edct_table = edct_table_400; + break; + case 512: + edct_table = edct_table_256; + break; + case 480: + edct_table = edct_table_240; + break; + case 400: + edct_table = edct_table_200; + break; + case 128: + edct_table = edct_table_64; + break; + case 80: + edct_table = edct_table_40; + break; + default: + fprintf(stderr, "edct/edst(): length is not in table!"); + exit(-1); + break; + } + return edct_table; +} + +/*-----------------------------------------------------------------* + * edct() + * + * DCT transform + *-----------------------------------------------------------------*/ + +void edct( + const float *x, /* i : input signal */ + float *y, /* o : output transform */ + short length /* i : length */ +) +{ + short i; + float re[L_FRAME_PLUS/2]; + float im[L_FRAME_PLUS/2]; + const float *edct_table = 0; + float local; + + edct_table = get_edct_table(length); + + /* Twiddling and Pre-rotate */ + for (i = 0; i < length/2; i++) + { + re[i] = x[2*i] * edct_table[i] + x[length-1-2*i] * edct_table[length/2-1-i]; + im[i] = x[length-1-2*i] * edct_table[i] - x[2*i] * edct_table[length/2-1-i]; + } + + DoFFT(re, im, length/2); + + local = (0.75f * EVS_PI)/ length; + + for (i = 0; i < length/2; i++) + { + float tmp; + tmp = re[i] - im[i] * local; /* 3*pi/(4*length) is a constant */ + im[i] = im[i] + re[i] * local; + re[i] = tmp; + } + + /* Post-rotate and obtain the output data */ + for (i = 0; i < length/2; i++) + { + y[2*i] = re[i] * edct_table[i] + im[i] * edct_table[length/2-1-i]; + y[length-1-2*i] = re[i] * edct_table[length/2-1-i] - im[i] * edct_table[i]; + } + + return; +} + +/*-------------------------------------------------------------------------* + * FUNCTION : edst() + * + * PURPOSE : DST_IV transform + *-------------------------------------------------------------------------*/ +void edst( + const float *x, /* i : input signal */ + float *y, /* o : output transform */ + short length /* i : length */ +) +{ + short i; + float re[L_FRAME_PLUS/2]; + float im[L_FRAME_PLUS/2]; + const float *edct_table = 0; + float local; + + edct_table = get_edct_table(length); + + /* Twiddling and Pre-rotate */ + for (i = 0; i < length/2; i++) + { + re[i] = x[length-1-2*i] * edct_table[i] + x[2*i] *edct_table[length/2-1-i]; + im[i] = x[2*i] * edct_table[i] - x[length-1-2*i] * edct_table[length/2-1-i]; + } + + DoFFT(re, im, length/2); + + local = (0.75f * EVS_PI)/ length; + + for (i = 0; i < length/2; i++) + { + float tmp; + tmp = re[i] - im[i] * local; /* 3*pi/(4*length) is a constant */ + im[i] = im[i] + re[i] * local; + re[i] = tmp; + } + + /* Post-rotate and obtain the output data */ + for (i = 0; i < length/2; i++) + { + y[2*i] = re[i] * edct_table[i] + im[i] * edct_table[length/2-1-i]; + y[length-1-2*i] = im[i] * edct_table[i] - re[i] * edct_table[length/2-1-i]; + } + + return; +} + +/*-----------------------------------------------------------------* + * iedct_short() + * + * Inverse EDCT for short frames + *-----------------------------------------------------------------*/ + +void iedct_short( + const float *in, /* i : input vector */ + float *out, /* o : output vector */ + const short segment_length /* i : length */ +) +{ + float alias[MAX_SEGMENT_LENGTH]; + short i; + + edct(in, alias, segment_length/2); + + for (i = 0; i < segment_length/4; i++) + { + out[i] = alias[segment_length/4 + i]; + out[segment_length/4 + i] = -alias[segment_length/2 - 1 - i]; + out[segment_length/2 + i] = -alias[segment_length/4 - 1 - i]; + out[3*segment_length/4 + i] = -alias[i]; + } + + return; +} diff --git a/lib_com/enh1632.c b/lib_com/enh1632.c new file mode 100644 index 000000000..f0c389c80 --- /dev/null +++ b/lib_com/enh1632.c @@ -0,0 +1,710 @@ +/****************************************************************************************************** + + (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +/* + =========================================================================== + 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" + +#define WMC_TOOL_SKIP + +/***************************************************************************** + * + * 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 ); +#ifdef WMOPS + multiCounter[currCounter].lshr--; +#endif + } + else + { + if ( var2 == 0 || var1 == 0 ) + { + var_out = var1; + } + else if ( var2 >= 16 ) + { + var_out = 0; + } + else + { + var_out = var1 << var2; + } + } + +#ifdef WMOPS + multiCounter[currCounter].lshl++; +#endif + + BASOP_CHECK(); + + + 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 ); +#ifdef WMOPS + multiCounter[currCounter].lshl--; +#endif + } + 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 ); + } + } + +#ifdef WMOPS + multiCounter[currCounter].lshr++; +#endif + + BASOP_CHECK(); + + + 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 ); +#ifdef WMOPS + multiCounter[currCounter].L_lshr--; +#endif + } + 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; + } + } + +#ifdef WMOPS + multiCounter[currCounter].L_lshl++; +#endif + + BASOP_CHECK(); + + 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 ); +#ifdef WMOPS + multiCounter[currCounter].L_lshl--; +#endif + } + 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 ); + } + } + +#ifdef WMOPS + multiCounter[currCounter].L_lshr++; +#endif + + BASOP_CHECK(); + + + 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 ); +#ifdef WMOPS + multiCounter[currCounter].shl--; +#endif + } + else + { + var2 = -var2; + var_out = shr_r( var1, var2 ); +#ifdef WMOPS + multiCounter[currCounter].shr_r--; +#endif + } + +#ifdef WMOPS + multiCounter[currCounter].shl_r++; +#endif + + 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 ); +#ifdef WMOPS + multiCounter[currCounter].L_shl--; +#endif + } + else + { + var2 = -var2; + var_out = L_shr_r( L_var1, var2 ); +#ifdef WMOPS + multiCounter[currCounter].L_shr_r--; +#endif + } + +#ifdef WMOPS + multiCounter[currCounter].L_shl_r++; +#endif + + 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 ) ); + +#ifdef WMOPS + multiCounter[currCounter].s_and--; + multiCounter[currCounter].lshl--; + multiCounter[currCounter].lshr--; + multiCounter[currCounter].s_or--; + multiCounter[currCounter].rotr++; +#endif + + 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 ) ); + +#ifdef WMOPS + multiCounter[currCounter].lshr--; + multiCounter[currCounter].s_and--; + multiCounter[currCounter].lshl--; + multiCounter[currCounter].s_or--; + multiCounter[currCounter].rotl++; +#endif + + 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 ) ); + +#ifdef 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 + + 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 ) ) ); + +#ifdef 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 + + return ( L_var_out ); +} + +#undef WMC_TOOL_SKIP diff --git a/lib_com/enh1632.h b/lib_com/enh1632.h new file mode 100644 index 000000000..d21bf1157 --- /dev/null +++ b/lib_com/enh1632.h @@ -0,0 +1,538 @@ +/****************************************************************************************************** + + (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +/* + =========================================================================== + 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" + + +/***************************************************************************** + * + * 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; + +#ifdef WMOPS + multiCounter[currCounter].s_max++; +#endif + + 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; + +#ifdef WMOPS + multiCounter[currCounter].s_min++; +#endif + + 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; + +#ifdef WMOPS + multiCounter[currCounter].L_max++; +#endif + + 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; + +#ifdef WMOPS + multiCounter[currCounter].L_min++; +#endif + + 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; + +#ifdef WMOPS + multiCounter[currCounter].s_and++; +#endif + + 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; + +#ifdef WMOPS + multiCounter[currCounter].L_and++; +#endif + + 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; + +#ifdef WMOPS + multiCounter[currCounter].s_or++; +#endif + + 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; + +#ifdef WMOPS + multiCounter[currCounter].L_or++; +#endif + + 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; + +#ifdef WMOPS + multiCounter[currCounter].s_xor++; +#endif + + 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; + +#ifdef WMOPS + multiCounter[currCounter].L_xor++; +#endif + + return ( L_var_out ); +} + + +#endif /*_ENH1632_H*/ + +/* end of file */ diff --git a/lib_com/enh40.c b/lib_com/enh40.c new file mode 100644 index 000000000..929e3a950 --- /dev/null +++ b/lib_com/enh40.c @@ -0,0 +1,1395 @@ +/****************************************************************************************************** + + (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +/* + =========================================================================== + 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" +#ifdef BASOP_NOGLOB +#include +#endif /* BASOP_NOGLOB */ + +#define WMC_TOOL_SKIP + +#ifdef _MSC_VER +#pragma warning( disable : 4310 ) +#endif + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#ifndef BASOP_NOGLOB +Word40 L40_shl( Word40 L40_var1, Word16 var2 ) +#else /* BASOP_NOGLOB */ +Word40 L40_shl_o( Word40 L40_var1, Word16 var2, Flag *Overflow ) +#endif /* BASOP_NOGLOB */ +{ + + Word40 L40_var_out; + Word40 L40_constant; + +#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 ) + L40_constant = L40_set( 0xc000000000 ); +#else + L40_constant = L40_set( 0xc000000000LL ); +#endif + + if ( var2 < 0 ) + { + var2 = -var2; + L40_var_out = L40_shr( L40_var1, var2 ); + } + + else + { + L40_var_out = L40_var1; + + for ( ; var2 > 0; var2-- ) + { +#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 ) + if ( L40_var_out > 0x003fffffffff ) +#else + if ( L40_var_out > 0x003fffffffffLL ) +#endif + { +#ifndef BASOP_NOGLOB + Overflow = 1; + exit( 1 ); + /* L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out); */ +#else /* BASOP_NOGLOB */ + *Overflow = 1; + L40_var_out = MAX_40; +#endif /* BASOP_NOGLOB */ + break; + } + + else if ( L40_var_out < L40_constant ) + { +#ifndef BASOP_NOGLOB + Overflow = 1; + exit( 2 ); + /* L40_var_out = L40_UNDERFLOW_OCCURED( L40_var_out); */ +#else /* BASOP_NOGLOB */ + *Overflow = 1; + L40_var_out = MIN_40; +#endif /* BASOP_NOGLOB */ + break; + } + + else + { + L40_var_out = L40_var_out << 1; + } + } + } + +#ifdef WMOPS + multiCounter[currCounter].L40_shl++; +#endif + + BASOP_CHECK(); + + return ( L40_var_out ); +} + +#ifdef BASOP_NOGLOB +Word40 L40_shl( Word40 L40_var1, Word16 var2 ) +{ + + Word40 L40_var_out; + Word40 L40_constant; + +#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 ) + L40_constant = L40_set( 0xc000000000 ); +#else + L40_constant = L40_set( 0xc000000000LL ); +#endif + + if ( var2 < 0 ) + { + var2 = -var2; + L40_var_out = L40_shr( L40_var1, var2 ); + } + + else + { + L40_var_out = L40_var1; + + for ( ; var2 > 0; var2-- ) + { +#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 ) + if ( L40_var_out > 0x003fffffffff ) +#else + if ( L40_var_out > 0x003fffffffffLL ) +#endif + { + assert( 0 ); + L40_var_out = MAX_40; + break; + } + + else if ( L40_var_out < L40_constant ) + { + assert( 0 ); + L40_var_out = MIN_40; + break; + } + + else + { + L40_var_out = L40_var_out << 1; + } + } + } + +#ifdef WMOPS + multiCounter[currCounter].L40_shl++; +#endif + + BASOP_CHECK(); + + + return ( L40_var_out ); +} +#endif /* BASOP_NOGLOB */ + +/***************************************************************************** + * + * 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 ); + } + else + { + L40_var_out = L40_var1 >> var2; + } + +#ifdef WMOPS + multiCounter[currCounter].L40_shr++; +#endif + + 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 ); + +#ifdef WMOPS + multiCounter[currCounter].L40_negate++; +#endif + + 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. + * + *****************************************************************************/ +#ifdef BASOP_NOGLOB + +Word40 L40_add_o( Word40 L40_var1, Word40 L40_var2, Flag *Overflow ) +{ + Word40 L40_var_out; + + L40_var_out = L40_var1 + L40_var2; + +#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 ) + if ( ( ( ( L40_var1 & 0x8000000000 ) >> 39 ) != 0 ) && ( ( ( L40_var2 & 0x8000000000 ) >> 39 ) != 0 ) && ( ( ( L40_var_out & 0x8000000000 ) >> 39 ) == 0 ) ) + { + *Overflow = 1; + L40_var_out = MIN_40; + } + else if ( ( ( ( L40_var1 & 0x8000000000 ) >> 39 ) == 0 ) && ( ( ( L40_var2 & 0x8000000000 ) >> 39 ) == 0 ) && ( ( ( L40_var_out & 0x8000000000 ) >> 39 ) != 0 ) ) + { + *Overflow = 1; + L40_var_out = MAX_40; + } +#else + if ( ( ( ( L40_var1 & 0x8000000000LL ) >> 39 ) != 0 ) && ( ( ( L40_var2 & 0x8000000000LL ) >> 39 ) != 0 ) && ( ( ( L40_var_out & 0x8000000000LL ) >> 39 ) == 0 ) ) + { + *Overflow = 1; + L40_var_out = MIN_40; + } + else if ( ( ( ( L40_var1 & 0x8000000000LL ) >> 39 ) == 0 ) && ( ( ( L40_var2 & 0x8000000000LL ) >> 39 ) == 0 ) && ( ( ( L40_var_out & 0x8000000000LL ) >> 39 ) != 0 ) ) + { + *Overflow = 1; + L40_var_out = MAX_40; + } +#endif + +#ifdef WMOPS + multiCounter[currCounter].L40_add++; +#endif + + + BASOP_CHECK(); + + + return ( L40_var_out ); +} + +#endif /* BASOP_NOGLOB */ +Word40 L40_add( Word40 L40_var1, Word40 L40_var2 ) +{ + Word40 L40_var_out; + + L40_var_out = L40_var1 + L40_var2; + +#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 ) + if ( ( ( ( L40_var1 & 0x8000000000 ) >> 39 ) != 0 ) && ( ( ( L40_var2 & 0x8000000000 ) >> 39 ) != 0 ) && ( ( ( L40_var_out & 0x8000000000 ) >> 39 ) == 0 ) ) + { +#ifndef BASOP_NOGLOB + Overflow = 1; + exit( 2 ); + /* L40_var_out = L40_UNDERFLOW_OCCURED( L40_var_out); */ +#else /* BASOP_NOGLOB */ + assert( 0 ); + L40_var_out = MIN_40; +#endif /* BASOP_NOGLOB */ + } + else if ( ( ( ( L40_var1 & 0x8000000000 ) >> 39 ) == 0 ) && ( ( ( L40_var2 & 0x8000000000 ) >> 39 ) == 0 ) && ( ( ( L40_var_out & 0x8000000000 ) >> 39 ) != 0 ) ) + { +#ifndef BASOP_NOGLOB + Overflow = 1; + exit( 1 ); + /* L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out); */ +#else /* BASOP_NOGLOB */ + assert( 0 ); + L40_var_out = MAX_40; +#endif /* BASOP_NOGLOB */ + } +#else + if ( ( ( ( L40_var1 & 0x8000000000LL ) >> 39 ) != 0 ) && ( ( ( L40_var2 & 0x8000000000LL ) >> 39 ) != 0 ) && ( ( ( L40_var_out & 0x8000000000LL ) >> 39 ) == 0 ) ) + { +#ifndef BASOP_NOGLOB + Overflow = 1; + exit( 2 ); + /* L40_var_out = L40_UNDERFLOW_OCCURED( L40_var_out); */ +#else /* BASOP_NOGLOB */ + assert( 0 ); + L40_var_out = MIN_40; +#endif /* BASOP_NOGLOB */ + } + else if ( ( ( ( L40_var1 & 0x8000000000LL ) >> 39 ) == 0 ) && ( ( ( L40_var2 & 0x8000000000LL ) >> 39 ) == 0 ) && ( ( ( L40_var_out & 0x8000000000LL ) >> 39 ) != 0 ) ) + { +#ifndef BASOP_NOGLOB + Overflow = 1; + exit( 1 ); + /* L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out); */ +#else /* BASOP_NOGLOB */ + assert( 0 ); + L40_var_out = MAX_40; +#endif /* BASOP_NOGLOB */ + } +#endif + +#ifdef WMOPS + multiCounter[currCounter].L40_add++; +#endif + + BASOP_CHECK(); + + + 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. + * + *****************************************************************************/ +#ifndef BASOP_NOGLOB +Word40 L40_sub( Word40 L40_var1, Word40 L40_var2 ) +#else /* BASOP_NOGLOB */ +Word40 L40_sub_o( Word40 L40_var1, Word40 L40_var2, Flag *Overflow ) +#endif /* BASOP_NOGLOB */ +{ + Word40 L40_var_out; + + L40_var_out = L40_var1 - L40_var2; + +#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 ) + if ( ( ( ( L40_var1 & 0x8000000000 ) >> 39 ) != 0 ) && ( ( ( L40_var2 & 0x8000000000 ) >> 39 ) == 0 ) && ( ( ( L40_var_out & 0x8000000000 ) >> 39 ) == 0 ) ) + { +#ifndef BASOP_NOGLOB + Overflow = 1; + exit( 2 ); + /* L40_var_out = L40_UNDERFLOW_OCCURED( L40_var_out); */ +#else /* BASOP_NOGLOB */ + *Overflow = 1; + L40_var_out = MIN_40; +#endif /* BASOP_NOGLOB */ + } + else if ( ( ( ( L40_var1 & 0x8000000000 ) >> 39 ) == 0 ) && ( ( ( L40_var2 & 0x8000000000 ) >> 39 ) != 0 ) && ( ( ( L40_var_out & 0x8000000000 ) >> 39 ) != 0 ) ) + { +#ifndef BASOP_NOGLOB + Overflow = 1; + exit( 1 ); + /* L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out); */ +#else /* BASOP_NOGLOB */ + *Overflow = 1; + L40_var_out = MAX_40; +#endif /* BASOP_NOGLOB */ + } +#else + if ( ( ( ( L40_var1 & 0x8000000000LL ) >> 39 ) != 0 ) && ( ( ( L40_var2 & 0x8000000000LL ) >> 39 ) == 0 ) && ( ( ( L40_var_out & 0x8000000000LL ) >> 39 ) == 0 ) ) + { +#ifndef BASOP_NOGLOB + Overflow = 1; + exit( 2 ); + /* L40_var_out = L40_UNDERFLOW_OCCURED( L40_var_out); */ +#else /* BASOP_NOGLOB */ + *Overflow = 1; + L40_var_out = MIN_40; +#endif /* BASOP_NOGLOB */ + } + else if ( ( ( ( L40_var1 & 0x8000000000LL ) >> 39 ) == 0 ) && ( ( ( L40_var2 & 0x8000000000LL ) >> 39 ) != 0 ) && ( ( ( L40_var_out & 0x8000000000LL ) >> 39 ) != 0 ) ) + { +#ifndef BASOP_NOGLOB + Overflow = 1; + exit( 1 ); + /* L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out); */ +#else /* BASOP_NOGLOB */ + *Overflow = 1; + L40_var_out = MAX_40; +#endif /* BASOP_NOGLOB */ + } +#endif + +#ifdef WMOPS + multiCounter[currCounter].L40_sub++; +#endif + + BASOP_CHECK(); + + + return ( L40_var_out ); +} + +#ifdef BASOP_NOGLOB +Word40 L40_sub( Word40 L40_var1, Word40 L40_var2 ) +{ + Word40 L40_var_out; + + L40_var_out = L40_var1 - L40_var2; + +#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 ) + if ( ( ( ( L40_var1 & 0x8000000000 ) >> 39 ) != 0 ) && ( ( ( L40_var2 & 0x8000000000 ) >> 39 ) == 0 ) && ( ( ( L40_var_out & 0x8000000000 ) >> 39 ) == 0 ) ) + { + assert( 0 ); + L40_var_out = MIN_40; + } + else if ( ( ( ( L40_var1 & 0x8000000000 ) >> 39 ) == 0 ) && ( ( ( L40_var2 & 0x8000000000 ) >> 39 ) != 0 ) && ( ( ( L40_var_out & 0x8000000000 ) >> 39 ) != 0 ) ) + { + assert( 0 ); + L40_var_out = MAX_40; + } +#else + if ( ( ( ( L40_var1 & 0x8000000000LL ) >> 39 ) != 0 ) && ( ( ( L40_var2 & 0x8000000000LL ) >> 39 ) == 0 ) && ( ( ( L40_var_out & 0x8000000000LL ) >> 39 ) == 0 ) ) + { + assert( 0 ); + L40_var_out = MIN_40; + } + else if ( ( ( ( L40_var1 & 0x8000000000LL ) >> 39 ) == 0 ) && ( ( ( L40_var2 & 0x8000000000LL ) >> 39 ) != 0 ) && ( ( ( L40_var_out & 0x8000000000LL ) >> 39 ) != 0 ) ) + { + assert( 0 ); + L40_var_out = MAX_40; + } +#endif + +#ifdef WMOPS + multiCounter[currCounter].L40_sub++; +#endif + + BASOP_CHECK(); + + + return ( L40_var_out ); +} +#endif /* BASOP_NOGLOB */ + +/***************************************************************************** + * + * 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 ); + } + else + { + L40_var_out = L40_var1; + } + +#ifdef WMOPS + multiCounter[currCounter].L40_abs++; +#endif + + 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; + +#ifdef WMOPS + multiCounter[currCounter].L40_max++; +#endif + + 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; + +#ifdef WMOPS + multiCounter[currCounter].L40_min++; +#endif + + 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. + * + *****************************************************************************/ +#ifndef BASOP_NOGLOB +Word32 L_saturate40( Word40 L40_var1 ) +#else /* BASOP_NOGLOB */ + +Word32 L_saturate40_o( Word40 L40_var1, Flag *Overflow ) +#endif /* BASOP_NOGLOB */ +{ + 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; +#ifndef BASOP_NOGLOB + Overflow = 1; +#else /* BASOP_NOGLOB */ + *Overflow = 1; +#endif /* BASOP_NOGLOB */ + } + + if ( L40_var1 > OVER_L40_var2 ) + { + L40_var1 = OVER_L40_var2; +#ifndef BASOP_NOGLOB + Overflow = 1; +#else /* BASOP_NOGLOB */ + *Overflow = 1; +#endif /* BASOP_NOGLOB */ + } + + L_var_out = L_Extract40( L40_var1 ); + +#ifdef WMOPS + multiCounter[currCounter].L_saturate40++; +#endif + + BASOP_CHECK(); + + + return ( L_var_out ); +} + +#ifdef BASOP_NOGLOB +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; + assert( 0 ); + } + + if ( L40_var1 > OVER_L40_var2 ) + { + L40_var1 = OVER_L40_var2; + assert( 0 ); + } + + L_var_out = L_Extract40( L40_var1 ); + +#ifdef WMOPS + multiCounter[currCounter].L_saturate40++; +#endif + + BASOP_CHECK(); + + + return ( L_var_out ); +} +#endif /* BASOP_NOGLOB */ + +/***************************************************************************** + * + * 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 ); + +#ifdef 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 + multiCounter[currCounter].Mpy_32_16_ss++; +#endif + + 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 ); + +#ifdef 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 + multiCounter[currCounter].Mpy_32_32_ss++; +#endif + + 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 : + * + * L_var_out 32 bit long unsigned integer (UWord32) 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 ); +#ifdef WMOPS + multiCounter[currCounter].L40_lshr--; +#endif + } + else + { + if ( var2 >= 40 ) + L40_var_out = 0x0000000000; + else + { + L40_var_out = L40_var1 << var2; + } + L40_var_out = L40_set( L40_var_out ); + } + +#ifdef WMOPS + multiCounter[currCounter].L40_lshl++; +#endif + + BASOP_CHECK(); + + + 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 ); +#ifdef WMOPS + multiCounter[currCounter].L40_lshl--; +#endif + } + else + { + if ( var2 >= 40 ) + L40_var_out = 0x0000000000; + else + { +#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 ) + L40_var_out = ( L40_var1 & 0xffffffffff ) >> var2; +#else + L40_var_out = ( L40_var1 & 0xffffffffffLL ) >> var2; +#endif + } + } + +#ifdef WMOPS + multiCounter[currCounter].L40_lshr++; +#endif + + BASOP_CHECK(); + + + 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++; + } + + while ( ( L40_var1 < (Word32) 0x80000000L ) || ( L40_var1 > (Word32) 0x7fffffffL ) ) + { + + L40_var1 = L40_shl( L40_var1, -1 ); + var_out--; + } + } + + + 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 ( var2 > 0 ) + { + if ( ( L40_var1 & ( (Word40) 1 << ( var2 - 1 ) ) ) != 0 ) + { + /* below line can not generate overflows on 40-bit */ + L40_var_out++; + } + } + } + + BASOP_CHECK(); + + + 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 ); + } + else + { + var2 = -var2; + L40_var_out = L40_shr_r( L40_var1, var2 ); + } + + + return ( L40_var_out ); +} + + +#undef WMC_TOOL_SKIP diff --git a/lib_com/enh40.h b/lib_com/enh40.h new file mode 100644 index 000000000..ca78cb33e --- /dev/null +++ b/lib_com/enh40.h @@ -0,0 +1,409 @@ +/****************************************************************************************************** + + (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +/* + =========================================================================== + 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" + +#if defined( BASOP_NOGLOB ) || defined( _MSC_VER ) +#define MAX_40 ( 0x0000007fffffffff ) +#define MIN_40 ( 0xffffff8000000000 ) +#endif + +#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 ); +#ifdef BASOP_NOGLOB +/* + * Overflowing operators + */ +Word40 L40_shl_o( Word40 L40_var1, Word16 var2, Flag *Overflow ); +Word40 L40_add_o( Word40 L40_var1, Word40 L40_var2, Flag *Overflow ); +Word40 L40_sub_o( Word40 L40_var1, Word40 L40_var2, Flag *Overflow ); +Word32 L_saturate40_o( Word40 L40_var1, Flag *Overflow ); +#endif /* BASOP_NOGLOB */ +/*#ifdef _MSC_VER*/ +static __inline Word40 L40_set( Word40 L40_var1 ) +{ + Word40 L40_var_out; + +#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 ) + L40_var_out = L40_var1 & 0x000000ffffffffff; + + if ( L40_var1 & 0x8000000000 ) + L40_var_out = L40_var_out | 0xffffff0000000000; +#else + L40_var_out = L40_var1 & 0x000000ffffffffffLL; + + if ( L40_var1 & 0x8000000000LL ) + L40_var_out = L40_var_out | 0xffffff0000000000LL; +#endif + +#ifdef WMOPS + multiCounter[currCounter].L40_set++; +#endif + + return ( L40_var_out ); +} +/*#endif*/ /* ifdef _MSC_VER */ + + +static __inline UWord16 Extract40_H( Word40 L40_var1 ) +{ + UWord16 var_out; + + var_out = (UWord16) ( L40_var1 >> 16 ); + +#ifdef WMOPS + multiCounter[currCounter].Extract40_H++; +#endif + + return ( var_out ); +} + + +static __inline UWord16 Extract40_L( Word40 L40_var1 ) +{ + UWord16 var_out; + + var_out = (UWord16) ( L40_var1 ); + +#ifdef WMOPS + multiCounter[currCounter].Extract40_L++; +#endif + + return ( var_out ); +} + + +static __inline UWord32 L_Extract40( Word40 L40_var1 ) +{ + UWord32 L_var_out; + + L_var_out = (UWord32) L40_var1; + +#ifdef WMOPS + multiCounter[currCounter].L_Extract40++; +#endif + + return ( L_var_out ); +} + + +static __inline Word40 L40_deposit_h( Word16 var1 ) +{ + Word40 L40_var_out; + + L40_var_out = ( (Word40) var1 ) << 16; + +#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 ) + if ( var1 & 0x8000 ) + { + L40_var_out = L40_set( L40_var_out | 0xff00000000 ); + +#ifdef WMOPS + multiCounter[currCounter].L40_set--; +#endif + } +#else + if ( var1 & 0x8000 ) + { + L40_var_out = L40_set( L40_var_out | 0xff00000000LL ); + +#ifdef WMOPS + multiCounter[currCounter].L40_set--; +#endif + } +#endif + +#ifdef WMOPS + multiCounter[currCounter].L40_deposit_h++; +#endif + + return ( L40_var_out ); +} + + +static __inline Word40 L40_deposit_l( Word16 var1 ) +{ + Word40 L40_var_out; + + L40_var_out = var1; + +#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 ) + if ( var1 & 0x8000 ) + { + L40_var_out = L40_set( L40_var_out | 0xffffff0000 ); + +#ifdef WMOPS + multiCounter[currCounter].L40_set--; +#endif + } +#else + if ( var1 & 0x8000 ) + { + L40_var_out = L40_set( L40_var_out | 0xffffff0000LL ); + +#ifdef WMOPS + multiCounter[currCounter].L40_set--; +#endif + } +#endif + +#ifdef WMOPS + multiCounter[currCounter].L40_deposit_l++; +#endif + + return ( L40_var_out ); +} + + +static __inline Word40 L40_deposit32( Word32 L_var1 ) +{ + Word40 L40_var_out; + + L40_var_out = (Word40) L_var1; + +#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 ) + if ( L_var1 & 0x80000000 ) + { + L40_var_out = L40_set( L40_var_out | 0xff00000000 ); + +#ifdef WMOPS + multiCounter[currCounter].L40_set--; +#endif + } +#else + if ( L_var1 & 0x80000000 ) + { + L40_var_out = L40_set( L40_var_out | 0xff00000000LL ); + +#ifdef WMOPS + multiCounter[currCounter].L40_set--; +#endif + } +#endif + +#ifdef WMOPS + multiCounter[currCounter].L40_deposit32++; +#endif + + return ( L40_var_out ); +} + + +static __inline Word40 L40_round( Word40 L40_var1 ) +{ + Word40 L40_var_out; + Word40 L40_constant; + +#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 ) + L40_constant = L40_set( 0xffffff0000 ); +#else + L40_constant = L40_set( 0xffffff0000LL ); +#endif + + L40_var_out = L40_add( 0x8000, L40_var1 ); + L40_var_out = L40_var_out & L40_constant; + +#ifdef WMOPS + multiCounter[currCounter].L40_set--; + multiCounter[currCounter].L40_add--; + multiCounter[currCounter].L40_round++; +#endif + + return ( L40_var_out ); +} + + +static __inline Word16 round40( Word40 L40_var1 ) +{ + Word16 var_out; + + var_out = extract_h( L_saturate40( L40_round( L40_var1 ) ) ); + +#ifdef WMOPS + multiCounter[currCounter].L40_round--; + multiCounter[currCounter].L_saturate40--; + multiCounter[currCounter].extract_h--; + multiCounter[currCounter].round40++; +#endif + + return ( var_out ); +} + + +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; + +#ifdef WMOPS + multiCounter[currCounter].L40_mult++; +#endif + + return ( L40_var_out ); +} + + +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 ); + +#ifdef WMOPS + multiCounter[currCounter].L40_mac++; +#endif + + return ( L40_var_out ); +} + + +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 ); + + + return ( var_out ); +} + + +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 ); + + + return ( L40_var_out ); +} + + +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 ); + + + return ( var_out ); +} + + +#endif /*_ENH40_H*/ + + +/* end of file */ diff --git a/lib_com/enhancer.c b/lib_com/enhancer.c new file mode 100644 index 000000000..e8bae9e3d --- /dev/null +++ b/lib_com/enhancer.c @@ -0,0 +1,244 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ + +static void agc2( const float *sig_in, float *sig_out,const short l_trm ); + +/*---------------------------------------------------------------------* + * enhancer() + * + * Enhancement of the excitation signal before synthesis + *---------------------------------------------------------------------*/ + +void enhancer( + const short codec_mode, /* i : flag indicating Codec Mode */ + const long core_brate, /* i : core bitrate */ + const short cbk_index, /* i : */ + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short coder_type, /* i : coding type */ + const short L_frame, /* i : frame size */ + const float voice_fac, /* i : subframe voicing estimation */ + const float stab_fac, /* i : LP filter stablility measure */ + const float norm_gain_code, /* i : normalized innovative cb. gain */ + const float gain_inov, /* i : gain of the unscaled innovation */ + float *gc_threshold, /* i/o: code threshold */ + float *code, /* i/o: innovation */ + float *pt_exc2, /* i/o: adapt. excitation/total exc. */ + const float gain_pit, /* i : Quantized pitch gain */ + float *dispMem /* i/o: Phase dispersion algorithm memory */ +) +{ + float tmp, gain_code, new_norm_gain_code, fac; + short i; + float pit_sharp; + float excp[L_SUBFR]; + + pit_sharp = gain_pit; + + /*-----------------------------------------------------------------* + * Phase dispersion + * + * Enhance noise at low bit rates + *-----------------------------------------------------------------*/ + + i = 2; /* no dispersion */ + if( Opt_AMR_WB ) + { + if ( core_brate <= ACELP_6k60 ) + { + i = 0; /* high dispersion */ + } + else if ( core_brate <= ACELP_8k85 ) + { + i = 1; /* low dispersion */ + } + } + else if( codec_mode == MODE1 && coder_type != UNVOICED ) + { + if ( core_brate <= ACELP_7k20 ) + { + i = 0; /* high dispersion */ + } + else if ( ( coder_type == GENERIC || coder_type == TRANSITION || coder_type == AUDIO || coder_type == INACTIVE ) && core_brate <= ACELP_9k60 ) + { + i = 1; /* low dispersion */ + } + } + else if( codec_mode == MODE2 ) + { + if( ((coder_type!=VOICED) && cbk_index<=2) || ((coder_type==UNVOICED) && L_frame==L_FRAME && cbk_index<=10) || ((coder_type==UNVOICED) && L_frame==L_FRAME16k && cbk_index<=14)) + { + i = 0; /* high dispersion */ + } + else if( (coder_type!=VOICED) && (cbk_index<=7) ) + { + i = 1; /* low dispersion */ + } + } + + phase_dispersion( norm_gain_code, gain_pit, code, i, dispMem ); + + /*------------------------------------------------------------ + * Noise enhancer + * + * Enhance excitation on noise (modify code gain). If signal is noisy and LPC filter is stable, + * move code gain 1.5 dB towards its threshold. This decreases by 3 dB noise energy variation. + *-----------------------------------------------------------*/ + + if ( norm_gain_code < *gc_threshold ) + { + new_norm_gain_code = (float)(norm_gain_code * 1.19f); + if ( new_norm_gain_code > *gc_threshold ) + { + new_norm_gain_code = *gc_threshold; + } + } + else + { + new_norm_gain_code = (float)(norm_gain_code / 1.19f); + if ( new_norm_gain_code < *gc_threshold ) + { + new_norm_gain_code = *gc_threshold; + } + } + *gc_threshold = new_norm_gain_code; + + /* calculate new code gain */ + fac = stab_fac * (0.5f * (1.0f - voice_fac)); /* 1 = unvoiced, 0 = voiced */ + gain_code = fac * new_norm_gain_code + (1.0f - fac) * norm_gain_code; + gain_code *= gain_inov; + + for (i=0; i 1.0 ) + { + pit_sharp = 1.0; + } + + if ( pit_sharp > 0.5 ) + { + for (i = 0; i < L_SUBFR; i++) + { + excp[i] = pt_exc2[i] * pit_sharp * 0.25f; + } + } + } + + /*----------------------------------------------------------------- + * 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 added to exc2 + *-----------------------------------------------------------------*/ + if( L_frame == L_FRAME16k ) + { + tmp = (float)(0.150f*(1.0f+voice_fac)); /* 0.30=voiced, 0=unvoiced */ + } + else + { + tmp = (float)(0.125f * (1.0f + voice_fac)); /* 0.25=voiced, 0=unvoiced */ + } + pt_exc2[0] += code[0] - (tmp * code[1]); + for ( i=1; i 0.5f ) + { + for (i = 0; i < L_SUBFR; i++) + { + excp[i] += pt_exc2[i]; + } + + agc2( pt_exc2, excp, L_SUBFR ); + mvr2r( excp, pt_exc2, L_SUBFR ); + } + } + } + + return; +} + +/*-----------------------------------------------------------------------* + * agc2() + * + * Adaptive gain control + *-----------------------------------------------------------------------*/ + +static void agc2( + const float *sig_in, /* i : postfilter input signal */ + float *sig_out, /* i/o: postfilter output signal */ + const short l_trm /* i : subframe size */ +) +{ + short i; + float gain_in, gain_out; + float g0, gain; + + + gain_out = 0.0f; + for(i=0; i +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + + +/*--------------------------------------------------------------------------* + * env_adj() + * + * Adjust the band energies of noise-fill and low resolution bands + *--------------------------------------------------------------------------*/ + +void env_adj ( + const short *pulses, /* i : number of pulses per band */ + const short length, /* i : length of spectrum */ + const short last_sfm, /* i : index of the last band */ + float *adj, /* o : adjustment factors for the envelope */ + const float env_stab, /* i : Envelope stability parameter */ + const short *sfmsize /* i : Band widths */ +) +{ + short i, j, group; + int npul; + short att_state; + short start, len; + float tmp; + float gain_adj; + short idx; + + att_state = 0; + len = 0; + start = 0; + + /* Find attenuation levels */ + for( i = 0; i <= last_sfm ; i++ ) + { + group = (sfmsize[i] >> 3) - 1; + npul = pulses[i]; + + if( length == L_FRAME32k ) + { + if( npul == 0 ) + { + /* Noise filled band */ + if ( group <= 1 ) + { + if ( i > 0 && pulses[i-1] != 0 && pulses[i+1] != 0 ) + { + adj[i] = 0.36f; + } + else if ( i > 0 && ( pulses[i-1] == 0 || pulses[i+1] == 0) ) + { + adj[i] = 0.54f; + } + else + { + adj[i] = 0.72f; + } + } + else if (i < last_sfm) + { + if ( pulses[i-1] != 0 && pulses[i+1] != 0 ) + { + adj[i] = 0.54f; + } + else + { + adj[i] = 0.72f; + } + } + else + { + adj[i] = 0.72f; + } + + if( att_state == 0 ) + { + start = i; + } + + len++; + att_state = 1; + } + else + { + adj[i] = 1.0f; + if(att_state == 1) /* End of attenuation region found */ + { + tmp = min(1, max(0, len-ENV_ADJ_START)*(1.0f/ENV_ADJ_INCL)); + for( j = start; j < i ; j++ ) + { + adj[j] = max(tmp + (1-tmp)*adj[j],env_stab); + } + len = 0; + att_state = 0; + } + } + } + /* length == L_FRAME16k */ + else + { + /* Calculate low accuracy band attenuation */ + gain_adj = 1.0f; + if( npul > 0 && npul < MAX_P_ATT ) + { + idx = (short)(npul * att_step[group] + 0.5f) - 1; + if( idx < MAX_P_ATT ) + { + gain_adj = gain_att[idx]; + } + } + adj[i] = gain_adj; + } + } + + /* Check if the sequence ended with an attenuation region */ + if( att_state == 1 ) + { + tmp = min(1, max(0, len-ENV_ADJ_START)*(1.0f/ENV_ADJ_INCL)); + + for( j = start; j < i ; j++ ) + { + adj[j] = max(tmp + (1-tmp)*adj[j],env_stab); + } + } + + return; +} diff --git a/lib_com/env_stab.c b/lib_com/env_stab.c new file mode 100644 index 000000000..5f52e4253 --- /dev/null +++ b/lib_com/env_stab.c @@ -0,0 +1,169 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include + +/*--------------------------------------------------------------------------* + * Local constants + *--------------------------------------------------------------------------*/ + +#define ENV_STAB_SMO_HO 10 /* number of hangover frames when switching from music to speech state */ + +/*--------------------------------------------------------------------------*/ +/* Function env_stability() */ +/* ~~~~~~~~~~~~~~~~~~~~~~~~~ */ +/* */ +/* Envelope stability measure */ +/*--------------------------------------------------------------------------*/ + +float env_stability( + const short *ynrm, /*i : Norm vector for current frame */ + const short nb_sfm, /*i : Number of sub-bands */ + short *mem_norm, /*i/o: Norm vector memory from past frame */ + short *mem_env_delta /*i/o: Envelope stability memory for smoothing (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; + float env_stab_f; + + /* 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]; + } + + inv_nb_sfm = 19418; /* Q19 */ + if (nb_sfm == 26) + { + inv_nb_sfm = 20165; /* Q19 */ + } + 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 ( sub(s_and(exp, 1), 1) == 0 ) + { + 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; + env_delta = round_fx(L_shl(L_tmp, 1)); /* Q13 */ + + if (Overflow != 0) /* Saturated due to the above up-shifting operation. */ + { + env_stab = stab_trans_fx[L_STAB_TBL-1]; /* The highest quantized index. */ + env_stab_f = ((float)env_stab)/32768.0f; /* Convert env_stab(Q15) to float */ + return env_stab_f; + } + + /* 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]; + if(sub(env_delta, M_STAB_TBL_FX) < 0) + { + env_stab = sub(0x7FFF,stab_trans_fx[i]); + } + + env_stab_f = ((float)env_stab)/32768.0f; /* Convert env_stab(Q15) to float */ + + return env_stab_f; +} + +/*--------------------------------------------------------------------------* + * env_stab_smo_fx() + * + * + *--------------------------------------------------------------------------*/ + +float env_stab_smo( + float env_stab, /*i : env_stab value */ + float *env_stab_state_p, /*i/o: env_stab state probabilities */ + short *ho_cnt /*i/o: hangover counter for speech state */ +) +{ + short state, prev_state; + float maxval, pp[NUM_ENV_STAB_PLC_STATES], pa[NUM_ENV_STAB_PLC_STATES]; + /* get previous state */ + prev_state = maximum(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 */ + env_stab = (env_stab - stab_trans[L_STAB_TBL-1])/(1-2*stab_trans[L_STAB_TBL-1]); + pp[0] = 1.0f-env_stab; + pp[1] = env_stab; + + /* calculate a priori likelihoods */ + pa[0] = dotp(env_stab_tp[0],env_stab_state_p,NUM_ENV_STAB_PLC_STATES); + pa[1] = dotp(env_stab_tp[1],env_stab_state_p,NUM_ENV_STAB_PLC_STATES); + + /* multiply elementwise with a posteriori likelihoods */ + v_mult(pa,pp,env_stab_state_p,NUM_ENV_STAB_PLC_STATES); + + /* renormalize state probabilities */ + v_multc(env_stab_state_p,1.0f/sum_f(env_stab_state_p,NUM_ENV_STAB_PLC_STATES),env_stab_state_p,NUM_ENV_STAB_PLC_STATES); + + /* find maximum index as return value */ + state = maximum(env_stab_state_p,NUM_ENV_STAB_PLC_STATES,&maxval); + + /* apply some hangover for speech */ + if (state==0 && prev_state==1) + { + *ho_cnt=ENV_STAB_SMO_HO; + } + if (*ho_cnt>0) + { + pp[0]=1; + pp[1]=0; + (*ho_cnt)--; + } + + return state; +} diff --git a/lib_com/env_stab_trans.c b/lib_com/env_stab_trans.c new file mode 100644 index 000000000..b7fb5dfd6 --- /dev/null +++ b/lib_com/env_stab_trans.c @@ -0,0 +1,124 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include + + +/*--------------------------------------------------------------------------* + * env_stab_transient_detect() + * + * Transient detector for envelope stability measure + *--------------------------------------------------------------------------*/ + +void env_stab_transient_detect( + const short is_transient, /* i: Transient flag */ + const short length, /* i : Length of spectrum (32 or 48 kHz) */ + const short norm[], /* i : quantization indices for norms */ + short *no_att_hangover, /* i/o: Frame counter for attenuation hangover */ + float *energy_lt, /* i/o: Long-term energy measure for transient detection */ + const short HQ_mode, /* i : HQ coding mode */ + const short bin_th, /* i : HVQ cross-over frequency bin */ + const float *coeff /* i : Coded spectral coefficients */ +) +{ + float d_max; + float e_frame; + short blk; + short i; + float E_sub[4]; + float delta_e_sub; + short norm_ind; + + short num_subframes = 4; + short bands_per_subframe = 9; + + if( HQ_mode == HQ_HVQ ) + { + e_frame = 0.0f; + + for (i = 0; i < bin_th; i++) + { + e_frame += coeff[i]*coeff[i]; + } + + e_frame = (float)sqrt(e_frame / bin_th); + + if (e_frame > ENERGY_TH) + { + *energy_lt = ENERGY_LT_BETA*(*energy_lt) + (1-ENERGY_LT_BETA)*e_frame; + } + + if (*no_att_hangover > 0) + { + (*no_att_hangover)--; + } + } + else + { + d_max = 0.0f; + e_frame = 0.0f; + if (is_transient && length == L_FRAME32k) + { + /* Measure subframe energies */ + for (blk = 0; blk < num_subframes; blk++) + { + E_sub[blk] = 0.0f; + for (i=0; i ENERGY_TH * num_subframes) + { + for (blk = 0; blk < num_subframes-1; blk++) + { + delta_e_sub = (E_sub[blk+1]-E_sub[blk]) / *energy_lt; + if (delta_e_sub > d_max) + { + d_max = delta_e_sub; + } + } + } + } + else + { + /* Update long-term energy measure */ + e_frame = 0.0f; + + for (i = 0; i < SFM_N_ENV_STAB; i++) + { + e_frame += dicn[norm[i]]; + } + + e_frame = e_frame / SFM_N_ENV_STAB; + + if (e_frame > ENERGY_TH) + { + *energy_lt = ENERGY_LT_BETA*(*energy_lt) + (1-ENERGY_LT_BETA)*e_frame; + } + } + + /* Add hang-over for conservative application of stability-dependent attenuation */ + if(d_max > DELTA_TH) + { + *no_att_hangover = ATT_LIM_HANGOVER; + } + else if (*no_att_hangover > 0) + { + (*no_att_hangover)--; + } + + } + + return; +} diff --git a/lib_com/est_tilt.c b/lib_com/est_tilt.c new file mode 100644 index 000000000..365430700 --- /dev/null +++ b/lib_com/est_tilt.c @@ -0,0 +1,57 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" + + +/*-------------------------------------------------------------------* + * est_tilt() + * + * Estimate spectral tilt based on the relative E of adaptive + * and innovative excitations + *-------------------------------------------------------------------*/ + +float est_tilt( /* o : tilt of the code */ + const float *adpt_exc, /* i : adaptive excitation vector */ + const float gain_pit, /* i : adaptive gain */ + const float *fixe_exc, /* i : algebraic exctitation vector */ + const float gain_code, /* i : algebraic code gain */ + float *voice_fac, /* o : voicing factor */ + const short L_subfr, /* i : subframe size */ + const short flag_tilt /* i : flag for special tilt */ +) +{ + float ener, tmp, tilt_code; + + ener = dotp( adpt_exc, adpt_exc, L_subfr ); + ener *= gain_pit * gain_pit; /* energy of pitch excitation */ + + tmp = dotp( fixe_exc, fixe_exc, L_subfr ); + tmp *= gain_code * gain_code; /* energy of innovative code excitation */ + + /* find voice factor (1=voiced, -1=unvoiced) */ + *voice_fac = (float)((ener - tmp) / (ener + tmp + 0.01f)); + + /* find tilt of code for next subframe */ + if (flag_tilt==0) + { + /*Between 0 (=unvoiced) and 0.5 (=voiced)*/ + tilt_code = (float)(0.25f*(1.0f + *voice_fac)); + } + else if (flag_tilt==1) + { + /*Between 0.25 (=unvoiced) and 0.5 (=voiced)*/ + tilt_code = (float)(0.25f + (*voice_fac+1.0f)*0.125f); + } + else + { + /*Between 0.28 (=unvoiced) and 0.56 (=voiced)*/ + tilt_code = (float)(0.28f + (*voice_fac+1.0f)*0.14f); + } + + return tilt_code; +} diff --git a/lib_com/fd_cng_com.c b/lib_com/fd_cng_com.c new file mode 100644 index 000000000..6d7bf29d6 --- /dev/null +++ b/lib_com/fd_cng_com.c @@ -0,0 +1,1081 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "prot.h" +#include "rom_com.h" + + + +/*------------------------------------------------------------------- + * Local functions + *-------------------------------------------------------------------*/ + +static void mhvals( int d, float * m ); + + +/*------------------------------------------------------------------- + * createFdCngCom() + * + * 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)); + + *hFdCngCom = hs; + + return; +} + + +/*------------------------------------------------------------------- + * initFdCngCom() + * + * + *-------------------------------------------------------------------*/ + +void initFdCngCom( + HANDLE_FD_CNG_COM hs, /* i/o: Contains the variables related to the FD-based CNG process */ + float scale +) +{ + + /* Calculate FFT scaling factor */ + hs->scalingFactor = 1 / (scale*scale*8.f); + + /* Initialize the overlap-add */ + set_f( hs->timeDomainBuffer, 0.0f, L_FRAME16k ); + set_f( hs->olapBufferAna, 0.0f, FFTLEN ); + set_f( hs->olapBufferSynth, 0.0f, FFTLEN ); + set_f( hs->olapBufferSynth2, 0.0f, FFTLEN ); + + /* Initialize the comfort noise generation */ + set_f( hs->fftBuffer, 0.0f, FFTLEN ); + set_f( hs->cngNoiseLevel, 0.0f, FFTCLDFBLEN ); + + /* Initialize quantizer */ + set_f( hs->sidNoiseEst, 0.0f, NPART ); + set_f( hs->A_cng, 0.0f, M+1 ); + hs->A_cng[0] = 1.f; + + /* Set some counters and flags */ + hs->inactive_frame_counter = 0; /* Either SID or zero frames */ + hs->active_frame_counter = 0; + hs->frame_type_previous = ACTIVE_FRAME; + hs->flag_noisy_speech = 0; + hs->likelihood_noisy_speech = 0.f; + hs->numCoreBands = 0; + hs->stopBand = 0; + hs->startBand = 0; + hs->stopFFTbin = 0; + hs->frameSize = 0; + hs->fftlen = 0; + + /* Initialize noise estimation algorithm */ + set_f( hs->periodog, 0.0f, PERIODOGLEN ); + mhvals(MSNUMSUBFR*MSSUBFRLEN, &(hs->msM_win)); + mhvals(MSSUBFRLEN, &(hs->msM_subwin)); + set_f( hs->msPeriodogSum, 0.0f, 2 ); + set_f( hs->msPsdSum, 0.0f, 2 ); + set_f( hs->msSlope, 0.0f, 2 ); + set_f( hs->msQeqInvAv, 0.0f, 2 ); + hs->msFrCnt_init_counter = 0; + hs->msFrCnt_init_thresh = 1; + hs->init_old = 0; + hs->offsetflag = 0; + hs->msFrCnt = MSSUBFRLEN; + hs->msMinBufferPtr = 0; + set_f( hs->msAlphaCor, 0.3f, 2 ); + + return; +} + + +/*------------------------------------------------------------------- + * deleteFdCngCom() + * + * Delete an instance of type FD_CNG_COM + *-------------------------------------------------------------------*/ + +void deleteFdCngCom( + HANDLE_FD_CNG_COM * hFdCngCom /* i/o: Contains the variables related to the FD-based CNG process */ +) +{ + HANDLE_FD_CNG_COM hsCom = *hFdCngCom; + if (hsCom != NULL) + { + free(hsCom); + *hFdCngCom = NULL; + } + + return; +} + + +/*------------------------------------------------------------------- + * initPartitions() + * + * Initialize the spectral partitioning + *-------------------------------------------------------------------*/ + +void initPartitions( + const int * part_in, + int npart_in, + int startBand, + int stopBand, + int * part_out, + int * npart_out, + int * midband, + float * psize, + float * psize_inv, + int stopBandFR +) +{ + int i, j, len_out; + + if (part_in != NULL) + { + if (stopBandFR > startBand) + { + len_out = stopBandFR - startBand; /*part_out*/ + for(i = 0 ; i < len_out ; i++) + { + part_out[i] = i; + } + } + else + { + len_out = 0; + } /*npart_in,part_out*/ + for(j=0 ; j= stopBandFR && part_in[j] >= startBand) + { + part_out[len_out++] = part_in[j] - startBand; + } + } + } + else + { + len_out = stopBand - startBand; /*part_out*/ + for (i = 0 ; i < len_out ; i++) + { + part_out[i] = i; + } + } + *npart_out = len_out; + getmidbands(part_out, len_out, midband, psize, psize_inv); + + return; +} + + +/*------------------------------------------------------------------- + * compress_range() + * + * Apply some dynamic range compression based on the log + *-------------------------------------------------------------------*/ + +void compress_range( + float* in, + float* out, + int len +) +{ + float* ptrIn = in; + float* ptrOut = out; + int i; + + /* out = log2( 1 + in ) */ + for(i = 0 ; i < len ; i++) + { + *ptrOut = (float)log10(*ptrIn + 1.f); + ptrIn++; + ptrOut++; + } + v_multc(out, 1.f/(float)log10(2.f), out, len); + + /* Quantize to simulate a fixed-point representation 6Q9 */ + v_multc(out, CNG_LOG_SCALING, out, len); + for(ptrOut = out ; ptrOut < out + len ; ptrOut++) + { + *ptrOut = (float)((int)(*ptrOut+0.5f)); + if ( *ptrOut == 0.f ) + { + *ptrOut = 1.f; + } + } + v_multc(out, 1./CNG_LOG_SCALING, out, len); + + return; +} + + +/*------------------------------------------------------------------- + * expand_range() + * + * Apply some dynamic range expansion to undo the compression + *-------------------------------------------------------------------*/ + +void expand_range( + float* in, + float* out, + int len +) +{ + float* ptrIn = in; + float* ptrOut = out; + int i; + + /* out = (2^(in) - 1) */ + for(i = 0 ; i < len ; i++) + { + *ptrOut = (float)pow(2.f,*ptrIn) - 1.f; + if ( *ptrOut < 0.0003385080526823181f ) + { + *ptrOut = 0.0003385080526823181f; + } + ptrIn++; + ptrOut++; + } + + return; +} + + +/*------------------------------------------------------------------- + * minimum_statistics() + * + * Noise estimation using Minimum Statistics (MS) + *-------------------------------------------------------------------*/ + +void minimum_statistics( + int len, /* i : Vector length */ + int lenFFT, /* i : Length of the FFT part of the vectors */ + float * psize, + float * msPeriodog, /* i : Periodograms */ + float * msNoiseFloor, + float * msNoiseEst, /* o : Noise estimates */ + float * msAlpha, + float * msPsd, + float * msPsdFirstMoment, + float * msPsdSecondMoment, + float * msMinBuf, + float * msBminWin, + float * msBminSubWin, + float * msCurrentMin, + float * msCurrentMinOut, + float * msCurrentMinSubWindow, + int * msLocalMinFlag, + int * msNewMinFlag, + float * msPeriodogBuf, + int * msPeriodogBufPtr, + HANDLE_FD_CNG_COM st /* i/o: FD_CNG structure containing all buffers and variables */ +) +{ + float msM_win = st->msM_win; + float msM_subwin = st->msM_subwin; + float * msPsdSum = st->msPsdSum; + float * msPeriodogSum = st->msPeriodogSum; + float slope; + float * ptr; + float msAlphaCorAlpha = MSALPHACORALPHA; + float msAlphaCorAlpha2 = 1.f-MSALPHACORALPHA; + + short i,j,k; + float scalar, scalar2, scalar3; + float snr, BminCorr, QeqInv, QeqInvAv; + float beta; + float msAlphaHatMin2; + int len2 = MSNUMSUBFR*len; + int current_len; + short start, stop, cnt; + int totsize; + + /* No minimum statistics at initialization */ + if (st->msFrCnt_init_counter < st->msFrCnt_init_thresh) + { + mvr2r(msPeriodog, msPsd, len); + mvr2r(msPeriodog, msNoiseFloor, len); + mvr2r(msPeriodog, msNoiseEst, len); + mvr2r(msPeriodog, msPsdFirstMoment, len); + set_f( msPsdSecondMoment, 0.0f, len); + msPeriodogSum[0] = dotp(msPeriodog, psize, lenFFT); + msPsdSum[0] = msPeriodogSum[0]; + if (lenFFT ignore them */ + if (msPeriodog[0]init_old) + { + set_f(msCurrentMinOut, FLT_MAX, len); + set_f(msCurrentMin, FLT_MAX, len); + set_f(msMinBuf, FLT_MAX, len2); + set_f(msCurrentMinSubWindow, FLT_MAX, len); + st->msFrCnt_init_counter++; + } + st->init_old = msPeriodog[0]; + } + + else + { + + /* Consider the FFT and CLDFB bands separately + - first iteration for FFT bins, + - second one for CLDFB bands in SWB mode */ + start = 0; + stop = lenFFT; + totsize = st->stopFFTbin-st->startBand; + cnt = 0; /*msAlphaCor*/ + while (stop > start) + { + current_len = stop-start; + + /* Compute smoothed correction factor for PSD smoothing */ + msPeriodogSum[cnt] = dotp(msPeriodog+start, psize+start, current_len); + scalar = msPeriodogSum[cnt]*msPeriodogSum[cnt] + DELTA; + scalar2 = msPsdSum[cnt] - msPeriodogSum[cnt]; + scalar = max(scalar / (scalar + scalar2*scalar2) , MSALPHACORMAX); + st->msAlphaCor[cnt] = msAlphaCorAlpha*st->msAlphaCor[cnt] + msAlphaCorAlpha2*scalar; + + /* Compute SNR */ + snr = dotp(msNoiseFloor+start, psize+start, current_len); + snr = (msPsdSum[cnt] + DELTA) / (snr + DELTA); + snr = (float)pow(snr, MSSNREXP); + msAlphaHatMin2 = min( MSALPHAHATMIN, snr ); + scalar = MSALPHAMAX * st->msAlphaCor[cnt]; /*msAlpha,msPsd,msPeriodog,msNoiseFloor*/ + for(j=start ; jmsQeqInvAv[cnt] = QeqInvAv; + + /* New minimum? */ + BminCorr = 1.f + MSAV * (float)sqrt(QeqInvAv); /*msPsd,msBminWin,msNewMinFlag,msCurrentMin,msCurrentMinSubWindow*/ + for(j=start ; jmsFrCnt >= MSSUBFRLEN) + { + i = 0; + while (i < 3) + { + if (st->msQeqInvAv[cnt] < msQeqInvAv_thresh[i]) + { + break; + } + else + { + i++; + } + } + st->msSlope[cnt] = msNoiseSlopeMax[i]; + } + + /* Consider the FFT and CLDFB bands separately */ + start = stop; + stop = len; + totsize = st->stopBand - st->stopFFTbin; + cnt++; + } /*while (stop > start)*/ + + /* Update minimum between sub windows */ + if( st->msFrCnt > 1 && st->msFrCnt < MSSUBFRLEN ) + { + /*msNewMinFlag,msCurrentMinSubWindow,msCurrentMinOut*/ + for(j=0 ; j 0) + { + msLocalMinFlag[j] = 1; + } + if (msCurrentMinSubWindow[j] < msCurrentMinOut[j]) + { + msCurrentMinOut[j] = msCurrentMinSubWindow[j]; + } + } + /* Get the current noise floor */ + mvr2r(msCurrentMinOut, msNoiseFloor, len); + } + + /* sub window complete */ + else + { + if (st->msFrCnt >= MSSUBFRLEN) + { + /* Collect buffers */ + mvr2r(msCurrentMinSubWindow, msMinBuf+len*st->msMinBufferPtr, len); + + /* Compute minimum among all buffers */ + mvr2r(msMinBuf, msCurrentMinOut, len); + ptr = msMinBuf + len; + for (i=1 ; imsSlope[0]; /*msLocalMinFlag,msNewMinFlag,msCurrentMinSubWindow,msCurrentMinOut*/ + for(j=0 ; jmsSlope[1]; + } + if ( msLocalMinFlag[j] && !msNewMinFlag[j] && + msCurrentMinSubWindow[j]msCurrentMinOut[j] ) + { + msCurrentMinOut[j] = msCurrentMinSubWindow[j]; + i = j; + for(k=0 ; k50.f*msPeriodogSum[0]) + { + if (st->offsetflag>0) + { + mvr2r(msPeriodog, msPsd, len); + mvr2r(msPeriodog, msCurrentMinOut, len); + set_f( st->msAlphaCor, 1.0f, cnt); + set_f( msAlpha, 0.0f, len); + mvr2r(msPeriodog, msPsdFirstMoment, len); + set_f( msPsdSecondMoment, 0.0f, len); + msPsdSum[0] = dotp(msPeriodog, psize, lenFFT); + if (lenFFToffsetflag = 1; + } + else + { + st->offsetflag = 0; + } + + + /* Increment frame counter */ + if (st->msFrCnt == MSSUBFRLEN) + { + st->msFrCnt = 1; + st->msMinBufferPtr++; + if (st->msMinBufferPtr==MSNUMSUBFR) + { + st->msMinBufferPtr = 0; + } + } + else + { + (st->msFrCnt)++; + } + + { + /* Smooth noise estimate during CNG phases */ /*msNoiseEst,msNoiseFloor*/ + for(j=0 ; jscalar) + { + msNoiseEst[j] = scalar; + } + assert(msNoiseEst[j] >= 0); + } + } + + return; +} + + +/*------------------------------------------------------------------- + * apply_scale() + * + * Apply bitrate-dependent scale + *-------------------------------------------------------------------*/ + +void apply_scale( + float *scale, + int bandwidth, + int bitrate +) +{ + int i; + int scaleTableSize = sizeof (scaleTable) / sizeof (scaleTable[0]); + + for (i = 0 ; i < scaleTableSize ; i++) + { + if ( (bandwidth == scaleTable[i].bwmode) && + (bitrate >= scaleTable[i].bitrateFrom) && + (bitrate < scaleTable[i].bitrateTo) ) + { + break; + } + } + + *scale += scaleTable[i].scale; + + return; +} + + +/*------------------------------------------------------------------- + * bandcombinepow() + * + * Compute the power for each partition + *-------------------------------------------------------------------*/ + +void bandcombinepow( + float* bandpow, /* i : Power for each band */ + int nband, /* i : Number of bands */ + int* part, /* i : Partition upper boundaries (band indices starting from 0) */ + int npart, /* i : Number of partitions */ + float* psize_inv, /* i : Inverse partition sizes */ + float* partpow /* o : Power for each partition */ +) +{ + + int i, p; + float temp; + + if (nband == npart) + { + mvr2r(bandpow, partpow, nband); + } + else + { + /* Compute the power in each partition */ + i = 0; /*part,partpow,psize_inv*/ + for (p = 0; p < npart; p++) + { + /* Arithmetic averaging of power for all bins in partition */ + temp = 0; + for ( ; i <= part[p]; i++) + { + temp += bandpow[i]; + } + partpow[p] = temp*psize_inv[p]; + } + } + + return; +} + + +/*------------------------------------------------------------------- + * scalebands() + * + * Scale partitions (with smoothing) + *-------------------------------------------------------------------*/ + +void scalebands( + float* partpow, /* i : Power for each partition */ + int* part, /* i : Partition upper boundaries (band indices starting from 0) */ + int npart, /* i : Number of partitions */ + int* midband, /* i : Central band of each partition */ + int nFFTpart, /* i : Number of FFT partitions */ + int nband, /* i : Number of bands */ + float* bandpow, /* o : Power for each band */ + short flag_fft_en +) +{ + int i, j=0, nint, startBand, startPart, stopPart; + float val, delta = 0.f; + + + /* Interpolate the bin/band-wise levels from the partition levels */ + if (nband == npart) + { + mvr2r(partpow, bandpow, npart); + } + else + { + startBand = 0; + startPart = 0; + stopPart = nFFTpart; + while (startBand < nband) + { + if (flag_fft_en || startPart>=nFFTpart) + { + + /* first half partition */ + j = startPart; + val = partpow[j]; + for (i = startBand; i <= midband[j]; i++) + { + bandpow[i] = val; + } + j++; + + delta = 1; + /* inner partitions */ + for ( ; j < stopPart ; j++) + { + nint = midband[j] - midband[j-1]; + /* log-linear interpolation */ /* Only one new LOG needs to be computed per loop iteration */ + delta = (float)exp( (log(partpow[j]+DELTA) - log(partpow[j-1]+DELTA)) * normReciprocal[nint] ); + val = partpow[j-1]; + for ( ; i < midband[j]; i++) + { + val *= delta; + bandpow[i] = val; + } + bandpow[i++] = partpow[j]; + } + if ( delta>1.f ) + { + delta = 1.f; + } + + /* last half partition */ + val = partpow[stopPart-1]; + for ( ; i <= part[stopPart-1]; i++) + { + val *= delta; + bandpow[i] = val; + } + } + startBand = part[stopPart-1]+1; + startPart = stopPart; + stopPart = npart; + } + } + + return; +} + + +/*------------------------------------------------------------------- + * getmidbands() + * + * Get central band for each partition + *-------------------------------------------------------------------*/ + +void getmidbands( + int* part, /* i : Partition upper boundaries (band indices starting from 0) */ + int npart, /* i : Number of partitions */ + int* midband, /* o : Central band of each partition */ + float* psize, /* o : Partition sizes */ + float* psize_inv /* o : Inverse of partition sizes */ +) +{ + int j; + + + /* first half partition */ + midband[0] = part[0]; + psize[0] = (float)part[0] + 1.f; + psize_inv[0] = normReciprocal[part[0] + 1]; + /* inner partitions */ /*part,midband,psize_inv*/ + for (j = 1; j < npart; j++) + { + midband[j] = (part[j-1]+1 + part[j]) >> 1; + psize[j] = (float)(part[j] - part[j-1]); + psize_inv[j] = normReciprocal[part[j] - part[j-1]]; + } + + return; +} + + +/*------------------------------------------------------------------- + * AnalysisSTFT() + * + * STFT analysis filterbank + *-------------------------------------------------------------------*/ + +void AnalysisSTFT( + const float * timeDomainInput, + float * fftBuffer, /* o : FFT bins */ + HANDLE_FD_CNG_COM st /* i/o: FD_CNG structure containing all buffers and variables */ +) +{ + float *olapBuffer = st->olapBufferAna; + const float *olapWin = st->olapWinAna; + + /* Shift and cascade for overlap-add */ + mvr2r(olapBuffer+st->frameSize, olapBuffer, st->fftlen-st->frameSize); + mvr2r(timeDomainInput, olapBuffer+st->fftlen-st->frameSize, st->frameSize); + + /* Window the signal */ + v_mult(olapBuffer, olapWin, fftBuffer, st->fftlen); + + + /* Perform FFT */ + RFFTN(fftBuffer, st->fftSineTab, st->fftlen, -1); + + return; +} + + +/*------------------------------------------------------------------- + * SynthesisSTFT() + * + * STFT synthesis filterbank + *-------------------------------------------------------------------*/ + +void SynthesisSTFT( + float * fftBuffer, /* i : FFT bins */ + float * timeDomainOutput, + float * olapBuffer, + const float * olapWin, + int tcx_transition, + HANDLE_FD_CNG_COM st /* i/o: FD_CNG structure containing all buffers and variables */ +) +{ + short i; + float buf[M+1+320], tmp; + + /* Perform IFFT */ + RFFTN(fftBuffer, st->fftSineTab, st->fftlen, 1); + + /* Perform overlap-add */ + mvr2r(olapBuffer+st->frameSize, olapBuffer, st->frameSize); + set_f( olapBuffer+st->frameSize, 0.0f, st->frameSize); /*olapBuffer, fftBuffer, olapWin*/ + if ( tcx_transition ) + { + for (i=0 ; i<5*st->frameSize/4 ; i++) + { + olapBuffer[i] = fftBuffer[i]; + } + } + else + { + for (i=st->frameSize/4 ; i<3*st->frameSize/4 ; i++) + { + olapBuffer[i] += fftBuffer[i] * olapWin[i-st->frameSize/4]; + } + for ( ; i<5*st->frameSize/4 ; i++) + { + olapBuffer[i] = fftBuffer[i]; + } + } + for ( ; i<7*st->frameSize/4 ; i++) + { + olapBuffer[i] = fftBuffer[i] * olapWin[i-3*st->frameSize/4]; + } + + for ( ; ifftlen ; i++) + { + olapBuffer[i] = 0; + } + + /* Get time-domain signal */ + v_multc( olapBuffer+st->frameSize/4, (float)(st->fftlen/2), timeDomainOutput, st->frameSize); + + /* Get excitation */ + v_multc( olapBuffer+st->frameSize/4-(M+1), (float)(st->fftlen/2), buf, M+1+st->frameSize ); + tmp = buf[0]; + preemph( buf+1, PREEMPH_FAC, M+st->frameSize, &tmp ); + residu( st->A_cng, M, buf+1+M, st->exc_cng, st->frameSize ); + + return; +} + + +/*------------------------------------------------------------------- + * mhvals() + * + * Compute some values used in the bias correction of the minimum statistics algorithm + *-------------------------------------------------------------------*/ + +static void mhvals( + int d, + float * m +) +{ + int i, j; + float qi, qj, q; + int len = sizeof(d_array)/sizeof(int); + + i = 0; + for (i=0 ; iA_cng, Aq+i*(M+1), M+1 ); + } + a2lsp_stab( Aq, lsp_new, lsp_old ); + if( first_CNG == 0 ) + { + mvr2r( lsp_old, lspCNG, M ); + } + for( i=0; iexc_cng, exc, L_frame ); + mvr2r( hs->exc_cng, exc2, L_frame ); + if( L_frame == L_FRAME ) + { + interp_code_5over2( exc2, bwe_exc, L_frame ); + } + else + { + interp_code_4over2( exc2, bwe_exc, L_frame ); + } + + return; +} diff --git a/lib_com/fft.c b/lib_com/fft.c new file mode 100644 index 000000000..54b3016f7 --- /dev/null +++ b/lib_com/fft.c @@ -0,0 +1,3619 @@ + /*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + + #include + #include "wmc_auto.h" + #include + #include "options.h" + #include "cnst.h" + #include "prot.h" + #include "rom_com.h" + + /*-----------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------*/ + + static void cdftForw( short n, float *a, const short *ip, const float *w ); + static void bitrv2_SR( short n, const short *ip, float *a ); + static void cftfsub( short n, float *a, const float *w ); + static void cft1st(short n, float *a, const float *w); + static void cftmdl(short n, short l, float *a, const float *w); + static void fft16( float *x, float *y, const short *Idx ); + static void fft5_shift1( int n1, float *zRe, float *zIm, const short *Idx ); + static void fft8( float *x, float *y, const short *Idx ); + static void fft15_shift2( int n1, float *zRe, float *zIm, const short *Idx ); + static void fft15_shift8( int n1, float *zRe, float *zIm, const short *Idx ); + static void fft5_shift4( int n1, float *zRe, float *zIm, const short *Idx ); + static void fft5_32( float *zRe, float *zIm, const short *Idx ); + static void fft64( float *x, float *y, const short *Idx ); + static void fft32_15( float *x, float *y, const short *Idx ); + static void fft32_5( float *x, float *y, const short *Idx ); + static void fft8_5( float *x, float *y, const short *Idx ); + static void fft5_8( int n1, float *zRe, float *zIm, const short *Idx ); + static void fft4_5( float *x, float *y, const short *Idx ); + static void fft5_4( int n1, float *zRe, float *zIm, const short *Idx ); + + static float fmac(float a, float b, float c) + { + return (((a) * (b)) + (c)); + } + + static float fnms(float a, float b, float c) + { + return ((c) - ((a) * (b))); + } + + /*-----------------------------------------------------------------* + * fft15_shift2() + * 15-point FFT with 2-point circular shift + *-----------------------------------------------------------------*/ + + static void fft15_shift2( + int n1, /* i : length of data */ + float *zRe, /* i/o : real part of input and output data */ + float *zIm, /* i/o : imaginary part of input and output data */ + const short *Idx /* i : pointer of the address table */ + ) + { + short in0, in8, in16, in24, in32, in1, in9, in17, in25, in33, in2, in10, in18, in26, in34; + float fi1, fi2, fi3, fi4, fi5, fi6, fi7, fi8, fi9, fi10, fi11, fi12, fi13, fi14, fi15; + float fi16, fi17, fi18, fi19, fi20, fi21, fi22, fi23, fi24, fi25, fi26, fi27, fi28, fi29, fi30; + float f2i1, f2i2, f2i3, f2i4, f2i5, f2i6, f2i7, f2i8, f2i9, f2i10, f2i11, f2i12; + float f2i13, f2i14, f2i15, f2i16, f2i17, f2i18, f2i19, f2i20, f2i21, f2i22, f2i23, f2i24; + float f3i1, f3i2, f3i3, f3i4, f3i5, f3i6, f3i7, f3i8, f3i9, f3i10, f3i11, f3i12, f3i13, f3i14, f3i15; //CR + float f4i1,f4i2, f4i3, f4i4, f4i5,f4i6, f4i7, f4i8, f4i9; + float f4i10, f4i11, f4i12, f4i13, f4i14, f4i15, f4i16, f4i17, f4i18, f4i19, f4i20, fo1, fo2, fo3, fo4; + float fo5,fo6, fo7, fo8, fo9,fo10, fo11, fo12, fo13, fo14, fo15, fo16, fo17, fo18; + float f2o1, f2o2, f2o3, f2o4, f2o5, f2o6, f2o7, f2o8, f2o9,f2o10, f2o11, f2o12, f2o13; + float f2o14, f2o15, f3o1, f3o2, f3o3, f3o4, f3o5, f3o6, f3o7,f3o8, f3o9, f3o10, f3o11; + float f3o12, f3o13, f3o14, f3o15, f4o1,f4o2, f4o3, f4o4, f4o5, f4o6; + float f4o7, f4o8, f4o9, f4o10,f4o11, f4o12, f4o13, f4o14, f4o15, f4o16, f4o17, f4o18, f4o19; + + in0 = Idx[0]; + in8 = Idx[n1]; + in16 = Idx[n1*2]; + in24 = Idx[n1*3]; + in32 = Idx[n1*4]; + in1 = Idx[n1*5]; + in9 = Idx[n1*6]; + in17 = Idx[n1*7]; + in25 = Idx[n1*8]; + in33 = Idx[n1*9]; + in2 = Idx[n1*10]; + in10 = Idx[n1*11]; + in18 = Idx[n1*12]; + in26 = Idx[n1*13]; + in34 = Idx[n1*14]; + + f2i13 = zRe[in0]; + f2i14 = zIm[in0]; + f2i21 = zRe[in1]; + f2i22 = zRe[in2]; + f2i23 = zIm[in1]; + f2i24 = zIm[in2]; + + f2i15 = f2i21 + f2i22; + f2i16 = FFT_15PONIT_WNK4 * (f2i22 - f2i21); + f2i17 = FFT_15PONIT_WNK4 * (f2i23 - f2i24); + f2i18 = f2i23 + f2i24; + fi1 = f2i13 + f2i15; + fi2 = f2i14 + f2i18; + + f2i19 = fnms(0.5f, f2i15, f2i13); + f2i20 = fnms(0.5f, f2i18, f2i14); + fi3 = f2i19 - f2i17; + fi4 = f2i19 + f2i17; + fi5 = f2i16 + f2i20; + fi6 = f2i20 - f2i16; + + f3i1 = zRe[in9]; + f4i2 = zRe[in10]; + f4i3 = zRe[in8]; + f3i2 = f4i2 + f4i3; + f3i3 = fnms(0.5f, f3i2, f3i1); + f3i4 = FFT_15PONIT_WNK4 * (f4i3 - f4i2); + + f3i5 = zIm[in9]; + f4i4 = zIm[in10]; + f4i5 = zIm[in8]; + f3i6 = f4i4 + f4i5; + f3i7 = FFT_15PONIT_WNK4 * (f4i4 - f4i5); + f3i8 = fnms(0.5f, f3i6, f3i5); + + f3i9 = zRe[in33]; + f4i6 = zRe[in34]; + f4i7 = zRe[in32]; + f3i10 = f4i6 + f4i7; + f3i11 = fnms(0.5f, f3i10, f3i9); + f3i12 = FFT_15PONIT_WNK4 * (f4i7 - f4i6); + + f3i13 = zIm[in33]; + f4i8 = zIm[in34]; + f4i9 = zIm[in32]; + f3i14 = f4i8 + f4i9; + f3i15 = FFT_15PONIT_WNK4 * (f4i8 - f4i9); + f4i1 = fnms(0.5f, f3i14, f3i13); + + fi7 = f3i1 + f3i2; + fi8 = f3i9 + f3i10; + fi9 = fi7 + fi8; + fi10 = f3i3 - f3i7; + fi11 = f3i11 - f3i15; + fi12 = fi10 + fi11; + fi13 = f3i5 + f3i6; + fi14 = f3i13 + f3i14; + fi15 = fi13 + fi14; + fi16 = f3i8 - f3i4; + fi17 = f4i1 - f3i12; + fi18 = fi16 + fi17; + fi19 = f3i4 + f3i8; + fi20 = f3i12 + f4i1; + fi21 = fi19 + fi20; + fi22 = f3i3 + f3i7; + fi23 = f3i11 + f3i15; + fi24 = fi22 + fi23; + + f4i10 = zRe[in24]; + fo6 = zRe[in25]; + fo7 = zRe[in26]; + f4i11 = fo6 + fo7; + f4i12 = fnms(0.5f, f4i11, f4i10); + f4i13 = FFT_15PONIT_WNK4 * (fo7 - fo6); + + f4i14 = zIm[in24]; + fo8 = zIm[in25]; + fo9 = zIm[in26]; + f4i15 = fo8 + fo9; + f4i16 = FFT_15PONIT_WNK4 * (fo8 - fo9); + f4i17 = fnms(0.5f, f4i15, f4i14); + + f4i18 = zRe[in18]; + f2o10 = zRe[in16]; + f2o11 = zRe[in17]; + f4i19 = f2o10 + f2o11; + f4i20 = fnms(0.5f, f4i19, f4i18); + fo1 = FFT_15PONIT_WNK4 * (f2o11 - f2o10); + + fo2 = zIm[in18]; + f2o12 = zIm[in16]; + f2o13 = zIm[in17]; + fo3 = f2o12 + f2o13; + fo4 = FFT_15PONIT_WNK4 * (f2o12 - f2o13); + fo5 = fnms(0.5f, fo3, fo2); + + fi25 = f4i10 + f4i11; + fi26 = f4i18 + f4i19; + fi27 = fi25 + fi26; + fi28 = f4i12 - f4i16; + fi29 = f4i20 - fo4; + fi30 = fi28 + fi29; + f2i1 = f4i14 + f4i15; + f2i2 = fo2 + fo3; + f2i3 = f2i1 + f2i2; + f2i4 = f4i17 - f4i13; + f2i5 = fo5 - fo1; + f2i6 = f2i4 + f2i5; + f2i7 = f4i13 + f4i17; + f2i8 = fo1 + fo5; + f2i9 = f2i7 + f2i8; + f2i10 = f4i12 + f4i16; + f2i11 = f4i20 + fo4; + f2i12 = f2i10 + f2i11; + + fo10 = FFT_15PONIT_WNK1 * (fi27 - fi9); + fo11 = fi27 + fi9; + fo12 = fnms(FFT_15PONIT_WNK5, fo11, fi1); + fo15 = fi13 - fi14; + fo16 = f2i1 - f2i2; + fo13 = fnms(FFT_15PONIT_WNK3, fo16, FFT_15PONIT_WNK2 * fo15); + fo14 = fmac(FFT_15PONIT_WNK2, fo16, FFT_15PONIT_WNK3 * fo15); + + zRe[in0] = fi1 + fo11; + fo17 = fo10 + fo12; + zRe[in18] = fo17 - fo14; + zRe[in24] = fo17 + fo14; + fo18 = fo12 - fo10; + zRe[in9] = fo18 - fo13; + zRe[in33] = fo18 + fo13; + + f2o1 = FFT_15PONIT_WNK1 * (f2i3 - fi15); + f2o2 = f2i3 + fi15; + f2o3 = fnms(FFT_15PONIT_WNK5, f2o2, fi2); + f2o6 = fi7 - fi8; + f2o7 = fi25 - fi26; + f2o4 = fnms(FFT_15PONIT_WNK3, f2o7, FFT_15PONIT_WNK2 * f2o6); + f2o5 = fmac(FFT_15PONIT_WNK2, f2o7, FFT_15PONIT_WNK3 * f2o6); + zIm[in0] = fi2 + f2o2; + f2o8 = f2o1 + f2o3; + zIm[in24] = f2o8 - f2o5; + zIm[in18] = f2o5 + f2o8; + f2o9 = f2o3 - f2o1; + zIm[in33] = f2o9 - f2o4; + zIm[in9] = f2o4 + f2o9; + + f2o14 = FFT_15PONIT_WNK1 * (fi30 - fi12); + f2o15 = fi30 + fi12; + f3o1 = fnms(FFT_15PONIT_WNK5, f2o15, fi3); + f3o4 = fi16 - fi17; + f3o5 = f2i4 - f2i5; + f3o2 = fnms(FFT_15PONIT_WNK3, f3o5, FFT_15PONIT_WNK2 * f3o4); + f3o3 = fmac(FFT_15PONIT_WNK2, f3o5, FFT_15PONIT_WNK3 * f3o4); + zRe[in2] = fi3 + f2o15; + f3o6 = f2o14 + f3o1; + zRe[in17] = f3o6 - f3o3; + zRe[in26] = f3o6 + f3o3; + f3o7 = f3o1 - f2o14; + zRe[in8] = f3o7 - f3o2; + zRe[in32] = f3o7 + f3o2; + + f3o8 = FFT_15PONIT_WNK1 * (f2i6 - fi18); + f3o9 = f2i6 + fi18; + f3o10 = fnms(FFT_15PONIT_WNK5, f3o9, fi6); + f3o13 = fi10 - fi11; + f3o14 = fi28 - fi29; + f3o11 = fnms(FFT_15PONIT_WNK3, f3o14, FFT_15PONIT_WNK2 * f3o13); + f3o12 = fmac(FFT_15PONIT_WNK2, f3o14, FFT_15PONIT_WNK3 * f3o13); + zIm[in2] = fi6 + f3o9; + f3o15 = f3o8 + f3o10; + zIm[in26] = f3o15 - f3o12; + zIm[in17] = f3o12 + f3o15; + f4o1 = f3o10 - f3o8; + zIm[in8] = f3o11 + f4o1; + zIm[in32] = f4o1 - f3o11; + + f4o2 = FFT_15PONIT_WNK1 * (f2i9 - fi21); + f4o3 = f2i9 + fi21; + f4o4 = fnms(FFT_15PONIT_WNK5, f4o3, fi5); + f4o7 = f2i10 - f2i11; + f4o8 = fi22 - fi23; + f4o5 = fmac(FFT_15PONIT_WNK2, f4o7, FFT_15PONIT_WNK3 * f4o8); + f4o6 = fnms(FFT_15PONIT_WNK3, f4o7, FFT_15PONIT_WNK2 * f4o8); + zIm[in1] = fi5 + f4o3; + f4o9 = f4o4 - f4o2; + f4o10 = f4o2 + f4o4; + + zIm[in10] = f4o6 + f4o9; + zIm[in34] = f4o9 - f4o6; + zIm[in25] = f4o10 - f4o5; + zIm[in16] = f4o5 + f4o10; + + f4o11 = FFT_15PONIT_WNK1 * (f2i12 - fi24); + f4o12 = f2i12 + fi24; + f4o13 = fnms(FFT_15PONIT_WNK5, f4o12, fi4); + f4o16 = f2i7 - f2i8; + f4o17 = fi19 - fi20; + f4o14 = fmac(FFT_15PONIT_WNK2, f4o16, FFT_15PONIT_WNK3 * f4o17); + f4o15 = fnms(FFT_15PONIT_WNK3, f4o16, FFT_15PONIT_WNK2 * f4o17); + zRe[in1] = fi4 + f4o12; + f4o18 = f4o13 - f4o11; + f4o19 = f4o11 + f4o13; + + zRe[in10] = f4o18 - f4o15; + zRe[in34] = f4o18 + f4o15; + zRe[in16] = f4o19 - f4o14; + zRe[in25] = f4o19 + f4o14; + + return; + } + + /*-----------------------------------------------------------------* + * fft15_shift8() + * 15-point FFT with 8-point circular shift + *-----------------------------------------------------------------*/ + + static void fft15_shift8( + int n1, /* i : length of data */ + float *zRe, /* i/o : real part of input and output data */ + float *zIm, /* i/o : imaginary part of input and output data */ + const short *Idx /* i : pointer of the address table */ + ) + { + short in0, in8, in16, in24, in32, in1, in9, in17, in25, in33, in2, in10, in18, in26, in34; + float fi1, fi2, fi3, fi4, fi5, fi6, fi7, fi8, fi9, fi10, fi11, fi12, fi13, fi14, fi15; + float fi16, fi17, fi18, fi19, fi20, fi21, fi22, fi23, fi24, fi25, fi26, fi27, fi28, fi29, fi30; + float f2i1, f2i2, f2i3, f2i4, f2i5, f2i6, f2i7, f2i8, f2i9, f2i10, f2i11, f2i12; + float f2i13, f2i14, f2i15, f3i1, f3i2, f3i3, f3i4, f3i5, f3i6, f3i7, f3i8, f3i9; + float f3i10, f3i11, f3i12, f3i13, f3i14, f3i15, f4i1, f4i2, f4i3, f4i4, f4i5, f4i6, f4i7, f4i8, f4i9; + float f4i10, f4i11, f4i12, f4i13, f4i14, f4i15, fo1, fo2, fo3, fo4, fo5, fo6; + float fo7, fo8, fo9, fo10, fo11, fo12, fo13, fo14, fo15, f2o1, f2o2, f2o3, f2o4; + float f2o5, f2o6, f2o7, f2o8, f2o9, f2o10, f2o11, f2o12, f2o13, f2o14, f2o15; + float f3o1, f3o2, f3o3, f3o4, f3o5, f3o6, f3o7, f3o8, f3o9, f3o10, f3o11, f3o12; + float f3o13, f3o14, f3o15, f4o1, f4o2, f4o3, f4o4, f4o5, f4o6, f4o7, f4o8, f4o9; + float f4o10, f4o11, f4o12, f4o13, f4o14, f4o15, f5o1, f5o2, f5o3, f5o4, f5o5, f5o6, f5o7; + float f5o8, f5o9, f5o10, f5o11, f5o12, f5o13, f5o14, f5o15, f5o16, f5o17, f5o18, f5o19, f5o21, f5o22; + + in0 = Idx[0] ; + in8 = Idx[n1]; + in16 = Idx[n1*2]; + in24 = Idx[n1*3]; + in32 = Idx[n1*4]; + in1 = Idx[n1*5]; + in9 = Idx[n1*6]; + in17 = Idx[n1*7]; + in25 = Idx[n1*8]; + in33 = Idx[n1*9]; + in2 = Idx[n1*10]; + in10 = Idx[n1*11]; + in18 = Idx[n1*12]; + in26 = Idx[n1*13]; + in34 = Idx[n1*14]; + + f2i13 = zRe[in0]; + f2i14 = zIm[in0]; + f3i6 = zRe[in1]; + f3i7 = zRe[in2]; + f3i8 = zIm[in1]; + f3i9 = zIm[in2]; + + f2i15 = f3i6 + f3i7; + f3i1 = FFT_15PONIT_WNK4 * (f3i7 - f3i6); + f3i2 = FFT_15PONIT_WNK4 * (f3i8 - f3i9); + f3i3 = f3i8 + f3i9; + + fi1 = f2i13 + f2i15; + fi2 = f2i14 + f3i3; + f3i4 = fnms(0.5f, f2i15, f2i13); + fi3 = f3i4 - f3i2; + fi4 = f3i4 + f3i2; + f3i5 = fnms(0.5f, f3i3, f2i14); + fi5 = f3i1 + f3i5; + fi6 = f3i5 - f3i1; + + f3i10 = zRe[in9]; + f4i11 = zRe[in10]; + f4i12 = zRe[in8]; + f3i14 = zIm[in9]; + f4i13 = zIm[in10]; + f4i14 = zIm[in8]; + f4i3 = zRe[in33]; + f4i15 = zRe[in34]; + fo1 = zRe[in32]; + f4i7 = zIm[in33]; + fo2 = zIm[in34]; + fo3 = zIm[in32]; + + + f3i11 = f4i11 + f4i12; + f3i12 = fnms(0.5f, f3i11, f3i10); + f3i13 = FFT_15PONIT_WNK4 * (f4i12 - f4i11); + f3i15 = f4i13 + f4i14; + f4i1 = FFT_15PONIT_WNK4 * (f4i13 - f4i14); + f4i2 = fnms(0.5f, f3i15, f3i14); + f4i4 = f4i15 + fo1; + f4i5 = fnms(0.5f, f4i4, f4i3); + f4i6 = FFT_15PONIT_WNK4 * (fo1 - f4i15); + f4i8 = fo2 + fo3; + f4i9 = FFT_15PONIT_WNK4 * (fo2 - fo3); + f4i10 = fnms(0.5f, f4i8, f4i7); + + fi7 = f3i10 + f3i11; + fi8 = f4i3 + f4i4; + fi9 = fi7 + fi8; + fi10 = f3i12 - f4i1; + fi11 = f4i5 - f4i9; + fi12 = fi10 + fi11; + fi13 = f3i14 + f3i15; + fi14 = f4i7 + f4i8; + fi15 = fi13 + fi14; + fi16 = f4i2 - f3i13; + fi17 = f4i10 - f4i6; + fi18 = fi16 + fi17; + fi19 = f3i13 + f4i2; + fi20 = f4i6 + f4i10; + fi21 = fi19 + fi20; + fi22 = f3i12 + f4i1; + fi23 = f4i5 + f4i9; + fi24 = fi22 + fi23; + + fo4 = zRe[in24]; + f2o5 = zRe[in25]; + f2o6 = zRe[in26]; + fo8 = zIm[in24]; + f2o7 = zIm[in25]; + f2o8 = zIm[in26]; + fo12 = zRe[in18]; + f2o9 = zRe[in16]; + f2o10 = zRe[in17]; + f2o1 = zIm[in18]; + f2o11 = zIm[in16]; + f2o12 = zIm[in17]; + + + fo5 = f2o5 + f2o6; + fo6 = fnms(0.5f, fo5, fo4); + fo7 = FFT_15PONIT_WNK4 * (f2o6 - f2o5); + fo9 = f2o7 + f2o8; + fo10 = FFT_15PONIT_WNK4 * (f2o7 - f2o8); + fo11 = fnms(0.5f, fo9, fo8); + fo13 = f2o9 + f2o10; + fo14 = fnms(0.5f, fo13, fo12); + fo15 = FFT_15PONIT_WNK4 * (f2o10 - f2o9); + f2o2 = f2o11 + f2o12; + f2o3 = FFT_15PONIT_WNK4 * (f2o11 - f2o12); + f2o4 = fnms(0.5f, f2o2, f2o1); + + fi25 = fo4 + fo5; + fi26 = fo12 + fo13; + fi27 = fi25 + fi26; + fi28 = fo6 - fo10; + fi29 = fo14 - f2o3; + fi30 = fi28 + fi29; + f2i1 = fo8 + fo9; + f2i2 = f2o1 + f2o2; + f2i3 = f2i1 + f2i2; + f2i4 = fo11 - fo7; + f2i5 = f2o4 - fo15; + f2i6 = f2i4 + f2i5; + f2i7 = fo7 + fo11; + f2i8 = fo15 + f2o4; + f2i9 = f2i7 + f2i8; + f2i10 = fo6 + fo10; + f2i11 = fo14 + f2o3; + f2i12 = f2i10 + f2i11; + + f2o13 = FFT_15PONIT_WNK1 * (fi27 - fi9); + f2o14 = fi27 + fi9; + f2o15 = fnms(FFT_15PONIT_WNK5, f2o14, fi1); + f3o3 = fi13 - fi14; + f3o4 = f2i1 - f2i2; + f3o1 = fnms(FFT_15PONIT_WNK3, f3o4, FFT_15PONIT_WNK2 * f3o3); + f3o2 = fmac(FFT_15PONIT_WNK2, f3o4, FFT_15PONIT_WNK3 * f3o3); + zRe[in0] = fi1 + f2o14; + f3o5 = f2o13 + f2o15; + zRe[in24] = f3o5 - f3o2; + zRe[in18] = f3o5 + f3o2; + f3o6 = f2o15 - f2o13; + zRe[in33] = f3o6 - f3o1; + zRe[in9] = f3o6 + f3o1; + + f3o7 = FFT_15PONIT_WNK1 * (f2i3 - fi15); + f3o8 = f2i3 + fi15; + f3o9 = fnms(FFT_15PONIT_WNK5, f3o8, fi2); + f3o12 = fi7 - fi8; + f3o13 = fi25 - fi26; + f3o10 = fnms(FFT_15PONIT_WNK3, f3o13, FFT_15PONIT_WNK2 * f3o12); + f3o11 = fmac(FFT_15PONIT_WNK2, f3o13, FFT_15PONIT_WNK3 * f3o12); + zIm[in0] = fi2 + f3o8; + f3o14 = f3o7 + f3o9; + zIm[in18] = f3o14 - f3o11; + zIm[in24] = f3o11 + f3o14; + f3o15 = f3o9 - f3o7; + zIm[in9] = f3o15 - f3o10; + zIm[in33] = f3o10 + f3o15; + + f4o1 = FFT_15PONIT_WNK1 * (fi30 - fi12); + f4o2 = fi30 + fi12; + f4o3 = fnms(FFT_15PONIT_WNK5, f4o2, fi3); + f4o6 = fi16 - fi17; + f4o7 = f2i4 - f2i5; + f4o4 = fnms(FFT_15PONIT_WNK3, f4o7, FFT_15PONIT_WNK2 * f4o6); + f4o5 = fmac(FFT_15PONIT_WNK2, f4o7, FFT_15PONIT_WNK3 * f4o6); + zRe[in2] = fi3 + f4o2; + f4o8 = f4o1 + f4o3; + zRe[in26] = f4o8 - f4o5; + zRe[in17] = f4o8 + f4o5; + f4o9 = f4o3 - f4o1; + zRe[in32] = f4o9 - f4o4; + zRe[in8] = f4o9 + f4o4; + + f4o10 = FFT_15PONIT_WNK1 * (f2i6 - fi18); + f4o11 = f2i6 + fi18; + f4o12 = fnms(FFT_15PONIT_WNK5, f4o11, fi6); + f4o15 = fi10 - fi11; + f5o1 = fi28 - fi29; + f4o13 = fnms(FFT_15PONIT_WNK3, f5o1, FFT_15PONIT_WNK2 * f4o15); + f4o14 = fmac(FFT_15PONIT_WNK2, f5o1, FFT_15PONIT_WNK3 * f4o15); + zIm[in2] = fi6 + f4o11; + f5o2 = f4o10 + f4o12; + zIm[in17] = f5o2 - f4o14; + zIm[in26] = f4o14 + f5o2; + f5o3 = f4o12 - f4o10; + zIm[in32] = f4o13 + f5o3; + zIm[in8] = f5o3 - f4o13; + + f5o4 = FFT_15PONIT_WNK1 * (f2i9 - fi21); + f5o5 = f2i9 + fi21; + f5o6 = fnms(FFT_15PONIT_WNK5, f5o5, fi5); + f5o9 = f2i10 - f2i11; + f5o10 = fi22 - fi23; + f5o7 = fmac(FFT_15PONIT_WNK2, f5o9, FFT_15PONIT_WNK3 * f5o10); + f5o8 = fnms(FFT_15PONIT_WNK3, f5o9, FFT_15PONIT_WNK2 * f5o10); + zIm[in1] = fi5 + f5o5; + f5o11 = f5o6 - f5o4; + f5o12 = f5o4 + f5o6; + zIm[in34] = f5o8 + f5o11; + zIm[in10] = f5o11 - f5o8; + + zIm[in16] = f5o12 - f5o7; + zIm[in25] = f5o7 + f5o12; + + f5o13 = FFT_15PONIT_WNK1 * (f2i12 - fi24); + f5o14 = f2i12 + fi24; + f5o15 = fnms(FFT_15PONIT_WNK5, f5o14, fi4); + f5o18 = f2i7 - f2i8; + f5o19 = fi19 - fi20; + f5o16 = fmac(FFT_15PONIT_WNK2, f5o18, FFT_15PONIT_WNK3 * f5o19); + f5o17 = fnms(FFT_15PONIT_WNK3, f5o18, FFT_15PONIT_WNK2 * f5o19); + zRe[in1] = fi4 + f5o14; + f5o21 = f5o15 - f5o13; + f5o22 = f5o13 + f5o15; + + zRe[in34] = f5o21 - f5o17; + zRe[in10] = f5o21 + f5o17; + zRe[in25] = f5o22 - f5o16; + zRe[in16] = f5o22 + f5o16; + + return; + } + + /*-----------------------------------------------------------------* + * fft5_shift1() + * 5-point FFT with 1-point circular shift + *-----------------------------------------------------------------*/ + + static void fft5_shift1( + int n1, /* i : length of data */ + float *zRe, /* i/o : real part of input and output data */ + float *zIm, /* i/o : imaginary part of input and output data */ + const short *Idx /* i : pointer of the address table */ + ) + { + float fi1, fi2, fi3, fi4, fi5, fi6, fi7, fi8; + float fo1, fo2, fo3, fo4, fo5, fo6, fo7, fo8; + short in1,in2,in3,in4,in5; + + in1 = Idx[0]; + in2 = Idx[n1]; + in3 = Idx[n1*2]; + in4 = Idx[n1*3]; + in5 = Idx[n1*4]; + + fi1 = zRe[in1]; + fi2 = zIm[in1]; + fo3 = zRe[in2]; + fo4 = zRe[in5]; + fo6 = zRe[in3]; + fo7 = zRe[in4]; + + fo5 = fo3 + fo4; + fo8 = fo6 + fo7; + fi3 = fo5 + fo8; + fi4 = fo6 - fo7; + fi5 = FFT_15PONIT_WNK1 * (fo5 - fo8); + fi6 = fo3 - fo4; + + fo3 = zIm[in2]; + fo4 = zIm[in5]; + fo6 = zIm[in3]; + fo7 = zIm[in4]; + + fo5 = fo3 + fo4; + fo8 = fo6 + fo7; + fi7 = fo3 - fo4; + fi8 = fo5 + fo8; + fo1 = fo6 - fo7; + fo2 = FFT_15PONIT_WNK1 * (fo5 - fo8); + + zRe[in1] = fi1 + fi3; + zIm[in1] = fi2 + fi8; + + fo3 = FFT_15PONIT_WNK2*fi7 + FFT_15PONIT_WNK3*fo1; + fo4 = FFT_15PONIT_WNK2*fo1 - FFT_15PONIT_WNK3*fi7; + fo7 = fi1-fi3/4; + fo5 = fi5 + fo7; + fo6 = fo7 - fi5; + + zRe[in2] = fo5 + fo3; + zRe[in3] = fo6 - fo4; + zRe[in4] = fo6 + fo4; + zRe[in5] = fo5 - fo3; + + fo3 = FFT_15PONIT_WNK2 * fi6 + FFT_15PONIT_WNK3 * fi4; + fo4 = FFT_15PONIT_WNK2 * fi4 - FFT_15PONIT_WNK3 * fi6; + fo7 = fi2-fi8/4; + fo5 = fo2 + fo7; + fo6 = fo7 - fo2; + + zIm[in2] = fo5 - fo3; + zIm[in3] = fo4 + fo6; + zIm[in4] = fo6 - fo4; + zIm[in5] = fo3 + fo5; + + return; + } + + /*-----------------------------------------------------------------* + * fft5_shift4() + * 5-point FFT with 4-point circular shift + *-----------------------------------------------------------------*/ + + static void fft5_shift4( + int n1, /* i : length of data */ + float *zRe, /* i/o : real part of input and output data */ + float *zIm, /* i/o : imaginary part of input and output data */ + const short *Idx /* i : pointer of the address table */ + ) + { + float fi1, fi2, fi3, fi4, fi5, fi6, fi7, fi8; + float fo1, fo2, fo3, fo4, fo5, fo6, fo7, fo8; + short in1,in2,in3,in4,in5; + + in1 = Idx[0]; + in2 = Idx[n1]; + in3 = Idx[n1*2]; + in4 = Idx[n1*3]; + in5 = Idx[n1*4]; + + fi1 = zRe[in1]; + fi2 = zIm[in1]; + fo3 = zRe[in2]; + fo4 = zRe[in5]; + fo6 = zRe[in3]; + fo7 = zRe[in4]; + + fo5 = fo3 + fo4; + fo8 = fo6 + fo7; + fi3 = fo5 + fo8; + fi4 = fo6 - fo7; + fi5 = FFT_15PONIT_WNK1 * (fo5 - fo8); + fi6 = fo3 - fo4; + + fo3 = zIm[in2]; + fo4 = zIm[in5]; + fo6 = zIm[in3]; + fo7 = zIm[in4]; + + fo5 = fo3 + fo4; + fo8 = fo6 + fo7; + fi7 = fo3 - fo4; + fi8 = fo5 + fo8; + fo1 = fo6 - fo7; + fo2 = FFT_15PONIT_WNK1 * (fo5 - fo8); + + zRe[in1] = fi1 + fi3; + zIm[in1] = fi2 + fi8; + + fo3 = FFT_15PONIT_WNK2*fi7 + FFT_15PONIT_WNK3*fo1; + fo4 = FFT_15PONIT_WNK2*fo1 - FFT_15PONIT_WNK3*fi7; + fo7 = fi1-fi3/4; + fo5 = fi5 + fo7; + fo6 = fo7 - fi5; + zRe[in2] = fo5 - fo3; + zRe[in4] = fo6 - fo4; + zRe[in3] = fo6 + fo4; + zRe[in5] = fo5 + fo3; + + fo3 = FFT_15PONIT_WNK2 * fi6 + FFT_15PONIT_WNK3 * fi4; + fo4 = FFT_15PONIT_WNK2 * fi4 - FFT_15PONIT_WNK3 * fi6; + fo7 = fi2-fi8/4; + fo5 = fo2 + fo7; + fo6 = fo7 - fo2; + + zIm[in3] = fo6 - fo4; + zIm[in2] = fo3 + fo5; + zIm[in4] = fo4 + fo6; + zIm[in5] = fo5 - fo3; + + return; + } + + /*-----------------------------------------------------------------* + * fft5_32() + * 5-point FFT called for 32 times + *-----------------------------------------------------------------*/ + + static void fft5_32( + float *zRe, /* i/o : real part of input and output data */ + float *zIm, /* i/o : imaginary part of input and output data */ + const short *Idx /* i : pointer of the address table */ + ) + { + float fi1, fi2, fi3, fi4, fi5, fi6, fi7, fi8; + float fo1, fo2, fo3, fo4, fo5, fo6, fo7, fo8; + short in1,in2,in3,in4,in5; + + in1 = Idx[0]; + in2 = Idx[32]; + in3 = Idx[64]; + in4 = Idx[96]; + in5 = Idx[128]; + + fi1 = zRe[in1]; + fi2 = zIm[in1]; + fo3 = zRe[in2]; + fo4 = zRe[in5]; + fo6 = zRe[in3]; + fo7 = zRe[in4]; + + fo5 = fo3 + fo4; + fo8 = fo6 + fo7; + fi3 = fo5 + fo8; + fi4 = fo6 - fo7; + fi5 = FFT_15PONIT_WNK1 * (fo5 - fo8); + fi6 = fo3 - fo4; + + fo3 = zIm[in2]; + fo4 = zIm[in5]; + fo6 = zIm[in3]; + fo7 = zIm[in4]; + + fo5 = fo3 + fo4; + fo8 = fo6 + fo7; + fi7 = fo3 - fo4; + fi8 = fo5 + fo8; + fo1 = fo6 - fo7; + fo2 = FFT_15PONIT_WNK1 * (fo5 - fo8); + + zRe[in1] = fi1 + fi3; + zIm[in1] = fi2 + fi8; + + fo3 = FFT_15PONIT_WNK2*fi7 + FFT_15PONIT_WNK3*fo1; + fo4 = FFT_15PONIT_WNK2*fo1 - FFT_15PONIT_WNK3*fi7; + fo7 = fi1-fi3/4; + fo5 = fi5 + fo7; + fo6 = fo7 - fi5; + + zRe[in2] = fo6 + fo4; + zRe[in3] = fo5 + fo3; + zRe[in4] = fo5 - fo3; + zRe[in5] = fo6 - fo4; + + fo3 = FFT_15PONIT_WNK2 * fi6 + FFT_15PONIT_WNK3 * fi4; + fo4 = FFT_15PONIT_WNK2 * fi4 - FFT_15PONIT_WNK3 * fi6; + fo7 = fi2-fi8/4; + fo5 = fo2 + fo7; + fo6 = fo7 - fo2; + + zIm[in2] = fo6 - fo4; + zIm[in3] = fo5 - fo3; + zIm[in4] = fo3 + fo5; + zIm[in5] = fo4 + fo6; + + return; + } + + /*-----------------------------------------------------------------* + * fft64() + * 64-point FFT + *-----------------------------------------------------------------*/ + + static void fft64( + float *x, /* i/o : real part of input and output data */ + float *y, /* i/o : imaginary part of input and output data */ + const short *Idx /* i : pointer of the address table */ + ) + { + short i,id,jd; + float z[128]; + for ( i=0; i<64; i++ ) + { + id = Idx[i]; + z[2*i] = x[id]; + z[2*i+1] = y[id]; + } + + cdftForw(128,z,Ip_fft64,w_fft64); + + for( i=0; i<64 ; i++) + { + jd = Odx_fft64[i]; + id = Idx[jd]; + x[id]=z[2*i]; + y[id]=z[2*i+1]; + } + + return; + } + + + /*-----------------------------------------------------------------* + * fft32_15() + * 32-point FFT called for 15 times + *-----------------------------------------------------------------*/ + + static void fft32_15( + float *x, /* i/o : real part of input and output data */ + float *y, /* i/o : imaginary part of input and output data */ + const short *Idx /* i : pointer of the address table */ + ) + { + short i,id,jd; + float z[64]; + + for( i=0; i<32; i++ ) + { + id = Idx[i]; + z[2*i] = x[id]; + z[2*i+1] = y[id]; + } + + cdftForw(64,z,Ip_fft32,w_fft32); + + for( i=0; i<32; i++ ) + { + jd = Odx_fft32_15[i]; + id = Idx[jd]; + x[id]=z[2*i]; + y[id]=z[2*i+1]; + } + + return; + } + + /*-----------------------------------------------------------------* + * fft32_5() + * 32-point FFT called for 5 times + *-----------------------------------------------------------------*/ + + static void fft32_5( + float *x, /* i/o : real part of input and output data */ + float *y, /* i/o : imaginary part of input and output data */ + const short *Idx /* i : pointer of the address table */ + ) + { + short i,id,jd; + float z[64]; + + for( i=0; i<32; i++ ) + { + id = Idx[i]; + z[2*i] = x[id]; + z[2*i+1] = y[id]; + } + + cdftForw(64,z,Ip_fft32,w_fft32); + + for( i=0; i<32; i++ ) + { + jd = Odx_fft32_5[i]; + id = Idx[jd]; + x[id]=z[2*i]; + y[id]=z[2*i+1]; + } + + return; + } + + /*-----------------------------------------------------------------* + * fft16() + * 16-point FFT + *-----------------------------------------------------------------*/ + + static void fft16( + float *x, /* i/o : real part of input and output data */ + float *y, /* i/o : imaginary part of input and output data */ + const short *Idx /* i : pointer of the address table */ + ) + { + short i,id,jd; + float z[32]; + + for(i=0; i<16 ; i++) + { + id = Idx[i]; + z[2*i] = x[id]; + z[2*i+1] = y[id]; + } + + cdftForw(32,z,Ip_fft16,w_fft16); + + for(i=0; i<16; i++) + { + jd = Odx_fft16[i]; + id = Idx[jd]; + x[id]=z[2*i]; + y[id]=z[2*i+1]; + } + + return; + } + + /*-----------------------------------------------------------------* + * fft8() + * 8-point FFT + *-----------------------------------------------------------------*/ + + static void fft8( + float *x, /* i/o : real part of input and output data */ + float *y, /* i/o : imaginary part of input and output data */ + const short *Idx /* i : pointer of the address table */ + ) + { + short i,id; + float z[16]; + + for(i=0; i<8; i++) + { + id = Idx[i]; + z[2*i] = x[id]; + z[2*i+1] = y[id]; + } + + cdftForw(16,z,Ip_fft8,w_fft8); + + for(i=0; i<8; i++) + { + id = Idx[i]; + x[id]=z[2*i]; + y[id]=z[2*i+1]; + } + + return; + } + + /*-----------------------------------------------------------------* + * fft8_5() + * 8-point FFT with shift 5 + *-----------------------------------------------------------------*/ + + static void fft8_5( + float *x, /* i/o : real part of input and output data */ + float *y, /* i/o : imaginary part of input and output data */ + const short *Idx /* i : pointer of the address table */ + ) + { + short i,id,jd; + float z[16]; + + for(i=0; i<8; i++) + { + id = Idx[i]; + z[2*i] = x[id]; + z[2*i+1] = y[id]; + } + + cdftForw(16,z,Ip_fft8,w_fft8); + + for(i=0; i<8; i++) + { + jd = Odx_fft8_5[i]; + id = Idx[jd]; + x[id]=z[2*i]; + y[id]=z[2*i+1]; + } + return; + } + + /*-----------------------------------------------------------------* + * fft5_8() + * 5-point FFT with shift 2 + *-----------------------------------------------------------------*/ + + static void fft5_8( + int n1, /* i : length of data */ + float *zRe, /* i/o : real part of input and output data */ + float *zIm, /* i/o : imaginary part of input and output data */ + const short *Idx /* i : pointer of the address table */ + ) + { + float fi1, fi2, fi3, fi4, fi5, fi6, fi7, fi8; + float fo1, fo2, fo3, fo4, fo5, fo6, fo7, fo8; + short in1,in2,in3,in4,in5; + + in1 = Idx[0]; + in2 = Idx[n1]; + in3 = Idx[n1*2]; + in4 = Idx[n1*3]; + in5 = Idx[n1*4]; + + fi1 = zRe[in1]; + fi2 = zIm[in1]; + fo3 = zRe[in2]; + fo4 = zRe[in5]; + fo6 = zRe[in3]; + fo7 = zRe[in4]; + + fo5 = fo3 + fo4; + fo8 = fo6 + fo7; + fi3 = fo5 + fo8; + fi4 = fo6 - fo7; + fi5 = FFT_15PONIT_WNK1 * (fo5 - fo8); + fi6 = fo3 - fo4; + + fo3 = zIm[in2]; + fo4 = zIm[in5]; + fo6 = zIm[in3]; + fo7 = zIm[in4]; + + fo5 = fo3 + fo4; + fo8 = fo6 + fo7; + fi7 = fo3 - fo4; + fi8 = fo5 + fo8; + fo1 = fo6 - fo7; + fo2 = FFT_15PONIT_WNK1 * (fo5 - fo8); + + zRe[in1] = fi1 + fi3; + zIm[in1] = fi2 + fi8; + + fo3 = FFT_15PONIT_WNK2*fi7 + FFT_15PONIT_WNK3*fo1; + fo4 = FFT_15PONIT_WNK2*fo1 - FFT_15PONIT_WNK3*fi7; + fo7 = fi1-fi3/4; + fo5 = fi5 + fo7; + fo6 = fo7 - fi5; + + zRe[in2] = fo6 - fo4; + zRe[in3] = fo5 - fo3; + zRe[in5] = fo6 + fo4; + zRe[in4] = fo5 + fo3; + + fo3 = FFT_15PONIT_WNK2 * fi6 + FFT_15PONIT_WNK3 * fi4; + fo4 = FFT_15PONIT_WNK2 * fi4 - FFT_15PONIT_WNK3 * fi6; + fo7 = fi2-fi8/4; + fo5 = fo2 + fo7; + fo6 = fo7 - fo2; + + zIm[in2] = fo4 + fo6; + zIm[in3] = fo3 + fo5; + zIm[in4] = fo5 - fo3; + zIm[in5] = fo6 - fo4; + + return; + } + + /*-----------------------------------------------------------------* + * fft4_5() + * 8-point FFT with shift 1 + *-----------------------------------------------------------------*/ + + static void fft4_5( + float *x, /* i/o : real part of input and output data */ + float *y, /* i/o : imaginary part of input and output data */ + const short *Idx /* i : pointer of the address table */ + ) + { + short i,id,jd; + float z[8]; + + for(i=0; i<4; i++) + { + id = Idx[i]; + z[2*i] = x[id]; + z[2*i+1] = y[id]; + } + + cdftForw(8,z,Ip_fft4,w_fft4); + + for(i=0; i<4; i++) + { + jd = Odx_fft4_5[i]; + id = Idx[jd]; + x[id]=z[2*i]; + y[id]=z[2*i+1]; + } + return; + } + + /*-----------------------------------------------------------------* + * fft5_4() + * 5-point FFT with shift 4 + *-----------------------------------------------------------------*/ + + static void fft5_4( int n1, float *zRe, float *zIm, const short *Idx ) + { + float fi1, fi2, fi3, fi4, fi5, fi6, fi7, fi8; + float fo1, fo2, fo3, fo4, fo5, fo6, fo7, fo8; + short in1,in2,in3,in4,in5; + + in1 = Idx[0]; + in2 = Idx[n1]; + in3 = Idx[n1*2]; + in4 = Idx[n1*3]; + in5 = Idx[n1*4]; + + fi1 = zRe[in1]; + fi2 = zIm[in1]; + fo3 = zRe[in2]; + fo4 = zRe[in5]; + fo6 = zRe[in3]; + fo7 = zRe[in4]; + + fo5 = fo3 + fo4; + fo8 = fo6 + fo7; + fi3 = fo5 + fo8; + fi4 = fo6 - fo7; + fi5 = FFT_15PONIT_WNK1 * (fo5 - fo8); + fi6 = fo3 - fo4; + + fo3 = zIm[in2]; + fo4 = zIm[in5]; + fo6 = zIm[in3]; + fo7 = zIm[in4]; + + fo5 = fo3 + fo4; + fo8 = fo6 + fo7; + fi7 = fo3 - fo4; + fi8 = fo5 + fo8; + fo1 = fo6 - fo7; + fo2 = FFT_15PONIT_WNK1 * (fo5 - fo8); + + zRe[in1] = fi1 + fi3; + zIm[in1] = fi2 + fi8; + + fo3 = FFT_15PONIT_WNK2*fi7 + FFT_15PONIT_WNK3*fo1; + fo4 = FFT_15PONIT_WNK2*fo1 - FFT_15PONIT_WNK3*fi7; + fo7 = fi1-fi3/4; + fo5 = fi5 + fo7; + fo6 = fo7 - fi5; + + zRe[in2] = fo5 - fo3; + zRe[in4] = fo6 - fo4; + zRe[in3] = fo6 + fo4; + zRe[in5] = fo5 + fo3; + + fo3 = FFT_15PONIT_WNK2 * fi6 + FFT_15PONIT_WNK3 * fi4; + fo4 = FFT_15PONIT_WNK2 * fi4 - FFT_15PONIT_WNK3 * fi6; + fo7 = fi2-fi8/4; + fo5 = fo2 + fo7; + fo6 = fo7 - fo2; + + zIm[in2] = fo3 + fo5; + zIm[in3] = fo6 - fo4; + zIm[in4] = fo4 + fo6; + zIm[in5] = fo5 - fo3; + + return; + } + + + /*-----------------------------------------------------------------* + * DoRTFT80() + * a low complexity 2-dimensional DFT of 80 points + *-----------------------------------------------------------------*/ + + void DoRTFT80( + float *x, /* i/o : real part of input and output data */ + float *y /* i/o : imaginary part of input and output data */ + ) + { + short j; + + /* Applying 16-point FFT for 5 times based on the address table Idx_dortft80 */ + for(j=0; j<5; j++) + { + fft16(x,y,Idx_dortft80+16*j); + } + + /* Applying 5-point FFT for 16 times based on the address table Idx_dortft80 */ + for(j=0; j<16; j++) + { + fft5_shift1(16,x,y,Idx_dortft80+j); + } + + return; + } + + /*-----------------------------------------------------------------* + * DoRTFT120() + * a low complexity 2-dimensional DFT of 120 points + *-----------------------------------------------------------------*/ + + void DoRTFT120( + float *x, /* i/o : real part of input and output data */ + float *y /* i/o : imaginary part of input and output data */ + ) + { + short j; + + /* Applying 8-point FFT for 15 times based on the address table Idx_dortft120 */ + for(j=0; j<15; j++) + { + fft8(x,y,Idx_dortft120+8*j); + } + + /* Applying 15-point FFT for 8 times based on the address table Idx_dortft120 */ + for(j=0; j<8; j++) + { + fft15_shift2(8,x,y,Idx_dortft120+j); + } + + return; + } + + /*-----------------------------------------------------------------* + * DoRTFT160() + * a low complexity 2-dimensional DFT of 160 points + *-----------------------------------------------------------------*/ + + void DoRTFT160( + float x[], /* i/o : real part of input and output data */ + float y[] /* i/o : imaginary part of input and output data */ + ) + { + short j; + + /* Applying 32-point FFT for 5 times based on the address table Idx_dortft160 */ + for(j=0; j<5; j++) + { + fft32_5(x,y,Idx_dortft160+32*j); + } + + /* Applying 5-point FFT for 32 times based on the address table Idx_dortft160 */ + for(j=0; j<32; j++) + { + fft5_32(x,y,Idx_dortft160+j); + } + + return; + } + + /*-----------------------------------------------------------------* + * DoRTFT320() + * a low complexity 2-dimensional DFT of 320 points + *-----------------------------------------------------------------*/ + + void DoRTFT320( + float *x, /* i/o : real part of input and output data */ + float *y /* i/o : imaginary part of input and output data */ + ) + { + short j; + + /* Applying 64-point FFT for 5 times based on the address table Idx_dortft160 */ + for(j=0; j<5; j++) + { + fft64(x,y,Idx_dortft320+64*j); + } + + /* Applying 5-point FFT for 64 times based on the address table Idx_dortft160 */ + for(j=0; j<64; j++) + { + fft5_shift4(64,x,y,Idx_dortft320+j); + } + + return; + } + + /*-----------------------------------------------------------------* + * DoRTFT480() + * a low complexity 2-dimensional DFT of 480 points + *-----------------------------------------------------------------*/ + + void DoRTFT480( + float *x, /* i/o : real part of input and output data */ + float *y /* i/o : imaginary part of input and output data */ + ) + { + short j; + + /* Applying 32-point FFT for 15 times based on the address table Idx_dortft160 */ + for(j=0; j<15; j++) + { + fft32_15(x,y,Idx_dortft480+32*j); + } + + /* Applying 5-point FFT for 32 times based on the address table Idx_dortft160 */ + for(j=0; j<32; j++) + { + fft15_shift8(32,x,y,Idx_dortft480+j); + } + + return; + } + + /*-----------------------------------------------------------------* + * DoRTFT40() + * a low complexity 2-dimensional DFT of 40 points + *-----------------------------------------------------------------*/ + + void DoRTFT40( + float *x, /* i/o : real part of input and output data */ + float *y /* i/o : imaginary part of input and output data */ + ) + { + short j; + /* Applying 8-point FFT for 5 times based on the address table Idx_dortft40 */ + for(j=0; j<5; j++) + { + fft8_5(x,y,Idx_dortft40+8*j); + } + + /* Applying 5-point FFT for 8 times based on the address table Idx_dortft40 */ + for(j=0; j<8; j++) + { + fft5_8(8,x,y,Idx_dortft40+j); + } + + return; + } + + /*-----------------------------------------------------------------* + * DoRTFT20() + * a low complexity 2-dimensional DFT of 20 points + *-----------------------------------------------------------------*/ + + void DoRTFT20( + float *x, /* i/o : real part of input and output data */ + float *y /* i/o : imaginary part of input and output data */ + ) + { + short j; + + /* Applying 4-point FFT for 5 times based on the address table Idx_dortft20 */ + for(j=0; j<5; j++) + { + fft4_5(x,y,Idx_dortft20+4*j); + } + + /* Applying 5-point FFT for 4 times based on the address table Idx_dortft20 */ + for(j=0; j<4; j++) + { + fft5_4(4,x,y,Idx_dortft20+j); + } + + return; + } + + /*-----------------------------------------------------------------* + * DoRTFT128() + * FFT with 128 points + *-----------------------------------------------------------------*/ + + void DoRTFT128( + float *x, /* i/o : real part of input and output data */ + float *y /* i/o : imaginary part of input and output data */ + ) + { + + int i; + float z[256]; + + for ( i=0; i<128; i++ ) + { + z[2*i] = x[i]; + z[2*i+1] = y[i]; + } + + cdftForw(256,z,Ip_fft128,w_fft128); + + x[0]=z[0]; + y[0]=z[1]; + for( i=1; i<128 ; i++) + { + x[128-i]=z[2*i]; + y[128-i]=z[2*i+1]; + } + + return; + } + + /*-----------------------------------------------------------------* + * cdftForw() + * Main fuction of Complex Discrete Fourier Transform + *-----------------------------------------------------------------*/ + + static void cdftForw( + short n, /* i : data length of real and imag */ + float *a, /* i/o : input/output data */ + const short *ip, /* i : work area for bit reversal */ + const float *w /* i : cos/sin table */ + ) + { + /* bit reversal */ + bitrv2_SR(n, ip + 2, a); + + /* Do FFT */ + cftfsub(n, a, w); + } + + /*-----------------------------------------------------------------* + * bitrv2_SR() + * Bit reversal + *-----------------------------------------------------------------*/ + + static void bitrv2_SR( + short n, /* i : data length of real and imag */ + const short *ip, /* i/o : work area for bit reversal */ + float *a /* i/o : input/output data */ + ) + { + short j, j1, k, k1, m, m2; + short l; + float xr, xi, yr, yi; + + if (n == 64) + { + m = 4; + l = -1; + } + else if (n == 256) + { + m = 8; + l = -1; + } + else if (n == 16) + { + m = 2; + l = -1; + } + else + { + l = n; + m = 1; + + while ((m << 3) < l) + { + l >>= 1; + m <<= 1; + } + l -= m * 8; + } + + m2 = 2 * m; + + if (l == 0) + { + for (k = 0; k < m; k++) + { + for (j = 0; j < k; j++) + { + j1 = 2 * j + ip[k]; + k1 = 2 * k + ip[j]; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 += 2 * m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 -= m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 += 2 * m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + } + + j1 = 2 * k + m2 + ip[k]; + k1 = j1 + m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + } + } + else + { + for (k = 1; k < m; k++) + { + for (j = 0; j < k; j++) + { + j1 = 2 * j + ip[k]; + k1 = 2 * k + ip[j]; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 += m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + } + } + } + + return; + } + + /*-----------------------------------------------------------------* + * cftfsub() + * Complex Discrete Fourier Transform + *-----------------------------------------------------------------*/ + + static void cftfsub( + short n, /* i : data length of real and imag */ + float *a, /* i/o : input/output data */ + const float *w /* i : cos/sin table */ + ) + { + short j, j1, j2, j3, l; + float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + l = 2; + if (n > 8) + { + cft1st(n, a, w); + + l = 8; + while ((l << 2) < n) + { + cftmdl(n, l, a, w); + l <<= 2; + } + } + + if ((l << 2) == n) + { + for (j = 0; j < l; j += 2) + { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[j] + a[j1]; + x0i = a[j + 1] + a[j1 + 1]; + x1r = a[j] - a[j1]; + x1i = a[j + 1] - a[j1 + 1]; + x2r = a[j2] + a[j3]; + x2i = a[j2 + 1] + a[j3 + 1]; + x3r = a[j2] - a[j3]; + x3i = a[j2 + 1] - a[j3 + 1]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + a[j2] = x0r - x2r; + a[j2 + 1] = x0i - x2i; + a[j1] = x1r - x3i; + a[j1 + 1] = x1i + x3r; + a[j3] = x1r + x3i; + a[j3 + 1] = x1i - x3r; + } + } + else + { + for (j = 0; j < l; j += 2) + { + j1 = j + l; + x0r = a[j] - a[j1]; + x0i = a[j + 1] - a[j1 + 1]; + a[j] += a[j1]; + a[j + 1] += a[j1 + 1]; + a[j1] = x0r; + a[j1 + 1] = x0i; + } + } + + return; + } + + /*-----------------------------------------------------------------* + * cft1st() + * Subfunction of Complex Discrete Fourier Transform + *-----------------------------------------------------------------*/ + + static void cft1st( + short n, /* i : data length of real and imag */ + float *a, /* i/o : input/output data */ + const float *w /* i : cos/sin table */ + ) + { + short j, k1, k2; + float wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; + float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + x0r = a[0] + a[2]; + x0i = a[1] + a[3]; + x1r = a[0] - a[2]; + x1i = a[1] - a[3]; + x2r = a[4] + a[6]; + x2i = a[5] + a[7]; + x3r = a[4] - a[6]; + x3i = a[5] - a[7]; + a[0] = x0r + x2r; + a[1] = x0i + x2i; + a[4] = x0r - x2r; + a[5] = x0i - x2i; + a[2] = x1r - x3i; + a[3] = x1i + x3r; + a[6] = x1r + x3i; + a[7] = x1i - x3r; + wk1r = w[2]; + x0r = a[8] + a[10]; + x0i = a[9] + a[11]; + x1r = a[8] - a[10]; + x1i = a[9] - a[11]; + x2r = a[12] + a[14]; + x2i = a[13] + a[15]; + x3r = a[12] - a[14]; + x3i = a[13] - a[15]; + a[8] = x0r + x2r; + a[9] = x0i + x2i; + a[12] = x2i - x0i; + a[13] = x0r - x2r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[10] = wk1r * (x0r - x0i); + a[11] = wk1r * (x0r + x0i); + x0r = x3i + x1r; + x0i = x3r - x1i; + a[14] = wk1r * (x0i - x0r); + a[15] = wk1r * (x0i + x0r); + k1 = 0; + + for (j = 16; j < n; j += 16) + { + k1 += 2; + k2 = 2 * k1; + wk2r = w[k1]; + wk2i = w[k1 + 1]; + wk1r = w[k2]; + wk1i = w[k2 + 1]; + wk3r = wk1r - 2 * wk2i * wk1i; + wk3i = 2 * wk2i * wk1r - wk1i; + x0r = a[j] + a[j + 2]; + x0i = a[j + 1] + a[j + 3]; + x1r = a[j] - a[j + 2]; + x1i = a[j + 1] - a[j + 3]; + x2r = a[j + 4] + a[j + 6]; + x2i = a[j + 5] + a[j + 7]; + x3r = a[j + 4] - a[j + 6]; + x3i = a[j + 5] - a[j + 7]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + x0r -= x2r; + x0i -= x2i; + a[j + 4] = wk2r * x0r - wk2i * x0i; + a[j + 5] = wk2r * x0i + wk2i * x0r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j + 2] = wk1r * x0r - wk1i * x0i; + a[j + 3] = wk1r * x0i + wk1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j + 6] = wk3r * x0r - wk3i * x0i; + a[j + 7] = wk3r * x0i + wk3i * x0r; + wk1r = w[k2 + 2]; + wk1i = w[k2 + 3]; + wk3r = wk1r - 2 * wk2r * wk1i; + wk3i = 2 * wk2r * wk1r - wk1i; + x0r = a[j + 8] + a[j + 10]; + x0i = a[j + 9] + a[j + 11]; + x1r = a[j + 8] - a[j + 10]; + x1i = a[j + 9] - a[j + 11]; + x2r = a[j + 12] + a[j + 14]; + x2i = a[j + 13] + a[j + 15]; + x3r = a[j + 12] - a[j + 14]; + x3i = a[j + 13] - a[j + 15]; + a[j + 8] = x0r + x2r; + a[j + 9] = x0i + x2i; + x0r -= x2r; + x0i -= x2i; + a[j + 12] = -wk2i * x0r - wk2r * x0i; + a[j + 13] = -wk2i * x0i + wk2r * x0r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j + 10] = wk1r * x0r - wk1i * x0i; + a[j + 11] = wk1r * x0i + wk1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j + 14] = wk3r * x0r - wk3i * x0i; + a[j + 15] = wk3r * x0i + wk3i * x0r; + } + + return; + } + + /*-----------------------------------------------------------------* + * cftmdl() + * Subfunction of Complex Discrete Fourier Transform + *-----------------------------------------------------------------*/ + + static void cftmdl( + short n, /* i : data length of real and imag */ + short l, /* i : initial shift for processing */ + float *a, /* i/o : input/output data */ + const float *w /* i : cos/sin table */ + ) + { + short j, j1, j2, j3, k, k1, k2, m, m2; + float wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; + float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + m = l << 2; + for (j = 0; j < l; j += 2) + { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[j] + a[j1]; + x0i = a[j + 1] + a[j1 + 1]; + x1r = a[j] - a[j1]; + x1i = a[j + 1] - a[j1 + 1]; + x2r = a[j2] + a[j3]; + x2i = a[j2 + 1] + a[j3 + 1]; + x3r = a[j2] - a[j3]; + x3i = a[j2 + 1] - a[j3 + 1]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + a[j2] = x0r - x2r; + a[j2 + 1] = x0i - x2i; + a[j1] = x1r - x3i; + a[j1 + 1] = x1i + x3r; + a[j3] = x1r + x3i; + a[j3 + 1] = x1i - x3r; + } + + wk1r = w[2]; + for (j = m; j < l + m; j += 2) + { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[j] + a[j1]; + x0i = a[j + 1] + a[j1 + 1]; + x1r = a[j] - a[j1]; + x1i = a[j + 1] - a[j1 + 1]; + x2r = a[j2] + a[j3]; + x2i = a[j2 + 1] + a[j3 + 1]; + x3r = a[j2] - a[j3]; + x3i = a[j2 + 1] - a[j3 + 1]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + a[j2] = x2i - x0i; + a[j2 + 1] = x0r - x2r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j1] = wk1r * (x0r - x0i); + a[j1 + 1] = wk1r * (x0r + x0i); + x0r = x3i + x1r; + x0i = x3r - x1i; + a[j3] = wk1r * (x0i - x0r); + a[j3 + 1] = wk1r * (x0i + x0r); + } + + k1 = 0; + m2 = 2 * m; + for (k = m2; k < n; k += m2) + { + k1 += 2; + k2 = 2 * k1; + wk2r = w[k1]; + wk2i = w[k1 + 1]; + wk1r = w[k2]; + wk1i = w[k2 + 1]; + wk3r = wk1r - 2 * wk2i * wk1i; + wk3i = 2 * wk2i * wk1r - wk1i; + for (j = k; j < l + k; j += 2) + { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[j] + a[j1]; + x0i = a[j + 1] + a[j1 + 1]; + x1r = a[j] - a[j1]; + x1i = a[j + 1] - a[j1 + 1]; + x2r = a[j2] + a[j3]; + x2i = a[j2 + 1] + a[j3 + 1]; + x3r = a[j2] - a[j3]; + x3i = a[j2 + 1] - a[j3 + 1]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + x0r -= x2r; + x0i -= x2i; + a[j2] = wk2r * x0r - wk2i * x0i; + a[j2 + 1] = wk2r * x0i + wk2i * x0r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j1] = wk1r * x0r - wk1i * x0i; + a[j1 + 1] = wk1r * x0i + wk1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3] = wk3r * x0r - wk3i * x0i; + a[j3 + 1] = wk3r * x0i + wk3i * x0r; + } + + wk1r = w[k2 + 2]; + wk1i = w[k2 + 3]; + wk3r = wk1r - 2 * wk2r * wk1i; + wk3i = 2 * wk2r * wk1r - wk1i; + for (j = k + m; j < l + (k + m); j += 2) + { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[j] + a[j1]; + x0i = a[j + 1] + a[j1 + 1]; + x1r = a[j] - a[j1]; + x1i = a[j + 1] - a[j1 + 1]; + x2r = a[j2] + a[j3]; + x2i = a[j2 + 1] + a[j3 + 1]; + x3r = a[j2] - a[j3]; + x3i = a[j2 + 1] - a[j3 + 1]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + x0r -= x2r; + x0i -= x2i; + a[j2] = -wk2i * x0r - wk2r * x0i; + a[j2 + 1] = -wk2i * x0i + wk2r * x0r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j1] = wk1r * x0r - wk1i * x0i; + a[j1 + 1] = wk1r * x0i + wk1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3] = wk3r * x0r - wk3i * x0i; + a[j3 + 1] = wk3r * x0i + wk3i * x0r; + } + } + + return; + } + + static + void cftbsub( + short n, + float *a, + const float *w /* i : cos/sin table */ + ) + { + short j, j1, j2, j3, l; + float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + l = 2; + if (n > 8) + { + cft1st(n, a, w); + l = 8; + + while ((l << 2) < n) + { + cftmdl(n, l, a, w); + l <<= 2; + } + } + + if ((l << 2) == n) + { + for (j = 0; j < l; j += 2) + { + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[j] + a[j1]; + x0i = -a[j + 1] - a[j1 + 1]; + x1r = a[j] - a[j1]; + x1i = -a[j + 1] + a[j1 + 1]; + x2r = a[j2] + a[j3]; + x2i = a[j2 + 1] + a[j3 + 1]; + x3r = a[j2] - a[j3]; + x3i = a[j2 + 1] - a[j3 + 1]; + a[j] = x0r + x2r; + a[j + 1] = x0i - x2i; + a[j2] = x0r - x2r; + a[j2 + 1] = x0i + x2i; + a[j1] = x1r - x3i; + a[j1 + 1] = x1i - x3r; + a[j3] = x1r + x3i; + a[j3 + 1] = x1i + x3r; + } + } + else + { + for (j = 0; j < l; j += 2) + { + j1 = j + l; + x0r = a[j] - a[j1]; + x0i = -a[j + 1] + a[j1 + 1]; + a[j] += a[j1]; + a[j + 1] = -a[j + 1] - a[j1 + 1]; + a[j1] = x0r; + a[j1 + 1] = x0i; + } + } + } + + static + void rftfsub( + short n, + float *a, + short nc, + const float *c + ) + { + short j, k, kk, ks, m; + float wkr, wki, xr, xi, yr, yi; + + m = n >> 1; + ks = 2 * nc / m; + kk = 0; + for (j = 2; j < m; j += 2) + { + k = n - j; + kk += ks; + wkr = 0.5f - c[nc - kk]; + wki = c[kk]; + xr = a[j] - a[k]; + xi = a[j + 1] + a[k + 1]; + yr = wkr * xr - wki * xi; + yi = wkr * xi + wki * xr; + a[j] -= yr; + a[j + 1] -= yi; + a[k] += yr; + a[k + 1] -= yi; + } + } + + + static + void rftbsub( + short n, + float *a, + short nc, + const float *c + ) + { + short j, k, kk, ks, m; + float wkr, wki, xr, xi, yr, yi; + + a[1] = -a[1]; + m = n >> 1; + ks = 2 * nc / m; + kk = 0; + for (j = 2; j < m; j += 2) + { + k = n - j; + kk += ks; + wkr = 0.5f - c[nc - kk]; + wki = c[kk]; + xr = a[j] - a[k]; + xi = a[j + 1] + a[k + 1]; + yr = wkr * xr + wki * xi; + yi = wkr * xi - wki * xr; + a[j] -= yr; + a[j + 1] = yi - a[j + 1]; + a[k] += yr; + a[k + 1] = yi - a[k + 1]; + } + a[m + 1] = -a[m + 1]; + } + + + static + void dctsub( + short n, + float *a, + short nc, + const float *c + ) + { + short j, k, kk, ks, m; + float wkr, wki, xr; + + m = n >> 1; + ks = nc / n; + kk = 0; + for (j = 1; j < m; j++) + { + k = n - j; + kk += ks; + wkr = c[kk] - c[nc - kk]; + wki = c[kk] + c[nc - kk]; + xr = wki * a[j] - wkr * a[k]; + a[j] = wkr * a[j] + wki * a[k]; + a[k] = xr; + } + a[m] *= c[0]; + } + + + /*-----------------------------------------------------------------* + * edct2() + * + * Transformation of the signal to DCT domain + * OR Inverse EDCT-II for short frames + *-----------------------------------------------------------------*/ + + void edct2( + short n, + short isgn, + float *in, + float *a, + const short *ip, + const float *w + ) + { + short j, nw, nc; + float xr; + + mvr2r(in, a, n); + + nw = ip[0]; + if (n > (nw << 2)) + { + nw = n >> 2; + } + + nc = ip[1]; + if (n > nc) + { + nc = n; + } + + if (isgn < 0) + { + xr = a[n - 1]; + for (j = n - 2; j >= 2; j -= 2) + { + a[j + 1] = a[j] - a[j - 1]; + a[j] += a[j - 1]; + } + a[1] = a[0] - xr; + a[0] += xr; + + if (n > 4) + { + rftbsub(n, a, nc, w + nw); + bitrv2_SR(n, ip + 2, a); + cftbsub(n, a, w); + } + else if (n == 4) + { + cftfsub(n, a, w); + } + } + + if (isgn >= 0) + { + a[0] *= 0.5f; + } + + dctsub(n, a, nc, w + nw); + + if (isgn >= 0) + { + if (n > 4) + { + bitrv2_SR(n, ip + 2, a); + cftfsub(n, a, w); + rftfsub(n, a, nc, w + nw); + } + else if (n == 4) + { + cftfsub(n, a, w); + } + xr = a[0] - a[1]; + a[0] += a[1]; + for (j = 2; j < n; j += 2) + { + a[j - 1] = a[j] - a[j + 1]; + a[j] += a[j + 1]; + } + a[n - 1] = xr; + + for (j = 0; j < n; j ++) + { + a[j] /= 32.0f; + } + } + } + + + void DoRTFTn( + float *x, /* i/o : real part of input and output data */ + float *y, /* i/o : imaginary part of input and output data */ + const short n /* i : size of the FFT up to 1024 */ + ) + { + + int i; + float z[2048]; + + for ( i=0; i 0); + + if (len == 640) + { + float x[320], y[320]; + int i; + + if (sign != -1) + { + rfft_pre(sine_table, data, len); + } + + for (i = 0; i < 320; i++) + { + x[i] = data[2*i]; + y[i] = data[2*i+1]; + } + DoRTFT320(x, y); + for (i = 0; i < 320; i++) + { + data[2*i] = x[i]; + data[2*i+1] = y[i]; + } + + if (sign == -1) + { + rfft_post(sine_table, data, len); + } + } + else + { + if (len == 512) + { + int i; + int const log2 = 9; + float reordered_data[512]; + + if (sign == -1) + { + fft_rel(data, len, log2); + reordered_data[0] = data[0]; + reordered_data[1] = data[len/2]; + for (i = 1; i < len/2; i++) + { + reordered_data[2*i] = data[i]; + reordered_data[2*i+1] = data[len-i]; + } + } + else + { + reordered_data[0] = data[0]; + reordered_data[len/2] = data[1]; + for (i = 1; i < len/2; i++) + { + reordered_data[i] = data[2*i]; + reordered_data[len-i] = data[2*i+1]; + } + ifft_rel(reordered_data, len, log2); + } + mvr2r(reordered_data, data, len); + } + else + { + assert(!"Not supported FFT length!"); + } + } + + return 0; + } + + static void butterfly(const float a, const float b, float *aPlusb, float *aMinusb) + { + *aPlusb = a + b; + *aMinusb = a - b; + } + + static void fft2(float *pInOut) + { + /* FFT MATRIX: + 1.0000 1.0000 + 1.0000 -1.0000 + */ + float re1, im1; + float re2, im2; + + re1 = pInOut[0]; + im1 = pInOut[1]; + re2 = pInOut[2]; + im2 = pInOut[3]; + pInOut[0] = re1 + re2; + pInOut[1] = im1 + im2; + + pInOut[2] = re1 - re2; + pInOut[3] = im1 - im2; + + } + + static const float C31 = 0.5f; /* cos(PI/3); sin(2*PI/3) */ +static const float C32 = 0.866025403784439f; /* cos(PI/3); sin(2*PI/3) */ + + static void fft3_2(float *pInOut) + { + float re1, im1; + float re2, im2; + float re3, im3; + + float tmp1, tmp2; + float tmp3, tmp4; + + re1 = pInOut[0]; + im1 = pInOut[1]; + re2 = pInOut[2]; + im2 = pInOut[3]; + re3 = pInOut[4]; + im3 = pInOut[5]; + + /* FFT MATRIX: + 1.0000 1.0000 1.0000 + C31 C32 + 1.0000 -0.5000 - 0.8660i -0.5000 + 0.8660i + 1.0000 -0.5000 + 0.8660i -0.5000 - 0.8660i + */ + tmp1 = re2 + re3; + tmp3 = im2 + im3; + tmp2 = re2 - re3; + tmp4 = im2 - im3; + pInOut[0] = re1 + tmp1; + pInOut[1] = im1 + tmp3; + pInOut[2] = re1 - C31 * tmp1 + C32 * tmp4; + pInOut[4] = re1 - C31 * tmp1 - C32 * tmp4; + + pInOut[3] = im1 - C32 * tmp2 - C31 * tmp3; + pInOut[5] = im1 + C32 * tmp2 - C31 * tmp3; + + } + + + static void fft4(float *pInOut) + { + float re1, im1; + float re2, im2; + float re3, im3; + float re4, im4; + + float tmp1, tmp2; + float tmp3, tmp4; + float tmp5, tmp6; + float tmp7, tmp8; + + re1 = pInOut[0]; + im1 = pInOut[1]; + re2 = pInOut[2]; + im2 = pInOut[3]; + re3 = pInOut[4]; + im3 = pInOut[5]; + re4 = pInOut[6]; + im4 = pInOut[7]; + + /* + 1.0000 1.0000 1.0000 1.0000 + 1.0000 -1.0000i -1.0000 1.0000i + 1.0000 -1.0000 1.0000 -1.0000 + 1.0000 1.0000i -1.0000 -1.0000i + */ + tmp1 = re1 + re3; + tmp3 = re2 + re4; + tmp5 = im1 + im3; + tmp7 = im2 + im4; + pInOut[0] = tmp1 + tmp3; + pInOut[4] = tmp1 - tmp3; + + pInOut[1] = tmp5 + tmp7; + pInOut[5] = tmp5 - tmp7; + tmp2 = re1 - re3; + tmp4 = re2 - re4; + tmp6 = im1 - im3; + tmp8 = im2 - im4; + pInOut[2] = tmp2 + tmp8; + pInOut[6] = tmp2 - tmp8; + + pInOut[3] = -tmp4 + tmp6; + pInOut[7] = tmp4 + tmp6; + + } + + static const float C51 = 0.309016994374947f; /* cos(2*PI/5); */ +static const float C52 = 0.951056516295154f; /* sin(2*PI/5); */ +static const float C53 = 0.809016994374947f; /* cos( PI/5); */ +static const float C54 = 0.587785252292473f; /* sin( PI/5); */ + + static void fft5(float *pInOut) + { + float re1, im1; + float re2, im2; + float re3, im3; + float re4, im4; + float re5, im5; + + float tmp1, tmp2; + float tmp3, tmp4; + float tmp5, tmp6; + float tmp7, tmp8; + + + re1 = pInOut[0]; + im1 = pInOut[1]; + re2 = pInOut[2]; + im2 = pInOut[3]; + re3 = pInOut[4]; + im3 = pInOut[5]; + re4 = pInOut[6]; + im4 = pInOut[7]; + re5 = pInOut[8]; + im5 = pInOut[9]; + + /* + 1.0000 1.0000 1.0000 1.0000 1.0000 + C51 C52 C53 C54 + 1.0000 0.3090 - 0.9511i -0.8090 - 0.5878i -0.8090 + 0.5878i 0.3090 + 0.9511i + 1.0000 -0.8090 - 0.5878i 0.3090 + 0.9511i 0.3090 - 0.9511i -0.8090 + 0.5878i + 1.0000 -0.8090 + 0.5878i 0.3090 - 0.9511i 0.3090 + 0.9511i -0.8090 - 0.5878i + 1.0000 0.3090 + 0.9511i -0.8090 + 0.5878i -0.8090 - 0.5878i 0.3090 - 0.9511i + */ + tmp1 = re2 + re5; + tmp2 = re2 - re5; + tmp3 = im2 + im5; + tmp4 = im2 - im5; + tmp5 = re3 + re4; + tmp6 = re3 - re4; + tmp7 = im3 + im4; + tmp8 = im3 - im4; + + + pInOut[0] = re1 + tmp1 + tmp5; + pInOut[1] = im1 + tmp3 + tmp7; + + pInOut[2] = re1 + C51 * tmp1 - C53 * tmp5 + C52 * tmp4 + C54 * tmp8; + pInOut[8] = re1 + C51 * tmp1 - C53 * tmp5 - C52 * tmp4 - C54 * tmp8; + pInOut[3] = im1 - C52 * tmp2 - C54 * tmp6 + C51 * tmp3 - C53 * tmp7; + pInOut[9] = im1 + C52 * tmp2 + C54 * tmp6 + C51 * tmp3 - C53 * tmp7; + pInOut[4] = re1 - C53 * tmp1 + C51 * tmp5 + C54 * tmp4 - C52 * tmp8; + pInOut[6] = re1 - C53 * tmp1 + C51 * tmp5 - C54 * tmp4 + C52 * tmp8; + pInOut[5] = im1 - C54 * tmp2 + C52 * tmp6 - C53 * tmp3 + C51 * tmp7; + pInOut[7] = im1 + C54 * tmp2 - C52 * tmp6 - C53 * tmp3 + C51 * tmp7; + + + } + + static const float C81 = 0.707106781186548f; /* cos(PI/4); */ + + static void fft8_2(float *pInOut) + { + float re0, im0, re4, im4; + + float re1_7p, re1_7m; + float im1_7p, im1_7m; + float re2_6p, re2_6m; + float im2_6p, im2_6m; + float re3_5p, re3_5m; + float im3_5p, im3_5m; + + re0 = pInOut[0]; + im0 = pInOut[1]; + re4 = pInOut[8]; + im4 = pInOut[9]; + butterfly(pInOut[1*2 ], pInOut[7*2 ],&re1_7p, &re1_7m); + butterfly(pInOut[1*2+1], pInOut[7*2+1],&im1_7p, &im1_7m); + butterfly(pInOut[2*2 ], pInOut[6*2 ],&re2_6p, &re2_6m); + butterfly(pInOut[2*2+1], pInOut[6*2+1],&im2_6p, &im2_6m); + butterfly(pInOut[3*2 ], pInOut[5*2 ],&re3_5p, &re3_5m); + butterfly(pInOut[3*2+1], pInOut[5*2+1],&im3_5p, &im3_5m); + + /* + 0: 1 + 0i 1 + 0i 1 + 0i 1 + 0i 1 + 0i 1 + 0i 1 + 0i 1 + 0i + 1: 1 + 0i C81 - C81i 0 - 1i -C81 - C81i -1 - 0i -C81 + C81i - 0 + 1i C81 + C81i + 2: 1 + 0i 0 - 1i -1 - 0i - 0 + 1i 1 + 0i 0 - 1i - 1 - 0i - 0 + 1i + 3: 1 + 0i -C81 - C81i -0 + 1i C81 - C81i -1 - 0i C81 + C81i 0 - 1i -C81 + C81i + 4: 1 + 0i - 1 - 0i 1 + 0i - 1 - 0i 1 + 0i - 1 - 0i 1 + 0i - 1 - 0i + 5: 1 + 0i -C81 + C81i 0 - 1i C81 + C81i -1 - 0i C81 - C81i - 0 + 1i -C81 - C81i + 6: 1 + 0i - 0 + 1i -1 - 0i 0 - 1i 1 + 0i - 0 + 1i - 1 - 0i - 0 - 1i + 7: 1 + 0i C81 + C81i -0 + 1i -C81 + C81i -1 - 0i -C81 - C81i - 0 - 1i C81 - C81i + */ + pInOut[ 0] = re0 + re4 + re1_7p + re2_6p + re3_5p; + pInOut[ 1] = im0 + im4 + im1_7p + im2_6p + im3_5p; + + pInOut[ 2] = re0 + C81*(re1_7p - re3_5p) - re4 + C81*( im1_7m + im3_5m) + im2_6m; + pInOut[ 3] = im0 + C81*(im1_7p - im3_5p) - im4 - C81* (re1_7m + re3_5m) - re2_6m; + + pInOut[ 4] = re0 - re2_6p + re4 + im1_7m - im3_5m; + pInOut[ 5] = im0 - im2_6p + im4 - re1_7m + re3_5m; + + pInOut[ 6] = re0 + C81*(-re1_7p + re3_5p) - re4 + C81*( im1_7m + im3_5m) - im2_6m; + pInOut[ 7] = im0 + C81*(-im1_7p + im3_5p) - im4 - C81* (re1_7m + re3_5m) + re2_6m; + + pInOut[ 8] = re0 - re1_7p + re2_6p - re3_5p + re4; + pInOut[ 9] = im0 - im1_7p + im2_6p - im3_5p + im4; + + pInOut[10] = re0 + C81*(-re1_7p + re3_5p) - re4 - C81*( im1_7m + im3_5m) + im2_6m; + pInOut[11] = im0 + C81*(-im1_7p + im3_5p) - im4 + C81* (re1_7m + re3_5m) - re2_6m; + + pInOut[12] = re0 - re2_6p + re4 - im1_7m + im3_5m; + pInOut[13] = im0 - im2_6p + im4 + re1_7m - re3_5m; + + pInOut[14] = re0 + C81*(re1_7p - re3_5p) - re4 - C81*( im1_7m + im3_5m) - im2_6m; + pInOut[15] = im0 + C81*(im1_7p - im3_5p) - im4 + C81* (re1_7m + re3_5m) + re2_6m; + + } + + static void nextFFT(float *x, int length) + { + switch(length) + { + case 2: + fft2(x); + break; + case 3: + fft3_2(x); + break; + case 4: + fft4(x); + break; + case 5: + fft5(x); + break; + case 8: + fft8_2(x); + break; + default: + assert(!"length not supported"); + break; + } + } + + static const int CTFFTfactors[] = {9,8,7,5,4,3,2,0}; + + static __inline int findFactor(const int length) + { + int i = 0; + int factor = 0; + + while(CTFFTfactors[i]!=0) + { + if(0==(length%CTFFTfactors[i])) + { + factor = CTFFTfactors[i]; + break; + } + i++; + } + return factor; + } + + static __inline void twiddle(float *x, const int length, const int n1, const int n2) + { + int i, ii; + double pi = 4. * atan(1.); + float sinValOrg, cosValOrg; + float sinVal=0.f, cosVal=1.f; + float twReal=0.f, twImag=1.f; + + cosValOrg = (float) cos(-2*pi*1./(double)length); + sinValOrg = (float) sin(-2*pi*1./(double)length); + for(i=1; i0&&(length/factor>1)) + { + n1 = factor; + n2 = length/factor; + + /* DATA Resorting for stage1 */ + dest = scratch; + for (i=0; i<2*n1; i+=2) + { + src = x+i; + for(ii=0; ii1) + { + float *tmp = scratch1; + int n1_inv=1, n2_inv=1; + int n2 = factor[0/*idx*/]; + int n1 = length/n2; + int idx, incr; + + while(((n1_inv*n1)%n2)!=1) + { + n1_inv++; + } + while(((n2_inv*n2)%n1)!=1) + { + n2_inv++; + } + idx = 0; + incr = n1*n1_inv; + cnt = 0; + for(i=0; ilength) + { + idx -= length; + } + } + tmp[cnt++] = x[2*idx ]; + tmp[cnt++] = x[2*idx+1]; + idx++; + } + for(cnt=0; cntlength) + { + idx -= length; + } + } + } + for(cnt=0; cnt + #include "wmc_auto.h" + #include + #include "prot.h" + + + + #if defined __ICL + #define restrict __restrict + #else + #define restrict + #endif + + #ifdef _MSC_VER + #pragma warning(disable : 4305) /* disable truncation from double to float warning (VC++)*/ + #endif + + static void fft8(float *vec); + static void fft10(float *vec); + static void fft16(float *vec); + static void fft20(float *vec); + static void fft30(float *vec); + static void fft5s(float *x, int stride); + + + static const float INV_SQRT2 = 7.071067811865475e-1; +static const float COS_PI_DIV8 = 9.238795325112867e-1; +static const float COS_3PI_DIV8 = 3.826834323650898e-1; +static const float SQRT2PLUS1 = 2.414213562373095; +static const float SQRT2MINUS1 = 4.142135623730952e-1; + + + #ifdef _MSC_VER + #pragma warning(default : 4305) + #endif + + /******************************************************************************* + Functionname: fft8 + ******************************************************************************* + + Description: 8-point FFT. Complex-valued input takes 52 real additions + and 4 real multiplications. + + Arguments: vec - pointer to data (interleaved real / imaginary parts) + + Return: none + + *******************************************************************************/ + static void fft8(float * restrict vec) + { + float temp1[16]; + float temp2[16]; + + + /* Pre-additions */ + temp1[0] = vec[0] + vec[8]; + temp1[2] = vec[0] - vec[8]; + temp1[1] = vec[1] + vec[9]; + temp1[3] = vec[1] - vec[9]; + temp1[4] = vec[2] + vec[10]; + temp1[6] = vec[2] - vec[10]; + temp1[5] = vec[3] + vec[11]; + temp1[7] = vec[3] - vec[11]; + temp1[8] = vec[4] + vec[12]; + temp1[10] = vec[4] - vec[12]; + temp1[9] = vec[5] + vec[13]; + temp1[11] = vec[5] - vec[13]; + temp1[12] = vec[6] + vec[14]; + temp1[14] = vec[6] - vec[14]; + temp1[13] = vec[7] + vec[15]; + temp1[15] = vec[7] - vec[15]; + + /* Pre-additions and core multiplications */ + temp2[0] = temp1[0] + temp1[8]; + temp2[4] = temp1[0] - temp1[8]; + temp2[1] = temp1[1] + temp1[9]; + temp2[5] = temp1[1] - temp1[9]; + temp2[8] = temp1[2] - temp1[11]; + temp2[10] = temp1[2] + temp1[11]; + temp2[9] = temp1[3] + temp1[10]; + temp2[11] = temp1[3] - temp1[10]; + temp2[2] = temp1[4] + temp1[12]; + temp2[7] = temp1[4] - temp1[12]; + temp2[3] = temp1[5] + temp1[13]; + temp2[6] = temp1[13]- temp1[5]; + + temp1[1] = temp1[6] + temp1[14]; + temp1[2] = temp1[6] - temp1[14]; + temp1[0] = temp1[7] + temp1[15]; + temp1[3] = temp1[7] - temp1[15]; + + temp2[12] = (temp1[0] + temp1[2]) * INV_SQRT2; + temp2[14] = (temp1[0] - temp1[2]) * INV_SQRT2; + temp2[13] = (temp1[3] - temp1[1]) * INV_SQRT2; + temp2[15] = (temp1[1] + temp1[3]) * -INV_SQRT2; + + /* Post-additions */ + vec[0] = temp2[0] + temp2[2]; + vec[8] = temp2[0] - temp2[2]; + vec[1] = temp2[1] + temp2[3]; + vec[9] = temp2[1] - temp2[3]; + vec[4] = temp2[4] - temp2[6]; + vec[12] = temp2[4] + temp2[6]; + vec[5] = temp2[5] - temp2[7]; + vec[13] = temp2[5] + temp2[7]; + vec[6] = temp2[8] + temp2[14]; + vec[14] = temp2[8] - temp2[14]; + vec[7] = temp2[9] + temp2[15]; + vec[15] = temp2[9] - temp2[15]; + vec[2] = temp2[10]+ temp2[12]; + vec[10] = temp2[10]- temp2[12]; + vec[3] = temp2[11]+ temp2[13]; + vec[11] = temp2[11]- temp2[13]; + + } + + + + /******************************************************************************* + Functionname: fft16 + ******************************************************************************* + + Description: 16-point FFT. Complex-valued input takes 144 real additions and + 24 real multiplications. + + Arguments: vec - pointer to data (interleaved real / imaginary parts) + + Return: none + + *******************************************************************************/ + /* fast implementation, completely unrolled and inlined */ + static void fft16(float * restrict vec) + { + float temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, + temp18, temp19, temp110, temp111, temp112, temp113, temp114, temp115; + float temp20, temp21, temp22, temp23, temp24, temp25, temp26, temp27, + temp28, temp29, temp210, temp211, temp212, temp213, temp214, temp215; + float vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, + vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; + + + /* even */ + vec0 = vec[0] + vec[16]; + vec1 = vec[1] + vec[17]; + vec2 = vec[2] + vec[18]; + vec3 = vec[3] + vec[19]; + vec4 = vec[4] + vec[20]; + vec5 = vec[5] + vec[21]; + vec6 = vec[6] + vec[22]; + vec7 = vec[7] + vec[23]; + vec8 = vec[8] + vec[24]; + vec9 = vec[9] + vec[25]; + vec10 = vec[10] + vec[26]; + vec11 = vec[11] + vec[27]; + vec12 = vec[12] + vec[28]; + vec13 = vec[13] + vec[29]; + vec14 = vec[14] + vec[30]; + vec15 = vec[15] + vec[31]; + + /* Pre-additions */ + temp10 = vec0 + vec8; + temp12 = vec0 - vec8; + temp11 = vec1 + vec9; + temp13 = vec1 - vec9; + temp14 = vec2 + vec10; + temp16 = vec2 - vec10; + temp15 = vec3 + vec11; + temp17 = vec3 - vec11; + temp18 = vec4 + vec12; + temp110 = vec4 - vec12; + temp19 = vec5 + vec13; + temp111 = vec5 - vec13; + temp112 = vec6 + vec14; + temp114 = vec6 - vec14; + temp113 = vec7 + vec15; + temp115 = vec7 - vec15; + + /* Pre-additions and core multiplications */ + temp20 = temp10 + temp18; + temp24 = temp10 - temp18; + temp21 = temp11 + temp19; + temp25 = temp11 - temp19; + temp28 = temp12 - temp111; + temp210 = temp12 + temp111; + temp29 = temp13 + temp110; + temp211 = temp13 - temp110; + temp22 = temp14 + temp112; + temp27 = temp14 - temp112; + temp23 = temp15 + temp113; + temp26 = temp113- temp15; + + temp11 = temp16 + temp114; + temp12 = temp16 - temp114; + temp10 = temp17 + temp115; + temp13 = temp17 - temp115; + + temp212 = (temp10 + temp12) * INV_SQRT2; + temp214 = (temp10 - temp12) * INV_SQRT2; + temp213 = (temp13 - temp11) * INV_SQRT2; + temp215 = (temp11 + temp13) * -INV_SQRT2; + + + + /* odd */ + vec0 = vec[0] - vec[16]; + vec1 = vec[1] - vec[17]; + vec2 = vec[2] - vec[18]; + vec3 = vec[3] - vec[19]; + vec4 = vec[4] - vec[20]; + vec5 = vec[5] - vec[21]; + vec6 = vec[6] - vec[22]; + vec7 = vec[7] - vec[23]; + vec8 = vec[8] - vec[24]; + vec9 = vec[9] - vec[25]; + vec10 = vec[10] - vec[26]; + vec11 = vec[11] - vec[27]; + vec12 = vec[12] - vec[28]; + vec13 = vec[13] - vec[29]; + vec14 = vec[14] - vec[30]; + vec15 = vec[15] - vec[31]; + + /* Pre-additions and core multiplications */ + temp19 = (vec2 + vec14) * -COS_3PI_DIV8; + temp110 = (vec2 - vec14) * COS_PI_DIV8; + temp18 = (vec3 + vec15) * COS_3PI_DIV8; + temp111 = (vec3 - vec15) * COS_PI_DIV8; + temp15 = (vec4 + vec12) * -INV_SQRT2; + temp16 = (vec4 - vec12) * INV_SQRT2; + temp14 = (vec5 + vec13) * INV_SQRT2; + temp17 = (vec5 - vec13) * INV_SQRT2; + temp113 = (vec6 + vec10) * -COS_PI_DIV8; + temp114 = (vec6 - vec10) * COS_3PI_DIV8; + temp112 = (vec7 + vec11) * COS_PI_DIV8; + temp115 = (vec7 - vec11) * COS_3PI_DIV8; + + /* Core multiplications */ + vec2 = temp18 * SQRT2PLUS1 - temp112 * SQRT2MINUS1; + vec3 = temp19 * SQRT2PLUS1 - temp113 * SQRT2MINUS1; + vec4 = temp110 * SQRT2MINUS1 - temp114 * SQRT2PLUS1; + vec5 = temp111 * SQRT2MINUS1 - temp115 * SQRT2PLUS1; + + /* Post-additions */ + temp18 += temp112; + temp19 += temp113; + temp110+= temp114; + temp111+= temp115; + + vec6 = vec0 + temp14; + vec10 = vec0 - temp14; + vec7 = vec1 + temp15; + vec11 = vec1 - temp15; + + vec12 = temp16 - vec9; + vec14 = temp16 + vec9; + vec13 = vec8 + temp17; + vec15 = vec8 - temp17; + + temp10 = vec6 - vec14; + temp12 = vec6 + vec14; + temp11 = vec7 + vec15; + temp13 = vec7 - vec15; + temp14 = vec10 + vec12; + temp16 = vec10 - vec12; + temp15 = vec11 + vec13; + temp17 = vec11 - vec13; + + vec10 = temp18 + temp110; + temp110 = temp18 - temp110; + vec11 = temp19 + temp111; + temp111 = temp19 - temp111; + + temp112 = vec2 + vec4; + temp114 = vec2 - vec4; + temp113 = vec3 + vec5; + temp115 = vec3 - vec5; + + + /* Post-additions */ + *vec++ = temp20 + temp22; + *vec++ = temp21 + temp23; + *vec++ = temp12 + vec10; + *vec++ = temp13 + vec11; + *vec++ = temp210+ temp212; + *vec++ = temp211+ temp213; + *vec++ = temp10 + temp112; + *vec++ = temp11 + temp113; + *vec++ = temp24 - temp26; + *vec++ = temp25 - temp27; + *vec++ = temp16 + temp114; + *vec++ = temp17 + temp115; + *vec++ = temp28 + temp214; + *vec++ = temp29 + temp215; + *vec++ = temp14 + temp110; + *vec++ = temp15 + temp111; + *vec++ = temp20 - temp22; + *vec++ = temp21 - temp23; + *vec++ = temp12 - vec10; + *vec++ = temp13 - vec11; + *vec++ = temp210- temp212; + *vec++ = temp211- temp213; + *vec++ = temp10 - temp112; + *vec++ = temp11 - temp113; + *vec++ = temp24 + temp26; + *vec++ = temp25 + temp27; + *vec++ = temp16 - temp114; + *vec++ = temp17 - temp115; + *vec++ = temp28 - temp214; + *vec++ = temp29 - temp215; + *vec++ = temp14 - temp110; + *vec++ = temp15 - temp111; + + } + + + /******************************************************************************* + Functionname: fft15 + ******************************************************************************* + + Description: 15-point FFT. Complex-valued input takes 176 real additions + and 34 real multiplications. + + Arguments: vec - pointer to data (interleaved real / imaginary parts) + + Return: none + + *******************************************************************************/ + static void fft15(float * restrict vec) + { + + float r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17; + float i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17; + float tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, + tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17, tmp18, tmp19, + tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27, tmp28, tmp29; + + + /* Pre-additions real part */ + r1 = vec[2] + vec[8]; + r2 = vec[2] - vec[8]; + r3 = vec[4] + vec[16]; + r4 = vec[4] - vec[16]; + r5 = vec[6] + vec[24]; + r6 = vec[6] - vec[24]; + r7 = vec[10] + vec[20]; + r8 = vec[10] - vec[20]; + r9 = vec[12] + vec[18]; + r10 = vec[12] - vec[18]; + r11 = vec[14] + vec[26]; + r12 = vec[14] - vec[26]; + r13 = vec[22] + vec[28]; + r14 = vec[22] - vec[28]; + + tmp2 = r1 + r3; + tmp4 = r1 - r3; + tmp6 = r2 + r14; + tmp8 = r2 - r14; + tmp10 = r4 + r12; + tmp12 = r4 - r12; + tmp14 = r5 + r9; + tmp16 = r5 - r9; + tmp18 = r11 + r13; + tmp20 = r11 - r13; + + /* Pre-additions imaginary part */ + i1 = vec[3] + vec[9]; + i2 = vec[3] - vec[9]; + i3 = vec[5] + vec[17]; + i4 = vec[5] - vec[17]; + i5 = vec[7] + vec[25]; + i6 = vec[7] - vec[25]; + i7 = vec[11] + vec[21]; + i8 = vec[11] - vec[21]; + i9 = vec[13] + vec[19]; + i10 = vec[13] - vec[19]; + i11 = vec[15] + vec[27]; + i12 = vec[15] - vec[27]; + i13 = vec[23] + vec[29]; + i14 = vec[23] - vec[29]; + + tmp3 = i1 + i3; + tmp5 = i1 - i3; + tmp7 = i2 + i14; + tmp9 = i2 - i14; + tmp11 = i4 + i12; + tmp13 = i4 - i12; + tmp15 = i5 + i9; + tmp17 = i5 - i9; + tmp19 = i11 + i13; + tmp21 = i11 - i13; + + + /* Pre-additions and core multiplications */ + tmp28= tmp4 + tmp20; + tmp29= tmp5 + tmp21; + r4 = tmp2 + tmp18; + i4 = tmp3 + tmp19; + r3 = (r4 + tmp14) * -1.25f; + i3 = (i4 + tmp15) * -1.25f; + r2 = (tmp29 - i8) * -8.660254037844387e-1f; + i2 = (tmp28 - r8) * 8.660254037844387e-1f; + r1 = r4 + r7; + i1 = i4 + i7; + r0 = r1 + vec[0] + tmp14; + i0 = i1 + vec[1] + tmp15; + r7 = tmp4 - tmp20; + i7 = tmp5 - tmp21; + r8 = (tmp3 - tmp19) * -4.841229182759272e-1f; + i8 = (tmp2 - tmp18) * 4.841229182759272e-1f; + tmp0 = tmp6 + r10; + tmp1 = tmp7 + i10; + tmp2 = r6 - tmp10; + tmp3 = i6 - tmp11; + r10 = tmp7 * -2.308262652881440f; + i10 = tmp6 * 2.308262652881440f; + r11 = tmp8 * 1.332676064001459f; + i11 = tmp9 * 1.332676064001459f; + r6 = (r7 - tmp16) * 5.590169943749475e-1f; + i6 = (i7 - tmp17) * 5.590169943749475e-1f; + r12 = (tmp1 + tmp3) * 5.877852522924733e-1f; + i12 = (tmp0 + tmp2) * -5.877852522924733e-1f; + r13 = (tmp7 - tmp11) * -8.816778784387098e-1f; + i13 = (tmp6 - tmp10) * 8.816778784387098e-1f; + r14 = (tmp8 + tmp12) * 5.090369604551274e-1f; + i14 = (tmp9 + tmp13) * 5.090369604551274e-1f; + r16 = tmp11 * 5.449068960040204e-1f; + i16 = tmp10 * -5.449068960040204e-1f; + r17 = tmp12 * 3.146021430912046e-1f; + i17 = tmp13 * 3.146021430912046e-1f; + + r4 *= 1.875f; + i4 *= 1.875f; + r1 *= -1.5f; + i1 *= -1.5f; + r7 *= -8.385254915624212e-1f; + i7 *= -8.385254915624212e-1f; + r5 = tmp29 * 1.082531754730548f; + i5 = tmp28 * -1.082531754730548f; + r9 = tmp1 * 1.538841768587627f; + i9 = tmp0 * -1.538841768587627f; + r15 = tmp3 * 3.632712640026803e-1f; + i15 = tmp2 * -3.632712640026803e-1f; + + + /* Post-additions real part */ + tmp2 = r0 + r1; + tmp4 = r3 + r6; + tmp6 = r3 - r6; + tmp8 = r4 + r5; + tmp10 = r4 - r5; + tmp12 = r7 + r8; + tmp14 = r7 - r8; + tmp16 = r13 + r16; + tmp18 = r14 + r17; + tmp20 = r10 - r13; + tmp22 = r11 - r14; + tmp24 = r12 + r15; + tmp26 = r12 - r9; + + r1 = tmp2 + r2; + r2 = tmp2 - r2; + r3 = tmp4 + tmp26; + r4 = tmp4 - tmp26; + r5 = tmp6 + tmp24; + r6 = tmp6 - tmp24; + r7 = tmp16 + tmp18; + r8 = tmp16 - tmp18; + r9 = tmp20 - tmp22; + r10 = tmp20 + tmp22; + r11 = r1 + tmp8; + r12 = r2 + tmp10; + r13 = r11 - tmp12; + r14 = r12 - tmp14; + r15 = r12 + tmp14; + r16 = r11 + tmp12; + + /* Post-additions imaginary part */ + tmp3 = i0 + i1; + tmp5 = i3 + i6; + tmp7 = i3 - i6; + tmp9 = i4 + i5; + tmp11 = i4 - i5; + tmp13 = i7 + i8; + tmp15 = i7 - i8; + tmp17 = i13 + i16; + tmp19 = i14 + i17; + tmp21 = i10 - i13; + tmp23 = i11 - i14; + tmp25 = i12 + i15; + tmp27 = i12 - i9; + + i1 = tmp3 + i2; + i2 = tmp3 - i2; + i3 = tmp5 + tmp27; + i4 = tmp5 - tmp27; + i5 = tmp7 + tmp25; + i6 = tmp7 - tmp25; + i7 = tmp17 + tmp19; + i8 = tmp17 - tmp19; + i9 = tmp21 - tmp23; + i10 = tmp21 + tmp23; + i11 = i1 + tmp9; + i12 = i2 + tmp11; + i13 = i11 - tmp13; + i14 = i12 - tmp15; + i15 = i12 + tmp15; + i16 = i11 + tmp13; + + *vec++ = r0; + *vec++ = i0; + *vec++ = r13 + r5 + r7; + *vec++ = i13 + i5 + i7; + *vec++ = r15 + r3 - r9; + *vec++ = i15 + i3 - i9; + *vec++ = r0 + r4; + *vec++ = i0 + i4; + *vec++ = r13 + r6 - r7; + *vec++ = i13 + i6 - i7; + *vec++ = r2; + *vec++ = i2; + *vec++ = r0 + r5; + *vec++ = i0 + i5; + *vec++ = r16 + r3 - r10; + *vec++ = i16 + i3 - i10; + *vec++ = r15 + r4 + r9; + *vec++ = i15 + i4 + i9; + *vec++ = r0 + r6; + *vec++ = i0 + i6; + *vec++ = r1; + *vec++ = i1; + *vec++ = r14 + r5 + r8; + *vec++ = i14 + i5 + i8; + *vec++ = r0 + r3; + *vec++ = i0 + i3; + *vec++ = r16 + r4 + r10; + *vec++ = i16 + i4 + i10; + *vec++ = r14 + r6 - r8; + *vec++ = i14 + i6 - i8; + + + } + + /******************************************************************************* + Functionname: fft5s + ******************************************************************************* + + Description: 5-point FFT. + + Arguments: x - pointer to input data (interleaved real / imaginary parts) + stride - stride for input data + + Return: none + + *******************************************************************************/ + static const float C51 = 0.9510565162951535f; +static const float C52 = -1.5388417685876270f; +static const float C53 = -0.3632712640026803f; +static const float C54 = 0.5590169943749475f; +static const float C55 = -1.25f; + + static void fft5s(float *x, int stride) + { + float r1,r2,r3,r4; + float s1,s2,s3,s4; + float t; + /* real part */ + r1 = x[1*stride] + x[4*stride]; + r4 = x[1*stride] - x[4*stride]; + r3 = x[2*stride] + x[3*stride]; + r2 = x[2*stride] - x[3*stride]; + t = (r1-r3) * C54; + r1 = r1 + r3; + x[0] = x[0] + r1; + r1 = x[0] + (r1 * C55); + r3 = r1 - t; + r1 = r1 + t; + t = (r4 + r2) * C51; + r4 = t + (r4 * C52); + r2 = t + (r2 * C53); + + /* imaginary part */ + s1 = x[1*stride+1] + x[4*stride+1]; + s4 = x[1*stride+1] - x[4*stride+1]; + s3 = x[2*stride+1] + x[3*stride+1]; + s2 = x[2*stride+1] - x[3*stride+1]; + t = (s1 - s3) * C54; + s1 = s1 + s3; + x[1] = x[1] + s1; + s1 = x[1] + (s1 * C55); + s3 = s1 - t; + s1 = s1 + t; + t = (s4 + s2) * C51; + s4 = t + (s4 * C52); + s2 = t + (s2 * C53); + + /* combination */ + x[1*stride] = r1 + s2; + x[4*stride] = r1 - s2; + x[2*stride] = r3 - s4; + x[3*stride] = r3 + s4; + + x[1*stride+1] = s1 - r2; + x[4*stride+1] = s1 + r2; + x[2*stride+1] = s3 + r4; + x[3*stride+1] = s3 - r4; + } + + + /** + * \brief Function performs a complex 10-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR10 bits. + * + * WOPS FLC version: 1093 cycles + * 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(float * restrict vec) + { + float t; + float r1,r2,r3,r4; + float s1,s2,s3,s4; + float y00,y01,y02,y03,y04,y05,y06,y07,y08,y09; + float y10,y11,y12,y13,y14,y15,y16,y17,y18,y19; + + /* 2 fft5 stages */ + + /* real part */ + r1 = vec[12] + vec[8]; + r4 = vec[12] - vec[8]; + r3 = vec[4] + vec[16]; + r2 = vec[4] - vec[16]; + t = (r1 - r3) * C54; + r1 = r1 + r3; + y00 = vec[0] + r1; + r1 = y00 + (r1 * C55); + r3 = r1 - t; + r1 = r1 + t; + t = (r4 + r2) * C51; + r4 = t + (r4 * C52); + r2 = t + (r2 * C53); + + /* imaginary part */ + s1 = vec[13] + vec[9]; + s4 = vec[13] - vec[9]; + s3 = vec[5] + vec[17]; + s2 = vec[5] - vec[17]; + t = (s1 - s3) * C54; + s1 = s1 + s3; + y01 = vec[1] + s1; + s1 = y01 + (s1 * C55); + s3 = s1 - t; + s1 = s1 + t; + t = (s4 + s2) * C51; + s4 = t + (s4 * C52); + s2 = t + (s2 * C53); + + /* combination */ + y04 = r1 + s2; + y16 = r1 - s2; + y08 = r3 - s4; + y12 = r3 + s4; + y05 = s1 - r2; + y17 = s1 + r2; + y09 = s3 + r4; + y13 = s3 - r4; + + /* real part */ + r1 = vec[2] + vec[18]; + r4 = vec[2] - vec[18]; + r3 = vec[14] + vec[6]; + r2 = vec[14] - vec[6]; + t = (r1 - r3) * C54; + r1 = r1 + r3; + y02 = vec[10] + r1; + r1 = y02 + (r1 * C55); + r3 = r1 - t; + r1 = r1 + t; + t = (r4 + r2) * C51; + r4 = t + (r4 * C52); + r2 = t + (r2 * C53); + + /* imaginary part */ + s1 = vec[3] + vec[19]; + s4 = vec[3] - vec[19]; + s3 = vec[15] + vec[7]; + s2 = vec[15] - vec[7]; + t = (s1 - s3) * C54; + s1 = s1 + s3; + y03 = vec[11] + s1; + s1 = y03 + (s1 * C55); + s3 = s1 - t; + s1 = s1 + t; + t = (s4 + s2) * C51; + s4 = t + (s4 * C52); + s2 = t + (s2 * C53); + + /* combination */ + y06 = r1 + s2; + y18 = r1 - s2; + y10 = r3 - s4; + y14 = r3 + s4; + y07 = s1 - r2; + y19 = s1 + r2; + y11 = s3 + r4; + y15 = s3 - r4; + + /* 5 fft2 stages */ + vec[0] = y00 + y02; + vec[1] = y01 + y03; + vec[2] = y12 - y14; + vec[3] = y13 - y15; + vec[4] = y04 + y06; + vec[5] = y05 + y07; + vec[6] = y16 - y18; + vec[7] = y17 - y19; + vec[8] = y08 + y10; + vec[9] = y09 + y11; + vec[10] = y00 - y02; + vec[11] = y01 - y03; + vec[12] = y12 + y14; + vec[13] = y13 + y15; + vec[14] = y04 - y06; + vec[15] = y05 - y07; + vec[16] = y16 + y18; + vec[17] = y17 + y19; + vec[18] = y08 - y10; + vec[19] = y09 - y11; + } + + /** + * \brief Function performs a complex 20-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR20 bits. + * + * WOPS FLC version: 1509 cycles + * 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(float *signal) + { + const int s = 2; + float *re = signal, *im = signal+1; + float r1,r2,r3,r4; + float s1,s2,s3,s4; + float x0,x1,x2,x3,x4; + float t,t0,t1,t2,t3,t4,t5,t6,t7; + float y00,y01,y02,y03,y04,y05,y06,y07,y08,y09; + float y10,y11,y12,y13,y14,y15,y16,y17,y18,y19; + float y20,y21,y22,y23,y24,y25,y26,y27,y28,y29; + float y30,y31,y32,y33,y34,y35,y36,y37,y38,y39; + + /* */ + + /* 1. FFT5 stage */ + + /* real part */ + x0 = re[s* 0]; + x1 = re[s*16]; + x2 = re[s*12]; + x3 = re[s* 8]; + x4 = re[s* 4]; + r1 = x1 + x4; + r4 = x1 - x4; + r3 = x2 + x3; + r2 = x2 - x3; + t = (r1 - r3) * C54; + r1 = r1 + r3; + y00 = x0 + r1; + r1 = y00 + (r1 * C55); + r3 = r1 - t; + r1 = r1 + t; + t = (r4 + r2) * C51; + r4 = t + (r4 * C52); + r2 = t + (r2 * C53); + + /* imaginary part */ + x0 = im[s* 0]; + x1 = im[s*16]; + x2 = im[s*12]; + x3 = im[s* 8]; + x4 = im[s* 4]; + s1 = x1 + x4; + s4 = x1 - x4; + s3 = x2 + x3; + s2 = x2 - x3; + t = (s1 - s3) * C54; + s1 = (s1 + s3); + y01 = (x0 + s1); + s1 = y01 + (s1 * C55); + s3 = (s1 - t); + s1 = (s1 + t); + t = (s4 + s2) * C51; + s4 = t + (s4 * C52); + s2 = t + (s2 * C53); + + /* combination */ + y08 = (r1 + s2); + y32 = (r1 - s2); + y16 = (r3 - s4); + y24 = (r3 + s4); + + y09 = (s1 - r2); + y33 = (s1 + r2); + y17 = (s3 + r4); + y25 = (s3 - r4); + + /* 2. FFT5 stage */ + + /* real part */ + x0 = re[s* 5]; + x1 = re[s* 1]; + x2 = re[s*17]; + x3 = re[s*13]; + x4 = re[s* 9]; + r1 = (x1 + x4); + r4 = (x1 - x4); + r3 = (x2 + x3); + r2 = (x2 - x3); + t = (r1 - r3) * C54; + r1 = (r1 + r3); + y02 = (x0 + r1); + r1 = y02 + (r1 * C55); + r3 = (r1 - t); + r1 = (r1 + t); + t = (r4 + r2) * C51; + r4 = t + (r4 * C52); + r2 = t + (r2 * C53); + + /* imaginary part */ + x0 = im[s* 5]; + x1 = im[s* 1]; + x2 = im[s*17]; + x3 = im[s*13]; + x4 = im[s* 9]; + s1 = (x1 + x4); + s4 = (x1 - x4); + s3 = (x2 + x3); + s2 = (x2 - x3); + t = (s1 - s3) * C54; + s1 = (s1 + s3); + y03 = (x0 + s1); + s1 = y03 + (s1 * C55); + s3 = (s1 - t); + s1 = (s1 + t); + t = (s4 + s2) * C51; + s4 = t + (s4 * C52); + s2 = t + (s2 * C53); + + /* combination */ + y10 = (r1 + s2); + y34 = (r1 - s2); + y18 = (r3 - s4); + y26 = (r3 + s4); + + y11 = (s1 - r2); + y35 = (s1 + r2); + y19 = (s3 + r4); + y27 = (s3 - r4); + + /* 3. FFT5 stage */ + + /* real part */ + x0 = re[s*10]; + x1 = re[s* 6]; + x2 = re[s* 2]; + x3 = re[s*18]; + x4 = re[s*14]; + r1 = (x1 + x4); + r4 = (x1 - x4); + r3 = (x2 + x3); + r2 = (x2 - x3); + t = (r1 - r3) * C54; + r1 = (r1 + r3); + y04 = (x0 + r1); + r1 = y04 + (r1 * C55); + r3 = (r1 - t); + r1 = (r1 + t); + t = (r4 + r2) * C51; + r4 = t + (r4 * C52); + r2 = t + (r2 * C53); + + /* imaginary part */ + x0 = im[s*10]; + x1 = im[s* 6]; + x2 = im[s* 2]; + x3 = im[s*18]; + x4 = im[s*14]; + s1 = (x1 + x4); + s4 = (x1 - x4); + s3 = (x2 + x3); + s2 = (x2 - x3); + t = (s1 - s3) * C54; + s1 = (s1 + s3); + y05 = (x0 + s1); + s1 = y05 + (s1 * C55); + s3 = (s1 - t); + s1 = (s1 + t); + t = (s4 + s2) * C51; + s4 = t + (s4 * C52); + s2 = t + (s2 * C53); + + /* combination */ + y12 = (r1 + s2); + y36 = (r1 - s2); + y20 = (r3 - s4); + y28 = (r3 + s4); + + y13 = (s1 - r2); + y37 = (s1 + r2); + y21 = (s3 + r4); + y29 = (s3 - r4); + + /* 4. FFT5 stage */ + + /* real part */ + x0 = re[s*15]; + x1 = re[s*11]; + x2 = re[s* 7]; + x3 = re[s* 3]; + x4 = re[s*19]; + r1 = (x1 + x4); + r4 = (x1 - x4); + r3 = (x2 + x3); + r2 = (x2 - x3); + t = (r1 - r3) * C54; + r1 = (r1 + r3); + y06 = (x0 + r1); + r1 = y06 + (r1 * C55); + r3 = (r1 - t); + r1 = (r1 + t); + t = (r4 + r2) * C51; + r4 = t + (r4 * C52); + r2 = t + (r2 * C53); + + /* imaginary part */ + x0 = im[s*15]; + x1 = im[s*11]; + x2 = im[s* 7]; + x3 = im[s* 3]; + x4 = im[s*19]; + s1 = (x1 + x4); + s4 = (x1 - x4); + s3 = (x2 + x3); + s2 = (x2 - x3); + t = (s1 - s3) * C54; + s1 = (s1 + s3); + y07 = (x0 + s1); + s1 = y07 + (s1 * C55); + s3 = (s1 - t); + s1 = (s1 + t); + t = (s4 + s2) * C51; + s4 = t + (s4 * C52); + s2 = t + (s2 * C53); + + /* combination */ + y14 = (r1 + s2); + y38 = (r1 - s2); + y22 = (r3 - s4); + y30 = (r3 + s4); + + y15 = (s1 - r2); + y39 = (s1 + r2); + y23 = (s3 + r4); + y31 = (s3 - r4); + + + /* 1. FFT4 stage */ + + /* Pre-additions */ + t0 = (y00 + y04); + t2 = (y00 - y04); + t1 = (y01 + y05); + t3 = (y01 - y05); + t4 = (y02 + y06); + t7 = (y02 - y06); + t5 = (y07 + y03); + t6 = (y07 - y03); + + /* Post-additions */ + re[s* 0] = (t0 + t4); + im[s* 0] = (t1 + t5); + re[s* 5] = (t2 - t6); + im[s* 5] = (t3 - t7); + re[s*10] = (t0 - t4); + im[s*10] = (t1 - t5); + re[s*15] = (t2 + t6); + im[s*15] = (t3 + t7); + + /* 2. FFT4 stage */ + + /* Pre-additions */ + t0 = (y08 + y12); + t2 = (y08 - y12); + t1 = (y09 + y13); + t3 = (y09 - y13); + t4 = (y10 + y14); + t7 = (y10 - y14); + t5 = (y15 + y11); + t6 = (y15 - y11); + + /* Post-additions */ + re[s* 4] = (t0 + t4); + im[s* 4] = (t1 + t5); + re[s* 9] = (t2 - t6); + im[s* 9] = (t3 - t7); + re[s*14] = (t0 - t4); + im[s*14] = (t1 - t5); + re[s*19] = (t2 + t6); + im[s*19] = (t3 + t7); + + + /* 3. FFT4 stage */ + + /* Pre-additions */ + t0 = (y16 + y20); + t2 = (y16 - y20); + t1 = (y17 + y21); + t3 = (y17 - y21); + t4 = (y18 + y22); + t7 = (y18 - y22); + t5 = (y23 + y19); + t6 = (y23 - y19); + + /* Post-additions */ + re[s* 8] = (t0 + t4); + im[s* 8] = (t1 + t5); + re[s*13] = (t2 - t6); + im[s*13] = (t3 - t7); + re[s*18] = (t0 - t4); + im[s*18] = (t1 - t5); + re[s* 3] = (t2 + t6); + im[s* 3] = (t3 + t7); + + /* 4. FFT4 stage */ + + /* Pre-additions */ + t0 = (y24 + y28); + t2 = (y24 - y28); + t1 = (y25 + y29); + t3 = (y25 - y29); + t4 = (y26 + y30); + t7 = (y26 - y30); + t5 = (y31 + y27); + t6 = (y31 - y27); + + /* Post-additions */ + re[s*12] = (t0 + t4); + im[s*12] = (t1 + t5); + re[s*17] = (t2 - t6); + im[s*17] = (t3 - t7); + re[s* 2] = (t0 - t4); + im[s* 2] = (t1 - t5); + re[s* 7] = (t2 + t6); + im[s* 7] = (t3 + t7); + + /* 5. FFT4 stage */ + + /* Pre-additions */ + t0 = (y32 + y36); + t2 = (y32 - y36); + t1 = (y33 + y37); + t3 = (y33 - y37); + t4 = (y34 + y38); + t7 = (y34 - y38); + t5 = (y39 + y35); + t6 = (y39 - y35); + + /* Post-additions */ + re[s*16] = (t0 + t4); + im[s*16] = (t1 + t5); + re[s* 1] = (t2 - t6); + im[s* 1] = (t3 - t7); + re[s* 6] = (t0 - t4); + im[s* 6] = (t1 - t5); + re[s*11] = (t2 + t6); + im[s*11] = (t3 + t7); + + /* */ + /* */ + } + + /******************************************************************************* + Functionname: fft30 + ******************************************************************************* + + Description: 30-point FFT. + + Arguments: in - pointer to data (interleaved real / imaginary parts) + + Return: none + + *******************************************************************************/ + + static void fft30(float * restrict in) + { + int i; + float temp[60]; + float * temp_l = temp; + float * temp_lu = temp + 2*8; + float * temp_h = temp + 2*15; + float * temp_hu = temp + 2*15 + 2*8; + float *in_l = in + 2*0; + float *in_h = in + 2*15; + for(i=0; i<7; i++) + { + *temp_l++ = *in_l++; + *temp_l++ = *in_l++; + *temp_h++ = *in_h++; + *temp_h++ = *in_h++; + *temp_l++ = *in_h++; + *temp_l++ = *in_h++; + *temp_h++ = *in_l++; + *temp_h++ = *in_l++; + } + *temp_l++ = *in_l++; + *temp_l++ = *in_l++; + *temp_h++ = *in_h++; + *temp_h++ = *in_h++; + temp_l = temp; + temp_h = temp + 30; + fft15(temp_l); + fft15(temp_h); + + in_l = in + 2*0; + in_h = in + 2*15; + for(i=0; i<7; i++) + { + *in_l++ = *temp_l + *temp_h; + *in_h++ = *temp_l++ - *temp_h++; + *in_l++ = *temp_l + *temp_h; + *in_h++ = *temp_l++ - *temp_h++; + + *in_h++ = *temp_lu + *temp_hu; + *in_l++ = *temp_lu++ - *temp_hu++; + *in_h++ = *temp_lu + *temp_hu; + *in_l++ = *temp_lu++ - *temp_hu++; + } + *in_l++ = *temp_l + *temp_h; + *in_h++ = *temp_l++ - *temp_h++; + *in_l++ = *temp_l + *temp_h; + *in_h++ = *temp_l++ - *temp_h++; + } + + /*-------------------------------------------------------------------* + * fft_cldfb() + * + * Interface functions FFT subroutines + *--------------------------------------------------------------------*/ + void fft_cldfb ( + float *data, /* i/o: input/output vector */ + int size /* size of fft operation */ + ) + { + + switch(size) + { + case 5: + fft5s(data,2); + break; + case 8: + fft8(data); + break; + case 10: + fft10(data); + break; + case 16: + fft16(data); + break; + case 20: + fft20(data); + break; + case 30: + fft30(data); + break; + + default: + assert(0); + break; + } + } diff --git a/lib_com/fft_rel.c b/lib_com/fft_rel.c new file mode 100644 index 000000000..0064a5eab --- /dev/null +++ b/lib_com/fft_rel.c @@ -0,0 +1,267 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "prot.h" +#include "rom_com.h" + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ + +#define N_MAX_FFT 1024 +#define N_MAX_DIV2 (N_MAX_FFT>>1) +#define N_MAX_DIV4 (N_MAX_DIV2>>1) + +/*---------------------------------------------------------------------* + * fft_rel() + * + * 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_FFT. The table entries are defined as + * sin(2*pi*i) and cos(2*pi*i) for i = 0, 1, ..., N_MAX_FFT-1. The + * implementation assumes that any entry will not be needed + * outside the tables. Therefore, N_MAX_FFT and n must be properly + * set. The function has been tested with the values n = 16, + * 32, 64, 128, 256, and N_MAX_FFT = 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]. + *---------------------------------------------------------------------*/ + +void fft_rel( + float x[], /* i/o: input/output vector */ + const short n, /* i : vector length */ + const short m /* i : log2 of vector length */ +) +{ + short i, j, k, n1, n2, n4; + short step; + float xt, t1, t2; + float *x0, *x1, *x2; + float *xi2, *xi3, *xi4, *xi1; + const float *s, *c; + const short *idx; + + /* !!!! NMAX = 256 is hardcoded here (similar optimizations should be done for NMAX > 256) !!! */ + + float *x2even, *x2odd; + float temp[512]; + + if ( n == 128 || n == 256 || n == 512 ) + { + idx = fft256_read_indexes; + + /* Combined Digit reverse counter & Length two butterflies */ + if (n == 128) + { + x2 = temp; + for (i = 0; i < 64; i++) + { + j = *idx++; + k = *idx++; + + *x2++ = x[j>>1] + x[k>>1]; + *x2++ = x[j>>1] - x[k>>1]; + } + } + else if (n == 256) + { + x2 = temp; + for (i = 0; i < 128; i++) + { + j = *idx++; + k = *idx++; + + *x2++ = x[j] + x[k]; + *x2++ = x[j] - x[k]; + } + } + else if (n == 512) + { + x2even = temp; + x2odd = temp + 256; + + for (i = 0; i < 128; i++) + { + j = 2 * *idx++; + k = 2 * *idx++; + + *x2even++ = x[j] + x[k]; + *x2even++ = x[j] - x[k]; + *x2odd++ = x[++j] + x[++k]; + *x2odd++ = x[j] - x[k]; + } + } + + /*-----------------------------------------------------------------* + * 1st Stage Loop has been Unrolled because n4 is '1' and that + * allows the elimination of the 'for_ (j = 1; j < n4; j++)' loop + * and the associated pointers initialization. + * Also, it allows to Put the Data from 'temp' back into 'x' due + * to the previous Combined Digit Reverse and Length two butterflies + *-----------------------------------------------------------------*/ + + /*for_ (k = 2; k < 3; k++)*/ + { + x0 = temp; + x1 = x0 + 2; + x2 = x; + + for (i = 0; i < n; i += 4) + { + *x2++ = *x0++ + *x1; /* x[i] = xt + x[i+n2]; */ + *x2++ = *x0; + *x2++ = *--x0 - *x1++; /* x[i+n2] = xt - x[i+n2]; */ + *x2++ = -*x1; /* x[i+n2+n4] = -x[i+n2+n4]; */ + + x0 += 4; + x1 += 3; /* x1 has already advanced */ + } + } + } + else + { + /*-----------------------------------------------------------------* + * Digit reverse counter + *-----------------------------------------------------------------*/ + + j = 0; + x0 = &x[0]; + for (i = 0; i < n-1; i++) + { + if (i < j) + { + xt = x[j]; + x[j] = *x0; + *x0 = xt; + } + x0++; + k = n/2; + while (k <= j) + { + j -= k; + k = k>>1; + } + j += k; + } + + /*-----------------------------------------------------------------* + * Length two butterflies + *-----------------------------------------------------------------*/ + + x0 = &x[0]; + x1 = &x[1]; + for (i = 0; i < n/2; i++) + { + *x1 = *x0 - *x1; + *x0 = *x0*2 - *x1; + + x0++; + x0++; + x1++; + x1++; + } + + /*-----------------------------------------------------------------* + * 1st Stage Loop has been Unrolled because n4 is '1' and that + * allows the elimination of the 'for_ (j = 1; j < n4; j++)' loop + * and the associated pointers initialization. + *-----------------------------------------------------------------*/ + + /* for_ (k = 2; k < 3; k++) */ + { + x0 = x; + x1 = x0 + 2; + + for (i = 0; i < n; i += 4) + { + *x1 = *x0 - *x1; /* x[i+n2] = xt - x[i+n2]; */ + *x0 = *x0*2 - *x1++; /* x[i] = xt + x[i+n2]; */ + *x1 = -*x1; /* x[i+n2+n4] = -x[i+n2+n4]; */ + + x0 += 4; + x1 += 3; /* x1 has already advanced */ + } + } + } + + /*-----------------------------------------------------------------* + * 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_FFT must be set properly. + *-----------------------------------------------------------------*/ + + n4 = 1; + n2 = 2; + n1 = 4; + + step = N_MAX_DIV4; + + for (k = 3; k <= m; k++) + { + step >>= 1; + n4 <<= 1; + n2 <<= 1; + n1 <<= 1; + + x0 = x; + x1 = x0 + n2; + x2 = x1 + n4; + + for (i = 0; i < n; i += n1) + { + *x1 = *x0 - *x1; /* x[i+n2] = xt - x[i+n2]; */ + *x0 = *x0*2 - *x1; /* x[i] = xt + x[i+n2]; */ + *x2 = -*x2; /* x[i+n2+n4] = -x[i+n2+n4]; */ + + s = sincos_t_ext; + c = s + N_MAX_FFT/4; /* 1024/4 = 256, 256/4=64 */ + xi1 = x0; + xi3 = xi1 + n2; + xi2 = xi3; + x0 += n1; + xi4 = x0; + + for (j = 1; j < n4; j++) + { + xi3++; + xi1++; + xi4--; + xi2--; + c += step; + s+= step; /* autoincrement by ar0 */ + + t1 = *xi3**c + *xi4**s; /* t1 = *xi3**(pt_c+ind) + *xi4**(pt_s+ind); */ + t2 = *xi3**s - *xi4**c; /* t2 = *xi3**(pt_s+ind) - *xi4**(pt_c+ind); */ + + *xi4 = *xi2 - t2; + *xi2 = *xi1 - t1; + *xi1 = *xi1*2 - *xi2; + *xi3 = -2*t2 - *xi4; + } + + x1 += n1; + x2 += n1; + } + } + + return; +} diff --git a/lib_com/fill_spectrum.c b/lib_com/fill_spectrum.c new file mode 100644 index 000000000..1229cee0d --- /dev/null +++ b/lib_com/fill_spectrum.c @@ -0,0 +1,237 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*--------------------------------------------------------------------------* + * fill_spectrum() + * + * Apply spectral filling by + * - filling zero-bit bands below BWE region + * - applying BWE above transition frequency + *--------------------------------------------------------------------------*/ + +void fill_spectrum( + float *coeff, /* i/o: normalized MLT spectrum / nf spectrum */ + short *R, /* i : number of pulses per band */ + const short is_transient, /* i : transient flag */ + short norm[], /* i : quantization indices for norms */ + const float *hq_generic_fenv, /* i : HQ GENERIC envelope */ + const short hq_generic_offset, /* i : HQ GENERIC offset */ + const short nf_idx, /* i : noise fill index */ + const short length, /* i : Length of spectrum (32 or 48 kHz) */ + const float env_stab, /* i : Envelope stability measure [0..1] */ + short *no_att_hangover, /* i/o: Frame counter for attenuation hangover */ + float *energy_lt, /* i/o: Long-term energy measure for transient detection */ + short *bwe_seed, /* i/o: random seed for generating BWE input */ + const short hq_generic_exc_clas, /* i : HQ generic hf excitation class */ + const short core_sfm, /* i : index of the end band for core */ + short HQ_mode, /* i : HQ mode */ + float noise_level[], /* i : noise levels for harmonic modes */ + long core_brate, /* i : target bit-rate */ + float prev_noise_level[], /* i/o: noise factor in previous frame */ + short *prev_R, /* i/o: bit allocation info. in previous frame */ + float *prev_coeff_out, /* i/o: decoded spectrum in previous frame */ + const short *peak_idx, /* i : HVQ peak indices */ + const short Npeaks, /* i : Number of HVQ peaks */ + const short *npulses, /* i : Number of assigned pulses per band */ + short prev_is_transient, /* i : previous transient flag */ + float *prev_normq, /* i : previous norms */ + float *prev_env, /* i : previous noise envelopes */ + short prev_bfi, /* i : previous bad frame indicator */ + const short *sfmsize, /* i : Length of bands */ + const short *sfm_start, /* i : Start of bands */ + const short *sfm_end, /* i : End of bands */ + short *prev_L_swb_norm, /* i/o: last normalize length for harmonic mode */ + short prev_hq_mode, /* i : previous HQ mode */ + const short num_sfm, /* i : Number of bands */ + const short num_env_bands /* i : Number of envelope bands */ +) +{ + float CodeBook[FREQ_LENGTH]; + short cb_size = 0; + short last_sfm; + float CodeBook_mod[FREQ_LENGTH]; + float norm_adj[NB_SFM]; + short high_sfm = 23; + short flag_32K_env_hangover; + short bin_th = 0; + short peak_pos[L_HARMONIC_EXC]; + short bwe_peaks[L_FRAME48k]; + float normq_v[NB_SFM]; + float coeff_fine[L_FRAME48k]; + float coeff_out[L_FRAME48k]; + + set_s( peak_pos, 0, L_HARMONIC_EXC ); + set_s( bwe_peaks, 0, L_FRAME48k ); + set_f( norm_adj, 1.0f, num_sfm ); + set_f( coeff_out, 0.0f, L_FRAME48k ); + + if ( HQ_mode == HQ_TRANSIENT ) + { + last_sfm = num_sfm-1; + } + else if (HQ_mode == HQ_GEN_SWB || HQ_mode == HQ_GEN_FB) + { + last_sfm = max(core_sfm,num_env_bands-1); + } + else + { + last_sfm = core_sfm; + } + + if ( HQ_mode == HQ_HARMONIC ) + { + high_sfm = (core_brate == HQ_24k40) ? HVQ_THRES_SFM_24k-1 : HVQ_THRES_SFM_32k-1; + if( last_sfm < high_sfm ) + { + last_sfm = high_sfm; + } + } + else if ( HQ_mode == HQ_HVQ ) + { + bin_th = sfm_end[last_sfm]; + } + + /* Transient analysis for envelope stability measure */ + if( length == L_FRAME32k ) + { + env_stab_transient_detect( is_transient, length, norm, no_att_hangover, energy_lt, HQ_mode, bin_th, coeff ); + } + + if ( length == L_FRAME16k || ((length == L_FRAME32k && HQ_mode != HQ_HARMONIC && HQ_mode != HQ_HVQ) && *no_att_hangover == 0) ) + { + /* Norm adjustment function */ + env_adj( 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 ) ); + + /*----------------------------------------------------------------* + * Build noise-fill codebook + *----------------------------------------------------------------*/ + + if ( HQ_mode != HQ_HVQ ) + { + cb_size = build_nf_codebook( flag_32K_env_hangover, coeff, sfm_start, sfmsize, sfm_end, last_sfm, R, CodeBook, CodeBook_mod ); + } + + /*----------------------------------------------------------------* + * Prepare fine structure for Harmonic and HVQ + *----------------------------------------------------------------*/ + + if ( HQ_mode == HQ_HARMONIC ) + { + harm_bwe_fine( R, last_sfm, high_sfm, num_sfm, norm, sfm_start, sfm_end, prev_L_swb_norm, coeff, coeff_out, coeff_fine ); + } + else if ( HQ_mode == HQ_HVQ ) + { + hvq_bwe_fine( last_sfm, num_sfm, sfm_end, peak_idx, Npeaks, peak_pos, prev_L_swb_norm, coeff, bwe_peaks, coeff_fine ); + } + + /*----------------------------------------------------------------* + * Apply noise-fill + *----------------------------------------------------------------*/ + + if( HQ_mode != HQ_HVQ && cb_size > 0 ) + { + apply_noisefill_HQ( R, length, flag_32K_env_hangover, 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( last_sfm, sfm_end, num_sfm, coeff ); + } + + /*----------------------------------------------------------------* + * Apply noise-fill adjustment + *----------------------------------------------------------------*/ + + if( (length >= L_FRAME32k || core_brate > HQ_32k || core_brate < HQ_24k40) && HQ_mode != HQ_HVQ ) + { + apply_nf_gain( nf_idx, last_sfm, R, sfm_start, sfm_end, coeff ); + } + + /*----------------------------------------------------------------* + * Prepare fine strucutre for HQ GENERIC + *----------------------------------------------------------------*/ + if ( HQ_mode == HQ_GEN_SWB || HQ_mode == HQ_GEN_FB ) + { + hq_generic_fine( coeff, last_sfm, sfm_start, sfm_end, bwe_seed, coeff_fine ); + } + + /*----------------------------------------------------------------* + * Apply envelope + *----------------------------------------------------------------*/ + + if ( HQ_mode != HQ_HARMONIC && HQ_mode != HQ_HVQ ) + { + apply_envelope( coeff, norm, norm_adj, num_sfm, last_sfm, HQ_mode, length, sfm_start, sfm_end, normq_v, coeff_out, coeff_fine ); + } + + /*----------------------------------------------------------------* + * Harmonic BWE, HVQ BWE and HQ SWB BWE + *----------------------------------------------------------------*/ + + if( HQ_mode == HQ_HARMONIC ) + { + harm_bwe( coeff_fine, coeff, num_sfm, sfm_start, sfm_end, last_sfm, high_sfm, R, prev_hq_mode, norm, noise_level, prev_noise_level, bwe_seed, coeff_out ); + } + else if ( HQ_mode == HQ_HVQ ) + { + hvq_bwe( coeff, coeff_fine, sfm_start, sfm_end, sfmsize, last_sfm, + prev_hq_mode, bwe_peaks, bin_th, num_sfm, core_brate, R, norm, + noise_level, prev_noise_level, bwe_seed, coeff_out ); + } + else if ( HQ_mode == HQ_GEN_SWB || HQ_mode == HQ_GEN_FB ) + { + hq_generic_bwe( HQ_mode, coeff_fine, hq_generic_fenv, 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 + *----------------------------------------------------------------*/ + + if( length == L_FRAME16k && core_brate == HQ_32k ) + { + hq_wb_nf_bwe( coeff, is_transient, prev_bfi, 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, coeff_out ); + } + + /*----------------------------------------------------------------* + * Update memories + *----------------------------------------------------------------*/ + + if ( HQ_mode != HQ_HARMONIC && HQ_mode != HQ_HVQ ) + { + prev_noise_level[0] = 0.1f; + prev_noise_level[1] = 0.1f; + } + if ( !(length == L_FRAME16k && core_brate == HQ_32k ) ) + { + set_f( prev_env, 0, SFM_N_WB ); + set_f( prev_normq, 0, SFM_N_WB ); + } + + if ( length == L_FRAME32k && core_brate <= HQ_32k ) + { + *prev_R = R[SFM_N_WB-1]; + mvr2r( coeff_out + L_FRAME16k - L_HQ_WB_BWE, prev_coeff_out, L_HQ_WB_BWE ); + } + + mvr2r( coeff_out, coeff, L_FRAME48k ); + + return; +} diff --git a/lib_com/findpulse.c b/lib_com/findpulse.c new file mode 100644 index 000000000..fc04b8b44 --- /dev/null +++ b/lib_com/findpulse.c @@ -0,0 +1,107 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "prot.h" +#include "cnst.h" + + +/*----------------------------------------------------------------------------------* + * findpulse() + * + * Find first pitch pulse in a frame + *----------------------------------------------------------------------------------*/ + +short findpulse( /* o : pulse position */ + const short L_frame, /* i : length of the frame */ + const float res[], /* i : residual signal */ + const short T0, /* i : integer pitch */ + const short enc_dec, /* i : flag enc/dec, 0 - enc, 1 - dec */ + short *sign /* i/o: sign of the maximum */ +) +{ + const float *ptr; + float val, maxval; + short i, maxi; + float resf[L_FRAME16k]; /* Low pass filtered residual */ + + if ( enc_dec == ENC ) + { + /*-----------------------------------------------------------------* + * Very simple LP filter + *-----------------------------------------------------------------*/ + + resf[0] = 0.50f * res[0] + 0.25f * res[1]; + for (i=1; imaxval) + { + maxval = val; + maxi = i; + if(*ptr >= 0) + { + *sign = 0; + } + else + { + *sign = 1; + } + } + ptr--; + } + } + else + { + /*-----------------------------------------------------------------* + * Find "biggest" pulse in the last pitch section according to the sign + *-----------------------------------------------------------------*/ + + ptr = res; + maxval = 0; + maxi = 0; + + if( *sign == 0 ) + { + for (i=1; i<=T0; i++) + { + val = *ptr++; + if ( val >= maxval ) + { + maxval = val; + maxi = i; + } + } + } + else + { + for (i=1; i<=T0; i++) + { + val = *ptr++; + if (val<=maxval) + { + maxval = val; + maxi = i; + } + } + } + } + + return(maxi); +} diff --git a/lib_com/fine_gain_bits.c b/lib_com/fine_gain_bits.c new file mode 100644 index 000000000..cc386852e --- /dev/null +++ b/lib_com/fine_gain_bits.c @@ -0,0 +1,101 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "rom_com.h" +#include "prot.h" + + +/*-------------------------------------------------------------------------- + * subband_gain_bits() + * + * HQ core encoder + *--------------------------------------------------------------------------*/ + +void subband_gain_bits( + const short *Rk, /* i : bit allocation per band (Q3)*/ + const short N, /* i : number of bands */ + short *bits, /* o : gain bits per band */ + const short *sfmsize /* i : Size of bands */ +) +{ + short i,b,tot; + short bps; + + tot = 0; + + for ( i = 0; i < N; i++ ) + { + bps = (short)(((int) Rk[i]*(int)fg_inv_tbl_fx[sfmsize[i]>>3])>>18) ; + if (((sfmsize[i]*(bps+1)) << 3) - Rk[i] == 0) + { + /* correct approx. division result, to obtain exact integer division output */ + bps++; + } + bps = min(7, bps); + + + + b = fine_gain_bits[bps]; + + bits[i] = b; + tot += b; + } + + if ( tot == 0) + { + /* If no gain bits were assigned, use one bit anyway for potential PVQ overage */ + bits[0] = 1; + } + + return; +} + +/*--------------------------------------------------------------------------* + * assign_gain_bits() + * + * Assign gain adjustment bits and update bit budget + *--------------------------------------------------------------------------*/ + +short assign_gain_bits( /* o : Number of assigned gain bits */ + const short core, /* i : HQ core */ + const short BANDS, /* i : Number of bands */ + const short *band_width, /* i : Sub band bandwidth */ + short *Rk, /* i/o: Bit allocation/Adjusted bit alloc. (Q3)*/ + short *gain_bits_array, /* o : Assigned gain bits */ + short *Rcalc /* o : Bit budget for shape quantizer (Q3)*/ +) +{ + short subband_cnt; + short gain_bits_tot; + short i; + + /* Allocate gain bits for every subband used, based on bit rate and bandwidth */ + if( core == HQ_CORE ) + { + subband_gain_bits(Rk, BANDS, gain_bits_array, band_width); + } + else + { + set_s( gain_bits_array, 0, BANDS ); + } + + /* Re-adjust bit budget for gain quantization */ + subband_cnt = 0; + gain_bits_tot = 0; + *Rcalc = 0.0f; + for (i = 0; i < BANDS; i++) + { + if (Rk[i] > 0) + { + subband_cnt++; + Rk[i] -= gain_bits_array[i] * 8; + gain_bits_tot += gain_bits_array[i]; + *Rcalc += Rk[i]; + } + } + + return gain_bits_tot; +} diff --git a/lib_com/frame_ener.c b/lib_com/frame_ener.c new file mode 100644 index 000000000..b16a8f36c --- /dev/null +++ b/lib_com/frame_ener.c @@ -0,0 +1,97 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" + + +/*----------------------------------------------------------------------------------* +* fer_energy() +* +* Estimation of pitch-synchronous (voiced sounds) or half-frame energy +*----------------------------------------------------------------------------------*/ + +void fer_energy( + const int L_frame, /* i : frame length */ + const short clas, /* i : frame classification */ + const float *synth, /* i : synthesized speech at Fs = 12k8 Hz */ + const float pitch, /* i : pitch period */ + float *enr, /* o : pitch-synchronous or half_frame energy */ + const short offset /* i : speech pointer offset (0 or L_frame) */ +) +{ + short len; + const float *pt_synth; + + if( clas == VOICED_CLAS || clas == ONSET || clas == SIN_ONSET ) /* Voiced or Onset current frame */ + { + len = (short)( pitch + 0.5f ); /* pitch value */ + + pt_synth = synth; + if( offset != 0 ) + { + pt_synth = synth + L_frame - len; + } + + emaximum( pt_synth, len, enr ); /* pitch synchronous E */ + } + else + { + pt_synth = synth; + if( offset != 0 ) + { + pt_synth = synth + L_frame/2; + } + + *enr = dotp( pt_synth, pt_synth, L_frame/2 ); + *enr /= (float)(L_frame/2); + + } + return; +} + + +/*------------------------------------------------------------------------* + * frame_energy() + * + * Compute pitch-synchronous energy at the frame end + *------------------------------------------------------------------------*/ + +float frame_energy( + const short L_frame, /* i: length of the frame */ + const float *pitch, /* i: pitch values for each subframe */ + const float *speech, /* i: pointer to speech signal for E computation */ + const float lp_speech, /* i: long-term active speech energy average */ + float *frame_ener /* o: pitch-synchronous energy at frame end */ +) +{ + float enern; + const float *pt1; + short len; + float dotProd; + + len = (short)( 0.5f * (pitch[2] + pitch[3]) + 0.5f ); + if( len < L_SUBFR ) + { + len *= 2; + } + + pt1 = speech + L_frame - len; + + dotProd = dotp( pt1, pt1, len ); + if ( 0 == dotProd ) + { + *frame_ener = MIN_LOG_VAL_60dB; + } + else + { + *frame_ener = 10.0f * (float) log10( dotProd / (float) len ); + } + enern = *frame_ener - lp_speech; + + return enern; +} diff --git a/lib_com/g192.c b/lib_com/g192.c new file mode 100644 index 000000000..daa4db498 --- /dev/null +++ b/lib_com/g192.c @@ -0,0 +1,255 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include +#include "options.h" +#include "g192.h" + +#define WMC_TOOL_SKIP + +#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 "wmc_auto.h" /* Note that wmc_auto.h must be included after Winsock2.h because MAC() is defined in rpcerr.hand redefined within wmc_auto.h */ + + +#ifdef _MSC_VER +#pragma warning( disable : 4996 ) +#endif + +#define G192_SYNC_GOOD_FRAME (unsigned short) 0x6B21 +#define G192_SYNC_BAD_FRAME (unsigned short) 0x6B20 +#define G192_BIT0 (unsigned short) 0x007F +#define G192_BIT1 (unsigned short) 0x0081 +#define RTP_HEADER_PART1 (short)22 /* magic number by network simulator */ + +#ifndef MAX_BITS_PER_FRAME +#define MAX_BITS_PER_FRAME 2560 +#endif + +/* + * 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, + short * const num_bits, + unsigned short * const rtpSequenceNumber, + unsigned int * const rtpTimeStamp, + unsigned int * const rcvTime_ms) +{ + short short_serial [MAX_BITS_PER_FRAME]; + G192_ERROR err; + short 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, + short * const serial, + short * const num_bits, + unsigned short * const rtpSequenceNumber, + unsigned int * const rtpTimeStamp, + unsigned int * const rcvTime_ms) +{ + uint32_t rtpPacketSize; + uint16_t rtpPacketHeaderPart1; + uint32_t ssrc; + uint16_t rtpPayloadG192[2]; + uint16_t 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: %ud\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 = rtpPacketSize - 12; + if(rtpPayloadSize <= 2) + { + fprintf(stderr, "RTP payload size too small: %u\n", rtpPayloadSize); + return G192_INVALID_DATA; + } + + /* RTP payload */ + if(fread(rtpPayloadG192, sizeof(short), 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 == 0u || *num_bits + 2u != 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( fread(serial, sizeof(short), *num_bits, hG192->file) != (unsigned short)*num_bits) + { + 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 000000000..fc8cae656 --- /dev/null +++ b/lib_com/g192.h @@ -0,0 +1,66 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#ifndef G192_H +#define G192_H + +#include + +/* + * 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, + short * const num_bits, + unsigned short * const rtpSequenceNumber, + unsigned int * const rtpTimeStamp, + unsigned int * const rcvTime_ms); + +G192_ERROR +G192_ReadVoipFrame_short(G192_HANDLE const hG192, + short * const serial, + short * const num_bits, + unsigned short * const rtpSequenceNumber, + unsigned int * const rtpTimeStamp, + unsigned int * const rcvTime_ms); + +G192_ERROR +G192_Reader_Close(G192_HANDLE* phG192); + +#endif /* G192_H */ diff --git a/lib_com/get_gain.c b/lib_com/get_gain.c new file mode 100644 index 000000000..07f129362 --- /dev/null +++ b/lib_com/get_gain.c @@ -0,0 +1,38 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "prot.h" + + +/*----------------------------------------------------------------------------------* +* get_gain() +* +* +*----------------------------------------------------------------------------------*/ + +float get_gain( /* output: codebook gain (adaptive or fixed) */ + float x[], /* input : target signal */ + float y[], /* input : filtered codebook excitation */ + int n, /* input : segment length */ + float *en_y /* output: energy of y (sum of y[]^2, optional) */ +) +{ + float corr = 0.0f, ener = 1e-6f; + short i; + + for (i = 0; i < n; i++) + { + corr += x[i]*y[i]; + ener += y[i]*y[i]; + } + + if (en_y) + { + *en_y = ener; + } + + return(corr/ener); +} diff --git a/lib_com/gs_bitallocation.c b/lib_com/gs_bitallocation.c new file mode 100644 index 000000000..d2e1051fa --- /dev/null +++ b/lib_com/gs_bitallocation.c @@ -0,0 +1,452 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static float Find_bit_frac( const short nb_band, const short remaining_bits ); + +/*-------------------------------------------------------------------* + * bands_and_bit_alloc() + * + * AC mode (GSC) bands and bits allocation + *-------------------------------------------------------------------*/ + +void bands_and_bit_alloc( + const short cor_strong_limit, /* i : HF correlation */ + const short noise_lev, /* i : dwn scaling factor */ + const long core_brate, /* i : core bit rate */ + const short Diff_len, /* i : Lenght of the difference signal (before pure spectral)*/ + const short bits_used, /* i : Number of bit used before frequency Q */ + short *bit, /* i/o: Number of bit allowed for frequency quantization */ + float *Ener_per_bd_iQ, /* i/o: Quantized energy vector */ + short *max_ener_band, /* o : Sorted order */ + short *bits_per_bands_s,/* i/o: Number of bit allowed per allowed subband (Q3) */ + short *nb_subbands, /* o : Number of subband allowed */ + const float *exc_diff, /* i : Difference signal to quantize (encoder side only) */ + float *concat_in, /* o : Concatened PVQ's input vector (encoder side only) */ + short *pvq_len, /* o : Number of bin covered with the PVQ */ + const short coder_type, /* i : coding type */ + const short bwidth, /* i : input signal bandwidth */ + const short GSC_noisy_speech /* i : GSC noisy speech flag */ +) +{ + short bandoffset, i, j, nb_bands_max, bit_new_bands, bit_tmp, st_band, nb_bands; + float bit_fracf, etmp; + float sum_bit; + float ener_vec[MBANDS_GN]; + short nb_tot_bands; + short bit_index, bit_index_mem, imax; + short pos, band; + float SWB_bit_budget; + float bits_per_bands[MBANDS_GN]; + + /* initializations */ + nb_tot_bands = 16; + set_f( bits_per_bands, 0.0f, MBANDS_GN ); + + /* To adapt current energy band to PVQ freq band for sorting*/ + ener_vec[0] = Ener_per_bd_iQ[0] + Ener_per_bd_iQ[1]; + mvr2r( Ener_per_bd_iQ + 1, ener_vec, 15 ); + ener_vec[15] = ener_vec[14]; + + for(i = 0; i < MBANDS_GN; i++) + { + ener_vec[i] = (float)((short)(ener_vec[i]*4096.f+0.5f)); + } + + /*------------------------------------------------------------------------ + * 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; + bit_new_bands = 5; + + bit_index = BRATE2IDX(core_brate)*17; + bit_index_mem = bit_index; + + if( (coder_type == AUDIO || coder_type == INACTIVE) && bwidth == NB ) + { + if(core_brate >= ACELP_9k60) + { + *bit = (short)(core_brate*(1.0f/50) + 0.5f) - bits_used - 25; + } + else + { + *bit = (short)(core_brate*(1.0f/50) + 0.5f) - bits_used - 21; + } + + nb_tot_bands = 10; + } + else + { + *bit = (short)(core_brate*(1.0f/50) + 0.5f) - bits_used - GSC_freq_bits[bit_index]; + } + + if( GSC_noisy_speech ) + { + SWB_bit_budget = *bit; + nb_bands = 5; + st_band = nb_bands; + + set_f( bits_per_bands, 0, MBANDS_GN ); + + bit_fracf = Find_bit_frac(nb_bands, SWB_bit_budget); /* Supplementary bits distributed only on first bands */ + + nb_tot_bands = nb_bands_max - 6; + + if( nb_tot_bands > 16 ) + { + nb_tot_bands = 16; + } + + for(j = 0; j < 2; j++) + { + i = j; + max_ener_band[j] = i; + ener_vec[i] = 0; + } + + for(; j < nb_bands; j++) + { + i = maximum(ener_vec, nb_tot_bands, &etmp); + max_ener_band[j] = i; + ener_vec[i] = 0; + } + + set_f( bits_per_bands, bit_fracf, nb_bands ); + } + else + { + bit_index++; + bit_tmp = *bit - GSC_freq_bits[bit_index]; + bit_index++; + nb_bands_max += GSC_freq_bits[bit_index]; + bit_index++; + + *pvq_len = 112; + st_band = 7; + + if( core_brate <= ACELP_9k60 ) + { + *pvq_len = 80; + st_band = 5; + if( Diff_len == 0 ) + { + nb_bands_max += 2; + bit_tmp -= 13; + } + } + else if( Diff_len == 0 ) + { + nb_bands_max += 2; + bit_tmp -= 17; + } + + nb_bands = *pvq_len/16; + + /*------------------------------------------------------------------------ + * Adjustement of the maximum number of bands in function of the + * dynamics of the spectrum (more or less speech like) + *-----------------------------------------------------------------------*/ + + if( coder_type == INACTIVE || noise_lev >= NOISE_LEVEL_SP3 ) + { + /* Probably classification error -> concentrate bits on LF */ + if( core_brate >= ACELP_8k00 ) + { + nb_bands_max = nb_bands+1; + } + else + { + nb_bands_max = nb_bands; + } + } + else if( noise_lev >= NOISE_LEVEL_SP2 || + (core_brate <= ACELP_13k20 && 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 -= 2; + } + else if( noise_lev >= NOISE_LEVEL_SP1) /* Very low dynamic, tend to speech, code less HF */ + { + nb_bands_max -= 1; + } + + if( bwidth == NB && nb_bands_max > 10 ) + { + nb_bands_max = 10; + } + + /*------------------------------------------------------------------------ + * Find extra number of band to code according to bit rate availables + *-----------------------------------------------------------------------*/ + + while ( bit_tmp >= bit_new_bands && nb_bands <= nb_bands_max - 1 ) + { + bit_tmp -= bit_new_bands; + nb_bands++; + } + + /*------------------------------------------------------------------------ + * Fractional bits to distribute on the first x bands + *-----------------------------------------------------------------------*/ + + bit_fracf = Find_bit_frac(st_band, bit_tmp); /* Supplementary bits distributed only on first bands */ + + /*------------------------------------------------------------------------ + * Complete the bit allocation per frequency band + *-----------------------------------------------------------------------*/ + + imax = 5; + if( core_brate > ACELP_9k60 ) + { + imax = 7; + } + + for(i = 0; i < imax; i++) + { + bits_per_bands[i] = GSC_freq_bits[bit_index] + bit_fracf; + bit_index++; + } + + if( Diff_len == 0 ) + { + bit_index = bit_index_mem+10; + for( i = 0; i < 7; i++ ) + { + bits_per_bands[i] += GSC_freq_bits[bit_index]; + bit_index++; + } + } + + /*-------------------------------------------------------------------------- + * Complete the bit allocation per frequency band for 16kHz high brate mode + *--------------------------------------------------------------------------*/ + + for( j = st_band; j < nb_bands; j++ ) + { + bits_per_bands[j] = bit_new_bands; + } + + /*-------------------------------------------------------------------------- + * Compute a maximum band (band offset) for the search on maximal energy + * This is function of the spectral dynamic and the bitrate + *--------------------------------------------------------------------------*/ + + bandoffset = nb_tot_bands - (nb_bands + 2); + + if( noise_lev <= NOISE_LEVEL_SP1a ) + { + bandoffset--; + } + else if ( (core_brate <= ACELP_13k20 && (coder_type == INACTIVE || noise_lev >= NOISE_LEVEL_SP3)) || + (core_brate <= ACELP_13k20 && core_brate >= ACELP_9k60 && cor_strong_limit == 0) ) + { + bandoffset++; + } + + if( bandoffset < 0 ) + { + 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; + } + + for(j = 0; j < st_band; j++) + { + max_ener_band[j] = j; + ener_vec[j] = -10; + } + + pos = st_band; + for(; j < nb_bands; j++) + { + i = maximum(ener_vec, nb_tot_bands-bandoffset, &etmp); + if(i > pos) + { + pos = i; + } + max_ener_band[j] = i; + ener_vec[i] = -10; + } + + /* re-allocate bits to the frames such that the highest band with allocated bits is higher than the threshold */ + if( nb_tot_bands - bandoffset > nb_bands && ( pos > 7 && core_brate == ACELP_8k00 ) && bwidth == WB ) + { + band = nb_tot_bands-bandoffset-nb_bands; + for( j=0; j 0 ) + { + bits_per_bands[j] -= 1; + + if ( j == st_band - 1 - i ) + { + j = 0; + } + else + { + ++j; + } + + if( j == 0 && i < st_band - 1) + { + i++; + } + + bit_tmp -= 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; + j = 0; + for( i = 0; i < nb_bands; i++ ) + { + if( bits_per_bands[i] > 112 ) + { + sum_bit += bits_per_bands[i] - 112; + bits_per_bands[i] = 112; + j = i+1; + } + + /* safety check for overage bit reallocation */ + else if( bits_per_bands[i] + sum_bit/3 > 112 ) + { + j = i+1; + } + } + + if( sum_bit != 0 ) + { + sum_bit /= (nb_bands - j); + for( i = j; i < nb_bands; i++ ) + { + bits_per_bands[i] += sum_bit; + } + } + } + + /*-------------------------------------------------------------------------- + * second step of bit sum verification, normally sum_bit == *bit + *--------------------------------------------------------------------------*/ + + sum_bit = 0.00f; + for( i = 0; i < nb_bands; i++ ) + { + bits_per_bands[i] = (float)floor(bits_per_bands[i]); + sum_bit += bits_per_bands[i]; + } + + if( *bit > sum_bit ) + { + i = nb_bands-1; + while(*bit > sum_bit) + { + bits_per_bands[i]++; + sum_bit++; + i--; + if(i==0) + { + i = nb_bands-1; + } + } + } + + /*-------------------------------------------------------------------------- + * Recompute the real number/length of frequency bands to encode + *--------------------------------------------------------------------------*/ + + *nb_subbands = nb_bands; + *pvq_len = *nb_subbands*16; + + /*-------------------------------------------------------------------------- + * Concatenate bands (encoder only) + *--------------------------------------------------------------------------*/ + + if( exc_diff != NULL ) + { + for( j = 0; j < nb_bands; j++ ) + { + mvr2r( exc_diff + max_ener_band[j]*16, concat_in+j*16, 16 ); + } + } + for( j = 0; j < nb_bands; j++ ) + { + bits_per_bands_s[j] = ((short)bits_per_bands[j]) << 3; + } + + return; +} + + +/*-------------------------------------------------------------------* + * Find_bit_frac() + * + * Computes the fraction of the remaining bit budget to allocate to the bands + *-------------------------------------------------------------------*/ + +static float Find_bit_frac( + const short nb_band, + const short remaining_bits +) +{ + float var_out; + short inv_bandQ15; + int L_num; + + inv_bandQ15 = 6553; + if (nb_band == 7) + { + inv_bandQ15 = 4681; + } + L_num = inv_bandQ15*remaining_bits; + L_num *= 8; + var_out = L_num/262144.0f; + + return (var_out); +} diff --git a/lib_com/gs_gains.c b/lib_com/gs_gains.c new file mode 100644 index 000000000..076ea8478 --- /dev/null +++ b/lib_com/gs_gains.c @@ -0,0 +1,572 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static short VDQ_vec( float *Qvec_out, const float *mean_dic, const float *dic, + const short index, const short vec_en ); + +/*-------------------------------------------------------------------* + * Comp_and_apply_gain() + * + * Compute and apply the quantized per band gain + *-------------------------------------------------------------------*/ + +void Comp_and_apply_gain( + float exc_diffQ[], /* i/o: Quantized excitation */ + float Ener_per_bd_iQ[], /* o : Target ener per band */ + float Ener_per_bd_yQ[], /* o : Ener per band for norm vector */ + short Mbands_gn, /* i : number of bands */ + const short ReUseGain /* i : Reuse the gain in Ener_per_bd_yQ */ +) +{ + short i, i_band; + short StartBin, NB_Qbins; + float y_gain; + + /* Recreate excitation for local synthesis and decoder */ + StartBin = 0; + NB_Qbins = 0; + for( i_band = 0; i_band < Mbands_gn; i_band++ ) + { + StartBin += NB_Qbins; + NB_Qbins = mfreq_bindiv_loc[i_band]; + if( ReUseGain == 1 ) + { + y_gain = Ener_per_bd_yQ[i_band]; + } + else + { + y_gain = (float)pow(10, (Ener_per_bd_iQ[i_band]-Ener_per_bd_yQ[i_band])); + Ener_per_bd_yQ[i_band] = y_gain; + } + + for(i = StartBin ; i < NB_Qbins + StartBin ; i++) + { + exc_diffQ[i] *= y_gain; + } + } + + return; +} + +/*------------------------------------------------------------------* + * Ener_per_band_comp() + * + * Compute the energy per band in log domain for quantization purposes + * Loops are decomposed to accomodate the PVQ quantization + *------------------------------------------------------------------*/ + +void Ener_per_band_comp( + const float exc_diff[], /* i : target signal */ + float y_gain4[], /* o : Energy per band to quantize */ + const short Mband, /* i : Max band */ + const short Eflag /* i : flag of highest band */ +) +{ + float etmp; + const float *pt; + short i,j; + + pt = exc_diff; + for(j = 0; j < 2; j++) + { + y_gain4[j] = 0; + etmp = 0.02f; + + pt = exc_diff + j*8; + for(i = 0; i < 8; i++) + { + etmp += (*pt **pt); + pt++; + } + + /* normalized to 16 bins to easy the quantization */ + y_gain4[j] = (float)log10(sqrt(2*etmp)); + } + + for(j = 1; j < Mband-2; j++) + { + etmp = 0.01f; + + pt = exc_diff + j*16; + for(i = 0; i < 16; i++) + { + etmp += (*pt **pt); + pt++; + } + + y_gain4[j+1] = (float)log10(sqrt(etmp)); + } + + if( Eflag == 1 ) + { + etmp = 0.01f; + + pt = exc_diff + j*16; + for(i = 0; i < 32; i++) + { + etmp += (*pt **pt); + pt++; + } + + y_gain4[j+1] = (float)log10(sqrt(etmp/2)); + } + + return; +} + +/*-------------------------------------------------------------------* + * gsc_gainQ() + * + * Quantization of the energy per band + *-------------------------------------------------------------------*/ + +float gsc_gainQ( + Encoder_State *st, /* i/o: encoder state structure */ + const float y_gain4[], /* i : Energy per band */ + float y_gainQ[], /* o : quantized energy per band */ + const long core_brate, /* i : Core rate */ + const short coder_type, /* i : coding type */ + const short bwidth /* i : input signal bandwidth */ +) +{ + float y_gain_tmp[MBANDS_GN], y_gain_tmp2[MBANDS_GN]; + short i, idx_g = 0; + float mean_4g[1], ftmp1; + float Gain_off = 0.0f; + short Mbands_gn = MBANDS_GN; + float y_gain_tmp3[MBANDS_GN]; + + mean_4g[0] = 0; + + if( (coder_type == AUDIO || coder_type == INACTIVE) && bwidth == NB ) + { + ftmp1 = mean(y_gain4, 10) - 0.6f; + for(i = 0; i < Mbands_gn; i++) + { + if(y_gain4[i] < ftmp1) + { + y_gain_tmp2[i] = ftmp1; + } + else + { + y_gain_tmp2[i] = y_gain4[i]; + } + } + + /* Quantized mean gain without clipping */ + mean_4g[0] = mean(y_gain_tmp2, 10); + idx_g = (short)vquant(mean_4g, Gain_meanNB, mean_4g, Gain_mean_dicNB, 1, 64); + push_indice( st, IND_MEAN_GAIN2, idx_g, 6 ); + + for(i = 0; i < Mbands_gn; i++) + { + y_gain_tmp[i] = y_gain_tmp2[i] - mean_4g[0]; + } + + if( y_gain_tmp[9] < -0.3f ) + { + y_gain_tmp[9] = -0.3f; + } + + set_f(y_gain_tmp+10, 0.0f, MBANDS_GN-10); + idx_g = (short)vquant(y_gain_tmp, Mean_dic_NB, y_gain_tmp, Gain_dic1_NB, 3, 64); + push_indice( st, IND_Y_GAIN_TMP, idx_g, 6 ); + + if(core_brate < ACELP_9k60) + { + idx_g = (short)vquant(y_gain_tmp+3, Mean_dic_NB+3, y_gain_tmp+3, Gain_dic2_NB, 3, 32); + push_indice( st, IND_Y_GAIN_TMP, idx_g, 5 ); + + idx_g = (short)vquant(y_gain_tmp+6, Mean_dic_NB+6, y_gain_tmp+6, Gain_dic3_NB, 4, 16); + push_indice( st, IND_Y_GAIN_TMP, idx_g, 4 ); + } + else + { + idx_g = (short)vquant(y_gain_tmp+3, Mean_dic_NB+3, y_gain_tmp+3, Gain_dic2_NBHR, 3, 64); + push_indice( st, IND_Y_GAIN_TMP, idx_g, 6 ); + + idx_g = (short)vquant(y_gain_tmp+6, Mean_dic_NB+6, y_gain_tmp+6, Gain_dic3_NBHR, 4, 128); + push_indice( st, IND_Y_GAIN_TMP, idx_g, 7 ); + } + + if( core_brate <= ACELP_9k60 && 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] = mean(y_gain_tmp+6, 3); + y_gain_tmp[11] = mean(y_gain_tmp+7, 3); + y_gain_tmp[12] = mean(y_gain_tmp+8, 3); + y_gain_tmp[13] = mean(y_gain_tmp+9, 3); + y_gain_tmp[14] = mean(y_gain_tmp+10, 3); + y_gain_tmp[15] = mean(y_gain_tmp+11, 3); + } + else + { + set_f( y_gain_tmp + 10, 0, MBANDS_GN - 10 ); + } + } + else + { + ftmp1 = mean(y_gain4, 16); + for(i = 0; i < Mbands_gn; i++) + { + if(y_gain4[i] < ftmp1-0.6f) + { + y_gain_tmp2[i] = ftmp1-.6f; + } + else if(y_gain4[i] > ftmp1+0.6f) + { + y_gain_tmp2[i] = ftmp1+0.6f; + } + else + { + y_gain_tmp2[i] = y_gain4[i]; + } + } + + mean_4g[0] = mean(y_gain_tmp2, 16); + idx_g = (short)vquant(mean_4g, mean_m, mean_4g, mean_gain_dic, 1, 64); + push_indice( st, IND_MEAN_GAIN2, idx_g, 6 ); + + /* Subtraction of the average gain */ + for(i = 0; i < Mbands_gn; i++) + { + y_gain_tmp[i] = y_gain_tmp2[i] - mean_4g[0]; + } + + if( core_brate < ACELP_9k60 ) + { + /* prediction and quantization of the average gain */ + + /*--------------------------------------------------------------------------------------* + * Quantization of the first 8 bands + * Keep only 4 bands out of the last 8 bands + *--------------------------------------------------------------------------------------*/ + + mvr2r(y_gain_tmp, y_gain_tmp2, 8); + + y_gain_tmp2[8] = y_gain_tmp[8]; + y_gain_tmp2[9] = y_gain_tmp[10]; + y_gain_tmp2[10] = y_gain_tmp[12]; + y_gain_tmp2[11] = y_gain_tmp[14]; + + idx_g = 0; + idx_g = (short)vquant(y_gain_tmp2, YGain_mean_LR, y_gain_tmp2, YGain_dic1_LR, 3, 32); + push_indice( st, 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); + push_indice( st, IND_Y_GAIN_TMP, idx_g, 5 ); + + /*----------------------------------------------------------------------* + * Vector quantization of the first 8 bands + quantization of the 4 bands out of the last 8 + * Interpolation of the last 4 bands Q to create bands 8-16 + *----------------------------------------------------------------------*/ + + idx_g = (short)vquant(y_gain_tmp2+7, YGain_mean_LR+7, y_gain_tmp2+7, YGain_dic3_LR, 5, 32); + push_indice( st, IND_Y_GAIN_TMP, idx_g, 5 ); + + set_f(y_gain_tmp2+12, 0, MBANDS_GN-12); + + /* Update to quantized vector */ + mvr2r(y_gain_tmp2, y_gain_tmp, 8); + + mvr2r(y_gain_tmp2+8, y_gain_tmp3, 4); + set_f(y_gain_tmp+8, 0,8); + fft_rel(y_gain_tmp2+8, 4, 2); + + mvr2r(y_gain_tmp2+8, y_gain_tmp+8, 3); + y_gain_tmp[15] = y_gain_tmp2[11]; + ifft_rel(y_gain_tmp+8, 8, 3); + + for(i = 8; i < 16; i++) + { + y_gain_tmp[i] *= 1.41f; + } + + y_gain_tmp[8] = y_gain_tmp3[0]; + y_gain_tmp[10]= y_gain_tmp3[1]; + y_gain_tmp[12]= y_gain_tmp3[2]; + y_gain_tmp[14]= y_gain_tmp3[3]; + } + else + { + idx_g = (short)vquant(y_gain_tmp, YG_mean16, y_gain_tmp, YG_dicMR_1, 4, 64); + push_indice( st, IND_Y_GAIN_TMP, idx_g, 6 ); + + idx_g = (short)vquant(y_gain_tmp+4, YG_mean16+4, y_gain_tmp+4, YG_dicMR_2, 4, 32); + push_indice( st, IND_Y_GAIN_TMP, idx_g, 5 ); + + idx_g = (short)vquant(y_gain_tmp+8, YG_mean16+8, y_gain_tmp+8, YG_dicMR_3, 4, 32); + push_indice( st, IND_Y_GAIN_TMP, idx_g, 5 ); + + idx_g = (short)vquant(y_gain_tmp+12, YG_mean16+12, y_gain_tmp+12, YG_dicMR_4, 4, 16); + push_indice( st, IND_Y_GAIN_TMP, idx_g, 4 ); + } + } + + /* Gain adjustment to fit ACELP generic inactive coding gain at low rate */ + if( coder_type == INACTIVE ) + { + Gain_off = 0.0f; + { + if(core_brate <= ACELP_7k20 ) + { + Gain_off = 8.f; /* 0 dB */ + } + else if (core_brate <= ACELP_8k00 ) + { + Gain_off = 6.6f; /* ~-3.3 dB */ + } + else if (core_brate <= ACELP_9k60 ) + { + Gain_off = 4.8f; /* ~-2.4 dB */ + } + else if (core_brate <= ACELP_11k60 ) + { + Gain_off = 3.5f; /* ~-2.4 dB */ + } + else if (core_brate <= ACELP_13k20 ) + { + Gain_off = 3.0f; /* ~-2.4 dB */ + } + } + + } + + if( coder_type != INACTIVE ) + { + for( i = 0; i < Mbands_gn; i++ ) + { + y_gainQ[i] = y_gain_tmp[i] + mean_4g[0]; + } + } + else + { + /*mimic ACELP decay of energy for low rates*/ + for( i = 0; i < Mbands_gn; i++ ) + { + y_gainQ[i] = y_gain_tmp[i]+mean_4g[0]-(i*(Gain_off/20.f)/((float) Mbands_gn)); + } + } + + return mean_4g[0]; +} + +/*-------------------------------------------------------------------* + * gsc_gaindec() + * + * Generic signal frequency band decoding and application + *-------------------------------------------------------------------*/ + +float gsc_gaindec( /* o : average frequency gain */ + Decoder_State *st, /* i/o: decoder state structure */ + float y_gainQ[], /* o : quantized gain per band */ + const long core_brate, /* i : core used */ + float old_y_gain[], /* i/o: AR gain quantizer for low rate */ + const short coder_type, /* i : coding type */ + const short bwidth /* i : input signal bandwidth */ +) +{ + short idx_g, i; + float mean_4g; + float Gain_off = 0.0; + short Mbands_gn = MBANDS_GN; + float y_gain_tmp3[MBANDS_GN]; + + if( (coder_type == AUDIO || coder_type == INACTIVE) && bwidth == NB ) + { + idx_g = (short) get_next_indice( st, 6 ); + VDQ_vec(&mean_4g, Gain_meanNB, Gain_mean_dicNB, idx_g, 1 ); + + idx_g = (short) get_next_indice( st, 6 ); + VDQ_vec(y_gainQ, Mean_dic_NB, Gain_dic1_NB, idx_g, 3 ); + + if(core_brate < ACELP_9k60) + { + idx_g = (short) get_next_indice( st, 5 ); + VDQ_vec(y_gainQ+3, Mean_dic_NB+3, Gain_dic2_NB, idx_g, 3 ); + + idx_g = (short) get_next_indice( st, 4 ); + VDQ_vec(y_gainQ+6, Mean_dic_NB+6, Gain_dic3_NB, idx_g, 4 ); + } + else + { + idx_g = (short) get_next_indice( st, 6 ); + VDQ_vec(y_gainQ+3, Mean_dic_NB+3, Gain_dic2_NBHR, idx_g, 3 ); + + idx_g = (short) get_next_indice( st, 7 ); + VDQ_vec(y_gainQ+6, Mean_dic_NB+6, Gain_dic3_NBHR, idx_g, 4 ); + } + + if( core_brate <= ACELP_9k60 && coder_type == INACTIVE ) + { + /* Some energy is needed in high band for stat_noise_uv_enc + to be functional in inactive speech */ + y_gainQ[10] = mean(y_gainQ+6, 3); + y_gainQ[11] = mean(y_gainQ+7, 3); + y_gainQ[12] = mean(y_gainQ+8, 3); + y_gainQ[13] = mean(y_gainQ+9, 3); + y_gainQ[14] = mean(y_gainQ+10, 3); + y_gainQ[15] = mean(y_gainQ+11, 3); + } + else + { + set_f( y_gainQ + 10, 0, MBANDS_GN-10 ); + } + } + else + { + idx_g = (short) get_next_indice( st, 6 ); + VDQ_vec(&mean_4g, mean_m, mean_gain_dic, idx_g, 1 ); + + if( core_brate < ACELP_9k60 ) + { + /*--------------------------------------------------------------------------------------* + * UQ of the first 8 bands and half of the last 8 bands + *--------------------------------------------------------------------------------------*/ + + idx_g = (short) get_next_indice( st, 5 ); + VDQ_vec(y_gainQ, YGain_mean_LR, YGain_dic1_LR, idx_g, 3 ); + + idx_g = (short) get_next_indice( st, 5 ); + VDQ_vec(y_gainQ+3, YGain_mean_LR+3, YGain_dic2_LR, idx_g, 4 ); + + /*----------------------------------------------------------------------* + * Interpolation of the last 4 Q bands to create bands 8-16 + * And scaling + *----------------------------------------------------------------------*/ + + idx_g = (short) get_next_indice( st, 5 ); + VDQ_vec(y_gainQ+7, YGain_mean_LR+7, YGain_dic3_LR, idx_g, 5 ); + + mvr2r(y_gainQ + 8, y_gain_tmp3, 4); + set_f(y_gainQ + 12, 0.0f, 4); + + fft_rel(y_gainQ + 8, 4, 2); + + y_gainQ[15] = y_gainQ[11]; + y_gainQ[11] = 0.0f; + + ifft_rel(y_gainQ + 8, 8, 3); + + for(i = 8; i < 16; i++) + { + y_gainQ[i] *= 1.41f; + } + + /*----------------------------------------------------------------------* + * Copy the true Q values in the specific bands + *----------------------------------------------------------------------*/ + + y_gainQ[8] = y_gain_tmp3[0]; + y_gainQ[10]= y_gain_tmp3[1]; + y_gainQ[12]= y_gain_tmp3[2]; + y_gainQ[14]= y_gain_tmp3[3]; + } + else + { + idx_g = (short) get_next_indice( st, 6 ); + VDQ_vec(y_gainQ, YG_mean16, YG_dicMR_1, idx_g, 4 ); + + idx_g = (short) get_next_indice( st, 5 ); + VDQ_vec(y_gainQ+4, YG_mean16+4, YG_dicMR_2, idx_g, 4 ); + + idx_g = (short) get_next_indice( st, 5 ); + VDQ_vec(y_gainQ+8, YG_mean16+8, YG_dicMR_3, idx_g, 4 ); + + idx_g = (short) get_next_indice( st, 4 ); + VDQ_vec(y_gainQ+12, YG_mean16+12, YG_dicMR_4, idx_g, 4); + } + } + + /* Gain adjustment to fit ACELP generic inactive coding gain at low rate */ + if( coder_type == INACTIVE ) + { + Gain_off = 0.0f; + { + if(core_brate <= ACELP_7k20 ) + { + Gain_off = 8.f; /* 0 dB */ + } + else if (core_brate <= ACELP_8k00 ) + { + Gain_off = 6.6f; /* ~-3.3 dB */ + } + else if (core_brate <= ACELP_9k60 ) + { + Gain_off = 4.8f; /* ~-2.4 dB */ + } + else if (core_brate <= ACELP_11k60 ) + { + Gain_off = 3.5f; /* ~-2.4 dB */ + } + else if (core_brate <= ACELP_13k20 ) + { + Gain_off = 3.0f; /* ~-2.4 dB */ + } + } + + } + + if( coder_type != INACTIVE ) + { + for( i = 0; i < Mbands_gn; i++ ) + { + old_y_gain[i] = y_gainQ[i]; + y_gainQ[i] += mean_4g; + } + } + else + { + /*mimic ACELP decay of energy for low rates*/ + for( i = 0; i < Mbands_gn; i++ ) + { + old_y_gain[i] = y_gainQ[i]; + y_gainQ[i] += mean_4g-i*(Gain_off/20.f)/((float) Mbands_gn); + } + } + + return mean_4g; +} + +/*-------------------------------------------------------------------* + * VDQ_vec() + * + * Return the dequantized vector of index + *-------------------------------------------------------------------*/ + +static short VDQ_vec( + float *Qvec_out, /* o: Quanitzed vector */ + const float *mean_dic, /* i: average codebook */ + const float *dic, /* i: codebook */ + const short index, /* i: index of codebook*/ + const short vec_en /* i: vector length */ +) +{ + short i, j; + + j = index*vec_en; + for ( i = 0; i < vec_en; i++) + { + Qvec_out[i] = dic[j++]; + } + + for(i = 0; i < vec_en; i++) + { + Qvec_out[i] += mean_dic[i]; + } + + return index; +} diff --git a/lib_com/gs_inact_switching.c b/lib_com/gs_inact_switching.c new file mode 100644 index 000000000..001898eb9 --- /dev/null +++ b/lib_com/gs_inact_switching.c @@ -0,0 +1,108 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define ALPHA0 0.5f +#define BETA0 (1.0f-ALPHA0) + +/*-------------------------------------------------------------------* + * inact_switch_ematch() + * + * Apply energy matching when swithcing to INACTIVE frame coded by the GSC technology + *-------------------------------------------------------------------*/ + +void inact_switch_ematch( + float exc2[], /* i/o: CELP/GSC excitation buffer */ + float dct_exc_tmp[], /* i : GSC excitation in DCT domain */ + float lt_ener_per_band[], /* i/o: Long term energy per band */ + const short coder_type, /* i : Coding mode */ + const short L_frame, /* i : Frame lenght */ + const long core_brate, /* i : Core bit rate */ + const short bfi /* i : frame lost indicator */ + ,const short last_core, /* i : Last core used */ + const short last_codec_mode /* i : Last codec mode */ +) +{ + float Ener_per_bd[MBANDS_GN]; + float ftmp; + float *pt_exc; + short j, i; + + + /*-------------------------------------------------------------------------- + * average energy per band + *--------------------------------------------------------------------------*/ + + if( coder_type == AUDIO && bfi == 0) + { + Ener_per_band_comp( dct_exc_tmp, Ener_per_bd, 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]; + } + } + else if( coder_type == VOICED || coder_type == GENERIC || coder_type == TRANSITION || last_core != ACELP_CORE || last_codec_mode != MODE1 ) + { + /* Find spectrum and energy per band for GC and VC frames */ + edct( exc2, dct_exc_tmp, L_frame ); + Ener_per_band_comp( dct_exc_tmp, Ener_per_bd, 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]; + } + } + else if( coder_type == INACTIVE && core_brate <= ACELP_24k40 ) + { + /* Find spectrum and energy per band for inactive frames */ + edct( exc2, dct_exc_tmp, L_frame ); + Ener_per_band_comp( dct_exc_tmp, Ener_per_bd, MBANDS_GN, 1 ); + + /* More agressive smoothing in the first 50 frames */ + pt_exc = dct_exc_tmp; + for( i = 0; i < MBANDS_GN; i++ ) + { + /* Compute smoothing gain to apply with gain limitation */ + lt_ener_per_band[i] = ALPHA0*lt_ener_per_band[i] + BETA0*Ener_per_bd[i]; + + ftmp = lt_ener_per_band[i] - Ener_per_bd[i]; + ftmp = (float)pow(10, ftmp); + + if( i < 2 ) + { + for (j = 0; j < 8; j ++) + { + *pt_exc *= ftmp; + pt_exc++; + } + } + else + { + for (j = 0; j < 16; j ++) + { + *pt_exc *= ftmp; + pt_exc++; + } + } + } + + /* Going back to time */ + edct( dct_exc_tmp, exc2, L_frame ); + } + + return; +} diff --git a/lib_com/gs_noisefill.c b/lib_com/gs_noisefill.c new file mode 100644 index 000000000..6d113c17d --- /dev/null +++ b/lib_com/gs_noisefill.c @@ -0,0 +1,687 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + + +/*-------------------------------------------------------------------* + * gs_noisf() + * + * Noise fill-in function + *-------------------------------------------------------------------*/ + +static void gs_noisf( + const short Start_BIN, /* i : First bin for noise fill */ + const short NB_Qbins, /* i : Number of bin per band */ + const float Noise_fac, /* i : Noise level */ + const float *y_norm, /* i : Quantized pulses */ + float *exc_diffQ, /* o : Quantized pulses with noise added */ + short *seed_tcx, /* i : Random generator seed */ + const short coder_type /* i : coder type */ +) +{ + float ftmp; + short i, k; + short NB_zer = NB_Qbins/2; + + if( coder_type == INACTIVE ) + { + NB_zer = 2; + } + + /*----------------------------------------------* + * noise fill-in on unquantized subvector * + * injected only from 1066Hz to 6400Hz. * + *----------------------------------------------*/ + + for( k=Start_BIN; k ACELP_24k40 ) + { + noise_offset = .2f; + } + else if( bitrate >= ACELP_22k60 ) + { + noise_offset = .3f; + } + else if( bitrate >= ACELP_9k60 ) + { + noise_offset = 0.35f; + } + else + { + noise_offset = .4f; + } + + set_f( noisepb + i_band, noise_offset, Mbands_gn - i_band ); + + for( i = i_band; i < 5; i++ ) + { + if( noisepb[i] > 0.2f ) + { + noisepb[i] = 0.2f; + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * EstimateNoiseLevel() + * + * + *-------------------------------------------------------------------*/ + +static void EstimateNoiseLevel( + float *noisepb, /* o : Noise per band */ + const long bitrate, /* i : Bitrate of the codec */ + const short Diff_len, /* i : number of bin before cut-off frequency */ + const short Mbands_gn, /* i : number of bands */ + const short coder_type, /* i : coder type */ + const short noise_lev, /* i : pulses dynamic */ + const short pit_band_idx, /* i : bin position of the cut-off frequency */ + short last_bin, /* i : the last bin of bit allocation */ + short bwidth +) +{ + short i_band; + + i_band = 0; + + if( Diff_len < L_FRAME ) + { + EstimateNoiseLevel_inner(noisepb, bitrate, i_band, Mbands_gn); + + if( coder_type != INACTIVE ) + { + if( (bitrate == ACELP_8k00 && last_bin > 8) && bwidth != NB) + { + while(Mbands_gn > i_band ) + { + noisepb[i_band] *= 2.0f; + i_band++; + } + } + else + { + while(pit_band_idx > i_band ) + { + noisepb[i_band] /= 2.0f; + i_band++; + } + } + } + } + + if ( (coder_type == INACTIVE || noise_lev >= NOISE_LEVEL_SP3) ) + { + for( i_band = 9; i_band < Mbands_gn; i_band++ ) + { + noisepb[i_band] *= 1.15f; + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * Apply_NoiseFill() + * + * + *-------------------------------------------------------------------*/ + +static void Apply_NoiseFill( + float *exc_diffQ, /* i/o: Noise per band */ + short *seed_tcx, /* i : Seed for noise */ + const float *noisepb, /* i : Noise per band */ + const short Diff_len, /* i : number of bin before cut-off frequency */ + const short Mbands_gn, /* i : number of bands */ + const short coder_type, /* i : coder type */ + const short *freq_nsbin_per_band /* i : bin per bands tables */ +) +{ + short StartBin, NB_Qbins, i_band; + StartBin = 0; + NB_Qbins = 0; + + for( i_band = 0; i_band < Mbands_gn; i_band++ ) + { + StartBin += NB_Qbins; + NB_Qbins = freq_nsbin_per_band[i_band]; + + if( Diff_len < L_FRAME ) + { + gs_noisf( StartBin, NB_Qbins, noisepb[i_band], exc_diffQ, exc_diffQ, seed_tcx, coder_type ); + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * freq_dnw_scaling() + * + * + *-------------------------------------------------------------------*/ + +void freq_dnw_scaling( + const short cor_strong_limit, /* i : HF correlation */ + const short coder_type, /* i : coder type */ + const short noise_lev, /* i : Noise level */ + const long core_brate, /* i : Core bitrate */ + float fy_norm[] /* i/o: Frequency quantized parameter */ +) +{ + float sc_dyn; + short start_sc, i; + + sc_dyn = 1.0f; + start_sc = L_FRAME; + + if( core_brate <= ACELP_8k00 && coder_type == INACTIVE ) + { + sc_dyn *= .15f; + start_sc = 64; + } + else if( coder_type == INACTIVE ) + { + sc_dyn *= .25f; + start_sc = 80; + } + else + { + sc_dyn = (float)(NOISE_LEVEL_SP3 - noise_lev)/10.0f + 0.4f; + start_sc = 112 + (NOISE_LEVEL_SP3 - noise_lev) * 16; + + if( noise_lev == NOISE_LEVEL_SP0 ) + { + start_sc = L_FRAME; + } + } + + for(i = start_sc; i < L_FRAME; i++) + { + fy_norm[i] *= sc_dyn; + } + + if( (core_brate < ACELP_13k20 && cor_strong_limit == 0) || core_brate < ACELP_9k60) + { + for(i = 160; i < L_FRAME; i++) + { + if( fy_norm[i] > 1.0f ) + { + fy_norm[i] = 1.0f; + } + + if( fy_norm[i] < -1.0f ) + { + fy_norm[i] = -1.0f; + } + } + } + else if( core_brate < ACELP_22k60 ) + { + for(i = 160; i < L_FRAME; i++) + { + if( fy_norm[i] > 1.5f ) + { + fy_norm[i] = 1.5f; + } + + if( fy_norm[i] < -1.5f ) + { + fy_norm[i] = -1.5f; + } + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * Decreas_freqPeak() + * + * + *-------------------------------------------------------------------*/ + +static void Decreas_freqPeak( + float *lsf_new, /* i : ISFs at the end of the frame */ + float *exc_diffQ, /* i/o: frequency coefficients of per band */ + float thr_rat /* i : threshold of ratio between consecutive lsf_new_diff */ +) +{ + short i, j, k; + short last_bin = 0; + short pos = 0; + float *src; + float avrg, max; + float lsf_new_diff[M]; + lsf_new_diff[0] = 0; /* prevent unitialized value */ + for(j=1; j<(M-1); j++) + { + lsf_new_diff[j] = lsf_new[j] - lsf_new[j-1]; + } + + avrg = 0.0f; + /* This is to prevent a possible div by 0 in the '*(src) = (*src > 0) ?...' + loop. The value of 'max' is not important because it will be mutiplied + by 'avrg' and the result will be close to 0. The 'fabs(*src)/max' + div by 0 error will be avoided. */ + max = 0.001f; + for(i=160; i max) + { + max = (float)fabs(exc_diffQ[i]); + pos = i; + } + avrg += (float)fabs(exc_diffQ[i]); + } + avrg /= 96; + last_bin = M-1; /* When the search is false, should equate the end of the vector, not the beginning */ + for(i=0; i<(M-1); i++) + { + if(lsf_new[i] > 4000) + { + last_bin = i; + break; + } + } + + for(i=last_bin; i<14; i++) + { + if( lsf_new_diff[i] < thr_rat*lsf_new_diff[i-1] ) + { + src = &exc_diffQ[(i-1)*16]; + for(j=0; j<2; j++) + { + for(k=0; k<16; k++) + { + if(fabs(*src) > 2.0f*avrg) + { + *(src) = (*src > 0) ? (float)(avrg*(2.0f-fabs(*src)/max)) : (float)(-avrg*(2.0f-fabs(*src)/max)); + } + src++; + } + } + } + } + + if(fabs(exc_diffQ[pos]) == max && max > 4.0f*avrg) + { + for(i=pos-1; i 8 || Diff_len != 0) && last_coder_type == AUDIO) + { + MAX_Bin = 10; + bwe_flag = 1; + } + else + { + MAX_Bin = 15; + } + + last_bin_tmp = last_bin; + if(last_bin < MAX_Bin) + { + last_bin = MAX_Bin; + } + last_bin += 1; + } + else + { + last_bin = MBANDS_GN; + last_bin_tmp = last_bin; + } + + if( bfi ) + { + set_f( noisepb, 0.4f, MBANDS_GN ); + } + else + { + EstimateNoiseLevel( noisepb, core_brate, Diff_len, last_bin, coder_type, noise_lev, pit_band_idx, last_bin_tmp, bwidth ); + } + + if( exc_wo_nf != NULL ) + { + mvr2r( exc_diffQ, exc_wo_nf, L_FRAME ); + } + + if( GSC_noisy_speech && !bfi ) + { + set_f( noisepb, 0.1f, MBANDS_GN ); + } + + Apply_NoiseFill( exc_diffQ, seed_tcx, noisepb, Diff_len, last_bin, coder_type, mfreq_bindiv ); + + /*--------------------------------------------------------------------------------------* + * Quantize average gain + * Substract Q averaged gain + * VQ of remaining gain per band + *--------------------------------------------------------------------------------------*/ + + if( core_brate == ACELP_8k00 && bwidth != NB ) + { + Ener_per_band_comp( exc_diffQ, Ener_per_bd_yQ, last_bin+1, 0 ); + } + else + { + Ener_per_band_comp( exc_diffQ, Ener_per_bd_yQ, MBANDS_GN, 1 ); + + if( nb_subfr < 4 ) + { + for( i = L_FRAME-16; i < L_FRAME; i++ ) + { + exc_diffQ[i] *= (0.067f * i - 15.0f); + } + } + } + /*--------------------------------------------------------------------------------------* + * Check potential energy excitation overshoot + *--------------------------------------------------------------------------------------*/ + if( bfi ) + { + if (GSC_noisy_speech == 0 && coder_type > UNVOICED) /* Here coder_type == last_coder_type because of the bfi */ + { + for( i=0; i end) + { + *src-- = *dst--; + } + + if( (bitallocation_exc[0] != 0 || bitallocation_exc[1] != 0) && core_brate == ACELP_8k00 ) + { + exc_diffQ[160] = 0.0f; + } + + envelop_modify(exc_diffQ, seed_tcx, last_bin, Ener_per_bd_iQ); + + mvr2r( &exc_diffQ[last_bin*16], &exc_dct_in[last_bin*16], L_FRAME-last_bin*16 ); + } + + if( nb_subfr < 4 ) + { + for( i = L_FRAME-16; i < L_FRAME; i++ ) + { + exc_dct_in[i] *= (0.067f*i-15.f); + } + } + + if( ener < 2*(*last_ener) && ener > 0.5f*(*last_ener) ) + { + length_bin = 6; + if(last_coder_type != AUDIO) + { + set_s( last_bitallocation_band, 0, 6 ); + mvr2r( &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++) + { + if( !(bitallocation_band[i] == 0 && last_bitallocation_band[i-4] == 0)) + { + src = &exc_dct_in[(i+length_bin)*16]; + dst = &last_exc_dct_in[(i+length_bin)*16]; + for(j=0; j<16; j++) + { + if(fabs(*src) > 3.0f*fabs(*dst)) + { + *src = (*src > 0) ? (float)(0.5f*(*src + fabs(*dst))) : (float)(0.5f*(*src - fabs(*dst))); + } + else if(fabs(*dst) > 3.0f*fabs(*src)) + { + *src = (*src > 0) ? (float)(0.7f*(*src) + 0.3f*fabs(*dst)) : (float)(0.7f*(*src) - 0.3f*fabs(*dst)); + } + src++; + dst++; + } + } + } + } + + if( bwe_flag == 1 ) + { + Decreas_freqPeak( lsf_new, exc_dct_in, 0.3f ); + } + else + { + Decreas_freqPeak( lsf_new, exc_dct_in, 0.5f ); + } + } + + mvr2r( &exc_dct_in[64], &last_exc_dct_in[64], L_FRAME-64 ); + mvs2s( &bitallocation_band[4], last_bitallocation_band, 6 ); + *last_ener = ener; + + return; +} diff --git a/lib_com/gs_preech.c b/lib_com/gs_preech.c new file mode 100644 index 000000000..39f1add36 --- /dev/null +++ b/lib_com/gs_preech.c @@ -0,0 +1,95 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.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) + + +/*-------------------------------------------------------------------* + * pre_echo_att() + * + * Attenuation of the pre-echo when encoder specifies an attack + *-------------------------------------------------------------------*/ + +void pre_echo_att( + float *Last_frame_ener, /* i/o: Energy of the last frame */ + float *exc, /* i/o: Excitation of the current frame */ + const short attack_flag, /* i : flag signalling attack encoded by AC mode (GSC) */ + const short last_coder_type /* i : Last coder type */ +) +{ + float etmp; + float etmp1; + float finc[ATT_LENGHT], ratio; + short attack_pos, i; + + if ( attack_flag == 1 && last_coder_type == AUDIO) + { + /*-------------------------------------------------------------------------* + * 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++) + { + finc[i] = sum2_f( exc + i*ATT_SEG_LEN, ATT_SEG_LEN )*((float)(ATT_LENGHT-i)/(ATT_LENGHT)); + } + + etmp = -1; + attack_pos = maximum(finc, ATT_LENGHT, &etmp); + + /* Scaled the maximum energy and allowed 6 dB increase*/ + etmp *= INV_ATT_SEG_LEN; + etmp1 = etmp; + *Last_frame_ener *= 4.0f; + + /* If the maximum normalized energy > last frame energy + 6dB */ + if( etmp > *Last_frame_ener && attack_pos > 0 ) + { + /* Find the average energy before the attack */ + etmp = sum_f( finc, attack_pos ) + 0.01f; + etmp /= (attack_pos*ATT_SEG_LEN); + + /* Find the correction factor and apply it before the attack */ + ratio = (float)sqrt(*Last_frame_ener/etmp); + + + /* Pre-echo atttenuation should never increase the energy */ + ratio = min(ratio, 1.0f); + for(i = 0; i < attack_pos*ATT_SEG_LEN; i++) + { + exc[i] *= ratio; + } + } + *Last_frame_ener = etmp1; + } + else + { + /*-------------------------------------------------------* + * In normal cases, just compute the energy of the frame + *-------------------------------------------------------*/ + + etmp = sum2_f( exc, L_FRAME ) + 0.01f; + + etmp *= INV_L_FRAME; + *Last_frame_ener = etmp; + } + + return; +} diff --git a/lib_com/guided_plc_util.c b/lib_com/guided_plc_util.c new file mode 100644 index 000000000..9fe04ee6e --- /dev/null +++ b/lib_com/guided_plc_util.c @@ -0,0 +1,302 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "prot.h" +#include "wmc_auto.h" +#include "rom_com.h" + + +/*-------------------------------------------------------------------* + * Local function + *-------------------------------------------------------------------*/ + +static void reorder_lsfs( float *lsf, float min_dist, const short n, int sr_core ); + + +/*-------------------------------------------------------------------* + * getLookAheadResSig() + * + * + *-------------------------------------------------------------------*/ + +void getLookAheadResSig( + float *speechLookAhead, + const float *A, + float *res, + int L_frame, + int L_subfr, + int m, + int numSubFrame +) +{ + const float *p_A; + short i_subfr; + short subfr_len[2] = { 0 }; + + subfr_len[0] = L_subfr; + subfr_len[1] = L_frame < L_FRAME16k ? (short)(0.75*L_subfr) : L_subfr; + + p_A = A; + for (i_subfr=0; i_subfrlsf_adaptive_mean[i] = ( decState->lsfoldbfi1[i]+ decState->lsfoldbfi0[i]+lsf[i])/3; + decState->lsfoldbfi1[i] = decState->lsfoldbfi0[i]; + decState->lsfoldbfi0[i] = lsf[i]; + } + + return; +} + + +/*-------------------------------------------------------------------* + * getConcealedLP() + * + * + *-------------------------------------------------------------------*/ + +void getConcealedLP( + HANDLE_PLC_ENC_EVS memDecState, + float *AqCon, + const float lsfBase[], + const float sr_core, + int last_good, + int L_frame +) +{ + float *lsf = memDecState->lsf_con; + float lsp[(NB_DIV+1)*M]; + short k; + + dlpc_bfi( L_frame, &lsf[0], memDecState->lsfold, last_good, + 1 /* assumes packet loss */ , memDecState->mem_MA, memDecState->mem_AR, &(memDecState->stab_fac), memDecState->lsf_adaptive_mean, + 1, NULL, 0, NULL, NULL, lsfBase); + + mvr2r( memDecState->lspold, lsp, M ); + + for ( k=0; k<1; k++ ) + { + lsf2lsp(&lsf[k*M], &lsp[(k+1)*M], M, sr_core); + } + + int_lsp( L_FRAME, &lsp[0], &lsp[M], AqCon, M, interpol_frac_12k8, 0 ); + + return; +} + +/*-------------------------------------------------------------------* + * RecLpcSpecPowDiffuseLc() + * + * + *-------------------------------------------------------------------*/ + +void RecLpcSpecPowDiffuseLc( + float *lspq, + float *lsp_old, + float *lsfq, + Decoder_State *st + , int reset_q +) +{ + const float *means; + float lsf_old[M]; + short i; + + + means = PlcGetlsfBase ( st->lpcQuantization, st->narrowBand, st->sr_core ); + + mvr2r( st->lsf_old, lsf_old, M ); + + modify_lsf( lsf_old, M, st->sr_core + , reset_q + ); + + lsf2lsp(lsf_old, lsp_old, M, st->sr_core); + + if (reset_q) + { + for (i=0; imem_MA[i] + means[i]; + } + + v_sort( lsfq, 0, M - 1 ); + + reorder_lsfs( lsfq, LSF_GAP, M, st->sr_core); + + lsf2lsp(lsfq, lspq, M, st->sr_core); + } + else + { + modify_lsf( lsfq, M, st->sr_core, reset_q ); + + lsf2lsp(lsfq, lspq, M, st->sr_core); + } + + + return; +} + + +/*-------------------------------------------------------------------* + * modify_lsf() + * + * + *-------------------------------------------------------------------*/ + +void modify_lsf( + float *lsf, + const short n, + const int sr_core + , int reset_q +) +{ + short i, k; + float gap; + float th; + + th = 1900; + + if (reset_q==0) + { + th = 800; + } + + if(sr_core == 16000) + { + th *= 1.25; + } + + + i = 1; + + while(lsf[i] < th && i < n) + { + i++; + } + gap = lsf[i - 1] / i; + + for(k = 0; k < i - 1; k++) + { + lsf[k] = gap * (k + 1); + } + + return; +} + + +/*-------------------------------------------------------------------* + * reorder_lsfs() + * + * + *-------------------------------------------------------------------*/ + +static void reorder_lsfs( + float *lsf, /* i/o: vector of lsfs in the frequency domain (0..0.5)*/ + float min_dist, /* i : minimum required distance */ + const short n, /* i : LPC order */ + int sr_core +) +{ + short i; + float lsf_min; + float lsf_max; + float fac; + float th1, th2; + + th1 = 1000.0f; + th2 = 1900.0f; + + + if(sr_core == 16000) + { + min_dist *= 1.25; + th1 *= 1.25; + th2 *= 1.25; + } + + /*-----------------------------------------------------------------* + * Verify the LSF ordering and minimum GAP + *-----------------------------------------------------------------*/ + fac = 3.0; + + lsf_min = min_dist * fac; + for (i = 0; i < n; i++) + { + + if (lsf[i] > th1) + { + fac = 2.0; + } + else + { + if (lsf[i] > 1900.0) + { + fac = 1.0; + } + } + + if (lsf[i] < lsf_min) + { + lsf[i] = lsf_min; + } + + lsf_min = lsf[i] + min_dist * fac; + } + + /*------------------------------------------------------------------------------------------* + * Reverify the LSF ordering and minimum GAP in the reverse order (security) + *------------------------------------------------------------------------------------------*/ + + lsf_max = (float)(sr_core)/2.0f - min_dist * fac; + + if( lsf[n-1] > lsf_max ) /* If danger of unstable filter in case of resonance in HF */ + { + for (i = n-1; i >=0; i--) /* Reverify the minimum LSF gap in the reverse sens */ + { + + if (lsf[i] <= th2) + { + fac = 2.0; + } + else + { + if (lsf[i] <= th1) + { + fac = 3.0; + } + } + + if (lsf[i] > lsf_max) + { + lsf[i] = lsf_max; + } + + lsf_max = lsf[i] - min_dist * fac; + } + } + + return; +} diff --git a/lib_com/hp50.c b/lib_com/hp50.c new file mode 100644 index 000000000..412ae766d --- /dev/null +++ b/lib_com/hp50.c @@ -0,0 +1,106 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "typedef.h" +#include "options.h" +#include "prot.h" + + +#define WMC_TOOL_SKIP + + +/* + * hp20 + * + * Function: + * 2nd order high pass filter with nominal cut off frequency at 20 Hz. + * + * Returns: + * void + */ + +void hp20(Float32 signal[], Word32 lg, Float32 mem[], Word32 fs) +{ + Word16 i; + Float32 x0, x1, x2, y0, y1, y2; + Float32 a1, a2, b1, b2; + + + + y1 = mem[0]; + y2 = mem[1]; + x0 = mem[2]; + x1 = mem[3]; + + if (fs == 8000) + { + /* hp filter 20Hz at 3dB for 8000KHz 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 = 1.977786483776764f; + a2 = -0.978030508491796f; + b1 = -1.977908496134280f; + b2 = 0.988954248067140f; + + } + else if (fs==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 = 1.988892905899653f; + a2 = -0.988954249933127f; + b1 = -1.988923577916390f; + b2 = 0.994461788958195f; + + } + else if (fs==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 = 1.994446410541927f; + a2 = -0.994461789075954f; + b1 = -1.994454099808940f; + b2 = 0.997227049904470f; + + + } + else + { + /* 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 = 1.996297601769122f; + a2 = -0.996304442992686f; + b1 = -1.996301022380904f; + b2 = 0.998150511190452f; + + } + + for(i = 0; i < lg; i++) + { + x2 = x1; + x1 = x0; + x0 = signal[i]; + y0 = (y1*a1) + (y2*a2) + (x0*b2) + (x1*b1) + (x2*b2); + signal[i] = y0; + y2 = y1; + y1 = y0; + } + + mem[0] = ((y1 > 1e-10) | (y1 < -1e-10)) ? y1 : 0; + mem[1] = ((y2 > 1e-10) | (y2 < -1e-10)) ? y2 : 0; + mem[2] = ((x0 > 1e-10) | (x0 < -1e-10)) ? x0 : 0; + mem[3] = ((x1 > 1e-10) | (x1 < -1e-10)) ? x1 : 0; + + + return; +} diff --git a/lib_com/hq2_bit_alloc.c b/lib_com/hq2_bit_alloc.c new file mode 100644 index 000000000..0e2018853 --- /dev/null +++ b/lib_com/hq2_bit_alloc.c @@ -0,0 +1,993 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "prot.h" +#include "rom_com.h" +#include "basop_util.h" +#include "basop_mpy.h" +#include "stl.h" + +#define WMC_TOOL_SKIP + +/*------------------------------------------------------------------- + * Local constants + *-------------------------------------------------------------------*/ + +#define MIN_BITS_FIX 0 +#define HQ_16k40_BIT (HQ_16k40/50) /* 16400/50=328 , FOR FIX TMP */ +#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( sub(abs_s(sub(Ravg_fx, shl(y_index_fx[j], QRavg))), th_5_fx) > 0 ) + { + enr_diffcnt_fx = add(enr_diffcnt_fx, 1); + } + } + + IF( enr_diffcnt_fx > 0 ) + { + scale_fact_fx = 11468; + move16(); /* 0.35f 11468.8(Q15) */ + } + ELSE + { + scale_fact_fx = 19661; + move16(); /* 0.60f 19660.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); + + test(); + 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 ( L_sub(L_R_temp[i], L_Bits_needed) < 0 ) + { + L_R_temp[i] = 0x0L; + move32(); + + 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 ( + float *y, /* i : band energy of sub-vectors */ + int B_fx, /* i : number of available bits */ + short N_fx, /* i : number of sub-vectors */ + Word32 *L_Rsubband, + short p2a_bands_fx, + long L_core_brate, /* i : core bit rate */ + short p2a_flags_fx[], + short band_width_fx[] +) +{ + 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; + + Word32 L_y[BANDS_MAX]; + for(i=0; i= 0x0L && sub(j_fx, grp_rngmax_fx[i]) < 0x0 ) + { + test(); + k_fx = add(k_fx, 1); + j_fx = add(j_fx, 1); + } + + temp_fx = k_fx; + move16(); + IF( sub(temp_fx, 1) > 0 ) + { + FOR( temp_fx = 2; temp_fx <= k_fx ; ) + { + IF( L_sub(L_temp_band_energy[gmax_range_fx[i]+temp_fx-1], L_temp_band_energy[gmax_range_fx[i]+temp_fx]) < 0 ) + { + BREAK; + } + ELSE IF( L_sub(L_temp_band_energy[gmax_range_fx[i]+temp_fx-1], L_temp_band_energy[gmax_range_fx[i]+temp_fx]) >= 0 ) + { + temp_fx = add(temp_fx, 1); + IF( sub(temp_fx, k_fx) > 0 ) + { + temp_fx = sub(temp_fx, 1); + BREAK; + } + } + } + + gmax_range_fx[i] = add(gmax_range_fx[i], temp_fx); + } + ELSE + { + gmax_range_fx[i] = add(gmax_range_fx[i], temp_fx); + } + } + + 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 = 0x0L; + move32(); + + FOR(j=1; j< harmonic_band_fx; j++) + { + IF( L_sub(L_temp_band_energydiff[j], L_G1_BE_DIFF_VAL) > 0 ) + { + G1_BE_DIFF_POS_fx = j; + move16(); + L_G1_BE_DIFF_VAL = L_temp_band_energydiff[j]; + move32(); + } + } + + test(); + test(); + IF( sub(G1_BE_DIFF_POS_fx, gmax_range_fx[0] ) < 0 && G1_BE_DIFF_POS_fx > 0 ) + { + final_gr_fact_pos_fx = 0; + move16(); + } + ELSE IF ( sub(G1_BE_DIFF_POS_fx, gmax_range_fx[0]) >= 0 && sub(G1_BE_DIFF_POS_fx, gmax_range_fx[1] ) < 0 ) + { + final_gr_fact_pos_fx = 1; + move16(); + } + ELSE + { + final_gr_fact_pos_fx = 2; + move16(); + } + + test(); + IF( final_gr_fact_pos_fx == 0 || sub(final_gr_fact_pos_fx, 1) == 0 ) + { + IF( L_sub(L_core_brate, HQ_16k40 ) == 0 ) + { + 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( L_sub(L_core_brate, HQ_16k40) == 0 ) + { + 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 */ + } + } + + FOR ( i = 0; i < sub(N_fx, harmonic_band_fx); i++ ) + { + y_index_fx[i] = extract_h(L_shl(L_temp_band_energy[harmonic_band_fx+i], sub(16, SWB_BWE_LR_Qbe))); + move16(); + index_fx[i] = add(harmonic_band_fx, i); + move16(); + } + + reordvct(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 = 1; + move32(); + FOR(i=0; i<3; i++) + { + L_norm_sum = L_add( L_norm_sum, L_Ravg_sub[i]); + move32(); + } + + /*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(Mpy_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 = Mpy_32_16(L_Ravg_sub[GRP_SB-1], sub(GRP_SB, 1)); /* Qbe+0+1 */ + L_temp = Mpy_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 */ + + IF( sub(lf_hf_ge_r_fx , 26214) > 0x0 && L_sub(L_avg_enhf_en_diff, (Word32)(8< 0x0L) /* 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 = Mpy_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); + + test(); + if( sub(Bits_grp_fx[GRP_SB-1], esthf_bits_fx) < 0 ) + { + 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( sub(final_gr_fact_pos_fx, 1) == 0 ) + { + L_temp = Mpy_32_16(L_Ravg_sub[1], extract_h(L_mult(bits_fact_fx, B_norm_fx))); + L_temp = Mpy_32_16(L_temp, Inv_norm_sum_fx); + Bits_grp_fx[1] = extract_h(L_shr(L_temp, exp_shift)); + + L_temp = Mpy_32_16(L_Ravg_sub[2], extract_h(L_mult(bits_fact1_fx, B_norm_fx))); + L_temp = Mpy_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]); + } + ELSE + { + L_temp = Mpy_32_16(L_Ravg_sub[0], extract_h(L_mult(bits_fact_fx, B_norm_fx))); + L_temp = Mpy_32_16(L_temp, Inv_norm_sum_fx); + Bits_grp_fx[0] = extract_h(L_shr(L_temp, exp_shift)); + + L_temp = Mpy_32_16(L_Ravg_sub[2], extract_h(L_mult(bits_fact1_fx, B_norm_fx))); + L_temp = Mpy_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]); + } + + IF( sub(Bits_grp_fx[2], THR2 ) < 0 ) + { + 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 + { + set_val_Word32(L_Rsubband+grp_bound_fx[i], 0x0L, sub(grp_bound_fx[i+1], grp_bound_fx[i])); + IF( sub(i, GRP_SB-1) == 0 ) + { + set_val_Word16(p2a_flags_fx+grp_bound_fx[i], 0, sub(grp_bound_fx[i+1], grp_bound_fx[i])); + } + } + } + return; +} + +void hq2_bit_alloc ( + const float band_energy[], /* i : band energy of each subband */ + const short bands, /* i : total number of subbands in a frame */ + Word32 L_Rk[], /* i/o: Bit allocation/Adjusted bit alloc. */ + short *bit_budget_fx, /* i/o: bit bugdet */ + short *p2a_flags, /* i : HF tonal indicator */ + const Word16 weight_fx, /* i : weight (Q13) */ + const short band_width[], /* i : Sub band bandwidth */ + const short num_bits, /* i : available bits */ + const short hqswb_clas, /* i : HQ2 class information */ + const short bwidth, /* i : input bandwidth */ + const short 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; + + Word32 L_band_energy[BANDS_MAX]; + + for(k=0; k 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 = QRk+exp_normd-(exp_normn)-1; */ + 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 && sub(bit_budget_norm_fx, tmp) < 0 ) + { + 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 = Mpy_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); + } + } + + negflag = 0; + move16(); + L_Rcalc = 0; + move32(); + FOR (k = 0; k < bands; k++) + { + IF ( L_sub(L_Rk[k], MIN_BITS_FIX) < 0 ) + { + L_Rk[k] = 0x0L; + move32(); + negflag = 1; + move16(); + } + L_Rcalc = L_add( L_Rcalc , L_Rk[k]); /*SWB_BWE_LR_QRk */ + } + + /* prune noiselike bands with low allocation */ + IF ( sub(num_bits, HQ_16k40_BIT) <= 0 && negflag == 0) + { + L_maxxy = 0; + move32(); + maxdex_fx = -1; + move16(); + L_Rcalc = 0; + move32(); + + /* find worst under-allocation */ + FOR (k = sub(bands, 1); k >= 0; k--) + { + /* dummy = ((float) min (band_width[k], max (12, band_width[k] / 4))) - Rk[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(); + test(); + IF ( p2a_flags[k] == 0 && L_sub(L_dummy, L_maxxy) > 0 && L_Rk[k] > 0 ) + { + maxdex_fx = k; + move16(); + L_maxxy = L_dummy; + move32();/*SWB_BWE_LR_QRk */ + } + } + + /* prune worst allocation and recalculate total allocation */ + IF ( sub(maxdex_fx, -1) > 0) + { + L_Rk[maxdex_fx] = 0; + move32(); + } + FOR (k = 0; k < bands; k++) + { + L_Rcalc = L_add(L_Rcalc, L_Rk[k]); /*SWB_BWE_LR_QRk */ + } + } + test(); + IF ( L_sub(L_Rcalc, L_Rcalc1) == 0 && sub(bwidth, SWB) == 0 ) + { + /* Reallocate bits to individual subbands for HQ_NORMAL mode */ + /* if bits allocated to subbands areless than predefined threshold */ + IF( sub(hqswb_clas, HQ_NORMAL) == 0 && sub(num_bits, HQ_16k40_BIT) < 0 ) + { + L_dummy = 0x0L; + move32(); + FOR( k = 0; k < bands; k++ ) + { + test(); + test(); + test(); + test(); + test(); + IF( sub(k, 11) < 0 && L_sub(L_Rk[k], L_THR1) < 0 ) + { + L_Rk[k] = 0x0L; + move32(); + } + ELSE IF( sub(k, 11) >= 0 && sub(k, 16) < 0 && L_sub(L_Rk[k], L_THR2) < 0 ) + { + L_Rk[k] = 0x0L; + move32(); + } + ELSE IF( sub(k, 16) >= 0 && sub(k, bands ) < 0 && L_sub(L_Rk[k], L_THR3) < 0 ) + { + L_Rk[k] = 0x0L; + move32(); + } + + L_dummy = L_add(L_dummy, L_Rk[k]); + } + + IF( L_sub(L_dummy, L_Rcalc ) == 0 ) + { + test(); + IF( sub(hqswb_clas, HQ_NORMAL) == 0 && sub(num_bits, HQ_16k40_BIT) < 0) + { + bit_budget_temp_fx = *bit_budget_fx; + move16(); + FOR( k=0; kBER_detect */ + } + ELSE IF( sub(bit_budget_temp_fx, *bit_budget_fx ) == 0 ) + { + BREAK; + } + } + ELSE + { + BREAK; + } + } + } + ELSE + { + BREAK; + } + } + ELSE IF ( L_sub(L_Rcalc, L_Rcalc1 ) == 0 && sub(bwidth, SWB) != 0) + { + BREAK; + } + + L_Rcalc1 = L_Rcalc; + move32(); + + } + return; +} diff --git a/lib_com/hq2_core_com.c b/lib_com/hq2_core_com.c new file mode 100644 index 000000000..2b163f71d --- /dev/null +++ b/lib_com/hq2_core_com.c @@ -0,0 +1,553 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" +#include "basop_util.h" +#include "basop_proto_func.h" + +/*--------------------------------------------------------------------------* + * mdct_spectrum_denorm() + * + * + *--------------------------------------------------------------------------*/ + +void mdct_spectrum_denorm( + const int inp_vector[], + float y2[], + const short band_start[], + const short band_end[], + const short band_width[], + const float band_energy[], + const int npulses[], + const short bands, + const float ld_slope, + const float pd_thresh +) +{ + short i, k; + float Eyy, gamma, pd, gain_tweak; + + for (k = 0; k < bands; k++) + { + Eyy = 0; + for (i = band_start[k]; i <= band_end[k]; i++) + { + Eyy += (float) inp_vector[i] * inp_vector[i]; + } + + if (Eyy > 0.0f) + { + /* Set gamma to be pulse gain which results in perfect quantized subband energy */ + gamma = (float) sqrt (pow (2.0f, band_energy[k]) / Eyy); + + /* Adjust gamma based on pulse density (0 bit MSE gain estimator) */ + pd = (float) npulses[k] / band_width[k]; + if (pd < pd_thresh) + { + gain_tweak = (float) pow (2.0f, (ld_slope * log2_f (pd / pd_thresh))); + gamma *= gain_tweak; + } + + for (i = band_start[k]; i <= band_end[k]; i++) + { + y2[i] = gamma * inp_vector[i]; + } + } + } + + return; +} +/*--------------------------------------------------------------------------* + * hq2_core_configure() + * + * + *--------------------------------------------------------------------------*/ + +void hq2_core_configure( + const short frame_length, /* i : frame length */ + const short num_bits, /* i : number of bits */ + const short is_transient, /* i : transient flag */ + short *bands, + short *length, + short band_width[], + short band_start[], + short band_end[], + Word32 *L_qint, + Word16 *eref_fx, + Word16 *bit_alloc_weight_fx, + short *gqlevs, + short *Ngq, + short *p2a_bands, + float *p2a_th, + float *pd_thresh, + float *ld_slope, + float *ni_coef, + float *ni_pd_th, + long bwe_br +) +{ + const Xcore_Config *xcore_config; + + short i, k; + short bands_sh; + + if( frame_length == L_FRAME8k ) + { + if( is_transient ) + { + if (num_bits <= ACELP_7k20 / 50) + { + xcore_config = &xcore_config_8kHz_007200bps_short; + } + else if (num_bits <= ACELP_8k00 / 50) + { + xcore_config = &xcore_config_8kHz_008000bps_short; + } + else if (num_bits <= ACELP_13k20 / 50) + { + xcore_config = &xcore_config_8kHz_013200bps_short; + } + else + { + xcore_config = &xcore_config_8kHz_016400bps_short; + } + } + else + { + if (num_bits <= ACELP_7k20 / 50) + { + xcore_config = &xcore_config_8kHz_007200bps_long; + } + else if (num_bits <= ACELP_8k00 / 50) + { + xcore_config = &xcore_config_8kHz_008000bps_long; + } + else if (num_bits <= ACELP_13k20 / 50) + { + xcore_config = &xcore_config_8kHz_013200bps_long; + } + else + { + xcore_config = &xcore_config_8kHz_016400bps_long; + } + } + } + else if( frame_length == L_FRAME16k ) + { + if( is_transient ) + { + if (num_bits <= ACELP_13k20 / 50) + { + xcore_config = &xcore_config_16kHz_013200bps_short; + } + else + { + xcore_config = &xcore_config_16kHz_016400bps_short; + } + } + else + { + if (num_bits <= ACELP_13k20 / 50) + { + xcore_config = &xcore_config_16kHz_013200bps_long; + } + else + { + xcore_config = &xcore_config_16kHz_016400bps_long; + } + } + } + else /* (bwidth == SWB) */ + { + if( is_transient ) + { + if (bwe_br == ACELP_13k20) + { + xcore_config = &xcore_config_32kHz_013200bps_short; + } + else + { + xcore_config = &xcore_config_32kHz_016400bps_short; + } + } + else + { + if (bwe_br == ACELP_13k20) + { + xcore_config = &xcore_config_32kHz_013200bps_long; + } + else + { + xcore_config = &xcore_config_32kHz_016400bps_long; + } + } + } + + *bands = xcore_config->bands; + *length = xcore_config->bw; + *L_qint = xcore_config->L_qint; + *eref_fx = xcore_config->eref_fx; + *bit_alloc_weight_fx = xcore_config->bit_alloc_weight_fx; + *gqlevs = xcore_config->gqlevs; + *Ngq = xcore_config->Ngq; + + *p2a_bands = xcore_config->p2a_bands; + *p2a_th = xcore_config->p2a_th; + + *pd_thresh = xcore_config->pd_thresh; + *ld_slope = xcore_config->ld_slope; + *ni_coef = xcore_config->ni_coef; + *ni_pd_th = xcore_config->ni_pd_th; + + mvs2s (xcore_config->band_width, band_width, *bands); + + /* Expand band_width[] table for short windows */ + if( is_transient ) + { + bands_sh = *bands; + *bands = NUM_TIME_SWITCHING_BLOCKS * bands_sh; + *length *= NUM_TIME_SWITCHING_BLOCKS; + + for( i = 1; i <= 3; i++ ) + { + for( k = 0; k < bands_sh; k++ ) + { + band_width[i * bands_sh + k] = band_width[k]; + } + } + } + + /* Formulate band_start and band_end tables from band_width table */ + band_start[0] = 0; + band_end[0] = band_width[0] - 1; + for( k = 1; k < *bands; k++ ) + { + band_start[k] = band_start[k - 1] + band_width[k - 1]; + band_end[k] = band_start[k] + band_width[k] - 1; + } + + + return; +} + +/*--------------------------------------------------------------------------* + * reverse_transient_frame_energies() + * + * + *--------------------------------------------------------------------------*/ + +void reverse_transient_frame_energies( + float band_energy[], /* o : band energies */ + const short bands /* i : number of bands */ +) +{ + short k, k1, k2; + float be; + + k1 = bands/4; + k2 = bands/2-1; + for( k = 0; k < bands/8; k++ ) + { + be = band_energy[k1]; + band_energy[k1] = band_energy[k2]; + band_energy[k2] = be; + k1++, k2--; + } + + k1 = 3*bands/4; + k2 = bands-1; + for( k = 0; k < bands/8; k++ ) + { + be = band_energy[k1]; + band_energy[k1] = band_energy[k2]; + band_energy[k2] = be; + k1++, k2--; + } + + return; +} + +#define WMC_TOOL_SKIP +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 +) +{ + Word16 k, k2 = 0; + Word16 ever_bits[BANDS_MAX], ever_sort[BANDS_MAX];/*Q12 */ + Word16 class_flag = 0; + Word16 rk_temp = 32767, ever_temp = 32767;/*Q12 */ + Word16 exp; + Word16 tmp; + Word32 L_tmp; + + for (k = 0; k < BANDS; k++) + { + if((( sub(k_sort[k],sub(BANDS,p2a_bands)) >= 0 )&&( sub(p2a_flags[k_sort[k]],1) == 0 )) || + (( sub(k_sort[k],sub(BANDS,2)) >= 0 )&&( sub(last_bitalloc[sub(k_sort[k], sub(BANDS,2))], 1) == 0 ))) + { + 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_bits[k] = extract_l(L_shr(L_tmp,tmp));/*Q12 */ + if( sub(ever_bits[k],rk_temp) < 0 ) + { + rk_temp = ever_bits[k]; + k2 = k; + } + class_flag = 1; + } + } + if( class_flag ==0 || sub(input_frame,L_FRAME8k) == 0) + { + for(k = 0; k < BANDS; k++) + { + if( sub(k_sort[k],sub(BANDS,p2a_bands)) < 0 && Rk_sort[k] > 0 ) + { + 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(sub(ever_sort[k],ever_temp) < 0) + { + ever_temp = ever_sort[k]; + k2 = k; + } + } + } + } + + k_num[0] = k2; + if(sub(k_sort[k2],sub(BANDS,1)) == 0) + { + for (k = 0; k < BANDS; k++) + { + if(sub(k_sort[k],sub(k_sort[k2],1)) == 0) + { + k_num[1] = k; + } + } + } + else if(k_sort[k2] == 0) + { + for (k = 0; k < BANDS; k++) + { + if(sub(k_sort[k],add(k_sort[k2],1)) == 0) + { + k_num[1] = k; + } + } + } + else + { + if ( L_sub( Rk[sub(k_sort[k2],1)],Rk[add(k_sort[k2],1)] ) < 0 ) + { + for (k = 0; k < BANDS; k++) + { + if(sub(k_sort[k],sub(k_sort[k2],1)) == 0) + { + k_num[1] = k; + } + } + } + else + { + for (k = 0; k < BANDS; k++) + { + if(sub(k_sort[k],add(k_sort[k2],1)) == 0) + { + k_num[1] = k; + } + } + } + } +} +#undef WMC_TOOL_SKIP + +/*--------------------------------------------------------------------------* + * spt_shorten_domain_pre() + * + * Compute shorten subband if previous frame has spectral peak. + *--------------------------------------------------------------------------*/ + +void spt_shorten_domain_pre( + const short band_start[], /* i: Starting position of sub band */ + const short band_end[], /* i: End position of sub band */ + const short prev_SWB_peak_pos[], /* i: Spectral peak */ + const short BANDS, /* i: total number of bands */ + const long bwe_br, /* i: bitrate information */ + short new_band_start[], /* o: Starting position of new shorten sub band */ + short new_band_end[], /* o: End position of new shorten sub band */ + short new_band_width[] /* o: new sub band bandwidth */ +) +{ + int j; + int k; + int kpos; + + short new_band_width_half; + const short *p_bw_SPT_tbl; /* pointer of bw_SPT_tbl */ + + p_bw_SPT_tbl = bw_SPT_tbl[0]; + if( bwe_br == HQ_16k40 ) + { + p_bw_SPT_tbl = bw_SPT_tbl[1]; + } + + kpos = 0; + j = 0; + for(k=BANDS-SPT_SHORTEN_SBNUM; k band_end[k] ) + { + new_band_end[j] = band_end[k]; + new_band_start[j] = new_band_end[j] - (new_band_width[j] - 1); + } + } + else + { + new_band_width[j] = p_bw_SPT_tbl[j]; + + /*shorten the bandwidth for pulse resolution*/ + new_band_width_half = new_band_width[j]/2; + new_band_start[j] = (band_start[k]+band_end[k])/2 - new_band_width_half; + new_band_end[j] = (band_start[k]+band_end[k])/2 + new_band_width_half; + } + + kpos++; + j++; + } + + return; +} + +/*--------------------------------------------------------------------------* + * spt_shorten_domain_band_save() + * + * Store the original subband information + *--------------------------------------------------------------------------*/ + +void spt_shorten_domain_band_save( + const short bands, /* i: total subband */ + const short band_start[], /* i: starting position of subband */ + const short band_end[], /* i: end position of subband */ + const short band_width[], /* i: band width of subband */ + short org_band_start[], /* o: starting position of subband */ + short org_band_end[], /* o: end position of subband */ + short org_band_width[] /* o: band width of subband */ +) +{ + int k; + int kpos; + + kpos = 0; + for(k=bands-SPT_SHORTEN_SBNUM; k +#include "wmc_auto.h" +#include "options.h" +#include "prot.h" + +/*--------------------------------------------------------------------------* + * hq2_noise_inject() + * + * HQ2 noise injection for WB signals + *--------------------------------------------------------------------------*/ + +void hq2_noise_inject( + float y2hat[], + const short band_start[], + const short band_end[], + const short band_width[], + float Ep[], + float Rk[], + const int npulses[], + short ni_seed, + const short bands, + const short ni_start_band, + const short bw_low, + const short bw_high, + const float enerL, + const float enerH, + float last_ni_gain[], + float last_env[], + short *last_max_pos_pulse, + short *p2a_flags, + short p2a_bands, + const short hqswb_clas, + const short bwidth, + const long bwe_br +) +{ + short i, j, k, ni_end_band, satur = 0, count[BANDS_MAX], max_pos_pulse, pos; + float ni_gain[BANDS_MAX], pd[BANDS_MAX], rand, peak[BANDS_MAX], fac, env[BANDS_MAX]; + short sb = bands; + + if( (hqswb_clas == HQ_HARMONIC || hqswb_clas == HQ_NORMAL) && (bwe_br == HQ_16k40 || bwe_br == HQ_13k20) && bwidth == SWB ) + { + sb = (bwe_br == HQ_16k40) ? 19 : 17; + } + + /* 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++) + { + pd[k] = (float) Rk[k] / band_width[k]; + env[k] = (float)sqrt(Ep[k]/band_width[k]); + + peak[k] = 0.0f; + count[k] = 0; + if(npulses[k] != 0) + { + for (i = band_start[k]; i <= band_end[k]; i++) + { + Ep[k] -= y2hat[i] * y2hat[i]; + if( fabs(y2hat[i]) > peak[k]) + { + peak[k] = (float)fabs(y2hat[i]); + } + + if(y2hat[i] != 0) + { + count[k]++; + } + } + + max_pos_pulse = k; + Ep[k] = Ep[k] > 0 ? (float)sqrt(Ep[k]/band_width[k]) : 0.0f; + } + else + { + Ep[k] = env[k]; + } + } + + for (k = ni_start_band; k < ni_end_band; k++) + { + /* calculate the noise gain */ + satur = (pd[k] >= 0.8f) ? 1 : 0; + if (satur == 0 && Ep[k] > 0) + { + if(npulses[k] != 0) + { + if( bwidth == SWB ) + { + if(hqswb_clas != HQ_TRANSIENT) + { + if(hqswb_clas == HQ_HARMONIC) + { + fac = (k <= sb) ? 6.0f*(1.5f - pd[k])*env[k]*Ep[k]/(peak[k]*peak[k]) : 1.5f*Ep[k]/peak[k]; + } + else + { + fac = (k <= sb) ? 5.0f*(1.5f - pd[k])*Ep[k]/(peak[k]) : 4.0f*Ep[k]/peak[k]; + } + } + else + { + fac = 1.1f; + } + } + else + { + fac = 20.0f*min(1.0f, (1.5f - pd[k]))*env[k]*Ep[k]/(peak[k]*peak[k]); + if(k > 1 && k < ni_end_band-1) + { + if(count[k+1] == 0 && env[k] > 0.5f*env[k+1] && env[k] < 2.0f*env[k-1]) + { + fac = 1.5f*env[k+1]/env[k]; + } + else if(count[k-1] == 0 && peak[k] > 2.0f*env[k]) + { + fac = env[k-1]/env[k]; + } + } + + if(k >= ni_end_band - p2a_bands && bwidth == WB) + { + if(bw_low*enerH > bw_high*enerL && peak[k] < 2.0f*env[k]) + { + fac *= (2.0f - Ep[k]/peak[k]); + } + + if( p2a_flags[k] == 0 && fac > 0 ) + { + fac *= min(1.25f*env[k]/(Ep[k]*fac), 1.5f); + } + } + } + } + else + { + fac = (hqswb_clas == HQ_HARMONIC && bwidth == SWB) ? 0.8f : 1.1f; + } + + ni_gain[k] = fac * Ep[k]; + } + else + { + ni_gain[k] = 0.0; + } + + /* smooth the noise gain between the current frame and the previous frame */ + pos = bwidth == SWB ? ni_end_band-1 : max(max_pos_pulse, *last_max_pos_pulse); + + if(k <= pos) + { + if(k > 0 && k < ni_end_band-1) + { + if( (env[k] > 0.5f*last_env[k] && env[k] < 2.0f*last_env[k]) || + (((env[k]+env[k-1]+env[k+1]) > 0.5f*(last_env[k]+last_env[k-1]+last_env[k+1])) && + ((env[k]+env[k-1]+env[k+1]) < 2.0f*(last_env[k]+last_env[k-1]+last_env[k+1]))) ) + { + if(ni_gain[k] > last_ni_gain[k]) + { + ni_gain[k] = 0.2f*ni_gain[k] + 0.8f*last_ni_gain[k]; + } + else + { + ni_gain[k] = 0.6f*ni_gain[k] + 0.4f*last_ni_gain[k]; + } + } + } + else if (k == ni_end_band-1) + { + if( (env[k] > 0.5f*last_env[k] && env[k] < 2.0f*last_env[k]) || + ((env[k]+env[k-1]) > 0.5f*(last_env[k]+last_env[k-1]) && + (env[k]+env[k-1]) < 2.0f*(last_env[k]+last_env[k-1])) ) + { + if(ni_gain[k] > last_ni_gain[k]) + { + ni_gain[k] = 0.2f*ni_gain[k] + 0.8f*last_ni_gain[k]; + } + else + { + ni_gain[k] = 0.6f*ni_gain[k] + 0.4f*last_ni_gain[k]; + } + } + } + } + + /* inject noise into the non-decoded coeffs */ + if(k >= ni_end_band - p2a_bands && p2a_flags[k] == 0 && bwidth != SWB) + { + for (i = band_start[k]; i <= band_end[k]; i++) + { + if (y2hat[i] != 0) + { + y2hat[i] *= 0.8f; + } + } + } + + if(k == max_pos_pulse && k < bands - p2a_bands && satur != 1 && bwidth != SWB) + { + j = 0; + if(ni_gain[k] < 0.01f) + { + fac = 0.0f; + } + else + { + fac = max(Ep[k]/ni_gain[k], 1.0f); + } + for (i = band_start[k]; i <= band_end[k]; i++) + { + if (y2hat[i] == 0) + { + rand = own_random (&ni_seed) / 32768.0f; + y2hat[i] += (fac - ((fac-1.0f)*j)/band_width[k])*ni_gain[k] * rand; + } + + j++; + } + } + else + { + for (i = band_start[k]; i <= band_end[k]; i++) + { + if (y2hat[i] == 0) + { + rand = own_random (&ni_seed) / 32768.0f; + y2hat[i] += ni_gain[k] * rand; + } + } + } + } + + mvr2r(env, last_env, ni_end_band); + mvr2r(ni_gain, last_ni_gain, ni_end_band); + *last_max_pos_pulse = max_pos_pulse; + + return; +} diff --git a/lib_com/hq_bit_allocation.c b/lib_com/hq_bit_allocation.c new file mode 100644 index 000000000..1900286fb --- /dev/null +++ b/lib_com/hq_bit_allocation.c @@ -0,0 +1,190 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + + +/*--------------------------------------------------------------------------* + * hq_bit_allocation() + * + * Assign bits for HQ fine structure coding with PVQ + *--------------------------------------------------------------------------*/ + +void hq_bit_allocation( + const long core_brate, /* i : Core bit-rate */ + const short length, /* i : Frame length */ + const short hqswb_clas, /* i : HQ class */ + short *num_bits, /* i/o: Remaining bit budget */ + const short *normqlg2, /* i : Quantized norms */ + const short nb_sfm, /* i : Number sub bands to be encoded */ + const short *sfmsize, /* i : Sub band bandwidths */ + float *noise_level, /* o : HVQ noise level */ + short *R, /* o : Bit allocation per sub band */ + short *Rsubband, /* o : Fractional bit allocation (Q3) */ + short *sum, /* o : Sum of allocated shape bits */ + short *core_sfm, /* o : Last coded band in core */ + const short num_env_bands /* i : Number sub bands to be encoded for HQ_SWB_BWE */ +) +{ + short sfm_limit = nb_sfm; + short i; + short idx[NB_SFM]; + short wnorm[NB_SFM]; + short avrg_wnorm; + short E_low; + short E_hb_mean; + short E_max; + short i_max; + + + set_s( R, 0, NB_SFM ); + for( i = 0; i < nb_sfm; i++ ) + { + idx[i] = i; + } + if( hqswb_clas != HQ_TRANSIENT && hqswb_clas != HQ_HVQ && !(length == L_FRAME16k && core_brate == HQ_32k)) + { + /* 'nf_idx' 2-bits index written later */ + *num_bits -= 2; + } + + if ( hqswb_clas == HQ_GEN_SWB || hqswb_clas == HQ_GEN_FB ) + { + if (core_brate == HQ_32k) + { + *num_bits -= HQ_GENERIC_SWB_NBITS2; + } + else + { + *num_bits -= HQ_GENERIC_SWB_NBITS; + } + if (length == L_FRAME48k) + { + *num_bits -= HQ_GENERIC_FB_NBITS; + } + } + + if( (length == L_FRAME48k) && (hqswb_clas != HQ_HARMONIC) && (hqswb_clas != HQ_HVQ) ) + { + map_quant_weight( normqlg2, wnorm, hqswb_clas == HQ_TRANSIENT ); + } + else + { + mvs2s( normqlg2, wnorm, nb_sfm ); + } + + + if( hqswb_clas == HQ_HARMONIC ) + { + /* classification and limit bandwidth for bit allocation */ + sfm_limit -= 2; + limit_band_noise_level_calc( wnorm, &sfm_limit, core_brate, noise_level ); + + /* Detect important band in high frequency region */ + E_low = sum_s(wnorm, SFM_G1); + i_max = 0; + E_max = MIN16B; + E_hb_mean = 0; + for( i = SFM_G1; i < nb_sfm; i++) + { + E_hb_mean += wnorm[i]; + if( wnorm[i] > E_max) + { + E_max = wnorm[i]; + i_max = i; + } + } + E_hb_mean = E_hb_mean >> 4; /* Truncated division by SFM_G1 */ + if ( E_max * 15 < E_low || E_max * 0.67 < E_hb_mean || i_max < sfm_limit ) + { + i_max = 0; + } + + set_s( wnorm + sfm_limit, -20, nb_sfm - sfm_limit ); + if ( i_max > 0) + { + wnorm[i_max] = E_max; + } + + } + + + if( hqswb_clas == HQ_HVQ ) + { + *sum = 0; + } + else if ( hqswb_clas == HQ_GEN_SWB || (hqswb_clas == HQ_TRANSIENT && length == L_FRAME32k && core_brate <= HQ_32k) ) + { + *sum = BitAllocF( wnorm, core_brate, *num_bits, nb_sfm, R, Rsubband, hqswb_clas, num_env_bands ); + } + else if( length == L_FRAME16k && core_brate == HQ_32k ) + { + if( hqswb_clas != HQ_TRANSIENT ) + { + avrg_wnorm = wnorm[10]; + for( i=11; i<18; i++ ) + { + avrg_wnorm += wnorm[i]; + } + + avrg_wnorm /= 8; + for( i=0; i<4; i++ ) + { + if( wnorm[i] < avrg_wnorm ) + { + wnorm[i] = avrg_wnorm; + } + } + + /* Estimate number of bits per band */ + *sum = BitAllocWB( wnorm, *num_bits, nb_sfm, R, Rsubband ); + } + else + { + reordvct(wnorm, nb_sfm, idx); + bitalloc( wnorm, idx, *num_bits, nb_sfm, QBIT_MAX2, R, sfmsize, hqswb_clas ); + bitallocsum( R, nb_sfm, sum, Rsubband, *num_bits, length, sfmsize ); + } + } + else + { + reordvct( wnorm, nb_sfm, idx ); + + /* enlarge the wnorm value so that more bits can be allocated to (sfm_limit/2 ~ sfm_limit) range */ + if( hqswb_clas == HQ_HARMONIC ) + { + for( i=sfm_limit/2; i +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + + +/*--------------------------------------------------------------------------* + * hq_configure() + * + * Configuration routine for HQ mode + *--------------------------------------------------------------------------*/ + +void hq_configure( + const short length, /* i : Frame length */ + const short hqswb_clas, /* i : HQ SWB class */ + const long core_brate, /* i : Codec bitrate */ + short *num_sfm, /* o : Total number of subbands */ + short *nb_sfm, /* o : Total number of coded bands */ + short *start_norm, /* o : First norm to be SDE encoded */ + short *num_env_bands, /* o : Number coded envelope bands */ + short *numnrmibits, /* o : Number of bits in fall-back norm encoding */ + short *hq_generic_offset, /* o : Freq offset for HQ GENERIC */ + short const **sfmsize, /* o : Subband bandwidths */ + short const **sfm_start, /* o : Subband start coefficients */ + short const **sfm_end /* o : Subband end coefficients */ +) +{ + *start_norm = 0; + + if( length == L_FRAME48k ) + { + if ( hqswb_clas == HQ_GEN_FB ) + { + *num_sfm = NB_SFM; + *sfmsize = band_len_HQ; + *sfm_start = band_start_HQ; + *sfm_end = band_end_HQ; + + if( core_brate == HQ_32k ) + { + *hq_generic_offset = HQ_GENERIC_FOFFSET_32K; + } + else if ( core_brate == HQ_16k40 || core_brate == HQ_24k40 ) + { + *hq_generic_offset = HQ_GENERIC_FOFFSET_24K4; + } + + /* setting start frequency of FD BWE */ + if( core_brate == HQ_32k ) + { + *num_env_bands = SFM_N_STA_10k; + } + else if( core_brate == HQ_16k40 || core_brate == HQ_24k40 ) + { + *num_env_bands = SFM_N_STA_8k; + } + + *nb_sfm = *num_sfm; + } + else + { + if(hqswb_clas == HQ_HARMONIC) + { + *num_sfm = SFM_N_HARM_FB; + *nb_sfm = SFM_N_HARM_FB; + *num_env_bands = SFM_N_HARM_FB; + + *sfmsize = band_len_harm; + *sfm_start = band_start_harm; + *sfm_end = band_end_harm; + } + else if(hqswb_clas == HQ_HVQ) + { + if( core_brate == HQ_24k40 ) + { + *num_sfm = SFM_N_HARM_FB; + *nb_sfm = HVQ_THRES_SFM_24k; + *num_env_bands = *num_sfm - *nb_sfm; + + *sfmsize = band_len_harm; + *sfm_start = band_start_harm; + *sfm_end = band_end_harm; + *start_norm = HVQ_THRES_SFM_24k; + } + else + { + *num_sfm = SFM_N_HARM_FB; + *nb_sfm = HVQ_THRES_SFM_32k; + *num_env_bands = *num_sfm - *nb_sfm; + + *sfmsize = band_len_harm; + *sfm_start = band_start_harm; + *start_norm = HVQ_THRES_SFM_32k; + *sfm_end = band_end_harm; + } + } + else + { + *num_sfm = NB_SFM; + *nb_sfm = *num_sfm; + *num_env_bands = NB_SFM; + + *sfmsize = band_len_HQ; + *sfm_start = band_start_HQ; + *sfm_end = band_end_HQ; + } + } + } + else if( length == L_FRAME32k ) + { + if( hqswb_clas == HQ_HARMONIC ) + { + *num_sfm = SFM_N_HARM; + *nb_sfm = SFM_N_HARM; + *num_env_bands = SFM_N_HARM; + + *sfmsize = band_len_harm; + *sfm_start = band_start_harm; + *sfm_end = band_end_harm; + } + else if ( hqswb_clas == HQ_HVQ ) + { + if( core_brate == HQ_24k40 ) + { + *num_sfm = SFM_N_HARM; + *nb_sfm = HVQ_THRES_SFM_24k; + *num_env_bands = *num_sfm - *nb_sfm; + + *sfmsize = band_len_harm; + *sfm_start = band_start_harm; + *sfm_end = band_end_harm; + *start_norm = HVQ_THRES_SFM_24k; + } + else + { + *num_sfm = SFM_N_HARM; + *nb_sfm = HVQ_THRES_SFM_32k; + *num_env_bands = *num_sfm - *nb_sfm; + + *sfmsize = band_len_harm; + *sfm_start = band_start_harm; + *start_norm = HVQ_THRES_SFM_32k; + *sfm_end = band_end_harm; + } + } + else if ( hqswb_clas == HQ_GEN_SWB ) + { + *num_sfm = SFM_N_SWB; + *sfmsize = band_len_HQ; + *sfm_start = band_start_HQ; + *sfm_end = band_end_HQ; + + if( core_brate == HQ_32k ) + { + *hq_generic_offset = HQ_GENERIC_FOFFSET_32K; + } + else if ( core_brate == HQ_24k40 ) + { + *hq_generic_offset = HQ_GENERIC_FOFFSET_24K4; + } + + /* setting start frequency of FD BWE */ + if( core_brate == HQ_32k ) + { + *num_env_bands = SFM_N_STA_10k; + } + else if( core_brate == HQ_24k40 ) + { + *num_env_bands = SFM_N_STA_8k; + } + + *nb_sfm = *num_sfm; + } + else + { + /* HQ_NORMAL and HQ_TRANSIENT */ + *num_sfm = SFM_N_SWB; + *nb_sfm = *num_sfm; + *num_env_bands = SFM_N_SWB; + + *sfmsize = band_len_HQ; + *sfm_start = band_start_HQ; + *sfm_end = band_end_HQ; + } + } + else + { + *num_sfm = SFM_N_WB; + *nb_sfm = *num_sfm; + *num_env_bands = SFM_N_WB; + + *sfmsize = band_len_wb; + *sfm_start = band_start_wb; + *sfm_end = band_end_wb; + } + + *numnrmibits = (*num_env_bands - 1) * NORMI_BITS; + + return; +} diff --git a/lib_com/hq_tools.c b/lib_com/hq_tools.c new file mode 100644 index 000000000..3cbef9572 --- /dev/null +++ b/lib_com/hq_tools.c @@ -0,0 +1,1733 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "prot.h" +#include "rom_com.h" + +/*--------------------------------------------------------------------------* + * Local functions + *--------------------------------------------------------------------------*/ + +static void overlap_hq_bwe( const float *hq_swb_overlap_buf, float *coeff_out1, const short n_swb_overlap_offset, const short n_swb_overlap, + const short *R, const short num_env_bands, const short num_sfm, const short *sfm_end ); + +/*--------------------------------------------------------------------------* + * hq_swb_harmonic_calc_norm_envelop() + * + * Calculate normalization envelop + *--------------------------------------------------------------------------*/ + +void hq_swb_harmonic_calc_norm_envelop( + float *SWB_signal, /* i : input signal */ + float *envelope, /* o : output envelope */ + int L_swb_norm, /* i : length of normaliztion */ + int SWB_flength /* i : length of input signal */ +) +{ + int lookback; + int env_index; + int n_freq; + int n_lag_now; + int n_lag; + int i; + + lookback = L_swb_norm/2; + env_index = 0; + for (n_freq = 0; n_freq < lookback; n_freq++) + { + n_lag_now = lookback+n_freq; + + /* Apply MA filter */ + envelope[env_index] = EPSILON; + for (n_lag=0; n_lag 0.0f) + { + CodeBook_mod[cb_size] = 1.0f; + E_cb_vec++; + } + else if (coeff[j] < 0.0f) + { + CodeBook_mod[cb_size] = -1.0f; + E_cb_vec++; + } + else + { + CodeBook_mod[cb_size] = 0.0f; + } + cb_size++; + } + + if (E_cb_vec < 2) + { + cb_size -= 8; + } + } + } + else + { + for (j = sfm_start[sfm]; j < sfm_end[sfm]; j++) + { + CodeBook[cb_size] = coeff[j]; + cb_size++; + } + } + } + } + + if (flag_32K_env_ho) + { + for (j = 0; j < cb_size; j++) + { + if (CodeBook_mod[j] != 0.0f) + { + /* Densify codebook */ + CodeBook[j] = sign(CodeBook_mod[j])*(CodeBook_mod[j]*CodeBook_mod[j] + CodeBook_mod[cb_size-j-1]*CodeBook_mod[cb_size-j-1]); + } + else + { + CodeBook[j] = CodeBook_mod[cb_size-j-1]; + } + } + } + + return cb_size; +} + +/*--------------------------------------------------------------------------* + * find_last_band() + * + * Find the last band which has bits allocated + *--------------------------------------------------------------------------*/ + +short find_last_band( /* o : index of last band */ + const short *bitalloc, /* i : bit allocation */ + const short nb_sfm /* i : number of possibly coded bands */ +) +{ + short sfm, core_sfm; + + core_sfm = nb_sfm-1; + + for (sfm = nb_sfm-1; sfm >= 0; sfm--) + { + if ( bitalloc[sfm] != 0 ) + { + core_sfm = sfm; + break; + } + } + + return core_sfm; +} + +/*--------------------------------------------------------------------------* + * apply_noisefill_HQ() + * + * Inject noise in non-coded bands + *--------------------------------------------------------------------------*/ + +void apply_noisefill_HQ( + const short *R, /* i : bit allocation */ + const short length, /* i : input frame length */ + const short flag_32K_env_ho,/* i : envelope stability hangover flag*/ + const long core_brate, /* i : core bit rate */ + const short last_sfm, /* i : last coded subband */ + const float *CodeBook, /* i : Noise-fill codebook */ + const float *CodeBook_mod, /* i : Densified noise-fill codebook */ + const short cb_size, /* i : Codebook length */ + const short *sfm_start, /* i : Subband start coefficient */ + const short *sfm_end, /* i : Subband end coefficient */ + const short *sfmsize, /* i : Subband band width */ + float *coeff /* i/o: coded/noisefilled spectrum */ +) +{ + short sfm; + short cb_pos; + float E_cb_vec; + float E_corr; + float cb_buff[64]; + short i,j; + + if( length >= L_FRAME32k || core_brate > HQ_32k || core_brate < HQ_24k40 ) + { + /* Read from codebook */ + cb_pos = 0; + + for (sfm = 0; sfm <= last_sfm; sfm++) + { + if (R[sfm] == 0) + { + if (flag_32K_env_ho) + { + E_cb_vec = 0.0f; + if (sfm < 20) + { + for (i = 0; i < sfmsize[sfm]; i++) + { + cb_buff[i] = CodeBook_mod[cb_pos]; + E_cb_vec += cb_buff[i]*cb_buff[i]; + cb_pos++; + if(cb_pos >= cb_size) + { + cb_pos = 0; + } + } + } + else + { + for (i = 0; i < sfmsize[sfm]; i++) + { + cb_buff[i] = CodeBook[cb_pos]; + E_cb_vec += cb_buff[i]*cb_buff[i]; + cb_pos++; + if(cb_pos >= cb_size) + { + cb_pos = 0; + } + } + } + + E_corr = E_cb_vec / ((float) sfmsize[sfm]); + E_corr = 1.0f / (float)sqrt(E_corr); + + for (j = sfm_start[sfm]; j < sfm_end[sfm]; j++) + { + coeff[j] = cb_buff[j - sfm_start[sfm]] * E_corr; + } + } + else + { + for (j = sfm_start[sfm]; j < sfm_end[sfm]; j++) + { + coeff[j] = CodeBook[cb_pos]; + cb_pos++; + cb_pos = (cb_pos>=cb_size) ? 0 : cb_pos; + } + } + } + } + } + + return; +} + + +/*--------------------------------------------------------------------------* + * harm_bwe_fine() + * + * Prepare harmonic BWE fine structure + *--------------------------------------------------------------------------*/ + +void harm_bwe_fine( + const short *R, /* i : bit allocation */ + const short last_sfm, /* i : last coded subband */ + const short high_sfm, /* i : higher transition band to BWE */ + const short num_sfm, /* i : total number of bands */ + const short *norm, /* i : quantization indices for norms */ + const short *sfm_start, /* i : Subband start coefficient */ + const short *sfm_end, /* i : Subband end coefficient */ + short *prev_L_swb_norm, /* i/o: last normalize length */ + float *coeff, /* i/o: coded/noisefilled normalized spectrum */ + float *coeff_out, /* o : coded/noisefilled spectrum */ + float *coeff_fine /* o : BWE fine structure */ +) +{ + short sfm; + short i; + float normq; + float SWB_signal[L_HARMONIC_EXC]; + float envelope[L_HARMONIC_EXC]; + float *src, *dst, *end; + + short norm_width = 64; + + /* shape the spectrum */ + for (sfm = 0; sfm <= last_sfm; sfm++) + { + if( R[sfm] != 0 ) + { + normq = dicn[norm[sfm]]; + for (i = sfm_start[sfm]; i < sfm_end[sfm]; i++) + { + coeff_out[i] = coeff[i]*normq; + } + } + else + { + for (i = sfm_start[sfm]; i < sfm_end[sfm]; i++) + { + coeff_out[i] = 0.0f; + } + } + } + + /* excitation replication */ + mvr2r( coeff_out, SWB_signal, L_HARMONIC_EXC ); + calc_normal_length( HQ_CORE, coeff_out, HQ_HARMONIC, -1, &norm_width, prev_L_swb_norm ); + hq_swb_harmonic_calc_norm_envelop( SWB_signal, 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]; + } + + dst = coeff_fine + sfm_end[last_sfm]; + end = coeff_fine + sfm_end[num_sfm-1]; + + if ( (sfm_end[last_sfm] - sfm_end[high_sfm]) <= L_HARMONIC_EXC - START_EXC ) + { + src = SWB_signal + START_EXC + (sfm_end[last_sfm] - sfm_end[high_sfm]); + } + else + { + src = SWB_signal + L_HARMONIC_EXC - 1; + } + + while (dst < end) + { + while (dst < end && src < &SWB_signal[L_HARMONIC_EXC]) + { + *dst++ = *src++; + } + src --; + + while (dst < end && src >= &SWB_signal[START_EXC]) + { + *dst++ = *src--; + } + src++; + } + + return; +} + +/*--------------------------------------------------------------------------* + * hvq_bwe_fine() + * + * Prepare HVQ BWE fine structure + *--------------------------------------------------------------------------*/ + +void hvq_bwe_fine( + const short last_sfm, /* i : last coded subband */ + const short num_sfm, /* i : total number of bands */ + const short *sfm_end, /* i : Subband end coefficient */ + const short *peak_idx, /* i : Peak index */ + const short Npeaks, /* i : Number of peaks */ + short *peak_pos, /* i/o: Peak positions */ + short *prev_L_swb_norm, /* i/o: last normalize length */ + float *coeff, /* i/o: coded/noisefilled normalized spectrum */ + short *bwe_peaks, /* o : Positions of peaks in BWE */ + float *coeff_fine /* o : HVQ BWE fine structure */ +) +{ + short i, j; + float SWB_signal[L_HARMONIC_EXC]; + float envelope[L_HARMONIC_EXC]; + float *src, *dst, *end; + short *peak_dst, *peak_src; + short norm_width = 64; + + /* excitation replication */ + mvr2r( coeff, SWB_signal, L_HARMONIC_EXC ); + calc_normal_length( HQ_CORE, coeff, HQ_HVQ, -1, &norm_width, prev_L_swb_norm ); + + hq_swb_harmonic_calc_norm_envelop( SWB_signal, 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]; + } + + 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 ( peak_idx[i] < L_HARMONIC_EXC ) + { + peak_pos[peak_idx[i]] = 1; + } + } + + i = L_HARMONIC_EXC-1; + while( i-- > 0 ) + { + if( peak_pos[i] == 1 ) + { + break; + } + } + + if( i < 180 ) + { + i = 180; + } + + for( j = L_HARMONIC_EXC-1; j > i+1; j-- ) + { + SWB_signal[j] = 0.0f; + } + + peak_dst = bwe_peaks + sfm_end[last_sfm]; + while ( dst < end ) + { + while ( dst < end && src < &SWB_signal[L_HARMONIC_EXC] ) + { + *dst++ = *src++; + *peak_dst++ = *peak_src++; + } + peak_src--; + src --; + + while (dst < end && src >= &SWB_signal[START_EXC]) + { + *dst++ = *src--; + *peak_dst++ = *peak_src--; + } + peak_src++; + src++; + } + + return; +} + +/*--------------------------------------------------------------------------* + * hq_fold_bwe() + * + * HQ mode folding BWE + *--------------------------------------------------------------------------*/ + +void hq_fold_bwe( + const short last_sfm, /* i : last coded subband */ + const short *sfm_end, /* i : Subband end coefficient */ + const short num_sfm, /* i : Number of subbands */ + float *coeff /* i/o: coded/noisefilled normalized spectrum */ +) +{ + short low_coeff; + short first_coeff; + float *src, *dst, *end; + + /* Find replication range for BWE */ + low_coeff = 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]; + + /* Generate BWE with spectral folding */ + while (dst < end) + { + while (dst < end && src >= &coeff[low_coeff]) + { + *dst++ = *src--; + } + + src++; + + while (dst < end && src < &coeff[first_coeff]) + { + *dst++ = *src++; + } + } + + return; +} + +/*--------------------------------------------------------------------------* + * apply_nf_gain() + * + * Apply noise fill gain + *--------------------------------------------------------------------------*/ + +void apply_nf_gain( + const short nf_idx, /* i : noise fill gain index */ + const short last_sfm, /* i : last coded subband */ + const short *R, /* i : bit allocation */ + const short *sfm_start, /* i : Subband start coefficient */ + const short *sfm_end, /* i : Subband end coefficient */ + float *coeff /* i/o: coded/noisefilled normalized spectrum */ +) +{ + short sfm; + short j; + float nf_scale; + + nf_scale = 1.0f / (1 << nf_idx); + 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] = coeff[j] * nf_scale; + } + } + } + + return; +} + +/*--------------------------------------------------------------------------* + * hq_generic_fine() + * + * Prepare HQ SWB BWE fine structure + *--------------------------------------------------------------------------*/ + +void hq_generic_fine( + float *coeff, /* i : coded/noisefilled normalized spectrum */ + const short last_sfm, /* i : Last coded band */ + const short *sfm_start, /* i : Subband start coefficient */ + const short *sfm_end, /* i : Subband end coefficient */ + short *bwe_seed, /* i/o: random seed for generating BWE input */ + float *coeff_out1 /* o : HQ SWB BWE input */ +) +{ + short sfm; + short i; + float multi; + + multi = 1.0f; + for (sfm = 0; sfm <= last_sfm; sfm++) + { + for (i = sfm_start[sfm]; i < sfm_end[sfm]; i++) + { + if (coeff[i]==0.f) + { + coeff_out1[i] = (float)multi*( own_random(bwe_seed)>0 ? 1.0f: -1.0f)*0.5f; + } + else + { + coeff_out1[i] = coeff[i]; + } + } + } + + return; +} + +/*--------------------------------------------------------------------------* + * harm_bwe() + * + * HQ Harmonic BWE + *--------------------------------------------------------------------------*/ + +void harm_bwe( + const float *coeff_fine, /* i : fine structure for BWE */ + const float *coeff, /* i : coded/noisefilled normalized spectrum */ + const short num_sfm, /* i : Number of subbands */ + const short *sfm_start, /* i : Subband start coefficient */ + const short *sfm_end, /* i : Subband end coefficient */ + const short last_sfm, /* i : last coded subband */ + const short high_sfm, /* i : higher transition band to BWE */ + const short *R, /* i : bit allocation */ + const short prev_hq_mode, /* i : previous hq mode */ + short *norm, /* i/o: quantization indices for norms */ + float *noise_level, /* i/o: noise levels for harmonic modes */ + float *prev_noise_level, /* i/o: noise factor in previous frame */ + short *bwe_seed, /* i/o: random seed for generating BWE input */ + float *coeff_out /* o : coded/noisefilled spectrum */ +) +{ + short i, j; + short sfm; + float normq; + float norm_adj; + float E_L; + + float alfa = 0.5f; + float alpha, beta; + short idx; + float fac; + float *src, *dst; + + for (sfm = 0; sfm <= last_sfm; sfm++) + { + if (R[sfm] == 0) + { + normq = dicn[norm[sfm]]; + for (i = sfm_start[sfm]; i < sfm_end[sfm]; i++) + { + coeff_out[i] = coeff[i]*normq; + } + } + } + noise_level[1] = noise_level[0]; + + /* shaping the BWE spectrum further by envelopes and noise factors */ + noise_level[0] = 0.9f*prev_noise_level[0] + 0.1f*noise_level[0]; + noise_level[1] = 0.9f*prev_noise_level[1] + 0.1f*noise_level[1]; + + if( prev_hq_mode == HQ_NORMAL || prev_hq_mode == HQ_GEN_SWB) + { + if( noise_level[0] < 0.25f ) + { + noise_level[0] *= 4.0f; + } + + if( noise_level[1] < 0.25f ) + { + noise_level[1] *= 4.0f; + } + } + + E_L = EPSILON; + for( i=last_sfm+1; i < num_sfm; i++ ) + { + E_L = EPSILON; + for (j = sfm_start[i]; j < sfm_end[i]; j++) + { + E_L += coeff_fine[j] * coeff_fine[j]; + } + E_L = (float)sqrt((sfm_end[i] - sfm_start[i])/E_L); + + normq = dicn[norm[i]]; + norm_adj = normq*E_L; + alfa = (i > 27) ? noise_level[1] : noise_level[0]; + beta = (float)sqrt(1.0f - alfa); + alpha = (float)sqrt(alfa) * 0.5f; + + for(sfm = sfm_start[i]; sfm < sfm_end[i]; sfm++) + { + coeff_out[sfm] = (beta*coeff_fine[sfm]*norm_adj + alpha*own_random(bwe_seed)/32768.0f*normq); + } + } + + prev_noise_level[0] = noise_level[0]; + prev_noise_level[1] = noise_level[1]; + idx = 16; + src = &coeff_out[sfm_end[high_sfm] + L_HARMONIC_EXC - START_EXC]; + dst = src-1; + + for( i = 0; i < idx; i++ ) + { + fac = i / (2.0f * idx); + *src++ *= 0.5f + fac; + *dst-- *= 0.5f + fac; + } + if( num_sfm ==33 ) + { + set_f(&coeff_out[800], 0, 160); + } + return; +} + +/*--------------------------------------------------------------------------* + * HVQ_bwe() + * + * HQ HVQ BWE + *--------------------------------------------------------------------------*/ + +void hvq_bwe( + const float *coeff, /* i : coded/noisefilled spectrum */ + const float *coeff_fine, /* i : BWE fine structure */ + const short *sfm_start, /* i : Subband start coefficient */ + const short *sfm_end, /* i : Subband end coefficient */ + const short *sfm_len, /* i : Subband length */ + const short last_sfm, /* i : last coded subband */ + const short prev_hq_mode, /* i : previous hq mode */ + const short *bwe_peaks, /* i : HVQ bwe peaks */ + const short bin_th, /* i : HVQ transition bin */ + const short num_sfm, /* i : Number of bands */ + const long core_brate, /* i : Core bit-rate */ + const short *R, /* i : Bit allocation */ + short *norm, /* i/o: quantization indices for norms */ + float *noise_level, /* i/o: noise levels for harmonic modes */ + float *prev_noise_level, /* i/o: noise factor in previous frame */ + short *bwe_seed, /* i/o: random seed for generating BWE input */ + float *coeff_out /* o : coded/noisefilled spectrum */ +) +{ + short i, j; + short N; + float normq; + float E_L; + + short bwe_noise_th = 0; + short peak_band, low, high, sel_norm; + short norm_ind; + float tmp_norm = 0; + short idx; + float fac; + float *src, *dst; + short istart, iend; + short offset = sfm_end[last_sfm]; + + mvr2r( coeff, coeff_out, L_FRAME48k ); + + bwe_noise_th = bin_th+(sfm_end[num_sfm-1] - bin_th)/HVQ_BWE_NOISE_BANDS; + logqnorm(&coeff_out[sfm_start[last_sfm]], &norm[last_sfm], 40, sfm_len[last_sfm], thren_HQ); + + /* shaping the BWE spectrum further by envelopes and noise factors */ + noise_level[0] = 0.9f*prev_noise_level[0] + 0.1f*noise_level[0]; + noise_level[1] = 0.9f*prev_noise_level[1] + 0.1f*noise_level[1]; + + if( prev_hq_mode == HQ_NORMAL || prev_hq_mode == HQ_GEN_SWB) + { + if( noise_level[0] < 0.25f ) + { + noise_level[0] *= 4.0f; + } + + if( noise_level[1] < 0.25f ) + { + noise_level[1] *= 4.0f; + } + } + + norm_ind = last_sfm+1; + if (core_brate == HQ_24k40) + { + peak_band = 0; + E_L = EPSILON; + for (i = sfm_start[norm_ind]; i < sfm_end[norm_ind+1]; i++) + { + if (bwe_peaks[i]) + { + peak_band = 1; + } + E_L += coeff_fine[i-offset] * coeff_fine[i-offset]; + } + E_L = (float)sqrt((sfm_end[norm_ind+1] - sfm_start[norm_ind])/E_L); + + 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]]; + + istart = sfm_start[norm_ind]; + iend = istart + sfm_len[norm_ind]/2; + for (i = istart; i < iend; i++) + { + coeff_out[i] = ((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)*normq; + } + + j = 0; + N = sfm_len[norm_ind]/2+sfm_len[norm_ind+1]/2-1; + istart = iend; + iend = sfm_start[norm_ind+1] + sfm_len[norm_ind+1]/2; + 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); + j++; + } + + istart = iend; + iend = sfm_end[norm_ind+1]; + for (i = istart; i < iend; i++) + { + coeff_out[i] = ((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)*tmp_norm; + } + + norm_ind += 2; + } + + for ( ; norm_ind < num_sfm; norm_ind++) + { + if ( R[norm_ind] == 0 ) + { + peak_band = 0; + E_L = EPSILON; + + for (i = sfm_start[norm_ind]; i < sfm_end[norm_ind]; i++) + { + if (bwe_peaks[i]) + { + peak_band = 1; + break; + } + } + + istart = sfm_start[norm_ind]; + iend = sfm_end[norm_ind]; + + if ( peak_band == 1 && norm_ind > last_sfm+1 && norm_ind < num_sfm-1 ) + { + istart -= sfm_len[norm_ind-1]/2; + iend += sfm_len[norm_ind+1]/2; + } + + for (i = istart; i < iend; i++) + { + E_L += coeff_fine[i-offset] * coeff_fine[i-offset]; + } + E_L = (float)sqrt((iend - istart)/E_L); + + if ( peak_band ) + { + if ( norm_ind+1 > num_sfm-1 ) + { + normq = 0.15f*dicn[norm[norm_ind-1]] + 0.85f*dicn[norm[norm_ind]]; + } + else + { + normq = 0.1f*dicn[norm[norm_ind-1]] + 0.8f*dicn[norm[norm_ind]] + 0.1f*dicn[norm[norm_ind+1]]; + } + } + else + { + low = norm_ind; + high = min(norm_ind+1, num_sfm-1); + sel_norm = norm[norm_ind-1]; + for (j = low; j <= high; j++) + { + if (norm[j] > sel_norm) + { + sel_norm = norm[j]; + } + } + normq = dicn[sel_norm]; + } + + for (i = sfm_start[norm_ind]; i < sfm_end[norm_ind]; i++) + { + coeff_out[i] = ((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)*normq; + } + } + else /* R[norm_ind] > 0 */ + { + for (i = sfm_start[norm_ind]; i < sfm_end[norm_ind]; i++) + { + coeff_out[i] = coeff[i]; /* Scaling already applied */ + } + } + + } + + prev_noise_level[0] = noise_level[0]; + prev_noise_level[1] = noise_level[1]; + idx = 16; + src = &coeff_out[sfm_end[last_sfm] + L_HARMONIC_EXC - START_EXC]; + dst = src-1; + + for( i = 0; i < idx; i++ ) + { + fac = i/(2.0f * idx); + *src++ *= 0.5f + fac; + *dst-- *= 0.5f + fac; + } + + return; +} +/*-------------------------------------------------------------------* +* hvq_concat_bands() +* +* Compute the band limits for concatenated bands for PVQ target signal in HVQ +*--------------------------------------------------------------------------*/ +void hvq_concat_bands +( + const short pvq_bands, /* i : Number of bands in concatenated PVQ target */ + const short *sel_bnds, /* i : Array of selected high bands */ + const short n_sel_bnds, /* i : Number of selected high bands */ + short *hvq_band_start, /* i : Band start indices */ + short *hvq_band_width, /* i : Band widths */ + short *hvq_band_end /* i : Band end indices */ +) +{ + short k; + short s; + + s = 0; + + for (k = 0; k < pvq_bands; k++) + { + + if( k >= pvq_bands - n_sel_bnds) + { + hvq_band_start[k] = hvq_band_end[k-1]; + hvq_band_width[k] = band_len_harm[sel_bnds[s]]; + hvq_band_end[k] = hvq_band_end[k-1] + band_len_harm[sel_bnds[s]]; + s++; + } + else + { + hvq_band_start[k] = k * HVQ_PVQ_COEFS; + hvq_band_width[k] = HVQ_PVQ_COEFS; + hvq_band_end[k] = (k + 1) * HVQ_PVQ_COEFS; + } + } + + return; +} + + +/*--------------------------------------------------------------------------* + * map_hq_generic_fenv_norm() + * + * mapping high frequency envelope to high band norm + *--------------------------------------------------------------------------*/ +void map_hq_generic_fenv_norm( + const short hqswb_clas, + const float *hq_generic_fenv, + short *ynrm, + short *normqlg2, + const short num_env_bands, + const short nb_sfm, + const short hq_generic_offset) +{ + float env_fl[17]; + short i; + + set_f( env_fl, 0, 17 ); + if (hq_generic_offset == 144) + { + env_fl[0] = hq_generic_fenv[1]; + env_fl[1] = hq_generic_fenv[2]*0.6640625f+hq_generic_fenv[3]*0.3359375f; + env_fl[2] = hq_generic_fenv[3]*0.6640625f+hq_generic_fenv[4]*0.3359375f; + env_fl[3] = hq_generic_fenv[4]*0.3359375f+hq_generic_fenv[5]*0.6640625f; + env_fl[4] = hq_generic_fenv[5]*0.3359375f+hq_generic_fenv[6]*0.6640625f; + env_fl[5] = hq_generic_fenv[7]; + env_fl[6] = hq_generic_fenv[8]*0.75f+hq_generic_fenv[9]*0.25f; + env_fl[7] = hq_generic_fenv[9]*0.75f+hq_generic_fenv[10]*0.25f; + env_fl[8] = hq_generic_fenv[10]*0.25f+hq_generic_fenv[11]*0.75f; + } + else + { + env_fl[0] = hq_generic_fenv[0]*0.3359375f+hq_generic_fenv[1]*0.6640625f; + env_fl[1] = hq_generic_fenv[1]*0.3359375f+hq_generic_fenv[2]*0.6640625f; + env_fl[2] = hq_generic_fenv[3]; + env_fl[3] = hq_generic_fenv[4]*0.6640625f+hq_generic_fenv[5]*0.3359375f; + env_fl[4] = hq_generic_fenv[5]*0.6640625f+hq_generic_fenv[6]*0.3359375f; + env_fl[5] = hq_generic_fenv[6]*0.3359375f+hq_generic_fenv[7]*0.6640625f; + env_fl[6] = hq_generic_fenv[7]*0.3359375f+hq_generic_fenv[8]*0.6640625f; + env_fl[7] = hq_generic_fenv[8]*0.3359375f+hq_generic_fenv[9]*0.6640625f; + env_fl[8] = hq_generic_fenv[9]*0.3359375f+hq_generic_fenv[10]*0.6640625f; + env_fl[9] = hq_generic_fenv[10]*0.25f+hq_generic_fenv[11]*0.75f; + env_fl[10] = hq_generic_fenv[12]; + env_fl[11] = hq_generic_fenv[13]; + } + + if (hqswb_clas == HQ_GEN_FB) + { + if (hq_generic_offset == 144) + { + env_fl[9] = hq_generic_fenv[12]; + env_fl[10] = hq_generic_fenv[12]*0.25f+hq_generic_fenv[13]*0.75f; + env_fl[11] = hq_generic_fenv[13]*0.5f+hq_generic_fenv[14]*0.5f; + env_fl[12] = hq_generic_fenv[14]; + env_fl[13] = hq_generic_fenv[14]; + } + else + { + env_fl[12] = hq_generic_fenv[14]; + env_fl[13] = hq_generic_fenv[14]*0.25f+hq_generic_fenv[15]*0.75f; + env_fl[14] = hq_generic_fenv[15]*0.5f+hq_generic_fenv[16]*0.5f; + env_fl[15] = hq_generic_fenv[16]; + env_fl[16] = hq_generic_fenv[16]; + } + } + + logqnorm_2( env_fl,40, num_env_bands, nb_sfm, ynrm+num_env_bands, normqlg2+num_env_bands, thren_HQ); + + for(i=num_env_bands; i0) + { + i=nb_sfm-1; + while(b_add_bits_denv>0 && i>=0) + { + if (Rsubband[i]>24) + { + Rsubband[i] -= 8; + b_add_bits_denv--; + } + i--; + } + } + + return; +} + +short get_nor_delta_hf( + Decoder_State *st, + short *ynrm, + short *Rsubband, + const short num_env_bands, + const short nb_sfm, + const short core_sfm +) +{ + short i; + short delta,bitsforDelta,add_bits_denv; + + add_bits_denv = 0; + if (core_sfm >= num_env_bands) + { + bitsforDelta = (short)get_next_indice(st,2); + bitsforDelta += 2; + add_bits_denv += 2; + + for(i=num_env_bands; i 39 ) + { + ynrm[i] = 39; + st->BER_detect = 1; + } + add_bits_denv += bitsforDelta; + } + } + + update_rsubband(nb_sfm, Rsubband,add_bits_denv); + } + return add_bits_denv; +} + +short calc_nor_delta_hf( + Encoder_State *st, + const float *t_audio, + short *ynrm, + short *Rsubband, + const short num_env_bands, + const short nb_sfm, + const short *sfmsize, + const short *sfm_start, + const short core_sfm +) +{ + short i; + short ynrm_t[44],normqlg2_t[44]; + short delta,max_delta,min_delta,bitsforDelta,add_bits_denv; + + + short temp_num=0; + + max_delta=-100; + calc_norm( t_audio, ynrm_t, normqlg2_t, 0, nb_sfm, sfmsize, sfm_start ); + add_bits_denv = 0; + for(i=num_env_bands; i 0) + { + delta += 1; + } + else + { + delta = -delta; + } + if (delta>max_delta) + { + max_delta = delta; + } + } + } + if (core_sfm >= num_env_bands) + { + if (max_delta < 16) + { + bitsforDelta = 2; + while(max_delta>=2) + { + bitsforDelta++; + max_delta >>= 1; + } + } + else + { + bitsforDelta = 5; + } + max_delta = (1<<(bitsforDelta-1))-1; + min_delta = (max_delta+1)*(-1); + + /* updating norm & storing delta norm */ + add_bits_denv = 2; + push_indice( st, IND_DELTA_ENV_HQ, bitsforDelta-2 , 2 ); + for(i=num_env_bands; i max_delta) + { + delta = max_delta; + } + else if (delta < min_delta) + { + delta = min_delta; + } + push_indice( st, IND_DELTA_ENV_HQ, delta - min_delta , bitsforDelta ); + ynrm[i] += delta; + add_bits_denv += bitsforDelta; + + + temp_num++; + } + } + + /* updating bit allocation */ + update_rsubband(nb_sfm, Rsubband,add_bits_denv); + + } + + return add_bits_denv; +} + +/*-------------------------------------------------------------------* +* hq_generic_bwe() +* +* HQ GENERIC BWE +*--------------------------------------------------------------------------*/ +void hq_generic_bwe( + const short HQ_mode, /* i : HQ mode */ + float *coeff_out1, /* i/o: BWE input & temporary buffer */ + const float *hq_generic_fenv, /* i : SWB frequency envelopes */ + float *coeff_out, /* o : SWB signal in MDCT domain */ + const short hq_generic_offset, /* i : frequency offset for representing hq generic*/ + short *prev_L_swb_norm, /* i/o: last normalize length */ + const short hq_generic_exc_clas, /* i : hq generic hf excitation class */ + const short *sfm_end, /* i : End of bands */ + const short num_sfm, /* i : Number of bands */ + const short num_env_bands, /* i : Number of coded envelope bands */ + const short *R /* i : Bit allocation */ +) +{ + short n_swb_overlap_offset, n_swb_overlap; + float hq_swb_overlap_buf[640]; + + n_swb_overlap_offset = swb_bwe_subband[0] + hq_generic_offset; + + n_swb_overlap = sfm_end[num_env_bands-1] - n_swb_overlap_offset; + mvr2r( &coeff_out[n_swb_overlap_offset], hq_swb_overlap_buf, n_swb_overlap + sfm_end[num_sfm-1] - sfm_end[num_env_bands-1] ); + + hq_generic_hf_decoding( HQ_mode, coeff_out1, hq_generic_fenv, coeff_out, hq_generic_offset, prev_L_swb_norm, hq_generic_exc_clas, R ); + + overlap_hq_bwe( hq_swb_overlap_buf, coeff_out, n_swb_overlap_offset, n_swb_overlap, R, num_env_bands, num_sfm, sfm_end ); + + return; +} + + +/*--------------------------------------------------------------------------* + * hq_wb_nf_bwe() + * + * HQ WB noisefill and BWE + *--------------------------------------------------------------------------*/ + +void hq_wb_nf_bwe( + const float *coeff, /* i : coded/noisefilled normalized spectrum */ + const short is_transient, /* i : is transient flag */ + const short prev_bfi, /* i : previous bad frame indicator */ + const float *normq_v, /* i : norms */ + const short num_sfm, /* i : Number of subbands */ + const short *sfm_start, /* i : Subband start coefficient */ + const short *sfm_end, /* i : Subband end coefficient */ + const short *sfmsize, /* i : Subband band width */ + const short last_sfm, /* i : last coded subband */ + const short *R, /* i : bit allocation */ + const short prev_is_transient, /* i : previous transient flag */ + float *prev_normq, /* i/o: previous norms */ + float *prev_env, /* i/o: previous noise envelopes */ + short *bwe_seed, /* i/o: random seed for generating BWE input */ + float *prev_coeff_out, /* i/o: decoded spectrum in previous frame */ + short *prev_R, /* i/o: bit allocation info. in previous frame */ + float *coeff_out /* o : coded/noisefilled spectrum */ +) +{ + short i; + short sfm; + short total_bit; + short num; + + float bitalloc_var; + float sharp; + float mean; + float peak; + float fabs_coeff_out; + float harm_para; + float alfa = 0.5; + float env; + float step; + float min_coef; + float avrg_norm; + float prev_avrg_norm; + + if( is_transient == 0 ) + { + if( prev_bfi == 1 ) + { + mvr2r(normq_v, prev_normq, SFM_N_WB); + } + + /* the variance of bit allocation */ + total_bit = 0; + bitalloc_var = 0.0f; + for (sfm = 8; sfm <= last_sfm; sfm++) + { + bitalloc_var += (float)abs(R[sfm] - R[sfm-1]); + total_bit += R[sfm]; + } + bitalloc_var = (last_sfm > 8 && total_bit > 0) ? (bitalloc_var / total_bit) : 0; + + /* calculate the peak-average ratio of saturable subbands */ + num = 0; + sharp = EPSILON; + for(sfm = last_sfm; sfm >= 8; sfm--) + { + if(R[sfm] >= rat[sfm]*sfmsize[sfm]) + { + peak = 0.0f; + mean = EPSILON; + for (i = sfm_start[sfm]; i < sfm_end[sfm]; i++) + { + fabs_coeff_out = (float)fabs(coeff_out[i]); + mean += fabs_coeff_out; + if(fabs_coeff_out > peak) + { + peak = fabs_coeff_out; + } + } + sharp += sfmsize[sfm]*peak/mean; + num ++; + } + } + + sharp = (num != 0) ? 2.0f*num/sharp : 1.0f; + harm_para = sharp; + if( last_sfm == 0 ) + { + step = 0; + } + else + { + step = 5.0f * sharp / last_sfm; + } + alfa = 2.5f; + + /* fill noise for the insaturable subbands */ + for( sfm = 0; sfm < num_sfm; sfm++ ) + { + env = 0.0f; + if(R[sfm] != 0 && R[sfm] < 1.5f*sfmsize[sfm]) + { + /* calculate the energy of the undecoded coefficients */ + peak = 0.0f; + min_coef = FLT_MAX; + env = normq_v[sfm]*normq_v[sfm]*sfmsize[sfm]; + for (i = sfm_start[sfm]; i < sfm_end[sfm]; i++) + { + fabs_coeff_out = (float)fabs(coeff_out[i]); + if(fabs_coeff_out < min_coef && coeff_out[i] != 0) + { + min_coef = fabs_coeff_out; + } + if(fabs_coeff_out > peak) + { + peak = fabs_coeff_out; + } + env -= coeff_out[i]*coeff_out[i]; + } + + if (env > 0 ) + { + if(sfm == 0) + { + avrg_norm = normq_v[0] + normq_v[1] + normq_v[2]; + prev_avrg_norm = prev_normq[0] + prev_normq[1] + prev_normq[2]; + } + else if (sfm == 25) + { + avrg_norm = normq_v[23] + normq_v[24] + normq_v[25]; + prev_avrg_norm = prev_normq[23] + prev_normq[24] + prev_normq[25]; + } + else + { + avrg_norm = normq_v[sfm-1] + normq_v[sfm] + normq_v[sfm+1]; + prev_avrg_norm = prev_normq[sfm-1] + prev_normq[sfm] + prev_normq[sfm+1]; + } + + if(bitalloc_var > 0.3f || 4.0f*normq_v[sfm] < peak) + { + /* calculate the noise magnitude of harmonic signal */ + env = (float)(avrg_norm*harm_para *sqrt(env/sfmsize[sfm])/peak); + } + else + { + /* calculate the noise magnitude of normal signal */ + env = sharp *(float)sqrt(env/sfmsize[sfm]); + if(alfa*normq_v[sfm] < peak) + { + env *= env/peak; + } + sharp += step; + } + if(env > 0.5f*min_coef) + { + env = 0.5f*min_coef; + } + + if(prev_bfi == 1) + { + prev_env[sfm] = env; + } + /* smooth the noise magnitudes between inter-frame */ + if(prev_avrg_norm > 0.5f*avrg_norm && prev_avrg_norm < 2.0f*avrg_norm && prev_is_transient == 0) + { + env = 0.5f*env + 0.5f*prev_env[sfm]; + } + + for (i = sfm_start[sfm]; i < sfm_end[sfm]; i++) + { + if (coeff[i] == 0) + { + coeff_out[i] = (float)( own_random(bwe_seed))/32768.0f; + coeff_out[i] *= env; + } + } + } + else + { + env = 0.0f; + } + } + else if(R[sfm] == 0) + { + /* fill random noise for 0 bit subbands */ + for (i = sfm_start[sfm]; i < sfm_end[sfm]; i++) + { + if(coeff[i] == 0) + { + coeff_out[i] = (float)( own_random(bwe_seed))/32768.0f; + coeff_out[i] *= normq_v[sfm]; + } + } + + env = normq_v[sfm]; + } + if(sfm == SFM_N_WB-1 && prev_is_transient == 0 && prev_normq[sfm] > 0.5f*normq_v[sfm] && prev_normq[sfm] < 2.0f*normq_v[sfm] && bitalloc_var <= 0.3f ) + { + float *p_prev_coeff_out = prev_coeff_out; + for (i = sfm_start[sfm]+12; i < sfm_end[sfm]; i++) + { + if( fabs(coeff_out[i]) > 4.0f * fabs(*p_prev_coeff_out) || + fabs(coeff_out[i]) < 0.25f * fabs(*p_prev_coeff_out) || + (R[sfm] * (*prev_R) == 0 && R[sfm] + (*prev_R) != 0) ) + { + coeff_out[i] = (coeff_out[i] > 0) ? (float)(0.5f*(fabs(coeff_out[i]) + fabs(*p_prev_coeff_out))) : (float)(-0.5f*(fabs(coeff_out[i]) + fabs(*p_prev_coeff_out))); + } + p_prev_coeff_out++; + } + } + + prev_env[sfm] = env; + } + } + 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++) + { + coeff_out[i] = (float)( own_random(bwe_seed))/32768.0f; + coeff_out[i] *= normq_v[sfm]; + } + } + } + + set_f( prev_env, 0, SFM_N_WB ); + } + + mvr2r(normq_v, prev_normq, SFM_N_WB); + mvr2r( coeff_out + L_FRAME16k - L_HQ_WB_BWE, prev_coeff_out, L_HQ_WB_BWE ); + *prev_R = R[SFM_N_WB-1]; + + return; +} + + +/*--------------------------------------------------------------------------* + * enforce_zero_for_min_envelope() + * + * Detect minimum level of envelope and set corresponding bands to zero + *--------------------------------------------------------------------------*/ + +void enforce_zero_for_min_envelope( + const short hqswb_clas, /* i : HQ coding mode */ + const short *ynrm, /* i : Envelope indices */ + float *coefsq, /* i/o: Quantized spectrum/zeroed spectrum */ + short nb_sfm, /* i : Number of coded sub bands */ + const short *sfm_start, /* i : Sub band start indices */ + const short *sfm_end /* i : Sub band end indices */ +) +{ + short i, j; + + /* prevent non-zero output for all-zero input */ + if( hqswb_clas != HQ_HVQ ) + { + if( ynrm[0] == 31 ) + { + for( j = sfm_start[0]; j < sfm_end[0]; j++ ) + { + coefsq[j] = 0.0f; + } + } + + for( i = 1; i < nb_sfm; i++ ) + { + if( ynrm[i] == 39 ) + { + for( j = sfm_start[i]; j < sfm_end[i]; j++ ) + { + coefsq[j] = 0.0f; + } + } + } + } + + return; +} + + +/*--------------------------------------------------------------------------* + * overlap_hq_bwe() + * + * Overlapping at the boundary between HQ core and BWE + *--------------------------------------------------------------------------*/ + +static void overlap_hq_bwe( + const float *hq_swb_overlap_buf, /* i : spectrum from HQ core */ + float *coeff_out, /* i/o: spectrum from BWE, overlapped output */ + const short n_swb_overlap_offset, /* i : starting offset of overlapping */ + const short n_swb_overlap, /* i : length of overlapping */ + const short *R, /* i : Bit allocation */ + const short num_env_bands, /* i : Number of coded envelope bands */ + const short num_sfm, /* i : Number of bands */ + const short *sfm_end /* i : Band end indices */ +) +{ + short i; + float step; + float weighting; + short n_band; + + if (R[num_env_bands-1] != 0) + { + mvr2r( hq_swb_overlap_buf, &coeff_out[n_swb_overlap_offset], n_swb_overlap ); + } + else + { + /*weighting = 0.8f;*/ + step = 1.0f / (float)n_swb_overlap; + weighting = 1.0f; + for (i = 0; i < n_swb_overlap; i++) + { + coeff_out[n_swb_overlap_offset+i] = hq_swb_overlap_buf[i] * weighting + coeff_out[n_swb_overlap_offset+i] * (1.0f - weighting); + weighting -= step; + } + } + + + for (n_band = num_env_bands; n_band < num_sfm; n_band++) + { + if (R[n_band] !=0 ) + { + for(i=sfm_end[n_band-1]; i> 1; + accY = my >> 1; + align = *ex - ey; + if (align < 0) + { + if( align > -32) /* If align < -32, (accY >> (-align) = 0 */ + { + accX = accX + (accY >> (-align)); + } + } + else + { + if( align < 32) /* If align > 32, (accX >> align) = 0 */ + { + accX = accY + (accX >> align); + } + else + { + accX = accY; + } + *ex = ey; + } + +#define WMC_TOOL_SKIP + expo = norm_l(accX); /* aligned to BASOP */ +#undef WMC_TOOL_SKIP + *mx = accX << expo; + *ex = *ex + expo - 1; + + return; +} diff --git a/lib_com/hvq_pvq_bitalloc.c b/lib_com/hvq_pvq_bitalloc.c new file mode 100644 index 000000000..3f3b80a2a --- /dev/null +++ b/lib_com/hvq_pvq_bitalloc.c @@ -0,0 +1,157 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*--------------------------------------------------------------------------*/ +/* Function hvq_pvq_bitalloc */ +/* ~~~~~~~~~~~~~~~~~~~~~~~~ */ +/* */ +/* Calculate the number of PVQ bands to code and allocate bits based on */ +/* the number of available bits. */ +/*--------------------------------------------------------------------------*/ + +short hvq_pvq_bitalloc( + short num_bits, /* i/o: Number of available bits (including gain bits) */ + const short brate, /* i : bitrate */ + const short bwidth, /* i : Encoded bandwidth */ + const short *ynrm, /* i : Envelope coefficients */ + const int manE_peak, /* i : Peak energy mantissa */ + const short expE_peak, /* i : Peak energy exponent */ + short *Rk, /* o : bit allocation for concatenated vector */ + short *R, /* i/o: Global bit allocation */ + short *sel_bands, /* o : Selected bands for encoding */ + short *n_sel_bands /* o : No. of selected bands for encoding */ +) +{ + short num_bands, k, band_max_bits; + short k_max; + short k_start; + float E_max; + int E_max5; + short expo; + short align; + int acc; + float tmp; + int env_mean; + short reciprocal; + short num_sfm; + short bit_cost; + + if (bwidth == FB) + { + num_sfm = SFM_N_HARM_FB; + } + else + { + num_sfm = SFM_N_HARM; + } + + if (brate == HQ_24k40) + { + band_max_bits = HVQ_BAND_MAX_BITS_24k; + k_start = HVQ_THRES_SFM_24k; + if (bwidth == FB) + { + reciprocal = 2731; + } + else + { + reciprocal = 3277; + } + } + else + { + band_max_bits = HVQ_BAND_MAX_BITS_32k; + k_start = HVQ_THRES_SFM_32k; + if (bwidth == FB) + { + reciprocal = 3641; + } + else + { + reciprocal = 4681; + } + } + + num_bands = num_bits / band_max_bits; + num_bits = num_bits - num_bands*band_max_bits; + + if (num_bits >= HVQ_NEW_BAND_BIT_THR) + { + num_bands++; + } + else + { + num_bits += band_max_bits; + } + + /* safety check in case of bit errors */ + if (num_bands < 1) + { + return 0; + } + + *n_sel_bands = 0; + env_mean = 0; + E_max = 0; + k_max = k_start; + for ( k = k_start; k < num_sfm; k++ ) + { + tmp = dicn[ynrm[k]]; + env_mean += ynrm[k]; + if( tmp > E_max ) + { + E_max = tmp; + k_max = k; + } + } + env_mean = 2*((int)env_mean * (int)reciprocal); + + if(band_len_harm[k_max] == 96) + { + bit_cost = 61; + } + else + { + QuantaPerDsDirac(band_len_harm[k_max], 1, hBitsN, &bit_cost); + } + + + expo = max(0, ynrm[k_max]-1) >> 1; + E_max5 = E_max5_tbl[ynrm[k_max]]; + align = expo - expE_peak; + align = align + (19 - 14) - (31 - 2*12); + if (align < 0) + { + acc = E_max5 - (manE_peak >> -align); + } + else + { + acc = (E_max5 >> align) - manE_peak; + } + if ( acc > 0 + && ((env_mean - (ynrm[k_max]<<16)) > 0x30000L) + && num_bands > 1 + && (num_bits - HVQ_PVQ_GAIN_BITS)<<3 >= bit_cost ) + { + sel_bands[*n_sel_bands] = k_max; + (*n_sel_bands)++; + R[k_max] = 1; /* Mark that the band has been encoded for fill_spectrum */ + } + + /* Allocate bits */ + for (k = 0; k < num_bands-1; k++) + { + Rk[k] = band_max_bits-HVQ_PVQ_GAIN_BITS; + } + Rk[num_bands-1] = num_bits-HVQ_PVQ_GAIN_BITS; + + return num_bands; +} diff --git a/lib_com/ifft_rel.c b/lib_com/ifft_rel.c new file mode 100644 index 000000000..a9357ea51 --- /dev/null +++ b/lib_com/ifft_rel.c @@ -0,0 +1,256 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "prot.h" +#include "rom_com.h" + + +/*-----------------------------------------------------------------* + * Local constants + *-----------------------------------------------------------------*/ + +#define N_MAX_FFT 1024 +#define INV_SQR2 0.70710676908493f + +/*---------------------------------------------------------------------* + * ifft_rel() + * + * Calculate the inverse FFT of a real signal + * + * Based on the FORTRAN code from the article "Real-valued Fast Fourier Transform Algorithms" + * by Sorensen, ... in IEEE Trans. on ASSP, Vol. ASSP-35, No. June 6th 1987. + * + * Input: the io[] signal containing the spectrum in the following order : + * + * Re[0], Re[1], .. Re[n/2], Im[n/2-1], .. Im[1] + *---------------------------------------------------------------------*/ + +void ifft_rel( + float io[], /* i/o: input/output vector */ + const short n, /* i : vector length */ + const short m /* i : log2 of vector length */ +) +{ + short i, j, k; + short step; + short n2, n4, n8, i0; + short is, id; + float *x,*xi0, *xi1, *xi2, *xi3, *xi4, *xup1, *xdn6, *xup3, *xdn8; + float xt; + float r1; + float t1, t2, t3, t4, t5; + float cc1, cc3, ss1, ss3; + const float *s, *s3, *c, *c3; + const short *idx; + float temp[512]; + float n_inv; + + n_inv = 1.0f/n; + + /*-----------------------------------------------------------------* + * IFFT + *-----------------------------------------------------------------*/ + + x = &io[-1]; + n2 = 2*n; + for (k=1; k> 1; + n4 = n2 >> 2; + n8 = n4 >> 1; + while (is < n-1) + { + xi1 = x + is + 1; + xi2 = xi1 + n4; + xi3 = xi2 + n4; + xi4 = xi3 + n4; + + for (i=is; i>1)]; + } + } + else if (n == 256) + { + for (i=0; i> 1; + while (k < j) + { + j = j - k; + k = k >> 1; + } + j = j + k; + } + } + + /*-----------------------------------------------------------------* + * Normalization + *-----------------------------------------------------------------*/ + + for (i=1; i<=n; i++) + { + x[i] = xi0[i] * n_inv; + } + + return; +} diff --git a/lib_com/igf_base.c b/lib_com/igf_base.c new file mode 100644 index 000000000..de22c9f76 --- /dev/null +++ b/lib_com/igf_base.c @@ -0,0 +1,641 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "prot.h" +#include "rom_com.h" + +/*---------------------------------------------------------------------* + * IGF_ApplyTransFac() + * + * + *---------------------------------------------------------------------*/ + +static int IGF_ApplyTransFac( /**< out: | multiplication factor */ + const int val, /**< in: Q15 | input value for multiplication, Q15 */ + const float transFac /**< in: Q14 | multiplicator for variable val, Q14: 1.25f=0x5000, 1.0f=0x4000, 0.5f=0x2000 */ +) +{ + int ret = val; + + if (transFac!=1.f) + { + ret = round_f(val*transFac); + ret +=(ret & 1); + } + + return ret; +} + + +/*---------------------------------------------------------------------* + * IGF_MapBitRateToIndex() + * + * maps a given bitrate to the IGF_BITRATE index + *---------------------------------------------------------------------*/ + +static short IGF_MapBitRateToIndex( /**< out: Q0 | return bit rate index */ + int bitRate, /**< in: | bitrate */ + int mode, /**< in: | bandwidth mode */ + int rf_mode /**< in: | flag to signal the RF mode */ +) +{ + short bitRateIndex = IGF_BITRATE_UNKNOWN; + + switch (mode) + { + case IGF_MODE_WB: + switch (bitRate) + { + case 13200: + if (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 (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_gridSetUp() + * + * IGF grid setup + *---------------------------------------------------------------------*/ + +static void IGF_gridSetUp( + H_IGF_GRID hGrid, /**< out: | IGF grid handle */ + short bitRateIndex, /**< in: | IGF bitrate index */ + int sampleRate, /**< in: | sample rate */ + int frameLength, /**< in: | frame length */ + float transFac, /**< in: | transFac */ + int igfMinFq /**< in: | IGF minimum frequency indicating lower start frequency for copy up */ +) +{ + int t; + int sfb; + int swb_offset_len; + int wrp_sfb; + const int *swb_offset; + float bandwidth; + + /* inits */ + swb_offset = NULL; + swb_offset_len = 0; + + switch (bitRateIndex) + { + case IGF_BITRATE_WB_9600: + case IGF_BITRATE_RF_WB_13200: + case IGF_BITRATE_SWB_9600: + 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]; + mvr2r(&igf_whitening_TH[(int)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]; + mvr2r(&igf_whitening_TH[(int)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]; + mvr2r(&igf_whitening_TH[(int)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); + } + + hGrid->infoIsRefined = 0; + frameLength = IGF_ApplyTransFac(frameLength, transFac); + bandwidth = (float)sampleRate / 2.0f / (float)frameLength; + hGrid->swb_offset_len = swb_offset_len; + hGrid->startSfb = 0; + hGrid->stopSfb = hGrid->swb_offset_len-1; + hGrid->startLine = hGrid->swb_offset[ hGrid->startSfb ]; + hGrid->stopLine = hGrid->swb_offset[ hGrid->stopSfb ]; + hGrid->startFrequency = round_f(bandwidth * hGrid->startLine); + hGrid->stopFrequency = round_f(bandwidth * hGrid->stopLine); + hGrid->minSrcSubband = round_f((igfMinFq * (frameLength)) / (sampleRate >> 1)); + hGrid->minSrcSubband += hGrid->minSrcSubband % 2; + hGrid->minSrcFrequency = round_f(bandwidth * hGrid->minSrcSubband); + hGrid->infoGranuleLen = frameLength; + hGrid->infoTransFac = transFac; + hGrid->sfbWrap[0] = 0; + hGrid->tile[0] = hGrid->startLine; + + switch (bitRateIndex) + { + /* SWB 13200 */ + case IGF_BITRATE_WB_9600: + 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_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; + wrp_sfb = 4; + + /*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 + IGF_ApplyTransFac(32, transFac); + hGrid->tile[1+1] = hGrid->swb_offset[hGrid->stopSfb]; + + break; + case IGF_BITRATE_SWB_16400: + hGrid->nTiles = 3; + wrp_sfb = 4; + + /*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] = 6; + hGrid->sbWrap[1] = hGrid->minSrcSubband + IGF_ApplyTransFac(48, transFac); + hGrid->tile[1+1] = hGrid->swb_offset[6]; + + /*3nd*/ + hGrid->sfbWrap[2+1] = hGrid->stopSfb; + hGrid->sbWrap[2] = hGrid->minSrcSubband + IGF_ApplyTransFac(64, transFac); + hGrid->tile[2+1] = hGrid->swb_offset[hGrid->stopSfb]; + + break; + case IGF_BITRATE_SWB_24400: + case IGF_BITRATE_SWB_32000: + hGrid->nTiles = 3; + wrp_sfb = 4; + + /*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] = 7; + hGrid->sbWrap[1] = hGrid->minSrcSubband + IGF_ApplyTransFac(32, transFac); + hGrid->tile[1+1] = hGrid->swb_offset[7]; + + /*3nd*/ + hGrid->sfbWrap[2+1] = hGrid->stopSfb; + hGrid->sbWrap[2] = hGrid->minSrcSubband + IGF_ApplyTransFac(64, transFac); + hGrid->tile[2+1] = hGrid->swb_offset[hGrid->stopSfb]; + break; + case IGF_BITRATE_SWB_48000: + hGrid->nTiles = 1; + wrp_sfb = hGrid->stopSfb; + + /*1st*/ + hGrid->sfbWrap[0+1] = hGrid->stopSfb; + hGrid->sbWrap[0] = 2*hGrid->startLine - hGrid->stopLine; + hGrid->tile[0+1] = hGrid->swb_offset[hGrid->stopSfb]; + + break; + case IGF_BITRATE_FB_16400: + hGrid->nTiles = 3; + wrp_sfb = 4; + + /*1st*/ + hGrid->sfbWrap[0+1] = wrp_sfb; + hGrid->sbWrap[0] = hGrid->minSrcSubband; + hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb]; + wrp_sfb = 7; + + /*2nd*/ + hGrid->sfbWrap[1+1] = wrp_sfb; + hGrid->sbWrap[1] = hGrid->minSrcSubband; + hGrid->tile[1+1] = hGrid->swb_offset[wrp_sfb]; + + /*3nd*/ + hGrid->sfbWrap[2+1] = hGrid->stopSfb; + hGrid->sbWrap[2] = hGrid->minSrcSubband; + hGrid->tile[2+1] = hGrid->swb_offset[hGrid->stopSfb]; + + break; + case IGF_BITRATE_FB_24400: + case IGF_BITRATE_FB_32000: + hGrid->nTiles = 4; + wrp_sfb = 4; + + /*1st*/ + hGrid->sfbWrap[0+1] = wrp_sfb; + hGrid->sbWrap[0] = hGrid->minSrcSubband; + hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb]; + wrp_sfb = 6; + + /*2nd*/ + hGrid->sfbWrap[1+1] = wrp_sfb; + hGrid->sbWrap[1] = hGrid->minSrcSubband + IGF_ApplyTransFac(32, transFac); + hGrid->tile[1+1] = hGrid->swb_offset[wrp_sfb]; + wrp_sfb = 9; + + /*3nd*/ + hGrid->sfbWrap[2+1] = wrp_sfb; + hGrid->sbWrap[2] = hGrid->minSrcSubband; + hGrid->tile[2+1] = hGrid->swb_offset[wrp_sfb]; + + /*4nd*/ + hGrid->sfbWrap[3+1] = hGrid->stopSfb; + hGrid->sbWrap[3] = hGrid->minSrcSubband + (hGrid->swb_offset[9] - hGrid->swb_offset[8]); + hGrid->tile[3+1] = hGrid->swb_offset[hGrid->stopSfb]; + break; + case IGF_BITRATE_FB_48000: + case IGF_BITRATE_FB_96000: + case IGF_BITRATE_FB_128000: + hGrid->nTiles = 1; + + /*1st*/ + hGrid->sfbWrap[0+1] = hGrid->stopSfb; + hGrid->sbWrap[0] = 2*hGrid->startLine - hGrid->stopLine; + hGrid->tile[0+1] = hGrid->swb_offset[hGrid->stopSfb]; + + break; + default: + assert(0); + }/*switch*/ + + + /* adapt level envelope: */ + switch(bitRateIndex) + { + case IGF_BITRATE_RF_WB_13200: + case IGF_BITRATE_WB_9600: + hGrid->gFactor = 0.800f; + hGrid->fFactor = 0.70f; + hGrid->lFactor = 0.60f; + break; + case IGF_BITRATE_SWB_13200: + case IGF_BITRATE_FB_16400: + case IGF_BITRATE_SWB_16400: + hGrid->gFactor = 0.930f; + hGrid->fFactor = 0.20f; + hGrid->lFactor = 0.85f; + break; + case IGF_BITRATE_FB_24400: + case IGF_BITRATE_SWB_24400: + case IGF_BITRATE_FB_32000: + case IGF_BITRATE_SWB_32000: + hGrid->gFactor = 0.965f; + hGrid->fFactor = 0.20f; + hGrid->lFactor = 0.85f; + break; + case IGF_BITRATE_FB_48000: + case IGF_BITRATE_SWB_48000: + hGrid->gFactor = 1.000f; + hGrid->fFactor = 0.20f; + hGrid->lFactor = 1.000f; + break; + case IGF_BITRATE_SWB_9600: + case IGF_BITRATE_RF_SWB_13200: + default: + hGrid->gFactor = 1.000f; + hGrid->fFactor = 0.00f; + hGrid->lFactor = 1.000f; + } + + for ( t = hGrid->nTiles+1; t < IGF_MAX_TILES; t++) + { + hGrid->tile[t] = 0; + hGrid->sbWrap[t - 1] = 0; + hGrid->sfbWrap[t] = 0; + } + + return; +} + + +/*---------------------------------------------------------------------* + * IGFCommonFuncsWriteSerialBit() + * + * write bits to bitstream + *---------------------------------------------------------------------*/ + +void IGFCommonFuncsWriteSerialBit( + void *st, /**< in: | encoder/decoder state structure */ + int *pBitOffset, /**< out: | bit offset */ + int bit /**< in: | value of bit */ +) +{ + if (st) + { + push_next_indice(st, bit, 1); + } + (*pBitOffset)++; + + return; +} + + +/*---------------------------------------------------------------------* + * IGFCommonFuncsIGFConfiguration() + * + * changes the IGF configuration + *---------------------------------------------------------------------*/ + +int IGFCommonFuncsIGFConfiguration( /**< out: | error value: 0 -> error, 1 -> ok */ + int bitRate, /**< in: | bitrate in bs e.g. 9600 for 9.6kbs */ + int mode, /**< in: | bandwidth mode */ + H_IGF_INFO hIGFInfo, /**< out: | IGF info handle */ + int rf_mode /**< in: flag to signal the RF mode */ +) +{ + H_IGF_GRID hGrid; + int retValue; + int sampleRate; + int frameLength; + int igfMinFq; + int maxHopsize; + + retValue = 0; /* bitrate index is unknown -> error! */ + + /* interface call for reading in settings */ + hIGFInfo->bitRateIndex = IGF_MapBitRateToIndex( bitRate, mode, rf_mode ); + + if (hIGFInfo->bitRateIndex != IGF_BITRATE_UNKNOWN) + { + retValue = 1; /* no error */ + + /* mapping to local values */ + sampleRate = igfMode[(int)hIGFInfo->bitRateIndex].sampleRate; + frameLength = igfMode[(int)hIGFInfo->bitRateIndex].frameLength; + igfMinFq = igfMode[(int)hIGFInfo->bitRateIndex].igfMinFq; + maxHopsize = igfMode[(int)hIGFInfo->bitRateIndex].maxHopsize; + + /* basic information */ + hIGFInfo->sampleRate = sampleRate; + hIGFInfo->frameLength = frameLength; + hIGFInfo->maxHopsize = maxHopsize; + hIGFInfo->nfSeed = 0; + + /* 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, 1.00f, 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, 1.25f, 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, 0.50f, igfMinFq ); + } + + return retValue; +} + + +/*---------------------------------------------------------------------* + * IGFCommonFuncsIGFGetCFTables() + * + * selects cumulative frequency tables and offsets for the IGF SCF arithmetic coder + *---------------------------------------------------------------------*/ + +int IGFCommonFuncsIGFGetCFTables( /**< out: | error value: 0 -> error, 1 -> ok */ + int bitRate, /**< in: | bitrate in bs e.g. 9600 for 9.6kbs */ + int mode, /**< in: | bandwidth mode */ + int rf_mode, /**< in: | flag to signal the RF mode */ + const unsigned short **cf_se00, /**< out: | CF table for t == 0 and f == 0 */ + const unsigned short **cf_se01, /**< out: | CF table for t == 0 and f == 1 */ + short *cf_off_se01, /**< out: | offset for CF table above */ + const unsigned short **cf_se02, /**< out: | CF tables for t == 0 and f >= 2 */ + const short **cf_off_se02, /**< out: | offsets for CF tables above */ + const unsigned short **cf_se10, /**< out: | CF table for t == 1 and f == 0 */ + short *cf_off_se10, /**< out: | offset for CF table above */ + const unsigned short **cf_se11, /**< out: | CF tables for t == 1 and f >= 1 */ + const short **cf_off_se11 /**< out: | offsets for CF tables above */ +) +{ + int retValue; + short bitRateIndex; + + retValue = 0; /* bitrate index is unknown -> error! */ + bitRateIndex = IGF_MapBitRateToIndex( bitRate, mode, rf_mode ); + + if(bitRateIndex != IGF_BITRATE_UNKNOWN) + { + retValue = 1; /* no error */ + + 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]; + *cf_se02 = &cf_se02_tab[bitRateIndex][0][0]; + *cf_off_se02 = &cf_off_se02_tab[bitRateIndex][0]; + *cf_se10 = &cf_se10_tab[0]; + *cf_off_se10 = cf_off_se10_tab; + *cf_se11 = &cf_se11_tab[0][0][0]; + *cf_off_se11 = &cf_off_se11_tab[0][0]; + break; + case IGF_BITRATE_FB_16400: + case IGF_BITRATE_FB_24400: + case IGF_BITRATE_FB_32000: + bitRateIndex = 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]; + *cf_se02 = &cf_se02_tab[bitRateIndex][0][0]; + *cf_off_se02 = &cf_off_se02_tab[bitRateIndex][0]; + *cf_se10 = &cf_se10_tab[0]; + *cf_off_se10 = cf_off_se10_tab; + *cf_se11 = &cf_se11_tab[0][0][0]; + *cf_off_se11 = &cf_off_se11_tab[0][0]; + break; + case IGF_BITRATE_FB_48000: + bitRateIndex = 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]; + *cf_se02 = &cf_se02_tab[bitRateIndex][0][0]; + *cf_off_se02 = &cf_off_se02_tab[bitRateIndex][0]; + *cf_se10 = &cf_se10_tab[0]; + *cf_off_se10 = cf_off_se10_tab; + *cf_se11 = &cf_se11_tab[0][0][0]; + *cf_off_se11 = &cf_off_se11_tab[0][0]; + break; + case IGF_BITRATE_FB_96000: + case IGF_BITRATE_FB_128000: + bitRateIndex = IGF_BITRATE_SWB_48000; + *cf_se00 = cf_se00_tab; + *cf_se01 = cf_se01_tab[bitRateIndex]; + *cf_off_se01 = cf_off_se01_tab[bitRateIndex]; + *cf_se02 = &cf_se02_tab[bitRateIndex][0][0]; + *cf_off_se02 = &cf_off_se02_tab[bitRateIndex][0]; + *cf_se10 = &cf_se10_tab[0]; + *cf_off_se10 = cf_off_se10_tab; + *cf_se11 = &cf_se11_tab[0][0][0]; + *cf_off_se11 = &cf_off_se11_tab[0][0]; + break; + case IGF_BITRATE_UNKNOWN: + default: + assert(0); + } + } + + return retValue; +} diff --git a/lib_com/index_pvq_opt.c b/lib_com/index_pvq_opt.c new file mode 100644 index 000000000..6bf79cfbe --- /dev/null +++ b/lib_com/index_pvq_opt.c @@ -0,0 +1,1163 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" +#include "wmc_auto.h" + + +/*-------------------------------------------------------------------* + * LOCAL DEFINITIONS + *-------------------------------------------------------------------*/ + +#define N_OPT 5 /* complexity setting, direct functional calculation limit */ +#define TABLE_LIM_OPT 96 /* odd divisor table recursion limit setting, due to dim 6 */ + +/* local typedefs for optimized pvq indexing, used only in this c-file to vectorize common function calls for c-code clarity */ +typedef void (*VEC2INDFUNCM) (const short* , short* , unsigned int*, unsigned int*); +typedef unsigned int (*NFUNCM) (short); +typedef unsigned int (*H_FUNCM) ( unsigned int ); +typedef void (*IND2VECFUNCM) ( short, short, unsigned int, short* ) ; +typedef void (*NDIM_FUNCM) ( short, short, unsigned int, short* ); + +typedef unsigned long long ui64; /* Basop Mpy32_32_uu simulation */ + +/* local constants for indexing functions c-code clarity */ +#ifndef ONE_U + +#define ZERO 0 +#define ONE 1 +#define ONE_U 1u +#define TWO 2 +#define SIGNBIT 0x80000000u + +#define MAXBIT 0x40000000L /* if Word32 */ +#define MINNEG 0xffffffffL + +#define UDIVBY3 2863311531U + + +/*-------------------------------------------------------------------* + * local_norm_l_opt + * + * rewritten version of STL norm_l for "int" fixed point normalization + * in floating point c-code. + *-------------------------------------------------------------------*/ +static +short local_norm_l_opt ( /* o : shifts needed for normalization */ + int l32var /* i : signed 32bit input value */ +) +{ + short l32res; + +#define WMC_TOOL_SKIP + MAC(1); + + if (l32var == (int)MINNEG ) + { + return (32-ONE); + } + else + { + if (l32var == ZERO) + { + return ZERO; + } + else + { + if (l32var < ZERO) + { + l32var = ~l32var; + } + + for (l32res = ZERO; l32var < (int)MAXBIT; l32res++) + { + l32var <<= ONE; + } + } + } +#undef WMC_TOOL_SKIP + + return (l32res); +} + + + +/*-------------------------------------------------------------------* + * floor_sqrt_exact() + * returns x = floor(sqrt(input)); where (x*x) <= input + *-------------------------------------------------------------------*/ +unsigned int floor_sqrt_exact( /* o : floor(sqrt(input)) */ + unsigned int input /* i : unsigned input [0.. UINT_MAX/4] */ +) +{ + double _tmp; + unsigned int x; + if (input == ZERO) + { + return ZERO; + } + + _tmp = (double) input ; + x = (unsigned int)(sqrt( _tmp )); /* floor is a part of the cast */ + return x; +} + +/*-------------------------------------------------------------------* + * f_odd_exact_div_opt() + * + * find 1/(den1*2+1) * ( num1p*num2p - num3) , + * if the result is known a priori to be exactly a 32bit unsigned integer + *-------------------------------------------------------------------*/ +static +unsigned int f_odd_exact_div_opt( /* o : see Eq. */ + unsigned int num1p, /* i : see Eq. */ + unsigned int num2p, /* i : see Eq. */ + unsigned int num3, /* i : see Eq. */ + unsigned int den1 /* i : see Eq. */ +) +{ + unsigned int tmp; + tmp = exactdivodd[den1] * (num1p*num2p - num3); + + return (tmp); +} + +/*---------------------------------------------------------------------------* + * f_even_exact_div_opt() + * + * returns (num1p*num2p - num3 )/ den1 + * if the result is known a priori to be exactly a 32bit unsigned integer + *--------------------------------------------------------------------------*/ +static +unsigned int f_even_exact_div_opt( /* o : see Eq. */ + unsigned int num1p, /* i : see Eq. */ + unsigned int num2p, /* i : see Eq. range should be larger than num1p */ + unsigned int num3, /* i : see Eq. */ + int den1 /* i : see Eq. */ +) +{ + unsigned int tmp1, oddfactor, UL_tmp; + int den1_m1; + short even_sh; + unsigned int UL_tmp_h; + ui64 ULL_tmp; + + den1_m1 = den1 - ONE; /* remove top bit */ + even_sh = (31) - local_norm_l_opt((den1_m1)^den1); /* NB STL operation defined for signed positive 32 bit variable */ + oddfactor = exactdivodd[den1_m1>>even_sh]; + even_sh -= ONE; + + ULL_tmp = (ui64)num1p*(ui64)num2p; /* use STL Mpy_32_32_uu functionality */ + UL_tmp_h = (unsigned int)(ULL_tmp>>32); /* high output from basicop */ + UL_tmp = (unsigned int) (ULL_tmp); /* low output from basicop */ + + if(num3 > UL_tmp) + { + UL_tmp_h = UL_tmp_h - ONE_U; + } + UL_tmp = (UL_tmp - num3); /* can and should underflow */ + UL_tmp = (UL_tmp_h<<(32-even_sh))|(UL_tmp>>even_sh); /* bitwise OR */ + + /* use tabled modular multiplicative inverse for the odd part division */ + tmp1 = UL_tmp*oddfactor; + + + return tmp1; +} + +/*-------------------------------------------------------------------* + * a_three() + *-------------------------------------------------------------------*/ +static +unsigned int a_three( /* o: offset for dim 3 */ + unsigned int 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)); + } + else + { + return ZERO; + } +} + +/*-------------------------------------------------------------------* + * a_four() + *-------------------------------------------------------------------*/ +static +unsigned int a_four( /* o: offset for dim 4 */ + unsigned int k_val /* i: nb unit pulses */ +) +{ + if(k_val) + { + return UDIVBY3*((k_val<0,k=0) */ + h_mem[1] = ONE_U; /* % A(*,k=1) */ + + if(dim_in==2) + { + for( k_val = TWO; k_val <= k_val_in; k_val++) + { + h_mem[k_val] = (unsigned int)((k_val<>1 ; + } + return; +} + + +/*-------------------------------------------------------------------* + * a_fwd() + * + * create offsets for A(n,k) from lower A(n-1,k) + *-------------------------------------------------------------------*/ +static +void a_fwd( + unsigned int *a_in, /* i/o: offsets */ + short n_items /* i : items, k's */ +) +{ + unsigned int a_1; + short i,i_prev; + unsigned int a_in0 ; /* i : start column value */ + + a_in0 = ONE_U; + i_prev=ZERO; + for(i=ONE; i <= n_items; i++) /*basic A fwd row recursion */ + { + a_1 = a_in0 + a_in[i_prev] + a_in[i] ; /* a_in addressed in at least two locations */ + a_in[i_prev] = a_in0; + a_in0 = a_1; + i_prev = i; /* no real need to count as it is a ptr update */ + } + a_in[i_prev] = a_in0; + + return; +} + +/*-------------------------------------------------------------------* + * a_bwd() + * + * create offsets for A(n,k) from higher A(n+1,k) + *-------------------------------------------------------------------*/ +static +void a_bwd( + unsigned int *a_in, /* i/o: offsets */ + short n_items /* i: n_items */ +) +{ + unsigned int a_1; + unsigned int a_in0; + short i; + short i_prev; + + a_in0 = ZERO; + i_prev = ZERO; + for(i=ONE; i<=n_items; i++) /*basic A reverse row recursion */ + { + a_1 = a_in[i] - a_in0 - a_in[i_prev]; + a_in[i_prev] = a_in0; + a_in0 = a_1; + i_prev = i; + } + a_in[i_prev] = a_in0; + return; +} + +static +unsigned int direct_row_A2U_rec_calc(short dim_in , short k_val_in, unsigned int a_km2, unsigned int 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) */ + + unsigned int divisor, km2_size, result; + + divisor = (unsigned int)(k_val_in-ONE); + km2_size = (a_km1>>ONE) + (a_km2>>ONE) + ONE_U ; + + if(divisor&ONE_U) + { + /* odd */ + result = ( (a_km2>>ONE ) + f_odd_exact_div_opt((unsigned int)(dim_in), a_km1, km2_size , divisor>>ONE) ); + } + else + { + /* even divisor */ + result = ( (a_km2>>ONE) + f_even_exact_div_opt((unsigned int)dim_in,a_km1, km2_size, divisor ) ); + } + return result; +} + +static +void a_u_fwd( + unsigned int *a_u_in, + short k_val_in, + short mem_size_m1 +) +{ + unsigned int u_kp1_prev; + unsigned int a_k_prev ; + + /* mem_size_m1 = 1 + k_val_in */ + u_kp1_prev = a_u_in[mem_size_m1]; /* previous n U (n,k+1) value*/ + a_k_prev = a_u_in[k_val_in]; /* previous n A(n,k) value*/ + + a_fwd(&a_u_in[ONE], 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 */ + /* assert(a_k_prev>0, a_k-curr>0) */ + + a_u_in[mem_size_m1] = ONE_U + u_kp1_prev + (a_k_prev>>ONE) + (a_u_in[k_val_in] >>ONE); + + return; +} + +/*-------------------------------------------------------------------* + * nm_h_prep_opt() + * + * find and return N_MPVQ(n,k) and also offsets A(n, 0 to k ) and U(n,k+1). + *-------------------------------------------------------------------*/ +static +unsigned int nm_h_prep_opt( /* o: msize for dim */ + short dim_in, /* i: dimension */ + short k_val_in, /* i: nb unit pulses */ + unsigned int *h /* o: A/U offsets array */ +) +{ + short mem_size_m1, k_val ; + short dim_tmp, d_start; + unsigned int h_saveA, h_saveB; /* registers for alternating A(n,k-1), A(n,k-2)*/ + unsigned int numDsub1; /* k_val_curr, k_val_prev*/; + + mem_size_m1 = k_val_in + ONE; + + if( k_val_in > TABLE_LIM_OPT ) + { + if( dim_in >= 3 ) + { + d_start = 3; + } + else + { + d_start = 2; + } + initOffsets(d_start, h, k_val_in); + + for(dim_tmp = d_start; dim_tmp < dim_in; dim_tmp++) + { + a_u_fwd(h, k_val_in, mem_size_m1); + } + } + else + { + h[ZERO] = ZERO; + h[ONE] = ONE_U; + numDsub1=(unsigned int) ((dim_in << ONE) - ONE); + h[TWO] = numDsub1; + + /* interleaved odd even calls */ + h_saveA = numDsub1 ; + h_saveB = ONE_U; + for (k_val = 3; k_val < (mem_size_m1); k_val++ ) + { + /* 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 += f_even_exact_div_opt(numDsub1, h_saveA, h_saveB, k_val - ONE); + h[k_val] = h_saveB; + + k_val++; /* next even k, odd divisor */ + if( k_val >= (mem_size_m1)) + { + break; + } + h_saveA += f_odd_exact_div_opt(numDsub1, h_saveB, h_saveA, (k_val - ONE)>>ONE); + h[k_val] = h_saveA; + } + /* always do the last (k+1) recursion based on U(n,k+1) = func( A(n-2,k+1), A(n-1,k+1) ) */ + h[mem_size_m1] = direct_row_A2U_rec_calc(dim_in, mem_size_m1 , h[mem_size_m1-2], h[k_val_in]); + } + + /* N_MPVQ(n,k) = 1 + U(n,k+1) + U(n,k) = 1 + U(n,k+1) + (A(n,k)-1)/2 ; */ /* A(n,k) always odd */ + return ( ONE + h[mem_size_m1] + (h[k_val_in]>>ONE) ); +} + + +/* + find_amp_split_offset_func_mem() + 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 +short find_amp_split_offset_func_mem( + unsigned int ind_in, + short k_val_in, + H_FUNCM h_func_ptr, /* i: offset function pointer */ + unsigned int *h_mem , + short k_test, /* o: k_value */ + unsigned int *tmp_offset /* o: offset found */ +) +{ + short not_ready, low,high ; + + low = 0; + high = k_val_in; + /* split over A(n,k)= h_mem(k), or use direct function */ + not_ready = ONE ; + while(not_ready) + { + k_test = (low+high)>>ONE; /*% split range in half */ + + if(h_mem) + { + *tmp_offset = h_mem[k_test]; /* memory search */ + } + else + { + *tmp_offset = (*h_func_ptr)((unsigned int)k_test); /* function search. NB only line difference to the memory search*/ + } + + if(ind_in > *tmp_offset ) + { + if(k_test < high) + { + low = 1 + k_test ; + } + else + { + not_ready=0; + } + } + else + { + if (*tmp_offset == ind_in ) + { + not_ready=0; + } + else + { + high = k_test - 1; + } + } + } + return k_test; +} + + +/* + get_lead_sign() + update index and return leading sign +*/ +static +short get_lead_sign(unsigned int *ind) +{ + short leading_sign; + + if( (*ind)&ONE_U) /* leading sign stored in LSB */ + { + leading_sign = -1; + } + else + { + leading_sign = 1; + } + (*ind) = (*ind)>>ONE; + + return leading_sign; +} + + +/*-------------------------------------------------------------------* + * mind2vec_one() + *-------------------------------------------------------------------*/ +static +void mind2vec_one( + short k_val_in, /* i: nb unit pulses */ + short leading_sign, /* i: leading sign */ + unsigned int ind, /* i: index */ + short *vec_out /* o: pulse train */ +) +{ + ind = 0; /* to avoid compiler warings */ + + vec_out[ind] = (leading_sign*k_val_in); /* NB input k_val_in can be zero */ +} + +/*-------------------------------------------------------------------* + * mind2vec_two() + *-------------------------------------------------------------------*/ +static +void mind2vec_two( + short k_val_in, /* i: nb unit pulses */ + short leading_sign, /* i: leading sign */ + unsigned int ind_in, /* i: index */ + short *vec_out /* o: pulse train */ +) +{ + unsigned int ind_tmp; + short val1; + + if(k_val_in > 0) /* k_val_in check */ + { + if (ind_in==0) + { + vec_out[0] = (leading_sign*k_val_in); + vec_out[1] = 0; + } + else if (ind_in == ( (unsigned int)(k_val_in<>ONE)); + vec_out[0] = leading_sign*(k_val_in - val1) ; + + if(ind_tmp&ONE_U) + { + vec_out[1] = -val1 ; + } + else + { + vec_out[1] = val1; + } + } + } +} + +static +short setval_update_sign( + short k_delta, + short k_max_local, + short *leading_sign, + unsigned int *ind_in, + short *vec_out +) +{ + if(k_delta != 0 ) + { + *vec_out = (*leading_sign)*k_delta; + *leading_sign = get_lead_sign(ind_in); + k_max_local = k_max_local-k_delta ; + } + return k_max_local; +} + +/*-------------------------------------------------------------------* + * mind2vec_three() + *-------------------------------------------------------------------*/ +static +void mind2vec_three( + short k_max_local, /* i: nb unit pulses */ + short leading_sign, /* i: leading sign */ + unsigned int ind_in, /* i: index */ + short *vec_out /* o: pulse train */ +) +{ + short k_delta ; + unsigned int acc_val; + + /* + use direct calculation of first amplitude + (to find amplitudes faster than using split or linear iteration) + */ + if(ind_in==0) + { + vec_out[0] = leading_sign*k_max_local; + } + else + { + acc_val = ((ONE_U + floor_sqrt_exact((ind_in<>ONE ); /* in BASOP use approximation + search for exact sqrt )*/ + + k_delta = k_max_local - (short)acc_val; + ind_in -= a_three(acc_val); /* remove amplitude offset A(n,k_acc) */ + + k_max_local = setval_update_sign( k_delta, k_max_local, &leading_sign,&ind_in,vec_out); + + mind2vec_two( k_max_local, leading_sign, ind_in ,&vec_out[1] ); + } + return; +} + +/*-------------------------------------------------------------------* + * mind2vec_direct , + general function for direct decoding using direct functions + (no memory recursion) + *-------------------------------------------------------------------*/ +static +void mind2vec_direct( + short k_max_local, /* i: nb unit pulses */ + short leading_sign, /* i: leading sign */ + unsigned int ind, /* i: index */ + H_FUNCM h_func_ptr, /* i : offset function */ + NDIM_FUNCM nd_func_ptr, /* i : next dimension function */ + short *vec_out /* o: pulse train */ +) +{ + short k_delta, k_test=0; + unsigned int tmp_offset; + + if(ind==0) + { + vec_out[0] = leading_sign*k_max_local; + } + else + { + k_test = find_amp_split_offset_func_mem(ind,k_max_local, h_func_ptr , NULL, k_test, &tmp_offset); + + k_delta = k_max_local - k_test; + ind = ind - tmp_offset; /* % remove amplitude offset A(n,k_acc) */ + k_max_local = setval_update_sign( k_delta, k_max_local, &leading_sign, &ind,vec_out); + (*nd_func_ptr)( k_max_local, leading_sign, ind , &vec_out[1] ); + } + return; +} + +/*-------------------------------------------------------------------* + * mind2vec_four() + *-------------------------------------------------------------------*/ +static +void mind2vec_four( + short k_val_in, /* i: nb unit pulses */ + short leading_sign, /* i: leading sign */ + unsigned int ind_in, /* i: index */ + short *vec_out /* o: pulse train */ +) +{ + mind2vec_direct(k_val_in,leading_sign, ind_in, a_four, mind2vec_three, vec_out); + return; +} + +/*-------------------------------------------------------------------* + * mind2vec_five() + *-------------------------------------------------------------------*/ +static +void mind2vec_five( + short k_val_in , /* i: nb unit pulses */ + short leading_sign, /* i: leading sign */ + unsigned int ind_in, /* i: index */ + short *vec_out /* o: pulse train */ +) +{ + mind2vec_direct(k_val_in,leading_sign, ind_in, a_five, mind2vec_four, vec_out); + return; +} + + +/*-------------------------------------------------------------------* + * mind2vec() + *-------------------------------------------------------------------*/ +static +void mind2vec( + short dim_in, /* i: dimension */ + short k_max_local, /* i: nb unit pulses */ + short leading_sign, /* i: leading sign */ + unsigned int ind, /* i: index */ + short *vec_out, /* o: pulse train */ + unsigned int *h_in /* i: offset vector A=1+2U */ +) +{ + short pos; + short k_acc, k_delta; + unsigned int tmp_offset; + + k_acc = k_max_local; + + pos = ZERO; + while (pos < dim_in) /* first to last position decoding */ + { + if(ind == 0) + { + vec_out[pos] = leading_sign*k_max_local; + break; /* "fast" recursion exit */ + } + else + { + { + /* linear magnitude search */ + k_acc = k_max_local; + tmp_offset = h_in[k_acc]; + while(tmp_offset > ind) + { + k_acc = k_acc - 1; + tmp_offset = h_in[k_acc]; + } + } + k_delta = k_max_local - k_acc; /* amplitude decoding */ + } + ind = ind - tmp_offset; /* remove amplitude index offset A(n,k_acc) */ + + k_max_local = setval_update_sign( k_delta, k_max_local, &leading_sign, &ind, &vec_out[pos]); + + /* move from A(n,kmax) to A(n-1, k_max_local), */ + a_bwd( h_in,k_max_local + 1 ); /* [0..k_max_local], no need to calculate U(n,k_max_local+1) in index decoding */ + pos = pos + 1; + } + return; +} + + +/*-------------------------------------------------------------------* + * vec2mind_one() + *-------------------------------------------------------------------*/ +static +void vec2mind_one( + const short *vec_in, /* i : PVQ abs pulse train */ + short *k_val_out_ptr , /* o : number of unit pulses */ + unsigned int *next_sign_ind, /* i/o: next sign ind */ + unsigned int *ind /* o : MPVQ index */ +) +{ + *k_val_out_ptr = -1; /* just to avoid compiler warnings */ + + *ind = ZERO; + /* *k_val_out_ptr = (short)abs(*vec_in); */ /* dim==1, function not called recursively */ + *next_sign_ind = (unsigned int)(*vec_in < ZERO); /* single sign always pushed out of MPVQ */ + return; +} + +/*-------------------------------------------------------------------* +* vec2mind_two() +*-------------------------------------------------------------------*/ +static +void vec2mind_two( + const short *vec_in, /* i : PVQ pulse train */ + short *k_val_out_ptr, /* o : number of unit pulses */ + unsigned int *next_sign_ind, /* i/o: next sign ind */ + unsigned int *ind /* o: MPVQ index */ +) +{ + unsigned int lead_sign_ind; + short abs0,abs1,abs01; + + abs0 = (short) abs(vec_in[0]); + abs1 = (short) abs(vec_in[1]); + + abs01 = abs0+abs1; + *k_val_out_ptr = abs01; + + if(abs01==0) /* zeroes can happen in a recursive encoding call */ + { + *next_sign_ind = SIGNBIT; + *ind = ZERO; + } + else + { + *next_sign_ind=0; + if(abs1 == 0) + { + *ind = ZERO; + } + else if(abs0 == 0) + { + *ind = (unsigned int)(abs1< 0 ) + { + *k_val_out_ptr += tmp_val; + } + else + { + *k_val_out_ptr -= tmp_val; + } + return ; +} + + +/*-------------------------------------------------------------------* + * vec2mind_three() + *-------------------------------------------------------------------*/ +static +void vec2mind_three( + const short *vec_in, /* i : PVQ pulse train */ + short *k_val_out_ptr, /* o : number of unit pulses */ + unsigned int *next_sign_ind, /* i/o: next sign ind */ + unsigned int *index /* o: MPVQ index */ +) +{ + + + vec2mind_gen345(vec_in,k_val_out_ptr, next_sign_ind, index, vec2mind_two, a_three); + + return ; +} + +/*-------------------------------------------------------------------* + * vec2mind_four() + *-------------------------------------------------------------------*/ +static +void vec2mind_four( + const short *vec_in, /* i : PVQ pulse train */ + short *k_val_out_ptr, /* o : number of unit pulses */ + unsigned int *next_sign_ind, /* i/o: next sign ind */ + unsigned int *index /* o: MPVQ index */ +) +{ + + vec2mind_gen345(vec_in,k_val_out_ptr, next_sign_ind, index, vec2mind_three, a_four); + + return ; +} + +/*-------------------------------------------------------------------* + * vec2mind_five() + *-------------------------------------------------------------------*/ +static +void vec2mind_five( + const short *vec_in, /* i : PVQ abs pulse train */ + short *k_val_out_ptr, /* o : number of unit pulses */ + unsigned int *next_sign_ind, /* i/o: next sign ind */ + unsigned int *index /* o: MPVQ index */ +) +{ + + vec2mind_gen345(vec_in,k_val_out_ptr, next_sign_ind, index, vec2mind_four, a_five); + + return ; +} + + + +/*-------------------------------------------------------------------* + * vec2mind() + *-------------------------------------------------------------------*/ +static +void vec2mind( + short dim_in, /* i : dim */ + short k_val_in, /* i : number of unit pulses */ + const short *vec_in, /* i : PVQ pulse train */ + unsigned int *next_sign_ind, /* o : pushed leading sign */ + unsigned int *index , /* o : MPVQ index */ + unsigned int *N_MPVQ_ptr, /* o : size(N_MPVQ(dim,K_val_in))*/ + unsigned int *h_mem /* o : offsets */ +) +{ + short pos, mem_size_m1 ; + short k_val_acc ; + short tmp_val; + + + mem_size_m1 = k_val_in + ONE; + + *next_sign_ind = SIGNBIT; /* % should always be 0 or 1 out, highest bit set signals no sign found yet*/ + + + pos = dim_in - 2; /* % address 2nd last sample */ + vec2mind_two(&vec_in[pos],&k_val_acc,next_sign_ind ,index); + initOffsets( 3, h_mem, k_val_in) ; + + + for (pos--; pos>=0; pos--) + { + /* + % Check if the leading sign 'bit' is to be added + */ + tmp_val = vec_in[pos]; + if( ((*next_sign_ind&SIGNBIT)==0 && (tmp_val != 0)) ) + { + *index = (*index<0 */ + + k_val_acc += (short)abs(tmp_val);/*% now increase acc k value for next N */ + + + if(pos) + { + a_u_fwd(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 */ + } + } + + /* 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 = ONE_U + (h_mem[k_val_acc]>>ONE) + h_mem[ mem_size_m1 ] ; /* total size size */ + + return; +} + +/*--------------------------------------------------------------------------* + * mpvq_encode_vec() + * + * returns struct with leading sign index, MPVQ-index , dim and N_MPVQ + *-------------------------------------------------------------------------*/ + +PvqEntry mpvq_encode_vec( /* o : leading_sign_index, index, size, k_val */ + const short *vec_in, /* i : signed pulse train */ + short dim_in, /* i : dimension */ + short k_val_local /* i : nb unit pulses */ +) +{ + PvqEntry result; + unsigned int h_mem[1+KMAX_NON_DIRECT+1]; /* allocate max offset memory for dim 6 */ + /* OPT: actually only 1+k_val_in+1 needed ) */ + unsigned int lead_sign_ind; + + VEC2INDFUNCM vec2mind_f[1+N_OPT] = { (VEC2INDFUNCM)NULL, vec2mind_one, vec2mind_two, vec2mind_three, vec2mind_four, vec2mind_five }; + /* VEC2INDFUNCM can be a static global */ + + + result.k_val = k_val_local; + result.dim = dim_in; + + /* NB, k_val_local may be changed in some sub encoding routines */ + if( dim_in > N_OPT) /* use the generic dimension function */ + { + vec2mind(dim_in, k_val_local, vec_in, &lead_sign_ind, &result.index, &result.size, h_mem); + } + else /* if (dim_in<=N_OPT) */ + { + (vec2mind_f[dim_in])(vec_in, &k_val_local, &lead_sign_ind, &result.index); + result.size = direct_msize(dim_in, k_val_local); /* k_val_local not used for dim==1 */ + } + result.lead_sign_ind=(short)lead_sign_ind; + + return result; +} + +/*-------------------------------------------------------------------* + * get_size_mpvq_calc_offset() + * + * unsigned int h_mem[1 + KMAX +1 ]; + * example using fixed size of offset vector input help variable + *-------------------------------------------------------------------*/ + +PvqEntry get_size_mpvq_calc_offset( /* o : size, dim, k_val */ + short dim_in, /* i : dimension */ + short k_val_in, /* i : nb unit pulses */ + unsigned int* h_mem /* o : offsets */ +) +{ + PvqEntry entry; + + entry.dim = dim_in; + entry.k_val = k_val_in; + entry.index = 0U; /* avoid gcc warning in struct passing */ + entry.lead_sign_ind = 0; /* avoid gcc warning in struct passing */ + if(dim_in > N_OPT ) /* non-direct solutions, use A+U relation */ + { + entry.size = nm_h_prep_opt(entry.dim, entry.k_val, h_mem); + } + else + { + entry.size = direct_msize(dim_in, entry.k_val); /* ues equations, h_mem is not used */ + } + + + return entry; +} + +/*-------------------------------------------------------------------* + * mpvq_decode_vec() + *-------------------------------------------------------------------*/ + +void mpvq_decode_vec( /* o : void */ + const PvqEntry *entry, /* i : sign_ind, index, dim, k_val */ + unsigned int *h_mem, /* i : A/U offsets */ + short *vec_out /* o : pulse train */ +) +{ + short i, leading_sign; + IND2VECFUNCM mind2vec_f[N_OPT+1] = { (IND2VECFUNCM)NULL, mind2vec_one, mind2vec_two, mind2vec_three, mind2vec_four, mind2vec_five }; + /*IND2VECFUNCM vector can be static global */ + + + for(i=0; idim; i++) + { + vec_out[i]=ZERO; /* set all of short output vector to zero */ + } + + leading_sign = 1; + if(entry->lead_sign_ind) + { + leading_sign = -1; + } + + if(entry->k_val != 0) + { + if(entry->dim > N_OPT ) /* N_OPT */ + { + /* generic */ + mind2vec(entry->dim, entry->k_val, leading_sign, entry->index, vec_out, h_mem); + } + else + { + /* specialized functions */ + (mind2vec_f[entry->dim])(entry->k_val, leading_sign, entry->index, vec_out); + } + } + return; +} + +#ifdef ONE_U +#undef ZERO +#undef ONE +#undef ONE_U +#undef TWO +#undef MAXBIT +#undef MINNEG +#undef SIGNBIT +#undef UDIVBY3 +#endif + + + +#endif diff --git a/lib_com/int_lsp.c b/lib_com/int_lsp.c new file mode 100644 index 000000000..5146a7439 --- /dev/null +++ b/lib_com/int_lsp.c @@ -0,0 +1,140 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*---------------------------------------------------------------------* + * int_lsp() + * + * Find the interpolated LSP parameters for all subframes + *---------------------------------------------------------------------*/ + +void int_lsp( + const short L_frame, /* i : length of the frame */ + const float lsp_old[], /* i : LSPs from past frame */ + const float lsp_new[], /* i : LSPs from present frame */ + float *Aq, /* o : LP coefficients in both subframes */ + const short m, /* i : order of LP filter */ + const float *int_coeffs, /* i : interpolation coefficients */ + const short Opt_AMR_WB /* i : flag indicating AMR-WB IO mode */ +) +{ + float lsp[M], fnew, fold; + short i, k; + const float *pt_int_coeffs; + + if( L_frame == L_FRAME ) + { + pt_int_coeffs = int_coeffs; + } + else /* L_frame == L_FRAME16k */ + { + pt_int_coeffs = interpol_frac_16k; + } + + for( k=0; kcore_brate == SID_1k75 ) + { + indice[0] = (short)get_next_indice( st, 6 ); + indice[1] = (short)get_next_indice( st, 6 ); + indice[2] = (short)get_next_indice( st, 6 ); + indice[3] = (short)get_next_indice( st, 5 ); + indice[4] = (short)get_next_indice( st, 5 ); + + disf_ns_28b( indice, isf_new ); + + reorder_isf( isf_new, ISF_GAP, M, INT_FS_12k8 ); + + isf2isp( isf_new, isp_new, M, INT_FS_12k8 ); + + /* return if SID frame (conversion to A(z) done in the calling function) */ + return; + } + + /*-----------------------------------------------------------------* + * ISF de-quantization of all other frames + *-----------------------------------------------------------------*/ + + if( st->core_brate == ACELP_6k60 ) + { + indice[0] = (short)get_next_indice( st, 8 ); + indice[1] = (short)get_next_indice( st, 8 ); + indice[2] = (short)get_next_indice( st, 7 ); + indice[3] = (short)get_next_indice( st, 7 ); + indice[4] = (short)get_next_indice( st, 6 ); + + disf_2s_36b( indice, isf_new, st->mem_AR, st->mem_MA ); + } + else + { + indice[0] = (short)get_next_indice( st, 8 ); + indice[1] = (short)get_next_indice( st, 8 ); + indice[2] = (short)get_next_indice( st, 6 ); + indice[3] = (short)get_next_indice( st, 7 ); + indice[4] = (short)get_next_indice( st, 7 ); + indice[5] = (short)get_next_indice( st, 5 ); + indice[6] = (short)get_next_indice( st, 5 ); + + disf_2s_46b( indice, isf_new, st->mem_AR, st->mem_MA); + } + + reorder_isf( isf_new, ISF_GAP, M, INT_FS_12k8 ); + + /* convert quantized ISFs to ISPs */ + isf2isp( isf_new, isp_new, M, INT_FS_12k8 ); + + /*-------------------------------------------------------------------------------------* + * FEC - update adaptive mean ISF vector + *-------------------------------------------------------------------------------------*/ + + for ( i=0; ilsf_adaptive_mean[i] = (st->lsfoldbfi1[i] + st->lsfoldbfi0[i] + isf_new[i]) / 3; + } + + /*-------------------------------------------------------------------------------------* + * ISP interpolation + * A(z) calculation + *-------------------------------------------------------------------------------------*/ + + if( st->rate_switching_reset ) + { + /*extrapolation instead of interpolation*/ + mvr2r( isp_new, st->lsp_old, M ); + mvr2r( isf_new, st->lsf_old, M ); + } + + /* ISP interpolation and A(z) calculation */ + int_lsp( L_FRAME, st->lsp_old, isp_new, Aq, M, interpol_isp_amr_wb, 1 ); + + /*------------------------------------------------------------------* + * Check ISF stability : distance between old ISF and current ISF + *------------------------------------------------------------------*/ + + st->stab_fac = lsf_stab( isf_new, st->lsf_old, 1, st->L_frame ); + + return; +} + +/*-------------------------------------------------------------------* + * disf_ns_28b() + * + * ISF de-quantizer for SID_1k75 frames (only for AMR-WB IO mode) + *-------------------------------------------------------------------*/ + +void disf_ns_28b( + short *indice, /* i : quantized indices (use indice[0] = -1 in the decoder) */ + float *isf_q /* o : ISF in the frequency domain (0..6400) */ +) +{ + short i; + + for (i = 0; i < 2; i++) + { + isf_q[i] = dico1_ns_28b[indice[0]*2+i]; + } + + for (i = 0; i < 3; i++) + { + isf_q[i+2] = dico2_ns_28b[indice[1]*3+i]; + isf_q[i+5] = dico3_ns_28b[indice[2]*3+i]; + } + + for (i = 0; i < 4; i++) + { + isf_q[i+8] = dico4_ns_28b[indice[3]*4+i]; + isf_q[i+12] = dico5_ns_28b[indice[4]*4+i]; + } + + for (i=0; i +#include "wmc_auto.h" +#include "options.h" +#include "prot.h" +#include "cnst.h" +#include "rom_com.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define kLagWinThGain1 0.6f +#define kLagWinThGain2 0.3f + + +/*-------------------------------------------------------------* + * procedure lag_wind() * + * ~~~~~~~~~ * + * lag windowing of the autocorrelations * + *-------------------------------------------------------------*/ + +void lag_wind( + float r[], /* i/o: autocorrelations */ + const short m, /* i : order of LP filter */ + const int sr, /* i : sampling rate */ + const short strength /* i : LAGW_WEAK, LAGW_MEDIUM, or LAGW_STRONG */ +) +{ + short i; + const float *wnd; + + assert(0 <= strength && strength <= NUM_LAGW_STRENGTHS); + + switch (sr) + { + case 8000: + assert(m <= 16); + assert(strength == LAGW_STRONG); + wnd = lag_window_8k; + break; + case 12800: + assert(m <= 16); + wnd = lag_window_12k8[strength]; + break; + case 16000: + assert(m <= 16); + wnd = lag_window_16k[strength]; + break; + case 24000: + case 25600: + assert(m <= 16); + wnd = lag_window_25k6[strength]; + break; + case 32000: + assert(m <= 16); + wnd = lag_window_32k[strength]; + break; + case 48000: + assert(m <= 16); + assert(strength == LAGW_STRONG); + wnd = lag_window_48k; + break; + default: + assert(!"Lag window not implemented for this sampling rate"); + return; + } + + for( i=0; i<=m; ++i ) + { + r[i] *= wnd[i]; + } + + return; +} + +/*-------------------------------------------------------------* + * procedure adapt_lag_wind() + * + * + *-------------------------------------------------------------*/ + +void adapt_lag_wind( + float r[], /* i/o: autocorrelations */ + int m, /* i : order of LP filter */ + const int Top, /* i : open loop pitch lags from curr. frame (or NULL if n/a) */ + const float Tnc, /* i : open loop pitch gains from curr. frame (NULL if n/a) */ + int sr /* i : sampling rate */ +) +{ + short strength; + short pitch_lag; + float pitch_gain; + + pitch_lag = (short)Top; + pitch_gain = (float)Tnc; + + if (pitch_lag < 80) + { + if (pitch_gain > kLagWinThGain1) + { + strength = LAGW_STRONG; + } + else + { + strength = LAGW_MEDIUM; + } + } + else if (pitch_lag < 160) + { + if (pitch_gain > kLagWinThGain2) + { + strength = LAGW_MEDIUM; + } + else + { + strength = LAGW_WEAK; + } + } + else + { + strength = LAGW_WEAK; + } + + lag_wind( r, m, sr, strength ); + + return; +} diff --git a/lib_com/lerp.c b/lib_com/lerp.c new file mode 100644 index 000000000..2a57d5e85 --- /dev/null +++ b/lib_com/lerp.c @@ -0,0 +1,143 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "prot.h" + + +/*-------------------------------------------------------------* + * procedure lerp() * + * * + * * + *-------------------------------------------------------------*/ + +static void lerp_proc( + float *f, + float *f_out, + int bufferNewSize, + int bufferOldSize +); + + +void lerp( + float *f, + float *f_out, + int bufferNewSize, + int bufferOldSize +) +{ + float maxFac; + + maxFac = 507.0/128.0; + + if( (float)bufferNewSize / bufferOldSize > maxFac ) + { + int tmpNewSize = bufferOldSize*2; + while(bufferNewSize > bufferOldSize) + { + if( (float)bufferNewSize / bufferOldSize <= maxFac ) + { + tmpNewSize = bufferNewSize; + } + + lerp_proc(f, f_out, tmpNewSize, bufferOldSize); + + f = f_out; + bufferOldSize = tmpNewSize; + tmpNewSize *= 2; + } + } + else if( (float)bufferOldSize / bufferNewSize > maxFac ) + { + int tmpNewSize = bufferOldSize/2; + while(bufferNewSize < bufferOldSize) + { + if( (float)bufferOldSize / bufferNewSize <= maxFac ) + { + tmpNewSize = bufferNewSize; + } + + lerp_proc(f, f_out, tmpNewSize, bufferOldSize); + + f = f_out; + bufferOldSize = tmpNewSize; + tmpNewSize /= 2; + } + } + else + { + lerp_proc(f, f_out, bufferNewSize, bufferOldSize); + } +} + +void lerp_proc( + float *f, + float *f_out, + int bufferNewSize, + int bufferOldSize +) +{ + int i, idx; + float pos, shift, diff; + float buf[2*L_FRAME_MAX]; + + + if( bufferNewSize == bufferOldSize ) + { + mvr2r( f, buf, bufferNewSize ); + mvr2r( buf, f_out, bufferNewSize ); + return; + } + + /* Using the basop code to avoid reading beyond end of input for bufferOldSize=320, bufferNewSize=640 */ + shift = (float)(L_shl(L_deposit_l(div_s( bufferOldSize, shl(bufferNewSize, 4))), 4-15+16))/65536.0f; + pos = 0.5f * shift - 0.5f; + + if (shift < 0.3f) + { + pos = pos - 0.13f; + } + + /* first point of interpolation */ + if( pos<0 ) + { + buf[0]=f[0]+pos*(f[1]-f[0]); + } + else + { + idx=(int)pos; + diff = pos - idx; + buf[0] = f[idx] + diff * (f[idx+1]-f[idx]); + } + + pos += shift; + + for ( i=1; i bufferOldSize-1 ) + { + idx=bufferOldSize-2; + } + + diff = pos - idx; + + buf[bufferNewSize-1] = f[idx]+diff*(f[idx+1]-f[idx]); + + mvr2r( buf, f_out, bufferNewSize ); + + return; +} diff --git a/lib_com/limit_t0.c b/lib_com/limit_t0.c new file mode 100644 index 000000000..336ef58ab --- /dev/null +++ b/lib_com/limit_t0.c @@ -0,0 +1,201 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.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( + const short L_frame, /* i : length of the frame */ + const short delta, /* i : Half the close-loop searched interval */ + const short pit_flag, /* i : selecting absolute(0) or delta(1) pitch quantization */ + const short limit_flag, /* i : flag for Q limits (0=restrained, 1=extended) */ + const short T0, /* i : rough pitch estimate around which the search is done */ + const short T0_frac, /* i : pitch estimate fractional part */ + short *T0_min, /* o : lower pitch limit */ + short *T0_max /* o : higher pitch limit */ +) +{ + short delta2, T1; + short pit_min, pit_max; + + if( limit_flag == 0 ) /* restrained Q limits */ + { + /* set limits */ + if( L_frame == L_FRAME ) + { + pit_max = PIT_MAX; + pit_min = PIT_MIN; + } + else /* L_frame == L_FRAME16k */ + { + pit_max = PIT16k_MAX; + pit_min = PIT16k_MIN; + } + + delta2 = 2 * delta - 1; + + T1 = T0; + if( T0_frac >= 2 ) + { + T1++; + } + *T0_min = T1 - delta; + + if( *T0_min < pit_min ) + { + *T0_min = pit_min; + } + *T0_max = *T0_min + delta2; + + if( *T0_max > pit_max ) + { + *T0_max = pit_max; + *T0_min = *T0_max - delta2; + } + } + else /* extended Q limits */ + { + + /* set limits */ + if( L_frame == L_FRAME ) + { + pit_max = PIT_MAX; + pit_min = PIT_MIN_EXTEND; + + if( limit_flag == 2 ) + { + pit_min = PIT_MIN_DOUBLEEXTEND; + } + } + else /* L_frame == L_FRAME16k */ + { + pit_max = PIT16k_MAX; + pit_min = PIT16k_MIN_EXTEND; + } + + delta2 = 2 * delta - 1; + + T1 = T0; + if( T0_frac >= 2 ) + { + T1++; + } + *T0_min = T1 - delta; + + if( pit_flag == 0 ) + { + /* subframes with absolute search: keep Q range */ + if( *T0_min < pit_min ) + { + *T0_min = pit_min; + } + *T0_max = *T0_min + delta2; + + if( *T0_max > pit_max ) + { + *T0_max = pit_max; + *T0_min = *T0_max - delta2; + } + } + else + { + /* subframes with relative search: extend Q range */ + if( *T0_min < pit_min - LIMIT_PIT_REL_LOWER ) + { + *T0_min = pit_min - LIMIT_PIT_REL_LOWER; + } + + if( *T0_min < L_INTERPOL ) + { + *T0_min = L_INTERPOL ; + } + *T0_max = *T0_min + delta2; + + if( *T0_max > pit_max + LIMIT_PIT_REL_UPPER ) + { + *T0_max = pit_max + LIMIT_PIT_REL_UPPER; + *T0_min = *T0_max - delta2; + } + } + } + + return; +} + +#define WMC_TOOL_SKIP + +/*-------------------------------------------------* +* Routine limit_T0_voiced() +* +* Close-loop pitch lag search limitation +*-------------------------------------------------*/ + +void limit_T0_voiced( + int nbits, + int res, + int T0, /* i : rough pitch estimate around which the search is done */ + int T0_frac, /* i : pitch estimate fractional part */ + int T0_res, /* i : pitch resolution */ + int *T0_min, /* o : lower pitch limit */ + int *T0_min_frac, /* o : lower pitch limit */ + int *T0_max, /* o : higher pitch limit */ + int *T0_max_frac, /* o : higher pitch limit */ + int pit_min, /* i : Minimum pitch lag */ + int pit_max /* i : Maximum pitch lag */ +) +{ + short T1, temp1, temp2; + + + /* Mid-point */ + T1 = T0; + if( (T0_res > 1) && (T0_frac >= (T0_res>>1)) ) + { + T1++; + } + + /* Lower-bound */ + temp1 = (T1*res) - (1<<(nbits-1)); + temp2 = temp1 / res; + *T0_min = temp2; + *T0_min_frac = temp1 - temp2*res; + if ( *T0_min < pit_min) + { + *T0_min = pit_min; + *T0_min_frac = 0; + } + + /* Higher-bound */ + temp1 = (*T0_min*res) + *T0_min_frac + (1< pit_max) + { + *T0_max = pit_max; + *T0_max_frac = res - 1; + temp1 = (*T0_max*res) + *T0_max_frac - (1< +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include "prot.h" /* Function prototypes */ + +/*-------------------------------------------------------------------------- + * logqnorm() + * + * Log quantization for norms of sub-vectors + *--------------------------------------------------------------------------*/ + +void logqnorm( + const float *x, /* i : coefficient vector */ + short *k, /* o : index */ + const short L, /* i : codebook length */ + const short N, /* i : sub-vector size */ + const float *thren /* i : quantization thresholds */ +) +{ + short i, j, j1, j2; + float temp, power; + + + temp = 0.0; + for (i=0; i 0) + { + *k = L - 1; + } + else + { + power = (float)sqrt(temp); + + j1 = 0; + j2 = L - 1; + while ((j2-j1)>1) + { + j = (j1 + j2) >> 1; + if ( power >= thren[j] ) + { + j2 = j; + } + else + { + j1 = j; + } + } + + *k = j2; + } + + return; +} + + +/*-------------------------------------------------------------------------- + * logqnorm_2() + * + * + *--------------------------------------------------------------------------*/ + +void logqnorm_2( + const float *env_fl, /* o : index */ + const short L, /* i : codebook length */ + const short n_env_band, /* i : sub-vector size */ + const short nb_sfm, /* i : sub-vector size */ + short *ynrm, + short *normqlg2, + const float *thren /* i : quantization thresholds */ +) +{ + short i, j, j1, j2; + float temp, power; + + for(i=n_env_band; i 0) + { + *ynrm = L - 1; + } + else + { + power = temp; + j1 = 0; + j2 = L - 1; + while ((j2-j1)>1) + { + j = (j1 + j2) >> 1; + if ( power >= thren[j] ) + { + j2 = j; + } + else + { + j1 = j; + } + } + *ynrm = j2; + } + *normqlg2 = dicnlg2[*ynrm]; + normqlg2++; + ynrm++; + } + + return; +} + +/*-------------------------------------------------------------------------- + * calc_norm() + * + * Calculate the norms for the spectral envelope + *--------------------------------------------------------------------------*/ + +void calc_norm( + const float *x, /* i : Input vector. */ + short *norm, /* o : Quantization indices for norms */ + short *normlg, /* o : Quantized norms in log2 */ + const short start_band, /* i : Indice of band to start coding */ + const short num_bands, /* i : Number of bands */ + const short *band_len, /* i : Length of bands */ + const short *band_start /* i : Start of bands */ +) +{ + short nrm; + short band; + + set_s(norm, 0, start_band); + + logqnorm(&x[band_start[start_band]], &nrm, 32, band_len[start_band], thren_HQ); + norm[start_band] = nrm; + normlg[start_band] = dicnlg2[nrm]; + + for (band = start_band + 1; band < start_band + num_bands; band++) + { + logqnorm( &x[band_start[band]], &nrm, 40, band_len[band], thren_HQ ); + norm[band] = nrm; + normlg[band] = dicnlg2[nrm]; + } + + return; +} diff --git a/lib_com/longarith.c b/lib_com/longarith.c new file mode 100644 index 000000000..14e92de75 --- /dev/null +++ b/lib_com/longarith.c @@ -0,0 +1,164 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "prot.h" + + +#define WMC_TOOL_SKIP + + +/** + * \brief long addition: a[] = a[] + b[] + * Addition of unsigned vectors a[] and b[] without saturation. + * All words of b[] are added with carry to the corresponding words in a. + * An assertion failure occurs, if lenb exceeds lena or if overflow occurs. + * + * \param unsigned short a[] + * Input/Output: vector of the length lena + * \param unsigned short b[] + * Input: vector of the length lenb + * \param int lena + * Input: length of vector a[] in units of 'unsigned short' + * Note: lena must be greater/equal lenb + * \param int lenb + * Input: length of vector b[] in units of 'unsigned short' + * + * \return void + */ + +void longadd(unsigned short a[], unsigned short b[], int lena, int lenb) +{ + int h; + long carry = 0; + + assert(lena >= lenb); + for (h=0; h < lenb; h++) + { + carry += ((unsigned long)a[h]) + ((unsigned long)b[h]); + a[h] = (unsigned short) carry; + carry = carry >> 16; + } + for (; h < lena; h++) + { + carry = ((unsigned long)a[h]) + carry; + a[h] = (unsigned short) carry; + carry = carry >> 16; + } + + assert(carry == 0); /* carry != 0 indicates addition overflow */ + return; +} + +/** + * \brief long shift right: d[] = a[] >> b + * Logical shift right of unsigned vectors a[] by b bit-positions. + * Vector d[] is filled with leading zeroes, where lend exceeds lena. + * It is allowed to overlay d[] with a[]. + * + * \param unsigned short a[] + * Input: vector of the length lena + * \param int b + * Input: number of bit positions to shift right + * \param unsigned short d[] + * Output: vector of the length lend + * Note: vector d[] can be overlaid with vector a[], i.e. a[] = a[] >> b + * \param int lena + * Input: length of vector a[] in units of 'unsigned short' + * \param int lend + * Input: length of vector d[] in units of 'unsigned short' + * + * \return void + */ + +void longshiftright(unsigned short a[], int b, unsigned short d[], int lena, int lend) +{ + int intb, fracb, fracb_u, k; + + + intb = b >> 4; + + a += intb; + lena -= intb; + + fracb = b & 0xF; + if (fracb) + { + fracb_u = 16-fracb; + for (k=0; k < lena-1; k++) + { + d[k] = ((a[k] >> fracb) | (a[k+1] << fracb_u)) & 0xFFFF; + } + d[k] = (a[k] >> fracb); + k++; + } + else + { + for (k=0; k < lena; k++) + { + d[k] = a[k]; + } + } + /* fill remaining upper bits with zero */ + for (; k < lend; k++) + { + d[k] = 0; + } + return; +} + +/** + * \brief long shift left: d[] = a[] << b + * Logical shift left of unsigned vectors a[] by b bit-positions. + * It is allowed to overlay d[] with a[]. + * + * \param unsigned short a[] + * Input: vector of the length len + * \param int b + * Input: number of bit positions to shift left + * \param unsigned short d[] + * Output: vector of the length len + * Note: vector d[] can be overlaid with vector a[], i.e. a[] = a[] << b + * \param int len + * Input: length of vector a[] and d[] in units of 'unsigned short' + * + * \return void + */ + +void longshiftleft(unsigned short a[], int b, unsigned short d[], int len) +{ + int intb; /* integer part of b */ + int fracb; /* shift left value for all upper words a[k] */ + int fracb_l; /* shift right value for all lower words a[k-1] */ + int k = len - 1; + + + intb = b >> 4; + fracb = b & 0xF; + + if (fracb) + { + fracb_l = 16-fracb; + for (; k >intb; k--) + { + d[k] = (a[k-intb] << fracb) | (a[k-intb-1] >> fracb_l); + } + d[k] = (a[k-intb] << fracb); + k--; + } + else + { + for (; k >= intb; k--) + { + d[k] = a[k-intb]; + } + } + for ( ; k >= 0; k--) + { + d[k] = 0; + } + return; +} diff --git a/lib_com/low_rate_band_att.c b/lib_com/low_rate_band_att.c new file mode 100644 index 000000000..62018f3d2 --- /dev/null +++ b/lib_com/low_rate_band_att.c @@ -0,0 +1,162 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "rom_com.h" +#include "prot.h" + + +/*--------------------------------------------------------------------------* + * fine_gain_pred() + * + * Fine gain prediction + *--------------------------------------------------------------------------*/ + +void fine_gain_pred( + const short *sfm_start, /* i : Sub band start indices */ + const short *sfm_end, /* i : Sub band end indices */ + const short *sfm_size, /* i : Sub band bandwidths */ + const short *i_sort, /* i : Energy sorting indices */ + const short *K, /* i : Number of pulses per band */ + const short *maxpulse, /* i : Maximum pulse per band */ + const short *R, /* i : Bits per sub band (Q3) */ + const short num_sfm, /* i : Number of sub bands */ + float *xq, /* i/o: Quantized vector /quantized vector with finegain adj */ + short *y, /* i/o: Quantized vector (int) */ + float *fg_pred, /* o : Predicted fine gains */ + const short core /* i : Core */ +) +{ + short i, band; + float gp; + float xx; + float accuracy; + short k, bw; + float att; + + for( band = 0; band < num_sfm; band++) + { + + k = K[i_sort[band]]; + if(k > 0) + { + bw = sfm_size[i_sort[band]]; + xx = 0; + for(i = sfm_start[i_sort[band]]; i < sfm_end[i_sort[band]]; i++) + { + xx += xq[i] * xq[i]; + } + + if ( xx > 0) + { + /* Normalize synthesis to RMS=1.0 */ + gp = (float) sqrt(bw / xx); + + if (core == HQ_CORE && R != NULL && R[i_sort[band]] <= 256) + { + accuracy = ((float)k/(float)bw)*maxpulse[i_sort[band]]; + att = 1.0f - 0.05f / accuracy; + att = max( 0.840896f, att); /* Limit attenuation to norm quantizer error, 2^-0.25 */ + gp *= att; + } + + fg_pred[band] = gp; + } + else + { + fg_pred[band] = 0; + } + } + else + { + fg_pred[band] = 0; + for(i = sfm_start[i_sort[band]]; i < sfm_end[i_sort[band]]; i++) + { + y[i] = 0; + xq[i] = 0; + } + } + } + return; +} + +/*--------------------------------------------------------------------------* + * get_max_pulses() + * + * Find the maximum pulse height (in unit pulses) in each band + *--------------------------------------------------------------------------*/ + +void get_max_pulses( + const short *band_start, /* i : Sub band start indices */ + const short *band_end, /* i : Sub band end indices */ + const short *k_sort, /* i : Indices for sorting by energy */ + const short *npulses, /* i : Pulses per sub band */ + const short BANDS, /* i : Number of bands */ + short *inp_vector, /* i/o: Encoded shape vectors (int)*/ + short *maxpulse /* o : Maximum pulse height per band */ +) +{ + short i, k; + int npul; + int maxp; + + for (k = 0; k < BANDS; k++) + { + npul = npulses[k_sort[k]]; + maxp = 0; + if (npul > 0) + { + for (i = band_start[k_sort[k]]; i < band_end[k_sort[k]]; i++) + { + if (abs(inp_vector[i]) > maxp) + { + maxp = abs(inp_vector[i]); + } + } + } + maxpulse[k_sort[k]] = maxp; + } + + return; +} + +/*--------------------------------------------------------------------------* + * fine_gain_dec() + * + * Fine gain decoder. Decodes fine gain adjustments and applies correction to + * predicted fine gains + *--------------------------------------------------------------------------*/ + +void fine_gain_dec +( + Decoder_State *st, /* i/o: Decoder state struct */ + const short *ord, /* i : Indices for energy order */ + const short num_sfm, /* i : Number of bands */ + const short *gain_bits, /* i : Gain adjustment bits per sub band */ + float *fg_pred /* i/o: Predicted gains / Corrected gains */ +) +{ + short band; + short gbits; + short idx; + float gain_dbq; + + for ( band = 0; band < num_sfm; band++) + { + gbits = gain_bits[ord[band]]; + if ( fg_pred[band] != 0 && gbits > 0 ) + { + idx = (short)get_next_indice( st, (short)gbits ); + gain_dbq = finegain[gbits-1][idx]; + + /* Update prediced gain with quantized correction */ + fg_pred[band] *= (float)pow(10, gain_dbq * 0.05f); + } + } + + return; +} diff --git a/lib_com/lpc_tools.c b/lib_com/lpc_tools.c new file mode 100644 index 000000000..71c0ad5d6 --- /dev/null +++ b/lib_com/lpc_tools.c @@ -0,0 +1,300 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + + +/*-----------------------------------------------------------------* + * Local constants + *-----------------------------------------------------------------*/ + +#define MAX_LEN_LP 960 +#define SCALE1_LPC 2037.1832275390625f /* LSP to LSF conversion factor */ + + +/*---------------------------------------------------------------------* + * autocorr() + * + * Compute autocorrelations of input signal + *---------------------------------------------------------------------*/ + +void autocorr( + const float *x, /* i : input signal */ + float *r, /* o : autocorrelations vector */ + const short m, /* i : order of LP filter */ + const short len, /* i : window size */ + const float *wind, /* i : window */ + const short rev_flag, /* i : flag to reverse window */ + const short sym_flag, /* i : symmetric window flag */ + const short no_thr /* i : flag to avoid thresholding */ +) +{ + float t[MAX_LEN_LP]; + float s; + short i, j; + + /* Windowing of signal */ + if (rev_flag == 1) + { + /* time reversed window */ + for (i = 0; i < len; i++) + { + t[i] = x[i] * wind[len-i-1]; + } + } + else if( sym_flag == 1 ) + { + /* symmetric window of even length */ + for( i=0; i 0.99945f) + { + flag=1;/* Test for unstable filter. If unstable keep old A(z) */ + } + + for ( j = 1; j <= i/2; j++ ) + { + l = i-j; + at = a[j] + rc[i-1] * a[l]; + a[l] += rc[i-1] * a[j]; + a[j] = at; + } + + a[i] = rc[i-1]; + + err += rc[i-1] * s; + if ( err <= 0.0f ) + { + err = 0.01f; + } + + if ( epsP != NULL) + { + epsP[i] = err; + } + } + + return (flag); +} + + +/*---------------------------------------------------------------------* + * E_LPC_int_lpc_tcx() + * + * + *---------------------------------------------------------------------*/ + +void E_LPC_int_lpc_tcx( + const float lsf_old[], /* input : LSFs from past frame */ + const float lsf_new[], /* input : LSFs from present frame */ + float a[] /* output: interpolated LP coefficients */ +) +{ + int i; + float lsf[M]; + + for (i = 0; i < M; i++) + { + lsf[i] = lsf_old[i]*0.125f + lsf_new[i]*0.875f; + } + + lsp2a_stab(lsf, a, M); + + return; +} + +/*---------------------------------------------------------------------* + * lsp_reorder() + * + * + *---------------------------------------------------------------------*/ + +static void lsp_reorder( + float *lsp, /* (I/O): lsp vector (acos() domain) */ + float min_dist, /* (I): minimum required distance */ + int lpcorder /* (I): LPC order */ +) +{ + short i; + float lsp_min, lsp_max; + + /* Verify the LSF ordering and minimum GAP */ + lsp_min = min_dist; + + for (i=0; i lsp_max) + { + /* Reverify the minimum LSF gap in the reverse sense */ + for (i = lpcorder-1; i>=0; --i) + { + if (lsp[i] > lsp_max) + { + lsp[i] = lsp_max; + } + lsp_max = lsp[i] - min_dist; + } + } + + return; +} + + +/*---------------------------------------------------------------------* + * E_LPC_lsp_unweight() + * + * Approximate unweighting + *---------------------------------------------------------------------*/ + +int E_LPC_lsp_unweight( + float lsp_w[], /* (I): weighted lsp */ + float lsp_uw[], /* (O): unweighted lsp */ + float lsf_uw[], /* (O): unweighted lsf */ + float inv_gamma /* (I): inverse weighting factor */ +) +{ + float lsp_w_orig[M], lsp_w_diff[M], mean, step; + const lsp_unw_triplet *unw_coeffs = NULL; + short i; + + /* Table selection */ + if ((float)fabs(inv_gamma - 1.0f / 0.94f) < 0.0001f) + { + unw_coeffs = p16_gamma0_94to1; + } + else if ((float)fabs(inv_gamma - 1.0f / 0.92f) < 0.0001f) + { + unw_coeffs = p16_gamma0_92to1; + } + else + { + assert(0); + } + + step = EVS_PI/(float)(M+1); + mean = step; + + /* Apply acos() and get mean removed version */ + for (i=0; i +#include "wmc_auto.h" +#include +#include +#include +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*---------------------------------------------------------------------* +* routine: lsf_dec_bfi() +* +* Estimate the lsfs in case of FER +* Bad frame, all active speech coders +*---------------------------------------------------------------------*/ + +void lsf_dec_bfi( + short codec_mode, /* i: : codec mode: MODE1 | MODE2 */ + float *lsf, /* o : estimated LSF vector */ + const float *lsfold, /* i : past quantized lsf */ + float *lsf_adaptive_mean, /* i : lsf adaptive mean, updated when BFI==0 */ + const float lsfBase[], /* i : base for differential lsf coding */ + float *mem_MA, /* i/o: quantizer memory for MA model */ + float *mem_AR, /* o : quantizer memory for AR model */ + float stab_fac, /* i : lsf stability factor */ + short last_coder_type, /* i : last coder type */ + short L_frame, /* i : frame length */ + const short last_good, /* i : last good received frame */ + const short nbLostCmpt, /* i : counter of consecutive bad frames */ + int plcBackgroundNoiseUpdated, /* i : background noise alreadyupdated? */ + float *lsf_q_cng, /* o : quantized lsfs of background noise */ + float *lsf_cng, /* i : long term target for fading to bg noise*/ + float *old_lsf_q_cng, /* i : old quantized lsfs for background noise*/ + short Last_GSC_pit_band_idx, /* i : AC mode (GSC) - Last pitch band index */ + short Opt_AMR_WB, /* i : IO flag */ + const short MODE1_bwidth /* i : coded bandwidth */ +) +{ + short i; + float alpha, tmp; + float lsf_mean[M]; + const float* pt_meansForFading; + const float* pt_meansForMemUpdate; + float beta; + + /* init vectors */ + if (codec_mode == MODE1) + { + pt_meansForMemUpdate = &lsf_mean[0]; + + if( Opt_AMR_WB ) + { + pt_meansForFading = mean_isf_amr_wb; + } + else + { + if( L_frame == L_FRAME ) + { + if( MODE1_bwidth == NB ) + { + pt_meansForFading = GENB_Ave; + } + else + { + pt_meansForFading = GEWB_Ave; + } + } + else + { + pt_meansForFading = GEWB2_Ave; + } + } + } + else + { + pt_meansForFading = pt_meansForMemUpdate = lsfBase; + if (lsf_cng != NULL && plcBackgroundNoiseUpdated) + { + pt_meansForFading = lsf_cng; + } + } + + /*----------------------------------------------------------------------* + * Initialize the alpha factor + *----------------------------------------------------------------------*/ + + if( nbLostCmpt <= 3 ) + { + if(last_coder_type == UNVOICED) + { + /* clearly unvoiced */ + alpha = ALPHA_UU; + } + else if( last_coder_type == AUDIO || last_good == INACTIVE_CLAS ) + { + if( Last_GSC_pit_band_idx > 0 && nbLostCmpt > 1 ) + { + alpha = 0.8f; + } + else + { + alpha = 0.995f; + } + } + else if(last_good == UNVOICED_CLAS ) + { + if( nbLostCmpt <= 1 ) + { + /* if stable, do not flatten the spectrum in the 1st erased frame */ + alpha = stab_fac * (1.0f - 2.0f*ALPHA_U) + 2.0f*ALPHA_U; /* [0.8, 1.0] */ + } + else if( nbLostCmpt == 2 ) + { + alpha = ALPHA_U*1.5f; /* 0.6 */ + } + else + { + /* go rapidly to CNG spectrum */ + alpha = ALPHA_U; + } + } + else if(last_good == UNVOICED_TRANSITION ) + { + alpha = ALPHA_UT; + } + else if(last_good == VOICED_CLAS || last_good == ONSET ) + { + /* clearly voiced - mild convergence to the CNG spectrum for the first 3 erased frames */ + alpha = ALPHA_V; + } + else if(last_good == SIN_ONSET) + { + alpha = ALPHA_S; + } + else + { + alpha = ALPHA_VT; + } + } + else + { + alpha = 1.f/nbLostCmpt; + } + + if( codec_mode == MODE1 ) + { + beta = BETA_FEC; + } + else + { + if( plcBackgroundNoiseUpdated ) + { + beta = 0.f; + } + else + { + beta = 0.25f; + } + } + + for( i=0; i L_FRAME */ + { + reorder_lsf( lsf, MODE1_LSF_GAP, M, L_frame * 50 ); + if(lsf_q_cng!=NULL) + { + reorder_lsf(lsf_q_cng, MODE1_LSF_GAP, M, L_frame * 50); + } + } + } + /* update the AR memory to be used in the next frame */ + mvr2r( lsf, mem_AR, M ); + + for(i=0; i +#include "wmc_auto.h" +#include +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include "stl.h" +#include "basop_proto_func.h" + +/*---------------------------------------------------------------------* + * midlsf_dec() + * + * + *---------------------------------------------------------------------*/ + +void midlsf_dec( + float qlsf0[], + float qlsf1[], + short idx, + float qlsf[], + int N, + int coder_type, + short *mid_lsf_int, + short prev_bfi, + short safety_net +) +{ + const float *ratio=NULL; + int j; + short bad_spacing = 0; + /* Select codebook */ + if ( coder_type == UNVOICED ) + { + ratio = tbl_mid_unv_wb_5b; + } + else + { + ratio = tbl_mid_gen_wb_5b; + } + + for (j=0; j 0 && j < N && qlsf[j] < qlsf[j-1] + LSF_GAP_MID ) + { + qlsf[j] = qlsf[j-1] + LSF_GAP_MID; + } + + } + } + else + { + /* otherwise, use regular LSF spacing and ordering as in the encoder */ + for (j=0; j 0 && j < N && qlsf[j] < qlsf[j-1] + LSF_GAP_MID ) + { + qlsf[j] = qlsf[j-1] + LSF_GAP_MID; + } + + } + } + if ( prev_bfi ) + { + /* continue redoing mid-LSF interpolation with 0.4 in order not to propagate the error */ + *mid_lsf_int = 1; + } + if ( safety_net ) + { + /* safety-net encountered -> stop redoing mid-LSF interpolation with 0.4 */ + *mid_lsf_int = 0; + } + } + else + { + /* use regular LSF spacing */ + for (j=0; j 0 && j < N && qlsf[j] < qlsf[j-1] + LSF_GAP_MID ) + { + qlsf[j] = qlsf[j-1] + LSF_GAP_MID; + } + } + } + + return; +} + + +/*---------------------------------------------------------------------* + * lsf_ind_is_active() + * + * + *---------------------------------------------------------------------*/ + +int lsf_ind_is_active( + const Word16 lsf_q_ind[], + const float means[], + int narrowband, + int cdk +) +{ + Word16 lsf[2], min_distance; + + lsf[0] = add(lsf_q_ind[0], LSFM(means[0])); + move16(); + lsf[1] = add(lsf_q_ind[1], LSFM(means[1])); + move16(); + + min_distance = lsf[0]; + 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.c b/lib_com/lsf_tools.c new file mode 100644 index 000000000..2f8e2a59b --- /dev/null +++ b/lib_com/lsf_tools.c @@ -0,0 +1,2343 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include "basop_proto_func.h" + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static float chebps2(const float x, const float *f, const short n); +static float LPC_chebyshev (float x, float f[], int n); +static void get_isppol( const float *isp, float f[], const short n ); + +/*---------------------------------------------------------------------* + * a2isp() + * + * Compute the ISPs from the LPC coefficients a[] using Chebyshev + * polynomials. The found ISPs are in the cosine domain with values + * in the range from 1 down to -1. + * The table grid[] contains the points (in the cosine domain) at + * which the polynomials are evaluated. + * + * The ISPs are the roots of the two polynomials F1(z) and F2(z) + * defined as + * F1(z) = [A(z) + z^-M A(z^-1)] + * and F2(z) = [A(z) - z^-M A(z^-1)]/ (1-z^-2) + * + * For an even order M=2N, F1(z) has M/2 conjugate roots on the unit circle + * and F2(z) has M/2-1 conjugate roots on the unit circle in addition to two + * roots at 0 and pi. + * + * For a 16th order LP analysis (M=16), F1(z) and F2(z) can be written as + * + * F1(z) = (1 + a[16]) * PRODUCT (1 - 2 cos(w_i) z^-1 + z^-2 ) + * i=0,2,...,14 + * + * F2(z) = (1 - a[16]) * PRODUCT (1 - 2 cos(w_i) z^-1 + z^-2 ) + * i=1,3,...,13 + * + * The ISPs are frequencies w_i, i=0...M-2 plus the last predictor + * coefficient a[M]. + *---------------------------------------------------------------------*/ + +void a2isp( + const float *a, /* i: LP filter coefficients */ + float *isp, /* o: Immittance spectral pairs */ + const float *old_isp /* i: ISP vector from past frame */ +) +{ + short j, i, nf, ip, order; + float xlow,ylow,xhigh,yhigh,xmid,ymid,xint; + float f1[NC+1], f2[NC]; + float *coef; + + /*-------------------------------------------------------------* + * 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.0f) || (a[M] < -1.0f) ) + { + for( i=0; i 1; i--) + { + f2[i] -= f2[i-2]; + } + + /*-----------------------------------------------------------------* + * 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.0f + isp[m-1]); + f2[i] *= (1.0f - isp[m-1]); + } + + /*-----------------------------------------------------------------* + * A(z) = (F1(z)+F2(z))/2 * + * F1(z) is symmetric and F2(z) is asymmetric * + *-----------------------------------------------------------------*/ + + a[0] = 1.0f; + for (i=1, j=m-1; i= 4) + { + temp2 = LPC_chebyshev (temp, q + offset, order_by_2); + } + else + { + temp2 = temp + q[0 + offset]; + } + + if ((temp2 * prev[iswitch]) <= 0.0 || frequency >= 0.5) + { + if (STEPindex == STEPSNUM - 1) + { + if (fabs (temp2) < fabs (prev[iswitch])) + { + freq[lspnumber] = frequency; + } + else + { + freq[lspnumber] = frequency - STEP; + } + if ((prev[iswitch]) < 0.0) + { + prev[iswitch] = 9e9f; + } + else + { + prev[iswitch] = -9e9f; + } + root = 0; + frequency = LastFreq; + STEPindex = 0; + } + else + { + if (STEPindex == 0) + { + LastFreq = frequency; + } + frequency -= STEPS[++STEPindex]; /* Go back one grid step */ + STEP = STEPS[STEPindex]; + } + } + else + { + prev[iswitch] = temp2; + frequency += STEP; + } + } /* while(root) */ + + lspnumber++; + if (lspnumber > order - 1) + { + notlast = 0; + } + iswitch = 1 - iswitch; + } /* while (notlast) */ + + /* stability check */ + space_min = 1; + for( i=1; i < order; i++ ) + { + space_min = ((freq[i] - freq[i-1]) < space_min)?(freq[i] - freq[i-1]): space_min; + } + + if( space_min <= 0 ) + { + return 0; + } + + return 1; +} + +/*-------------------------------------------------------------------* + * lsp2a() + * + * Convert LSPs to predictor coefficients a[] + *-------------------------------------------------------------------*/ + +void lsp2a ( + float *pc_in, /* i/o: predictor coefficients */ + float *freq, /* i/o: LSP coefficients */ + const short order /* i : order of LP analysis */ +) +{ + float p[LPC_SHB_ORDER], q[LPC_SHB_ORDER]; + float a[LPC_SHB_ORDER], a1[LPC_SHB_ORDER], a2[LPC_SHB_ORDER]; + float b[LPC_SHB_ORDER], b1[LPC_SHB_ORDER], b2[LPC_SHB_ORDER]; + + float xx; + int i, k; + int lspflag; + float *pc; + int order_by_2; + + lspflag = 1; + pc = &(pc_in[1]); + + order_by_2 = order / 2; + + /* check input for ill-conditioned cases */ + if ((freq[0] <= 0.0) || (freq[order - 1] >= 0.5)) + { + lspflag = 0; + + if (freq[0] <= 0) + { + freq[0] = 0.022f; + } + + if (freq[order - 1] >= 0.5) + { + freq[order - 1] = 0.499f; + } + } + + if (!lspflag) + { + xx = (freq[order - 1] - freq[0]) * recip_order[order]; + for (i = 1; i < order; i++) + { + freq[i] = freq[i - 1] + xx; + } + } + + for (i = 0; i <= order_by_2; i++) + { + a[i] = 0.; + a1[i] = 0.; + a2[i] = 0.; + b[i] = 0.; + b1[i] = 0.; + b2[i] = 0.; + } + + for (i = 0; i < order_by_2; i++) + { + p[i] = (float)cos (6.2832 * freq[2 * i]); + q[i] = (float)cos (6.2832 * freq[2 * i + 1]); + } + + a[0] = 0.25f; + b[0] = 0.25f; + + for (i = 0; i < order_by_2; i++) + { + a[i + 1] = a[i] - 2 * p[i] * a1[i] + a2[i]; + b[i + 1] = b[i] - 2 * q[i] * b1[i] + b2[i]; + a2[i] = a1[i]; + a1[i] = a[i]; + b2[i] = b1[i]; + b1[i] = b[i]; + } + a[0] = 0.25f; + b[0] = -0.25f; + + for (i = 0; i < order_by_2; i++) + { + a[i + 1] = a[i] - 2 * p[i] * a1[i] + a2[i]; + b[i + 1] = b[i] - 2 * q[i] * b1[i] + b2[i]; + a2[i] = a1[i]; + a1[i] = a[i]; + b2[i] = b1[i]; + b1[i] = b[i]; + } + + pc[0] = 2 * (a[order_by_2] + b[order_by_2]); + + for (k = 2; k <= order; k++) + { + a[0] = 0.0f; + b[0] = 0.0f; + + for (i = 0; i < order_by_2; i++) + { + a[i + 1] = a[i] - 2 * p[i] * a1[i] + a2[i]; + b[i + 1] = b[i] - 2 * q[i] * b1[i] + b2[i]; + a2[i] = a1[i]; + a1[i] = a[i]; + b2[i] = b1[i]; + b1[i] = b[i]; + } + pc[k - 1] = 2 * (a[order_by_2] + b[order_by_2]); + } + + return; +} + +/*-----------------------------------------------------------* + * get_lsppol() + * + * 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,..,n-2 + * F2(z) = product ( 1 - 2 LSF_i z^-1 + z^-2 ) + * i=1,3,5,..,n-1 + * + * where LSP_i are the LSPs in the cosine domain. + *-----------------------------------------------------------*/ + +static void get_lsppol( + const float lsp[], /* i : line spectral freq. (cosine domain) */ + float f[], /* o : the coefficients of F1 or F2 */ + const short n, /* i : no of coefficients (m/2) */ + short flag /* i : 1 ---> F1(z) ; 2 ---> F2(z) */ +) +{ + float b; + const float *plsp; + int i,j; + + plsp = lsp + flag - 1; + + f[0] = 1.0f; + b = -2.0f * *plsp; + f[1] = b; + + for (i = 2; i <= n; i++) + { + plsp += 2; + b = -2.0f * *plsp; + f[i] = b*f[i-1] + 2.0f*f[i-2]; + + for (j = i-1; j > 1; j--) + { + f[j] += b*f[j-1] + f[j-2]; + } + + f[1] += b; + } + + return; +} + +/*---------------------------------------------------------------------* + * a2lsp_stab() + * + * Compute the LSPs from the LPC coefficients a[] using Chebyshev + * polynomials. The found LSPs are in the cosine domain with values + * in the range from 1 down to -1. + * The table grid[] contains the points (in the cosine domain) at + * which the polynomials are evaluated. + * + * The ISPs are the roots of the two polynomials F1(z) and F2(z) + * defined as + * F1(z) = [A(z) + z^-M A(z^-1)]/ (1+z^-1) + * and F2(z) = [A(z) - z^-M A(z^-1)]/ (1-z^-1) + *---------------------------------------------------------------------*/ + +void a2lsp_stab( + const float *a, /* i: LP filter coefficients */ + float *lsp, /* o: LSP vector */ + const float *old_lsp /* i: LSP vector from past frame */ +) +{ + short j, i, nf, ip; + float xlow, ylow, xhigh, yhigh, xmid, ymid, xint; + float *pf1, *pf2; + const float *pa1, *pa2; + float f1[NC+1], f2[NC+1]; + + /*-------------------------------------------------------------* + * 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) * + *-------------------------------------------------------------*/ + + pf1 = f1; /* Equivalent code using indices */ + pf2 = f2; + *pf1++ = 1.0f; /* f1[0] = 1.0; */ + *pf2++ = 1.0f; /* f2[0] = 1.0; */ + pa1 = a + 1; + pa2 = a + M; + + for( i=0; i<=NC-1; i++ ) /* for (i=1, j=M; i<=NC; i++, j--) */ + { + *pf1 = *pa1 + *pa2 - *(pf1-1); /* f1[i] = a[i]+a[j]-f1[i-1]; */ + *pf2 = *pa1++ - *pa2-- + *(pf2-1);/* f2[i] = a[i]-a[j]+f2[i-1]; */ + pf1++; + pf2++; + } + + /*---------------------------------------------------------------------* + * 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; /* number of found frequencies */ + ip=0; /* flag to first polynomial */ + + pf1 = f1; /* start with F1(z) */ + + xlow = grid100[0]; + ylow = chebps2( xlow, pf1, NC ); + + j = 0; + while( (nf < M) && (j < GRID100_POINTS) ) + { + j++; + xhigh = xlow; + yhigh = ylow; + xlow = grid100[j]; + ylow = chebps2( xlow, pf1, NC ); + + if( ylow*yhigh <= 0.0 ) /* if sign change new root exists */ + { + j--; + /* divide the interval of sign change by NO_ITER */ + for (i = 0; i < NO_ITER; i++) + { + xmid = 0.5f * ( xlow + xhigh ); + ymid = chebps2( xmid, pf1, NC ); + if( ylow*ymid <= 0.0 ) + { + yhigh = ymid; + xhigh = xmid; + } + else + { + ylow = ymid; + xlow = xmid; + } + } + + /* linear interpolation for evaluating the root */ + ymid = (yhigh - ylow); + xint = xlow; + if ( ymid != 0 && ylow != 0) /* whenever ylow is 0, it doesn't make sense to compute the remaining part of the equation */ + { + xint -= ylow * (xhigh - xlow) / (ymid); + } +#ifdef DEBUG + else if (ymid == 0 && ylow != 0) + { + fprintf(stderr, "issue in a2lsp_stab\n"); + } +#endif + lsp[nf] = xint; /* new root */ + nf++; + ip = 1 - ip; /* flag to other polynomial */ + pf1 = ip ? f2 : f1; /* pointer to other polynomial */ + xlow = xint; + ylow = chebps2( xlow, pf1, NC ); + } + } + + /* Check if M roots found */ + /* if not use the LSPs from previous frame */ + if( nf < M ) + { + + for( i=0; i 0; i--) */ + { + *pf1-- += *pf1_1--; /* f1[i] += f1[i-1]; */ + *pf2-- -= *pf2_1--; /* f2[i] -= f2[i-1]; */ + } + + /*-----------------------------------------------------* + * A(z) = (F1(z)+F2(z))/2 * + * F1(z) is symmetric and F2(z) is antisymmetric * + *-----------------------------------------------------*/ + + pa1 = a; + *pa1++ = 1.0; /* a[0] = 1.0; */ + pa2 = a + m; + pf1 = f1 + 1; + pf2 = f2 + 1; + for (i = 0; i <= k; i++) /* for (i=1, j=M; i<=NC; i++, j--) */ + { + *pa1++ = 0.5f*(*pf1 + *pf2); /* a[i] = 0.5*(f1[i] + f2[i]); */ + *pa2-- = 0.5f*(*pf1++ - *pf2++);/* a[j] = 0.5*(f1[i] - f2[i]); */ + } + + return; +} + +/*--------------------------------------------------------------------------- + * reorder_lsf() + * + * To make sure that the LSFs are properly ordered and to keep a certain + * minimum distance between consecutive LSFs. + *--------------------------------------------------------------------------*/ + +void reorder_lsf( + float *lsf, /* i/o: LSF vector */ + const float min_dist, /* i : minimum required distance */ + const short n, /* i : LPC order */ + const float fs /* i : sampling frequency */ +) +{ + short i; + float lsf_min; + float lsf_max; + + /*-----------------------------------------------------------------* + * Verify the LSF ordering and minimum GAP + *-----------------------------------------------------------------*/ + + lsf_min = min_dist; + for (i = 0; i < n; i++) + { + if (lsf[i] < lsf_min) + { + lsf[i] = lsf_min; + } + lsf_min = lsf[i] + min_dist; + } + + /*------------------------------------------------------------------------------------------* + * Reverify the LSF ordering and minimum GAP in the reverse order (security) + *------------------------------------------------------------------------------------------*/ + + lsf_max = fs/2.0f - min_dist; + + if( lsf[n-1] > lsf_max ) /* If danger of unstable filter in case of resonance in HF */ + { + for (i = n-1; i >=0; i--) /* Reverify the minimum LSF gap in the reverse sens */ + { + if (lsf[i] > lsf_max) + { + lsf[i] = lsf_max; + } + + lsf_max = lsf[i] - min_dist; + } + } + + return; +} + +/*-------------------------------------------------------------------* + * space_lsfs() + * + *-------------------------------------------------------------------*/ + +void space_lsfs ( + float *lsfs, /* i/o: Line spectral frequencies */ + const short order /* i : order of LP analysis */ +) +{ + float delta; + short i, flag = 1; + + while (flag == 1) + { + flag = 0; + for (i = 0; i <= order; i++) + { + delta = (float)( i == 0 ? lsfs[0] : (i == order ? 0.5f - lsfs[i - 1] : (lsfs[i] - lsfs[i -1]))); + if (delta < SPC) + { + flag = 1; + delta -= SPC_plus; + if (i == order) + { + lsfs[i - 1] += delta; + } + else + { + if (i == 0) + { + lsfs[i] -= delta; + } + else + { + delta *= 0.5f; + lsfs[i - 1] += delta; + lsfs[i] -= delta; + } + } + } + } + } + + return; +} + +/*-------------------------------------------------------------------* + * lsp_weights() + * + *-------------------------------------------------------------------*/ + +void lsp_weights ( + const float *lsps, /* i : Line spectral pairs */ + float *weight, /* o : weights */ + const short order /* i : order of LP analysis */ +) +{ + short i; + float delta1, delta2; + + for (i = 0; i < order; i++) + { + delta1 = (float)((i == 0) ? lsps[i] : lsps[i] - lsps[i - 1]); + delta2 = (float)((i == order - 1) ? 0.5f - lsps[i] : lsps[i + 1] - lsps[i]); + + weight[i] = 250 * root_a_over_b(ALPHA_SQ, delta1 * delta2); + } + + if (order != LPC_SHB_ORDER_WB) + { + weight[3] *= 1.1f; + weight[4] *= 1.1f; + } + + return; +} + + +/*-----------------------------------------------------------------------* + * isf2isp() + * + * Transformation of ISF to ISP + * + * ISP are immitance spectral pairs in cosine domain (-1 to 1). + * ISF are immitance spectral pairs in frequency domain (0 to fs/2). + *-----------------------------------------------------------------------*/ + +void isf2isp( + const float isf[], /* i : isf[m] normalized (range: 0<=val<=fs/2) */ + float isp[], /* o : isp[m] (range: -1<=val<1) */ + const short m, /* i : LPC order */ + const float fs /* i : sampling frequency */ +) +{ + short i; + + for(i=0; i= 0; m--) + { + km = f[m]; + if (km <= -1.0 || km >= 1.0) + { + for ( j = 0; j < lpcorder; j++ ) + { + refl[j] = 0.f; + } + + return; + } + + refl[m] = -km; + denom = 1.0f / (1.0f - km * km); + + for (j = 0; j < m / 2; j++) + { + n = m - 1 - j; + x = denom * f[j] + km * denom * f[n]; + f[n] = denom * f[n] + km * denom * f[j]; + f[j] = x; + } + + if (m & 1) + { + f[j] = denom * f[j] + km * denom * f[j]; + } + } + + return; +} + + +/*----------------------------------------------------------------------------------* + * vq_dec_lvq() + * + * Multi-stage VQ decoder for LSF parameters, last stage LVQ + *----------------------------------------------------------------------------------*/ + +short vq_dec_lvq ( + short sf_flag, /* i : safety net flag */ + float x[], /* o : Decoded vector */ + short indices[], /* i : Indices */ + short stages, /* i : Number of stages */ + short N, /* i : Vector dimension */ + short mode, /* (i): mode_lvq, or mode_lvq_p */ + short no_bits, /* (i): no. bits for lattice */ + unsigned int *p_offset_scale1, + unsigned int *p_offset_scale2, + unsigned int *p_offset_scale1_p, + unsigned int *p_offset_scale2_p, + short *p_no_scales, + short *p_no_scales_p +) +{ + float x_lvq[16]; + short i; + short ber_flag; + /* clear vector */ + set_f(x, 0, N); + + /*-----------------------------------------------* + * add contribution of each stage + *-----------------------------------------------*/ + + if (sf_flag == 1) + { + for(i=0; i -1) + { + if (nbits0>0) /* */ + { + n_stages = 2; + levels0[0] = CBsizes[nbits0]; + bits0[0] = nbits0; + bits0[1] = cumleft-nbits0; + + if ( bits0[1] == 0 ) + { + n_stages--; + } + else + { + levels0[1] = CBsizes[cumleft-nbits0]; + } + } + else /* no bits for VQ stage */ + { + n_stages = 0; + } + + *stages0 = n_stages; + if(bits_lvq > 0) + { + bits0[n_stages] = bits_lvq; + levels0[n_stages] = bits_lvq; /* this is number of bits, not levels */ + *stages0 = n_stages+1; + } + } + else + { + *stages0 = 0; + } + + /*---------------------------------------------------* + * Calculate bit allocation for predictive quantizer + *---------------------------------------------------*/ + + if ( framemode_p > -1 ) + { + cumleft = BitsVQ_p[framemode_p]; + bits_lvq = nBits - cumleft; + nbits0 = CBbits_p[framemode_p]; + + if (nbits0 > -1) + { + if ( nbits0 > 0 ) + { + if ( framemode_p == 7 ) + { + /* for UNVOICED_WB only */ + n_stages = 3; + for( i=0; i0) + { + levels1[1] = CBsizes[nbits0]; + bits1[1] = nbits0; + n_stages = 2; + } + + levels1[n_stages] = bits_lvq; /* this is number of bits, not levels */ + bits1[n_stages] = bits_lvq; + *stages1 = n_stages+1; + } + } + else + { + *stages1 = 1; + bits1[0] = bits_lvq; + levels1[0] = bits_lvq; + } + } + else + { + fprintf(stderr, "lsf_allocate(): invalid number of bits in used predictive mode\n"); + exit(-1); + } + } + + return; +} + +/*----------------------------------------------------------------------------------* + * find_pred_mode() + * + * + *----------------------------------------------------------------------------------*/ + +short find_pred_mode( + const short coder_type, + const short bwidth, + const float int_fs, + short * p_mode_lvq, + short * p_mode_lvq_p, + short core_brate +) +{ + short idx, predmode; + + idx = bwidth; + if (idx>1) + { + idx = 1; + } + if ((int_fs == INT_FS_16k)) + { + idx = 2; + } + else + { + if ((core_brate>=GENERIC_MA_LIMIT)&&(coder_type==GENERIC) + &&(idx==1) + ) + { + idx = 3; + } + } + + predmode = predmode_tab[idx][coder_type]; + + if (idx<=2) + { + *p_mode_lvq = NO_CODING_MODES*idx + coder_type; + if (predmode>0) + { + *p_mode_lvq_p = *p_mode_lvq; + } + else + { + *p_mode_lvq_p = -1; + } + } + else /* WB 12.8 with MA pred in GENERIC*/ + { + *p_mode_lvq = NO_CODING_MODES + coder_type; + if (coder_type == GENERIC) + { + *p_mode_lvq_p = 18; + } + else + { + if (predmode>0) + { + *p_mode_lvq_p = *p_mode_lvq; + } + else + { + *p_mode_lvq_p = -1; + } + } + } + + + if (predmode==-1) + { + fprintf (stderr, "find_pred_mode(): incorrect coder_type specification: %d\n", coder_type); + exit(-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( + float *isf, /* i/o: ISF vector */ + const float min_dist, /* i : minimum required distance */ + const short n, /* i : LPC order */ + const float fs /* i : sampling frequency */ +) +{ + short i; + float isf_min; + float isf_max; + + /*-----------------------------------------------------------------* + * Verify the ISF ordering and minimum GAP + *-----------------------------------------------------------------*/ + + isf_min = min_dist; + for (i = 0; i < n-1; i++) + { + if (isf[i] < isf_min) + { + isf[i] = isf_min; + } + + isf_min = isf[i] + min_dist; + } + + /*------------------------------------------------------------------------------------------* + * Reverify the ISF ordering and minimum GAP in the reverse order (security) + *------------------------------------------------------------------------------------------*/ + + isf_max = fs/2.0f - min_dist; + + if( isf[n-2] > isf_max ) /* If danger of unstable filter in case of resonance in HF */ + { + for (i = n-2; i >=0; i--) /* Reverify the minimum ISF gap in the reverse sens */ + { + if (isf[i] > isf_max) + { + isf[i] = isf_max; + } + + isf_max = isf[i] - min_dist; + } + } + + return; +} + +/*----------------------------------------------------------------------------------* + * lsf_stab() + * + * Check LSF stability (distance between old LSFs and current LSFs) + *----------------------------------------------------------------------------------*/ + +float lsf_stab( /* o : LP filter stability */ + const float *lsf, /* i : LSF vector */ + const float *lsfold, /* i : old LSF vector */ + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short L_frame /* i : frame length */ +) +{ + short i, m; + float scale, stab_fac, tmp; + + tmp = 0.0f; + if ( Opt_AMR_WB ) + { + m = M-1; + } + else + { + m = M; + } + + for (i=0; i 1.0f) + { + stab_fac = 1.0f; + } + + if (stab_fac < 0.0f) + { + stab_fac = 0.0f; + } + return stab_fac; +} + + +/*--------------------------------------------------------------------- + * get_isppol() + * + * Find the polynomial F1(z) or F2(z) from the ISPs. + * This is performed by expanding the product polynomials: + * + * F1(z) = PRODUCT ( 1 - 2 isp_i z^-1 + z^-2 ) + * i=0,2,...,14 + * F2(z) = PRODUCT ( 1 - 2 isp_i z^-1 + z^-2 ) + * i=1,3,...,13 + * + * where isp_i are the ISPs in the cosine domain. + *---------------------------------------------------------------------*/ + +static void get_isppol( + const float *isp, /* i : Immitance spectral pairs (cosine domaine) */ + float f[], /* o : the coefficients of F1 or F2 */ + const short n /* i : nb. of coefficients (m/2) */ +) +{ + float b; + short i,j; + + f[0] = 1.0f; + b = (float)(-2.0f * *isp); + f[1] = b; + for (i = 2; i <= n; i++) + { + isp += 2; + b = (float)(-2.0f * *isp); + f[i] = (float)(b * f[i-1] + 2.0f * f[i-2]); + + for (j = i-1; j > 1; j--) + { + f[j] += b*f[j-1] + f[j-2]; + } + f[1] += b; + } + + return; +} + + +/*--------------------------------------------------------------------- + * chebps2() + * + * Evaluates the Chebyshev polynomial series + * + * The polynomial order is + * n = m/2 (m is the prediction order) + * The polynomial is given by + * C(x) = f(0)T_n(x) + f(1)T_n-1(x) + ... +f(n-1)T_1(x) + f(n)/2 + *---------------------------------------------------------------------*/ + +static float chebps2( /* o: the value of the polynomial C(x) */ + const float x, /* i: value of evaluation; x=cos(freq) */ + const float *f, /* i: coefficients of sum or diff polyn. */ + const short n /* i: order of polynomial */ +) +{ + float b1, b2, b0, x2; + short i; + + + x2 = (float)(2.0f * x); + b2 = f[0]; + + b1 = x2*b2 + f[1]; + + for (i=2; i A */ + lsp2a_stab( lsp, a, m ); + + /* A --> ISP */ + a2isp( a, isp, stable_isp ); + + /* Update to latest stable ISP */ + mvr2r( isp, stable_isp, M ); +} + +/*-------------------------------------------------------------------* + * isp2lsp() + * + * Convert ISPs to LSPs via predictor coefficients A[] + *-------------------------------------------------------------------*/ + +void isp2lsp( + const float *isp, /* i : LSP vector */ + float *lsp, /* o : ISP filter coefficients */ + float *stable_lsp, /* i/o: stable LSP filter coefficients */ + const short m /* i : order of LP analysis */ +) +{ + float a[M+1]; + + /* ISP --> A */ + isp2a( isp, a, m ); + + /* A --> LSP */ + a2lsp_stab( a, lsp, stable_lsp ); + + /* Update to latest stable LSP */ + mvr2r( lsp, stable_lsp, M ); +} + + +/*-------------------------------------------------------------------* + * lsf2isf() + * + * Convert LSPs to ISPs + *-------------------------------------------------------------------*/ + +void lsf2isf( + const float *lsf, /* i : LSF vector */ + float *isf, /* o : ISF vector */ + float *stable_isp, /* i/o: stable ISP filter coefficients */ + const short m, /* i : order of LP analysis */ + const float int_fs +) +{ + float tmp_lsp[M]; + float tmp_isp[M]; + + /* LSF --> LSP */ + lsf2lsp( lsf, tmp_lsp, m, int_fs ); + + /* LSP --> ISP */ + lsp2isp( tmp_lsp, tmp_isp, stable_isp, m ); + + /* ISP --> ISF */ + isp2isf( tmp_isp, isf, m, int_fs ); + + return; +} + +/*-------------------------------------------------------------------* + * isf2lsf() + * + * Convert ISFs to LSFs + *-------------------------------------------------------------------*/ + +void isf2lsf( + const float *isf, /* i : ISF vector */ + float *lsf, /* o : LSF vector */ + float *stable_lsp, /* i/o: stable LSP filter coefficients */ + const short m, /* i : order of LP analysis */ + const float int_fs +) +{ + float tmp_isp[M]; + float tmp_lsp[M]; + + /* ISF --> ISP */ + isf2isp( isf, tmp_isp, m, int_fs ); + + /* ISP --> LSP */ + isp2lsp( tmp_isp, tmp_lsp, stable_lsp, m ); + + /* LSP --> LSF */ + lsp2lsf( tmp_lsp, lsf, m, int_fs ); + + return; +} + +/*-----------------------------------------------------------------------* + * lsp2lsf() + * + * 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). + *-----------------------------------------------------------------------*/ + +void lsp2lsf( + const float lsp[], /* i : isp[m] (range: -1<=val<1) */ + float lsf[], /* o : isf[m] normalized (range: 0<=val<=fs/2) */ + const short m, /* i : LPC order */ + const float fs /* i : sampling frequency */ +) +{ + short i; + + /* convert LSPs to LSFs */ + for( i=0; i> 4; + branch[1] = index[2] >> 4; + + for(stage = 2; stage < N_STAGE_VQ-4; stage++) + { + branch[stage] = index[stage+1] >> 3; + } + + branch[4] = fins & 0x1; + branch[5] = (fins >> 1) & 0x1; + branch[6] = (fins >> 2) & 0x1; + branch[7] = (fins >> 3) & 0x1; + + /* Decode Codeword info */ + for(stage = 0; stage < 2; stage++) + { + codeword[stage] = (index[stage+1] & 15) << 3; + } + + for(stage = 2; stage < N_STAGE_VQ-4; stage++) + { + codeword[stage] = (index[stage+1] & 7) << 3; + } + + for(stage = N_STAGE_VQ-4; stage < N_STAGE_VQ; stage++) + { + codeword[stage] = (index[stage+1] & 3) << 3; + } + + state = (fins >> 2) << 2; + + /* stage #1 */ + iwd = NTRANS2[branch[0]+2][state] + codeword[0]; + D[0][0] = TCVQ_CB_SUB1[0][iwd][0]; + D[0][1] = TCVQ_CB_SUB1[0][iwd][1]; + state = NTRANS2[branch[0]][state]; + + /* stage #2 */ + pred[0] = IntraCoeff[0][0][0] * D[0][0] + IntraCoeff[0][0][1]*D[0][1]; + pred[1] = IntraCoeff[0][1][0] * D[0][0] + IntraCoeff[0][1][1]*D[0][1]; + + iwd = NTRANS2[branch[1]+2][state] + codeword[1]; + D[1][0] = TCVQ_CB_SUB1[1][iwd][0] + pred[0]; + D[1][1] = TCVQ_CB_SUB1[1][iwd][1] + pred[1]; + state = NTRANS2[branch[1]][state]; + + /* stage #3 - #4 */ + for(stage = 2; stage < N_STAGE_VQ-4; stage++) + { + pred[0] = IntraCoeff[stage-1][0][0] * D[stage-1][0] + IntraCoeff[stage-1][0][1]*D[stage-1][1]; + pred[1] = IntraCoeff[stage-1][1][0] * D[stage-1][0] + IntraCoeff[stage-1][1][1]*D[stage-1][1]; + + iwd = NTRANS2[branch[stage]+2][state] + codeword[stage]; + D[stage][0] = TCVQ_CB_SUB2[stage-2][iwd][0] + pred[0]; + D[stage][1] = TCVQ_CB_SUB2[stage-2][iwd][1] + pred[1]; + state = NTRANS2[branch[stage]][state]; + } + + /* stage #5 - #8 */ + for(stage = N_STAGE_VQ-4; stage < N_STAGE_VQ; stage++) + { + pred[0] = IntraCoeff[stage-1][0][0] * D[stage-1][0] + IntraCoeff[stage-1][0][1]*D[stage-1][1]; + pred[1] = IntraCoeff[stage-1][1][0] * D[stage-1][0] + IntraCoeff[stage-1][1][1]*D[stage-1][1]; + + iwd = NTRANS2[branch[stage]+2][state] + codeword[stage]; + D[stage][0] = TCVQ_CB_SUB3[stage-4][iwd][0] + pred[0]; + D[stage][1] = TCVQ_CB_SUB3[stage-4][iwd][1] + pred[1]; + state = NTRANS2[branch[stage]][state]; + } + + for(stage = 0; stage < N_STAGE_VQ; stage++) + { + for(i = 0; i < N_DIM; i++) + { + d_out[(N_DIM*stage) + i] = D[stage][i]; + } + } + return; +} + +/*--------------------------------------------------------------------------- + * qlsf_ARSN_tcvq_Dec_16k() + * + * Predictive BC-TCQ encoder for LSF quantization + *--------------------------------------------------------------------------*/ + +short qlsf_ARSN_tcvq_Dec_16k ( + float *y, /* o : Quantized LSF vector */ + short *indice, /* i : Indices */ + const short nBits /* i : number of bits */ +) +{ + short i; + float error_svq_q[M]; + short safety_net; + + /* Select Mode */ + safety_net = indice[0]; + + + if(safety_net == 1) + { + tcvq_Dec(&indice[1], y, safety_net); + + if(nBits>30) + { + for(i = 0; i < 8; i++) + { + error_svq_q[i] = AR_SVQ_CB1[indice[10]][i]; + error_svq_q[i+8] = AR_SVQ_CB2[indice[11]][i]; + } + + for(i = 0; i < M; i++) + { + y[i] = y[i] + error_svq_q[i] * scale_ARSN[i]; + } + } + } + else + { + tcvq_Dec(&indice[1], y, safety_net); + + if(nBits>30) + { + for(i = 0; i < 8; i++) + { + error_svq_q[i] = AR_SVQ_CB1[indice[10]][i]; + error_svq_q[i+8] = AR_SVQ_CB2[indice[11]][i]; + } + + for(i = 0; i < M; i++) + { + y[i] = y[i] + error_svq_q[i]; + } + } + } + + return safety_net; +} + + +/*-------------------------------------------------------------------* + * lsf_syn_mem_backup() + * + * back-up synthesis filter memory and LSF qunatizer memories (used in SC-VBR) + *-------------------------------------------------------------------*/ + +void lsf_syn_mem_backup( + Encoder_State *st, /* i: state structure */ + LPD_state* LPDmem, /* i: LPD state memory structure */ + float *btilt_code, /* i: tilt code */ + float *bgc_threshold, /* i: */ + float *clip_var_bck, /* o: */ + short *next_force_sf_bck, /* 0: */ + + float *lsp_new, /* i: LSP vector to quantize */ + float *lsp_mid, /* i: mid-frame LSP vector */ + float *clip_var, /* o: pitch clipping state var */ + float *mem_AR, /* o: quantizer memory for AR model */ + float *mem_MA, /* o: quantizer memory for AR model */ + float *lsp_new_bck, /* o: LSP vector to quantize- backup */ + float *lsp_mid_bck, /* o: mid-frame LSP vector - backup */ + short *mCb1, /* o: counter for stationary frame after a transition frame */ + float *Bin_E, /* o: FFT Bin energy 128 *2 sets */ + float *Bin_E_old, /* o: FFT Bin energy 128 sets */ + float *mem_syn_bck, /* o: synthesis filter memory */ + float *mem_w0_bck, /* o: memory of the weighting filter */ + float *streaklimit, + short *pstreaklen +) +{ + short i; + + *clip_var = st->clip_var[0]; + + for(i=0; imem_AR[i]; + mem_MA[i] = st->mem_MA[i]; + lsp_new_bck[i] = lsp_new[i]; + lsp_mid_bck[i] = lsp_mid[i]; + } + + *mCb1 = st->mCb1; + *streaklimit = st->streaklimit; + *pstreaklen = st->pstreaklen; + + for(i=0; iBin_E[i]; + } + + for(i=0; i<(L_FFT/2); i++) + { + Bin_E_old[i]=st->Bin_E_old[i]; + } + + /* back-up memories */ + for(i=0; iLPDmem.mem_syn[i]; + } + + *mem_w0_bck = st->LPDmem.mem_w0; + + *btilt_code = LPDmem->tilt_code; + *bgc_threshold = LPDmem->gc_threshold; + mvr2r( st->clip_var, clip_var_bck, 6 ); + *next_force_sf_bck = st->next_force_safety_net; + + + return; +} + + +/*-------------------------------------------------------------------* + * lsf_syn_mem_restore() + * + * restore synthesis filter memory and LSF quantizer memories + *-------------------------------------------------------------------*/ + +void lsf_syn_mem_restore( + Encoder_State *st, /* o: state structure */ + LPD_state* LPDmem, /* o: LPD_state vewctor */ + float btilt_code, /* i: */ + float gc_threshold, /* i: */ + float *clip_var_bck, /* i: */ + short next_force_sf_bck, /* i: */ + + float *lsp_new, /* o: LSP vector to quantize */ + float *lsp_mid, /* o: mid-frame LSP vector */ + float clip_var, /* i: pitch clipping state var */ + float *mem_AR, /* i: quantizer memory for AR model */ + float *mem_MA, /* i: quantizer memory for AR model */ + float *lsp_new_bck, /* i: LSP vector to quantize- backup */ + float *lsp_mid_bck, /* i: mid-frame LSP vector - backup */ + short mCb1, /* i: counter for stationary frame after a transition frame */ + float *Bin_E, /* i: FFT Bin energy 128 *2 sets */ + float *Bin_E_old, /* i: FFT Bin energy 128 sets */ + float *mem_syn_bck, /* i: synthesis filter memory */ + float mem_w0_bck, /* i: memory of the weighting filter */ + float streaklimit, + short pstreaklen +) +{ + short i; + + /* restore lsf memories */ + st->clip_var[0] = clip_var; + + for(i=0; imem_AR[i] = mem_AR[i]; + st->mem_MA[i] = mem_MA[i]; + lsp_new[i] = lsp_new_bck[i]; + lsp_mid[i] = lsp_mid_bck[i]; + } + + st->mCb1 = mCb1; + st->streaklimit = streaklimit; + st->pstreaklen = pstreaklen; + + for(i=0; iBin_E[i] = Bin_E[i]; + } + + for(i=0; i<(L_FFT/2); i++) + { + st->Bin_E_old[i]=Bin_E_old[i]; + } + + /* restoring memories */ + st->LPDmem.mem_w0 = mem_w0_bck; + + for(i=0; iLPDmem.mem_syn[i] = mem_syn_bck[i]; + } + + LPDmem->tilt_code = btilt_code; + LPDmem->gc_threshold = gc_threshold; + mvr2r( clip_var_bck, st->clip_var, 6 ); + st->next_force_safety_net = next_force_sf_bck; + + + return; +} + +/*--------------------------------------------------------------------------* + * lsf_update_memory() + * + * + *--------------------------------------------------------------------------*/ + +void lsf_update_memory( + int narrowband, /* i : narrowband flag */ + const float qlsf[], /* i : quantized lsf coefficients */ + float old_mem_MA[], /* i : MA memory */ + float mem_MA[] /* o : updated MA memory */ +) +{ + int i; + + for (i=0; i= 0; specix++) + { + ; + } + + lsf[lsfix++] = (specix-1 + spec_r[specix-1]/(spec_r[specix-1]-spec_r[specix]))*(12800/256); + + /*check for the next zero crossing*/ + for (; s * spec_i[specix] >= 0; specix++) + { + ; + } + + lsf[lsfix++] = (specix-1 + spec_i[specix-1]/(spec_i[specix-1]-spec_i[specix]))*(12800/256); + + spec_r[speclen] = s; + spec_i[speclen] = s; + + s =-s; + } + + if (lsfix < 16) + { + for(i=0; i<16; i++) + { + lsf[i] = old_lsf[i]; + } + } + + return; +} + +/*--------------------------------------------------------------------------* + * a2isf() + * + * + *--------------------------------------------------------------------------*/ + +#define SCALE1_HALF 1018.59161376953f + +typedef struct +{ + float re; + float im; +} Pfloat; + +void a2isf( + float *a, + float *isf, + const float *old_isf, + short lpcOrder +) +{ + float RealFFT[128]; + float ImagFFT[128]; + float RealOut[130]; + float ImagOut[130]; + float *ptrReal; + float *ptrImag; + int n, i, j; + const Pfloat *ptwiddle; + Pfloat *pwn17, pwn[128], *pwn15, tmpw15; + int N = 256; + float s[4]; + float L_tmp, L_tmp1; + float lpc[19], fftTmpRe[16], fftTmpIm[16]; + Pfloat twid[128]; + float c; + + set_zero(fftTmpRe, 16); + set_zero(fftTmpIm, 16); + + /* half length FFT */ + /*c = [sum(a) ((-1).^(1:length(a)))*a];*/ + + L_tmp = 0; + for(j=0; j<=lpcOrder; j++) + { + L_tmp += a[j]; + } + + L_tmp1 = 0; + for(j=0; jre) - (lpc[2*j+1] * ptwiddle->im); + fftTmpIm[j] = (lpc[2*j+1] * ptwiddle->re) + (lpc[2*j] * ptwiddle->im); + ptwiddle++; + } + + fftTmpRe[j] = lpc[2*j]*ptwiddle->re; + fftTmpIm[j] = lpc[2*j]*ptwiddle->im; + ptwiddle++; + j++; + for(; j<16; j++) + { + fftTmpRe[j] = 0; + fftTmpIm[j] = 0; + ptwiddle++; + } + + DoRTFTn(fftTmpRe, fftTmpIm, 16); + + for(j=0; j<16; j++) + { + ptrReal[j*8] = fftTmpRe[j]; + ptrImag[j*8] = fftTmpIm[j]; + } + + ptrReal++; + ptrImag++; + + } + + c = EVS_PI / ( 2.0f * (float)128 ); + + for ( i = 1 ; i < 128 ; i++ ) + { + twid[i-1].im = (float)sin( c * ( 2.0f * (float)i ) ); + twid[i-1].re = (float)cos( c * ( 2.0f * (float)i ) ); + } + ptwiddle = twid; + + /* pre-twiddle */ + for ( i = 1 ; i < 128 ; i++ ) + { + pwn[i-1].im = (float)sin( c * ( 18.0f * (float)i ) ); + pwn[i-1].re = (float)cos( c * ( 18.0f * (float)i ) ); + } + + pwn17 = pwn; + pwn15 = &tmpw15; + + /*Y(1) = real(X(1)) + imag(X(1));*/ + RealOut[0] = (RealFFT[0] + ImagFFT[0]); + ImagOut[0] = 0; + + /*Y(N/2+1) = 0.5*(X(1) + conj(X(1))).*exp(pi*i*128*(18)/N) - i*0.5*(X(1) - conj(X(1))).*exp(pi*i*128*(16)/N);*/ + RealOut[128] = 0; + ImagOut[128] = (RealFFT[0] + RealFFT[0]) - (ImagFFT[0] + ImagFFT[0]); + + /*Y(2:N/2) = (0.5*(X(2:N/2) + conj(X(N/2:-1:2))) - i*0.5*(X(2:N/2) - conj(X(N/2:-1:2))).*exp(-pi*i*r*(2)/N)).*exp(pi*i*r*(18)/N);*/ + for(i=1; ire * pwn17->re) + (ptwiddle->im * pwn17->im); + tmpw15.im = (ptwiddle->re * pwn17->im) - (ptwiddle->im * pwn17->re); + + /*RealOut[i] = mac_r(L_msu(L_msu(L_mult(ReAr, pwn17->re),ImAr, pwn17->im), ReBr, pwn15->v.im), ImBr, pwn15->re); move16();*/ + RealOut[i] = (ReAr * pwn17->re) - (ImAr * pwn17->im) - ((ReBr * pwn15->im) + (ImBr * pwn15->re)); + ImagOut[i] = (ReAr * pwn17->im) + (ImAr * pwn17->re) + (ReBr * pwn15->re) - (ImBr * pwn15->im); + + ptwiddle++; + pwn17++; + } + + spec2isf(RealOut, ImagOut, 128, isf, old_isf); + + isf[lpcOrder - 1] = (Float32)(acos(a[lpcOrder]) * SCALE1_HALF); + + return; +} diff --git a/lib_com/lsp_conv_poly.c b/lib_com/lsp_conv_poly.c new file mode 100644 index 000000000..629713223 --- /dev/null +++ b/lib_com/lsp_conv_poly.c @@ -0,0 +1,630 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +/* The conversion modes. */ +#define DOWNCONV 0 +#define UPCONV 1 +/* The cap of the inverse power spectrum. */ +#define MAXPOWERSPECT 1e-5f +#define N50 GRID50_POINTS +#define N40 GRID40_POINTS + + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static void powerspect( const float x[], const short N, float R[], float S[], float G[], const short mode ); + +static void spectautocorr( const float x[], const short N, const float G[], float r[] ); + +static void zeros2poly( float x[], float R[], float S[] ); + +static void polydecomp( float A[], float P[], float Q[] ); + +static void cheb2poly( float P[] ); + + +/*---------------------------------------------------------------------* + * lsp_convert_poly() + * + * Converts the LP filter estimated at 16.0 kHz sampling rate down + * 12.8 kHz frequency scale or alternatively from 12.8 kHz up to + * 16.0 kHz. The former is called down conversation and latter up + * conversion. The resulting LP filter is characterized with its + * line spectrum pairs. The original Lp filter can be either in + * its immittance, used for the AMR-WB IO mode, or line spectrum + * pair representation. + * + * The conversion is based the autocorrelation computed from the + * power spectrum of the LP filter that is truncated or extrapolated + * to the desired frequency scale. + *---------------------------------------------------------------------*/ + +short lsp_convert_poly( + float w[], /* i/o: LSP or ISP parameters */ + const short L_frame, /* i : flag for up or down conversion */ + const short Opt_AMRWB /* i : flag for the AMR-WB IO mode */ +) +{ + float epsP[M+1]; + float G[GRID50_POINTS], r[M+1], A[M+1], A_old[M+1], R[NC+1], S[NC+1]; + short i; + short flag; + + /*---------------------------------------------------------------------* + * Because AMR-WB IO uses immittance spectrum frequency representation + * instead of line spectrum frequency representation, the input + * parameters do not give the zeros of the polynomials R(x) and S(x). + * Hence R(x) and S(x) are formed via the polynomial A(z) of the linear + * prediction filter. + *---------------------------------------------------------------------*/ + + if( Opt_AMRWB ) + { + isp2a( w, A_old, M ); + polydecomp( A_old, R, S ); + } + + /*---------------------------------------------------------------------* + * Form the polynomials R(x) and S(x) from their zeros that are the + * line spectrum pairs of A(z). The polynomial coefficients can be + * scaled for convenience, because scaling will not affect the + * resulting LP coefficients. Scaling by 128 gives the correct offset + * to the power spectrum for n = 16. + *---------------------------------------------------------------------*/ + + else + { + zeros2poly( w, R, S ); + for (i = 0; i <= NC; i++) + { + R[i] *= 128.0f; + S[i] *= 128.0f; + } + lsp2a_stab( w, A_old, M ); + } + + /*---------------------------------------------------------------------* + * Conversion from 16.0 kHz down to 12.8 kHz. The power spectrum + * needs to be computed only up to 6.4 kHz, because the upper band + * is omitted. + *---------------------------------------------------------------------*/ + + if( L_frame == L_FRAME ) + { + powerspect( grid50, N50, R, S, G, DOWNCONV ); + spectautocorr( grid40, N40, G, r ); + } + + /*---------------------------------------------------------------------* + * Conversion from 12.8 kHz up to 16.0 kHz. + * Compute the power spectrum of the LP filter, extrapolate the + * power spectrum from 6.4 kHz to 8.0 kHz, and compute auto- + * correlation on this power spectrum. + *---------------------------------------------------------------------*/ + + else + { + powerspect( grid40, N40, R, S, G, UPCONV ); + for (i = N40; i < N50; i++) + { + G[i] = G[N40-1]; + } + + spectautocorr( grid50, N50, G, r ); + } + + /*---------------------------------------------------------------------* + * Compute the linear prediction coefficients from the autocorrelation + * and convert to line spectrum pairs. + *---------------------------------------------------------------------*/ + + flag = lev_dur( A, r, M, epsP ); + a2lsp_stab( A, w, stable_LSP ); + + return(flag); +} + + +/*---------------------------------------------------------------------* + * powerspect() + * + * Computes the power spectrum G(w) = 1/|A(w)|^2 at N points on + * the real axis x = cos w by utilizing the line spectrum frequency + * decomposition + * + * A(z) = (P(z) + Q(z))/2, + * + * where assuming A(z) of an even degree 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). + * + * The zeros of these polynomials give the line spectrum frequencies + * of A(z). It can be shown that for an even n, + * + * |A(x)|^2 = 2 (1 + x) R(x)^2 + 2 (1 - x) S(x)^2, + * + * where x = cos w, and R(x) and S(x) are the direct polynomials + * resulting from the Chebyshev series representation of P(z) + * and Q(z). + * + * This routine assumes the grid X = 1, x[0], x[1], .., x[m-1], + * -, ..., -x[1], -x[0], -1 such that x[i] = cos((i+1)*pi/N) for + * evaluating the power spectrum. Only m = (N-1)/2 - 1 grid points + * need to be stored, because cos(0) and cos(pi/2) are trivial, + * and the points above pi/2 are obtained readily using the symmetry + * of cosine. + * + * The power spectrum can be scaled as a*G[], where a is chosen + * for convenience. This is because the scaling has no impact on + * the LP coefficients to be determined based on the power spectrum. + *---------------------------------------------------------------------*/ + +static void powerspect( + const float x[], /* i: Grid points x[0:N-1] */ + const short N, /* i: Number of grid points */ + float R[], /* i: Coefficients of R(x) in R[0:NC] */ + float S[], /* i: Coefficients of S(x) in S[0:NC] */ + float G[], /* o: Power spectrum G[0:N] */ + const short mode /* i: Flag for up or down conversion */ +) +{ + float re, ro, se, so; + float s0, s1, r0, r1, x0, x1, x2; + Word16 i, j; + Word16 iuni, imid; + + /* init buffer */ + for(i=0; i cos(pi/2) = 0. + *---------------------------------------------------------------------*/ + + for (i = 1; i <= iuni; i++) + { + x0 = x[i-1]; + r0 = R[0]; + s0 = S[0]; + + for (j = 1; j <= NC; j++) + { + r0 = x0*r0 + R[j]; + s0 = x0*s0 + S[j]; + } + r0 = (1.0f + x0)*r0*r0; + s0 = (1.0f - x0)*s0*s0; + + G[i] = 2.0f*(r0 + s0); + } + + /*---------------------------------------------------------------------* + * 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++) + { + x0 = x[i-1]; + x2 = x0*x0; + + re = R[0]; + se = S[0]; + ro = R[1]; + so = S[1]; + + for (j = 2; j < NC; j+=2) + { + re = x2*re + R[j]; + ro = x2*ro + R[j+1]; + se = x2*se + S[j]; + so = x2*so + S[j+1]; + } + + re = x2*re + R[j]; + ro *= x0; + se = x2*se + S[j]; + so *= x0; + + r0 = re + ro; + s0 = se + so; + r1 = re - ro; + s1 = se - so; + + x1 = 1.0f + x0; + x2 = 1.0f - x0; + + r0 = x1*r0*r0; + s0 = x2*s0*s0; + r1 = x2*r1*r1; + s1 = x1*s1*s1; + + G[i] = 2.0f*(r0 + s0); + G[N-i-1] = 2.0f*(r1 + s1); + } + + /*---------------------------------------------------------------------* + * Compute the power spectrum 1/|A(x)|^2 from |A(x)|^2 with logic + * to prevent division by small number and upper bound the spectrum. + * This upper bound is implicit in fixed point arithmetic, but is + * needed explicitly in floating point implementations to avoid numeric + * problems. + *---------------------------------------------------------------------*/ + + for(i=0; i 0; j--) + { + R[j] += xr*R[j-1]; + S[j] += xs*S[j-1]; + } + } + + 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( + float A[], /* i: linear prediction coefficients */ + float R[], /* o: coefficients of R(x) */ + float S[] /* o: coefficients of S(x) */ +) +{ + float *P = &R[0], *Q = &S[0]; + Word16 i, j; + + P[0] = A[0]; + Q[0] = A[0]; + for (i = 1, j = M; i <= NC; i++, j--) + { + P[i] = A[i] + A[j] - P[i-1]; + Q[i] = A[i] - A[j] + Q[i-1]; + } + + cheb2poly(P); + cheb2poly(Q); + + return; +} + +/*---------------------------------------------------------------------* + * cheb2poly() + * + * Computes the coefficients of the explicit Chebyshev polynomial + * P(x) = P[0]*x^n + P[1]*x^(n-1) + ... + P[n] given the coefficients + * of the series + * + * C(x) = C[0]*T_n(x) + C[1]*T_n-1(x) + ... + C[n]*T_0(x), + * + * where T_n(x) is the nth Chebyshev polynomial of the first kind. + * This implementation assumes C[0] = 1. Only the value n = 8 is + * supported. + * + * The conversion from C(x) to P(x) is done in place such that the + * coefficients of C(x) are given in P[0:8] and those of P(x) are + * returned in the same array. + *---------------------------------------------------------------------*/ + +static void cheb2poly( + float P[] /* i/o: The coefficients of C(x) and P(x) */ +) +{ + float c1, c2, c3, c4, c5, c6, c7, c8; + + c1 = P[1]; + c2 = P[2]; + c3 = P[3]; + c4 = P[4]; + c5 = P[5]; + c6 = P[6]; + c7 = P[7]; + c8 = P[8]; + + P[0] = 128.0f; + P[1] = 64.0f*c1; + P[2] = 32.0f*c2 - 256.0f; + P[3] = 16.0f*c3 - 112.0f*c1; + P[4] = 160.0f - 48.0f*c2 + 8.0f*c4; + P[5] = 56.0f*c1 - 20.0f*c3 + 4.0f*c5; + P[6] = 18.0f*c2 - 32.0f - 8.0f*c4 + 2.0f*c6; + P[7] = 5.0f*c3 - 7.0f*c1 - 3.0f*c5 + c7; + P[8] = 1.0f - c2 + c4 - c6 + 0.5f*c8; + + return; +} diff --git a/lib_com/mime.h b/lib_com/mime.h new file mode 100644 index 000000000..3d0b659ca --- /dev/null +++ b/lib_com/mime.h @@ -0,0 +1,423 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + + +#define AMRWB_MAGIC_NUMBER "#!AMR-WB\n" /* defined in RFC4867 */ +#define EVS_MAGIC_NUMBER "#!EVS_MC1.0\n" /* defined in 26.445 */ + +static const Word32 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 */ + -1, /* AMRWB_IO_FUT1 */ + -1, /* AMRWB_IO_FUT2 */ + -1, /* AMRWB_IO_FUT3 */ + -1, /* AMRWB_IO_FUT4 */ + 0, /* SPEECH_BAD */ + 0 /* NO_DATA */ +}; + +static const Word32 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 */ +}; + +/* sorting tables for all AMR-WB IO modes */ + +static const Word16 sort_660[132] = +{ + 0, 5, 6, 7, 61, 84, 107, 130, 62, 85, + 8, 4, 37, 38, 39, 40, 58, 81, 104, 127, + 60, 83, 106, 129, 108, 131, 128, 41, 42, 80, + 126, 1, 3, 57, 103, 82, 105, 59, 2, 63, + 109, 110, 86, 19, 22, 23, 64, 87, 18, 20, + 21, 17, 13, 88, 43, 89, 65, 111, 14, 24, + 25, 26, 27, 28, 15, 16, 44, 90, 66, 112, + 9, 11, 10, 12, 67, 113, 29, 30, 31, 32, + 34, 33, 35, 36, 45, 51, 68, 74, 91, 97, + 114, 120, 46, 69, 92, 115, 52, 75, 98, 121, + 47, 70, 93, 116, 53, 76, 99, 122, 48, 71, + 94, 117, 54, 77, 100, 123, 49, 72, 95, 118, + 55, 78, 101, 124, 50, 73, 96, 119, 56, 79, + 102, 125 +}; + +static const Word16 sort_885[177] = +{ + 0, 4, 6, 7, 5, 3, 47, 48, 49, 112, + 113, 114, 75, 106, 140, 171, 80, 111, 145, 176, + 77, 108, 142, 173, 78, 109, 143, 174, 79, 110, + 144, 175, 76, 107, 141, 172, 50, 115, 51, 2, + 1, 81, 116, 146, 19, 21, 12, 17, 18, 20, + 16, 25, 13, 10, 14, 24, 23, 22, 26, 8, + 15, 52, 117, 31, 82, 147, 9, 33, 11, 83, + 148, 53, 118, 28, 27, 84, 149, 34, 35, 29, + 46, 32, 30, 54, 119, 37, 36, 39, 38, 40, + 85, 150, 41, 42, 43, 44, 45, 55, 60, 65, + 70, 86, 91, 96, 101, 120, 125, 130, 135, 151, + 156, 161, 166, 56, 87, 121, 152, 61, 92, 126, + 157, 66, 97, 131, 162, 71, 102, 136, 167, 57, + 88, 122, 153, 62, 93, 127, 158, 67, 98, 132, + 163, 72, 103, 137, 168, 58, 89, 123, 154, 63, + 94, 128, 159, 68, 99, 133, 164, 73, 104, 138, + 169, 59, 90, 124, 155, 64, 95, 129, 160, 69, + 100, 134, 165, 74, 105, 139, 170 +}; + +static const Word16 sort_1265[253] = +{ + 0, 4, 6, 93, 143, 196, 246, 7, 5, 3, + 47, 48, 49, 50, 51, 150, 151, 152, 153, 154, + 94, 144, 197, 247, 99, 149, 202, 252, 96, 146, + 199, 249, 97, 147, 200, 250, 100, 203, 98, 148, + 201, 251, 95, 145, 198, 248, 52, 2, 1, 101, + 204, 155, 19, 21, 12, 17, 18, 20, 16, 25, + 13, 10, 14, 24, 23, 22, 26, 8, 15, 53, + 156, 31, 102, 205, 9, 33, 11, 103, 206, 54, + 157, 28, 27, 104, 207, 34, 35, 29, 46, 32, + 30, 55, 158, 37, 36, 39, 38, 40, 105, 208, + 41, 42, 43, 44, 45, 56, 106, 159, 209, 57, + 66, 75, 84, 107, 116, 125, 134, 160, 169, 178, + 187, 210, 219, 228, 237, 58, 108, 161, 211, 62, + 112, 165, 215, 67, 117, 170, 220, 71, 121, 174, + 224, 76, 126, 179, 229, 80, 130, 183, 233, 85, + 135, 188, 238, 89, 139, 192, 242, 59, 109, 162, + 212, 63, 113, 166, 216, 68, 118, 171, 221, 72, + 122, 175, 225, 77, 127, 180, 230, 81, 131, 184, + 234, 86, 136, 189, 239, 90, 140, 193, 243, 60, + 110, 163, 213, 64, 114, 167, 217, 69, 119, 172, + 222, 73, 123, 176, 226, 78, 128, 181, 231, 82, + 132, 185, 235, 87, 137, 190, 240, 91, 141, 194, + 244, 61, 111, 164, 214, 65, 115, 168, 218, 70, + 120, 173, 223, 74, 124, 177, 227, 79, 129, 182, + 232, 83, 133, 186, 236, 88, 138, 191, 241, 92, + 142, 195, 245 +}; + +static const Word16 sort_1425[285] = +{ + 0, 4, 6, 101, 159, 220, 278, 7, 5, 3, + 47, 48, 49, 50, 51, 166, 167, 168, 169, 170, + 102, 160, 221, 279, 107, 165, 226, 284, 104, 162, + 223, 281, 105, 163, 224, 282, 108, 227, 106, 164, + 225, 283, 103, 161, 222, 280, 52, 2, 1, 109, + 228, 171, 19, 21, 12, 17, 18, 20, 16, 25, + 13, 10, 14, 24, 23, 22, 26, 8, 15, 53, + 172, 31, 110, 229, 9, 33, 11, 111, 230, 54, + 173, 28, 27, 112, 231, 34, 35, 29, 46, 32, + 30, 55, 174, 37, 36, 39, 38, 40, 113, 232, + 41, 42, 43, 44, 45, 56, 114, 175, 233, 62, + 120, 181, 239, 75, 133, 194, 252, 57, 115, 176, + 234, 63, 121, 182, 240, 70, 128, 189, 247, 76, + 134, 195, 253, 83, 141, 202, 260, 92, 150, 211, + 269, 84, 142, 203, 261, 93, 151, 212, 270, 85, + 143, 204, 262, 94, 152, 213, 271, 86, 144, 205, + 263, 95, 153, 214, 272, 64, 122, 183, 241, 77, + 135, 196, 254, 65, 123, 184, 242, 78, 136, 197, + 255, 87, 145, 206, 264, 96, 154, 215, 273, 58, + 116, 177, 235, 66, 124, 185, 243, 71, 129, 190, + 248, 79, 137, 198, 256, 88, 146, 207, 265, 97, + 155, 216, 274, 59, 117, 178, 236, 67, 125, 186, + 244, 72, 130, 191, 249, 80, 138, 199, 257, 89, + 147, 208, 266, 98, 156, 217, 275, 60, 118, 179, + 237, 68, 126, 187, 245, 73, 131, 192, 250, 81, + 139, 200, 258, 90, 148, 209, 267, 99, 157, 218, + 276, 61, 119, 180, 238, 69, 127, 188, 246, 74, + 132, 193, 251, 82, 140, 201, 259, 91, 149, 210, + 268, 100, 158, 219, 277 +}; + +static const Word16 sort_1585[317] = +{ + 0, 4, 6, 109, 175, 244, 310, 7, 5, 3, + 47, 48, 49, 50, 51, 182, 183, 184, 185, 186, + 110, 176, 245, 311, 115, 181, 250, 316, 112, 178, + 247, 313, 113, 179, 248, 314, 116, 251, 114, 180, + 249, 315, 111, 177, 246, 312, 52, 2, 1, 117, + 252, 187, 19, 21, 12, 17, 18, 20, 16, 25, + 13, 10, 14, 24, 23, 22, 26, 8, 15, 53, + 188, 31, 118, 253, 9, 33, 11, 119, 254, 54, + 189, 28, 27, 120, 255, 34, 35, 29, 46, 32, + 30, 55, 190, 37, 36, 39, 38, 40, 121, 256, + 41, 42, 43, 44, 45, 56, 122, 191, 257, 63, + 129, 198, 264, 76, 142, 211, 277, 89, 155, 224, + 290, 102, 168, 237, 303, 57, 123, 192, 258, 70, + 136, 205, 271, 83, 149, 218, 284, 96, 162, 231, + 297, 62, 128, 197, 263, 75, 141, 210, 276, 88, + 154, 223, 289, 101, 167, 236, 302, 58, 124, 193, + 259, 71, 137, 206, 272, 84, 150, 219, 285, 97, + 163, 232, 298, 59, 125, 194, 260, 64, 130, 199, + 265, 67, 133, 202, 268, 72, 138, 207, 273, 77, + 143, 212, 278, 80, 146, 215, 281, 85, 151, 220, + 286, 90, 156, 225, 291, 93, 159, 228, 294, 98, + 164, 233, 299, 103, 169, 238, 304, 106, 172, 241, + 307, 60, 126, 195, 261, 65, 131, 200, 266, 68, + 134, 203, 269, 73, 139, 208, 274, 78, 144, 213, + 279, 81, 147, 216, 282, 86, 152, 221, 287, 91, + 157, 226, 292, 94, 160, 229, 295, 99, 165, 234, + 300, 104, 170, 239, 305, 107, 173, 242, 308, 61, + 127, 196, 262, 66, 132, 201, 267, 69, 135, 204, + 270, 74, 140, 209, 275, 79, 145, 214, 280, 82, + 148, 217, 283, 87, 153, 222, 288, 92, 158, 227, + 293, 95, 161, 230, 296, 100, 166, 235, 301, 105, + 171, 240, 306, 108, 174, 243, 309 +}; + +static const Word16 sort_1825[365] = +{ + 0, 4, 6, 121, 199, 280, 358, 7, 5, 3, + 47, 48, 49, 50, 51, 206, 207, 208, 209, 210, + 122, 200, 281, 359, 127, 205, 286, 364, 124, 202, + 283, 361, 125, 203, 284, 362, 128, 287, 126, 204, + 285, 363, 123, 201, 282, 360, 52, 2, 1, 129, + 288, 211, 19, 21, 12, 17, 18, 20, 16, 25, + 13, 10, 14, 24, 23, 22, 26, 8, 15, 53, + 212, 31, 130, 289, 9, 33, 11, 131, 290, 54, + 213, 28, 27, 132, 291, 34, 35, 29, 46, 32, + 30, 55, 214, 37, 36, 39, 38, 40, 133, 292, + 41, 42, 43, 44, 45, 56, 134, 215, 293, 198, + 299, 136, 120, 138, 60, 279, 58, 62, 357, 139, + 140, 295, 156, 57, 219, 297, 63, 217, 137, 170, + 300, 222, 64, 106, 61, 78, 294, 92, 142, 141, + 135, 221, 296, 301, 343, 59, 298, 184, 329, 315, + 220, 216, 265, 251, 218, 237, 352, 223, 157, 86, + 171, 87, 164, 351, 111, 302, 65, 178, 115, 323, + 72, 192, 101, 179, 93, 73, 193, 151, 337, 309, + 143, 274, 69, 324, 165, 150, 97, 338, 110, 310, + 330, 273, 68, 107, 175, 245, 114, 79, 113, 189, + 246, 259, 174, 71, 185, 96, 344, 100, 322, 83, + 334, 316, 333, 252, 161, 348, 147, 82, 269, 232, + 260, 308, 353, 347, 163, 231, 306, 320, 188, 270, + 146, 177, 266, 350, 256, 85, 149, 116, 191, 160, + 238, 258, 336, 305, 255, 88, 224, 99, 339, 230, + 228, 227, 272, 242, 241, 319, 233, 311, 102, 74, + 180, 275, 66, 194, 152, 325, 172, 247, 244, 261, + 117, 158, 166, 354, 75, 144, 108, 312, 94, 186, + 303, 80, 234, 89, 195, 112, 340, 181, 345, 317, + 326, 276, 239, 167, 118, 313, 70, 355, 327, 253, + 190, 176, 271, 104, 98, 153, 103, 90, 76, 267, + 277, 248, 225, 262, 182, 84, 154, 235, 335, 168, + 331, 196, 341, 249, 162, 307, 148, 349, 263, 321, + 257, 243, 229, 356, 159, 119, 67, 187, 173, 145, + 240, 77, 304, 332, 314, 342, 109, 254, 81, 278, + 105, 91, 346, 318, 183, 250, 197, 328, 95, 155, + 169, 268, 226, 236, 264 +}; + +static const Word16 sort_1985[397] = +{ + 0, 4, 6, 129, 215, 304, 390, 7, 5, 3, + 47, 48, 49, 50, 51, 222, 223, 224, 225, 226, + 130, 216, 305, 391, 135, 221, 310, 396, 132, 218, + 307, 393, 133, 219, 308, 394, 136, 311, 134, 220, + 309, 395, 131, 217, 306, 392, 52, 2, 1, 137, + 312, 227, 19, 21, 12, 17, 18, 20, 16, 25, + 13, 10, 14, 24, 23, 22, 26, 8, 15, 53, + 228, 31, 138, 313, 9, 33, 11, 139, 314, 54, + 229, 28, 27, 140, 315, 34, 35, 29, 46, 32, + 30, 55, 230, 37, 36, 39, 38, 40, 141, 316, + 41, 42, 43, 44, 45, 56, 142, 231, 317, 63, + 73, 92, 340, 82, 324, 149, 353, 159, 334, 165, + 338, 178, 163, 254, 77, 168, 257, 153, 343, 57, + 248, 238, 79, 252, 166, 67, 80, 201, 101, 267, + 143, 164, 341, 255, 339, 187, 376, 318, 78, 328, + 362, 115, 232, 242, 253, 290, 276, 62, 58, 158, + 68, 93, 179, 319, 148, 169, 154, 72, 385, 329, + 333, 344, 102, 83, 144, 233, 323, 124, 243, 192, + 354, 237, 64, 247, 202, 209, 150, 116, 335, 268, + 239, 299, 188, 196, 298, 94, 195, 258, 123, 363, + 384, 109, 325, 371, 170, 370, 84, 110, 295, 180, + 74, 210, 191, 106, 291, 205, 367, 381, 377, 206, + 355, 122, 119, 120, 383, 160, 105, 108, 277, 380, + 294, 284, 285, 345, 208, 269, 249, 366, 386, 300, + 297, 259, 125, 369, 197, 97, 194, 286, 211, 281, + 280, 183, 372, 87, 155, 283, 59, 348, 327, 184, + 76, 111, 330, 203, 349, 69, 98, 152, 145, 189, + 66, 320, 337, 173, 358, 251, 198, 174, 263, 262, + 126, 241, 193, 88, 388, 117, 95, 387, 112, 359, + 287, 244, 103, 272, 301, 171, 162, 234, 273, 127, + 373, 181, 292, 85, 378, 302, 121, 107, 364, 346, + 356, 212, 278, 213, 65, 382, 288, 207, 113, 175, + 99, 296, 374, 368, 199, 260, 185, 336, 331, 161, + 270, 264, 250, 240, 75, 350, 151, 60, 89, 321, + 156, 274, 360, 326, 70, 282, 167, 146, 352, 81, + 91, 389, 266, 245, 177, 235, 190, 256, 204, 342, + 128, 118, 303, 104, 379, 182, 114, 375, 200, 96, + 293, 172, 214, 365, 279, 86, 289, 351, 347, 357, + 261, 186, 176, 271, 90, 100, 147, 322, 275, 361, + 71, 332, 61, 265, 157, 246, 236 +}; + +static const Word16 sort_2305[461] = +{ + 0, 4, 6, 145, 247, 352, 454, 7, 5, 3, + 47, 48, 49, 50, 51, 254, 255, 256, 257, 258, + 146, 248, 353, 455, 151, 253, 358, 460, 148, 250, + 355, 457, 149, 251, 356, 458, 152, 359, 150, 252, + 357, 459, 147, 249, 354, 456, 52, 2, 1, 153, + 360, 259, 19, 21, 12, 17, 18, 20, 16, 25, + 13, 10, 14, 24, 23, 22, 26, 8, 15, 53, + 260, 31, 154, 361, 9, 33, 11, 155, 362, 54, + 261, 28, 27, 156, 363, 34, 35, 29, 46, 32, + 30, 55, 262, 37, 36, 39, 38, 40, 157, 364, + 41, 42, 43, 44, 45, 56, 158, 263, 365, 181, + 192, 170, 79, 57, 399, 90, 159, 297, 377, 366, + 275, 68, 183, 388, 286, 194, 299, 92 , 70, 182, + 401, 172, 59, 91, 58, 400, 368, 161, 81, 160, + 264, 171, 80, 389, 390, 378, 379, 193, 298, 69, + 266, 265, 367, 277, 288, 276, 287, 184, 60, 195, + 82, 93, 71, 369, 402, 173, 162, 444, 300, 391, + 98, 76, 278, 61, 267, 374, 135, 411, 167, 102, + 380, 200, 87, 178, 65, 94, 204, 124, 72, 342, + 189, 305, 381, 396, 433, 301, 226, 407, 289, 237, + 113, 215, 185, 128, 309, 403, 116, 320, 196, 331, + 370, 422, 174, 64, 392, 83, 425, 219, 134, 188, + 432, 112, 427, 139, 279, 163, 436, 208, 447, 218, + 236, 229, 97, 294, 385, 230, 166, 268, 177, 443, + 225, 426, 101, 272, 138, 127, 290, 117, 347, 199, + 414, 95, 140, 240, 410, 395, 209, 129, 283, 346, + 105, 241, 437, 86, 308, 448, 203, 345, 186, 107, + 220, 415, 334, 319, 106, 313, 118, 123, 73, 207, + 421, 214, 384, 373, 438, 62, 371, 341, 75, 449, + 168, 323, 164, 242, 416, 324, 304, 197, 335, 404, + 271, 63, 191, 325, 96, 169, 231, 280, 312, 187, + 406, 84, 201, 100, 67, 382, 175, 336, 202, 330, + 269, 393, 376, 383, 293, 307, 409, 179, 285, 314, + 302, 372, 398, 190, 180, 89, 99, 103, 232, 78, + 88, 77, 136, 387, 165, 198, 394, 125, 176, 428, + 74, 375, 238, 227, 66, 273, 282, 141, 306, 412, + 114, 85, 130, 348, 119, 291, 296, 386, 233, 397, + 303, 405, 284, 445, 423, 221, 210, 205, 450, 108, + 274, 434, 216, 343, 337, 142, 243, 321, 408, 451, + 310, 292, 120, 109, 281, 439, 270, 429, 332, 295, + 418, 211, 315, 222, 326, 131, 430, 244, 327, 349, + 417, 316, 143, 338, 440, 234, 110, 212, 452, 245, + 121, 419, 350, 223, 132, 441, 328, 413, 317, 339, + 126, 104, 137, 446, 344, 239, 435, 115, 333, 206, + 322, 217, 228, 424, 453, 311, 351, 111, 442, 224, + 213, 122, 431, 340, 235, 246, 133, 144, 420, 329, + 318 +}; + +static const Word16 sort_2385[477] = +{ + 0, 4, 6, 145, 251, 360, 466, 7, 5, 3, + 47, 48, 49, 50, 51, 262, 263, 264, 265, 266, + 146, 252, 361, 467, 151, 257, 366, 472, 148, 254, + 363, 469, 149, 255, 364, 470, 156, 371, 150, 256, + 365, 471, 147, 253, 362, 468, 52, 2, 1, 157, + 372, 267, 19, 21, 12, 17, 18, 20, 16, 25, + 13, 10, 14, 24, 23, 22, 26, 8, 15, 53, + 268, 31, 152, 153, 154, 155, 258, 259, 260, 261, + 367, 368, 369, 370, 473, 474, 475, 476, 158, 373, + 9, 33, 11, 159, 374, 54, 269, 28, 27, 160, + 375, 34, 35, 29, 46, 32, 30, 55, 270, 37, + 36, 39, 38, 40, 161, 376, 41, 42, 43, 44, + 45, 56, 162, 271, 377, 185, 196, 174, 79, 57, + 411, 90, 163, 305, 389, 378, 283, 68, 187, 400, + 294, 198, 307, 92, 70, 186, 413, 176, 59, 91, + 58, 412, 380, 165, 81, 164, 272, 175, 80, 401, + 402, 390, 391, 197, 306, 69, 274, 273, 379, 285, + 296, 284, 295, 188, 60, 199, 82, 93, 71, 381, + 414, 177, 166, 456, 308, 403, 98, 76, 286, 61, + 275, 386, 135, 423, 171, 102, 392, 204, 87, 182, + 65, 94, 208, 124, 72, 350, 193, 313, 393, 408, + 445, 309, 230, 419, 297, 241, 113, 219, 189, 128, + 317, 415, 116, 328, 200, 339, 382, 434, 178, 64, + 404, 83, 437, 223, 134, 192, 444, 112, 439, 139, + 287, 167, 448, 212, 459, 222, 240, 233, 97, 302, + 397, 234, 170, 276, 181, 455, 229, 438, 101, 280, + 138, 127, 298, 117, 355, 203, 426, 95, 140, 244, + 422, 407, 213, 129, 291, 354, 105, 245, 449, 86, + 316, 460, 207, 353, 190, 107, 224, 427, 342, 327, + 106, 321, 118, 123, 73, 211, 433, 218, 396, 385, + 450, 62, 383, 349, 75, 461, 172, 331, 168, 246, + 428, 332, 312, 201, 343, 416, 279, 63, 195, 333, + 96, 173, 235, 288, 320, 191, 418, 84, 205, 100, + 67, 394, 179, 344, 206, 338, 277, 405, 388, 395, + 301, 315, 421, 183, 293, 322, 310, 384, 410, 194, + 184, 89, 99, 103, 236, 78, 88, 77, 136, 399, + 169, 202, 406, 125, 180, 440, 74, 387, 242, 231, + 66, 281, 290, 141, 314, 424, 114, 85, 130, 356, + 119, 299, 304, 398, 237, 409, 311, 417, 292, 457, + 435, 225, 214, 209, 462, 108, 282, 446, 220, 351, + 345, 142, 247, 329, 420, 463, 318, 300, 120, 109, + 289, 451, 278, 441, 340, 303, 430, 215, 323, 226, + 334, 131, 442, 248, 335, 357, 429, 324, 143, 346, + 452, 238, 110, 216, 464, 249, 121, 431, 358, 227, + 132, 453, 336, 425, 325, 347, 126, 104, 137, 458, + 352, 243, 447, 115, 341, 210, 330, 221, 232, 436, + 465, 319, 359, 111, 454, 228, 217, 122, 443, 348, + 239, 250, 133, 144, 432, 337, 326 +}; + +static const Word16 sort_SID[35] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34 +}; + +/* pointer table for bit sorting tables */ +static const Word16 *const sort_ptr[16] = { sort_660, sort_885, sort_1265, sort_1425, sort_1585, sort_1825, sort_1985, sort_2305, + sort_2385, sort_SID, NULL, NULL, NULL, NULL, NULL, NULL + }; + +/* 4 bit to 3 bit AMR-WB CMR remapping table */ +static const Word16 amrwb_3bit_cmr[16] = +{ + 0x00, /* AMRWB_660 */ + 0x01, /* AMRWB_885 */ + 0x02, /* AMRWB_1265 */ + 0x05, /* AMRWB_1425 */ + 0x03, /* AMRWB_1585 */ + 0x06, /* AMRWB_1825 */ + 0x06, /* AMRWB_1985 -> 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.c b/lib_com/modif_fs.c new file mode 100644 index 000000000..505adda57 --- /dev/null +++ b/lib_com/modif_fs.c @@ -0,0 +1,858 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + + +/*-------------------------------------------------------------------* + * modify_Fs() + * + * Function for resampling of signals + *-------------------------------------------------------------------*/ + +short modify_Fs( /* o : length of output */ + const float sigIn[], /* i : signal to decimate */ + short lg, /* i : length of input + 0 delay signaling */ + const int fin, /* i : frequency of input */ + float sigOut[], /* o : decimated signal */ + const int fout, /* i : frequency of output */ + float mem[] /* i/o: filter memory */ + ,int nblp /* i : flag indicating if NB low-pass is applied */ +) +{ + short i; + short lg_out, fac_num, fac_den, filt_len, frac, mem_len; + float num_den; + short datastep, fracstep; + float *sigIn_ptr; + float signal_tab[3*L_FILT_MAX + L_FRAME48k], *signal, *signal_ana; /* 3* as 2* for memory and 1* for future prediction */ + float A[M+1], r[M+1], epsP[M+1], val; + short mem_len_ana; + short plus_sample_in; + short j; + float mu_preemph; + float mem_preemph; + const Resampling_cfg *cfg_ptr; + short flag_low_order = 0; + short filt_len_tmp; + + /*-------------------------------------------------------------------* + * IIR filters for resampling to/from 8 kHz + *-------------------------------------------------------------------*/ + + /*-------------------------------------------------------------------* + * Find the resampling configuration + *-------------------------------------------------------------------*/ + + if ( fin == fout ) + { + /* just copy the signal and quit */ + for (i = 0; i < lg; i++) + { + sigOut[i] = sigIn[i]; + } + + return lg; + } + else + { + /* find the resampling configuration in the lookup table */ + for (cfg_ptr = &resampling_cfg_tbl[0]; (cfg_ptr->fin != 0) && !(cfg_ptr->fin == fin && cfg_ptr->fout == fout); cfg_ptr++) + { + } + + + /* find config with NB 4kHz low-pass */ + if (nblp && (fin > 8000) && (fout == 12800)) + { + flag_low_order = 1; + for (cfg_ptr++; (cfg_ptr->fin != 0) && !(cfg_ptr->fin == fin && cfg_ptr->fout == fout); cfg_ptr++) + { + } + } + +#define WMC_TOOL_SKIP + /* Retrieve and/or calculate the resampling parameters */ + fac_num = cfg_ptr->fac_num; + fac_den = (short)((cfg_ptr->fin * fac_num) / cfg_ptr->fout); + lg_out = (lg * fac_num) / fac_den; + filt_len = cfg_ptr->filt_len; + + mem_len = 2*filt_len; + plus_sample_in = 0; /* default, regular delay */ + frac = 0; + + if ( fin == 8000 && fout == 12800 ) + { + plus_sample_in = 7; + frac = 4; + } + + signal = signal_tab+2*L_FILT_MAX + L_FRAME48k - mem_len - lg; + signal_ana = signal; + mem_len_ana = mem_len; +#undef WMC_TOOL_SKIP + } + + /*-------------------------------------------------------------------* + * FIR filters for resampling to/from 12.8, 16, 32, 48 kHz + *-------------------------------------------------------------------*/ + + /* append filter memory */ + for (i=0; i<2*filt_len; i++) + { + signal[i] = mem[i]; + } + + for (i=0; i 0 ) + { + + autocorr( signal_ana+mem_len_ana+lg-LEN_WIN_SSS, r, 1, LEN_WIN_SSS, wind_sss, 0, 0, 0 ); + + mu_preemph = r[1] / r[0]; + mem_preemph = signal_ana[mem_len_ana+lg-LEN_WIN_SSS - 1]; + preemph( signal_ana+mem_len_ana+lg-LEN_WIN_SSS, mu_preemph, LEN_WIN_SSS, &mem_preemph ); + + /* Autocorrelations */ + autocorr( signal_ana+mem_len_ana+lg-LEN_WIN_SSS, r, M, LEN_WIN_SSS, wind_sss, 0, 0, 0 ); + + lag_wind( r, M, fin, LAGW_STRONG ); + + /* Levinson-Durbin */ + lev_dur( A, r, M, epsP ); + + for (i=0; i> 1; + } + + for(i=0; ifilter, frac, fac_num, filt_len_tmp ); + + frac = frac + fracstep; + if ( frac >= fac_num ) + { + frac = frac - fac_num; + sigIn_ptr++; + } + + sigIn_ptr += datastep; + } + + /* rescaling */ + if ( (fac_num > fac_den) == ((cfg_ptr->flags & RS_INV_FAC) != 0) ) + { + num_den = (float)fac_num / fac_den; + + for( i=0; i 0.25 ) */ + k3d = fk1 - 1; /* to compurte index in cu with respect to the last sample with - sign (ex 1.25 -> -0.75 ) */ + + kk = 0; + for(i = 0; i < lg-ct2[cind][11];) + { + sigOut[j++] = sigIn[i]; + for(k = 0; k < ct2[cind][10]; k++) + { + cc[kk][0] = sigIn[i+1]/3; + cc[kk][2] =(sigIn[i]+sigIn[i+2])/2-sigIn[i+1]; + cc[kk][3] = (sigIn[i]+sigIn[i+3]-sigIn[i+1]-sigIn[i+2]-4*cc[kk][2]) / 6; + cc[kk][1] = sigIn[i+2]-sigIn[i+1]-cc[kk][3]-cc[kk][2]; + i++; + + i2 = kk-2; + i1 = kk-1; + if( i1 < 0 ) + { + i1 += 4; + } + + if( i2 < 0 ) + { + i2 += 4; + } + + for(k1 = ct2[cind][k]; k1 < fk1; k1 += ct2[cind][8]) + { + k2 = k1 - k2d; + k3 = k3d - k1; + vv = (float)( cu[k1][2]*cc[i2][3] + cu[k1][1]*cc[i2][2] + cu[k1][0]*cc[i2][1] + cc[i2][0]); + vv += (float)( cu[k2][2]*cc[i1][3] + cu[k2][1]*cc[i1][2] + cu[k2][0]*cc[i1][1] + cc[i1][0]); + vv += (float)(-cu[k3][2]*cc[kk][3] + cu[k3][1]*cc[kk][2] - cu[k3][0]*cc[kk][1] + cc[kk][0]); + sigOut[j++] = vv; + } + + kk++; + if( kk == 4 ) + { + kk = 0; + } + } + } + + sigOut[j++] = sigIn[i]; + + for(k = 0; k < ct2[cind][11]-3; k++) + { + cc[kk][0] = sigIn[i+1]/3; + cc[kk][2] =(sigIn[i]+sigIn[i+2])/2-sigIn[i+1]; + cc[kk][3] = (sigIn[i]+sigIn[i+3]-sigIn[i+1]-sigIn[i+2]-4*cc[kk][2]) / 6; + cc[kk][1] = sigIn[i+2]-sigIn[i+1]-cc[kk][3]-cc[kk][2]; + i++; + + i2 = kk-2; + i1 = kk-1; + if( i1 < 0 ) + { + i1 += 4; + } + + if( i2 < 0 ) + { + i2 += 4; + } + + for(k1 = ct2[cind][k]; k1 < fk1; k1 += ct2[cind][8]) + { + k2 = k1 - k2d; + k3 = k3d - k1; + vv = (float)( cu[k1][2]*cc[i2][3] + cu[k1][1]*cc[i2][2] + cu[k1][0]*cc[i2][1] + cc[i2][0]); + vv += (float)( cu[k2][2]*cc[i1][3] + cu[k2][1]*cc[i1][2] + cu[k2][0]*cc[i1][1] + cc[i1][0]); + vv += (float)(-cu[k3][2]*cc[kk][3] + cu[k3][1]*cc[kk][2] - cu[k3][0]*cc[kk][1] + cc[kk][0]); + sigOut[j++] = vv; + } + + kk++; + + if( kk == 4 ) + { + kk = 0; + } + } + + kk--; + if( kk == -1 ) + { + kk = 3; + } + + if( ct2[cind][10] == 1 ) + { + sigOut[j++] = sigIn[i]; + } + + for(k1 = ct2[cind][k]; k1 < fk1; k1 += ct2[cind][8]) + { + k2 = k1 - k2d; + vv = (float)( cu[k2][2]*cc[kk][3] + cu[k2][1]*cc[kk][2] + cu[k2][0]*cc[kk][1] + cc[kk][0]); + sigOut[j++] = vv*3; + } + + if( ct2[cind][10] < 3 ) + { + sigOut[j++] = sigIn[i+1]; + } + + for( k1 = ct2[cind][k+1]; k1 < fk1; k1 += ct2[cind][8] ) + { + vv = (float)( cu[k1][2]*cc[kk][3] + cu[k1][1]*cc[kk][2] + cu[k1][0]*cc[kk][1] + cc[kk][0]); + sigOut[j++] = vv*3; + } + + if( ct2[cind][10] == 1 ) + { + sigOut[j++] = sigIn[i+2]; + } + } + + return lg_out; +} + +/*-------------------------------------------------------------------* + * Interpolate_allpass_steep() + * + * Interpolation by a factor 2 + *-------------------------------------------------------------------*/ + +void Interpolate_allpass_steep( + const float *in, /* i : input array of size N */ + float *state, /* i/o: memory */ + const short N, /* i : number of input samples */ + float *out /* o : output array of size 2*N */ +) +{ + short n, k; + float temp[ALLPASSSECTIONS_STEEP - 1]; + + /* upper allpass filter chain */ + for (k = 0; k < N; k++) + { + temp[0] = state[0] + AP2_STEEP[0] * in[k]; + state[0] = in[k] - AP2_STEEP[0] * temp[0]; + + /* for better performance, unroll this loop */ + for (n = 1; n < ALLPASSSECTIONS_STEEP - 1; n++) + { + temp[n] = state[n] + AP2_STEEP[n] * temp[n - 1]; + state[n] = temp[n - 1] - AP2_STEEP[n] * temp[n]; + } + + out[2 * k + 1] = state[ALLPASSSECTIONS_STEEP - 1] + AP2_STEEP[ALLPASSSECTIONS_STEEP - 1] * temp[ALLPASSSECTIONS_STEEP - 2]; + state[ALLPASSSECTIONS_STEEP - 1] = temp[ALLPASSSECTIONS_STEEP - 2] - AP2_STEEP[ALLPASSSECTIONS_STEEP - 1] * out[2 * k + 1]; + } + + /* lower allpass filter chain */ + for (k = 0; k < N; k++) + { + temp[0] = state[ALLPASSSECTIONS_STEEP] + AP1_STEEP[0] * in[k]; + state[ALLPASSSECTIONS_STEEP] = in[k] - AP1_STEEP[0] * temp[0]; + + /* for better performance, unroll this loop */ + for (n = 1; n < ALLPASSSECTIONS_STEEP - 1; n++) + { + temp[n] = state[ALLPASSSECTIONS_STEEP + n] + AP1_STEEP[n] * temp[n - 1]; + state[ALLPASSSECTIONS_STEEP + n] = temp[n - 1] - AP1_STEEP[n] * temp[n]; + } + + out[2 * k] = state[2 * ALLPASSSECTIONS_STEEP - 1] + AP1_STEEP[ALLPASSSECTIONS_STEEP - 1] * temp[ALLPASSSECTIONS_STEEP - 2]; + state[2 * ALLPASSSECTIONS_STEEP - 1] = temp[ALLPASSSECTIONS_STEEP - 2] - AP1_STEEP[ALLPASSSECTIONS_STEEP - 1] * out[2 * k]; + } + + return; +} + +/*-------------------------------------------------------------------* + * Decimate_allpass_steep() + * + * Decimation by a factor 2 + *-------------------------------------------------------------------*/ + +void Decimate_allpass_steep ( + const float *in, /* i : input array of size N */ + float *state, /* i/o: memory */ + const short N, /* i : number of input samples */ + float *out /* o : output array of size N/2 */ +) +{ + short n, k; + float temp[ALLPASSSECTIONS_STEEP]; + + /* upper allpass filter chain */ + for (k = 0; k < N / 2; k++) + { + temp[0] = state[0] + AP1_STEEP[0] * in[2 * k]; + state[0] = in[2 * k] - AP1_STEEP[0] * temp[0]; + + /* for better performance, unroll this loop */ + for (n = 1; n < ALLPASSSECTIONS_STEEP - 1; n++) + { + temp[n] = state[n] + AP1_STEEP[n] * temp[n - 1]; + if( fabs(temp[n]) < 1e-12 ) + { + temp[n] = sign(temp[n])*1e-12; + } + state[n] = temp[n - 1] - AP1_STEEP[n] * temp[n]; + } + + out[k] = state[ALLPASSSECTIONS_STEEP - 1] + AP1_STEEP[ALLPASSSECTIONS_STEEP - 1] * temp[ALLPASSSECTIONS_STEEP - 2]; + state[ALLPASSSECTIONS_STEEP - 1] = temp[ALLPASSSECTIONS_STEEP - 2] - AP1_STEEP[ALLPASSSECTIONS_STEEP - 1] * out[k]; + } + + /* lower allpass filter chain */ + temp[0] = state[ALLPASSSECTIONS_STEEP] + AP2_STEEP[0] * state[2 * ALLPASSSECTIONS_STEEP]; + state[ALLPASSSECTIONS_STEEP] = state[2 * ALLPASSSECTIONS_STEEP] - AP2_STEEP[0] * temp[0]; + + /* for better performance, unroll this loop */ + for (n = 1; n < ALLPASSSECTIONS_STEEP - 1; n++) + { + temp[n] = state[ALLPASSSECTIONS_STEEP + n] + AP2_STEEP[n] * temp[n - 1]; + if( fabs(temp[n]) < 1e-12 ) + { + temp[n] = sign(temp[n])*1e-12; + } + state[ALLPASSSECTIONS_STEEP + n] = temp[n - 1] - AP2_STEEP[n] * temp[n]; + } + + temp[ALLPASSSECTIONS_STEEP - 1] = state[2 * ALLPASSSECTIONS_STEEP - 1] + AP2_STEEP[ALLPASSSECTIONS_STEEP - 1] * + temp[ALLPASSSECTIONS_STEEP -2]; + + state[2 * ALLPASSSECTIONS_STEEP - 1] = temp[ALLPASSSECTIONS_STEEP - 2] - AP2_STEEP[ALLPASSSECTIONS_STEEP - 1] * + temp[ALLPASSSECTIONS_STEEP - 1]; + out[0] = (float)((out[0] + temp[ALLPASSSECTIONS_STEEP - 1]) * 0.5); + + for (k = 1; k < N / 2; k++) + { + temp[0] = state[ALLPASSSECTIONS_STEEP] + AP2_STEEP[0] * in[2 * k - 1]; + state[ALLPASSSECTIONS_STEEP] = in[2 * k - 1] - AP2_STEEP[0] * temp[0]; + + /* for better performance, unroll this loop */ + for (n = 1; n < ALLPASSSECTIONS_STEEP - 1; n++) + { + temp[n] = state[ALLPASSSECTIONS_STEEP + n] + AP2_STEEP[n] * temp[n - 1]; + if( fabs(temp[n]) < 1e-12 ) + { + temp[n] = sign(temp[n])*1e-12; + } + state[ALLPASSSECTIONS_STEEP + n] = temp[n - 1] - AP2_STEEP[n] * temp[n]; + } + + temp[ALLPASSSECTIONS_STEEP - 1] = state[2 * ALLPASSSECTIONS_STEEP - 1] + AP2_STEEP[ALLPASSSECTIONS_STEEP - 1] * + temp[ALLPASSSECTIONS_STEEP - 2]; + state[2 * ALLPASSSECTIONS_STEEP - 1] = temp[ALLPASSSECTIONS_STEEP - 2] - AP2_STEEP[ALLPASSSECTIONS_STEEP - 1] * + temp[ALLPASSSECTIONS_STEEP - 1]; + out[k] = (float)((out[k] + temp[ALLPASSSECTIONS_STEEP - 1]) * 0.5); + } + + /* z^(-1) */ + state[2 * ALLPASSSECTIONS_STEEP] = in[N - 1]; + + return; +} + +/*-------------------------------------------------------------------* + * interpolate_3_over_2_allpass() + * + * Interpolate 3/2 using allpass iir polyphase filter. Delay 4 samples @48k + *-------------------------------------------------------------------*/ + +void interpolate_3_over_2_allpass( + const float *input, /* i : input signal */ + const short len, /* i : number of input samples */ + float *out, /* o : output signal */ + float *mem, /* i/o: memory */ + const float *filt_coeff /* i : filter coefficients */ +) +{ + short i, loop_len; + float Vu[2], Vm[2], Vl[2]; /* Outputs of three cascaded allpass stages (upper, middle, and lower) */ + float out1_buff[L_FRAME32k*3]; + float * out1; + float mem_temp; + + out1 = out1_buff; + + for (i = 0; i < len; i++ ) + { + /* Upper branch */ + Vu[0] = mem[0] + filt_coeff[0] * ( input[i] - mem[1] ); + Vu[1] = mem[1] + filt_coeff[1] * ( Vu[0] - mem[2] ); + mem[3] = mem[2] + filt_coeff[2] * ( Vu[1] - mem[3] ); + + mem[1] = Vu[0]; + mem[2] = Vu[1]; + *out1++ = mem[3]; + + /* Middle branch */ + Vm[0] = mem[0] + filt_coeff[3] * (input[i]-mem[4]); + Vm[1] = mem[4] + filt_coeff[4] * (Vm[0]-mem[5]); + mem[6] = mem[5] + filt_coeff[5] * (Vm[1]-mem[6]); + + mem[4] = Vm[0]; + mem[5] = Vm[1]; + *out1++ = mem[6]; + + /* Lower branch */ + Vl[0] = mem[0] + filt_coeff[6] * (input[i]-mem[7]); + Vl[1] = mem[7] + filt_coeff[7] * (Vl[0]-mem[8]); + mem[9] = mem[8] + filt_coeff[8] * (Vl[1]-mem[9]); + + mem[0] = input[i]; + mem[7] = Vl[0]; + mem[8] = Vl[1]; + *out1++ = mem[9]; + } + + loop_len = len*3/2; + + /*decimate by 2 and LPF*/ + for(i = 0; i < loop_len; i++) + { + mem_temp = out1_buff[2*i]; + out[i] = (((0.0473147f)*(mem_temp+mem[10]))+((-0.151521f)*(mem[11]+mem[14]))); + out[i] = (out[i]+((0.614152f)*(mem[12]+mem[13]))); + mem[10] = mem[11]; + mem[11] = mem[12]; + mem[12] = mem[13]; + mem[13] = mem[14]; + mem[14] = mem_temp; + } + return; +} + +/*-------------------------------------------------------------------* +* decimate_2_over_3_allpass() +* +* Decimate 2/3 using allpass iir polyphase filter. +*-------------------------------------------------------------------*/ + +void decimate_2_over_3_allpass( + const float *input, /* i : input signal */ + const short len, /* i : number of input samples */ + float *out, /* o : output signal */ + float *mem, /* i/o: memory */ + const float *filt_coeff, /* i : filter coefficients */ + const float *lp_num, + const float *lp_den, + float *lp_mem +) +{ + short i, loop_len; + float Vu[2], Vm[2], Vl[2]; /* Outputs of three cascaded allpass stages (upper, middle, and lower) */ + float * out1; + float *in; + float out1_buff[L_FRAME48k*2]; + float tmp; + + /* Combine the 2nd order iir lpf with the decimation by 2 to improve the efficiency*/ + out1 = out1_buff; + + *out1++ = lp_num[0] * ( input[0] + lp_mem[0] ) - lp_den[2] * lp_mem[2]; + *out1++ = lp_num[1] * input[0] - lp_den[2] * lp_mem[1]; + + for (i=1; i < len; i++) + { + tmp = lp_num[0] * ( input[i] + input[i-1] ) - lp_den[2] * out1[-2]; + *out1++ = tmp; + tmp = lp_num[1] * input[i] - lp_den[2] * out1[-2]; + *out1++ = tmp; + } + lp_mem[0] = input[len-1]; + lp_mem[1] = out1[-1]; + lp_mem[2] = out1[-2]; + + /* do the all pass polyphase filter with pi/3 cutoff */ + out1 = out; + in = out1_buff; + loop_len = (short) len*2/3; + + for (i = 0; i < loop_len; i++ ) + { + /* Lower branch */ + Vl[0] = mem[8] + filt_coeff[6] * (*in - mem[9]); + Vl[1] = mem[9] + filt_coeff[7] * (Vl[0] - mem[10]); + mem[11] = mem[10] + filt_coeff[8] * (Vl[1] - mem[11]); + + mem[8] = *in++; + mem[9] = Vl[0]; + mem[10] = Vl[1]; + *out1 = mem[11]; + + /* Middle branch */ + Vm[0] = mem[4] + filt_coeff[3] * (*in - mem[5]); + Vm[1] = mem[5] + filt_coeff[4] * (Vm[0]-mem[6]); + mem[7] = mem[6] + filt_coeff[5] * (Vm[1]-mem[7]); + + mem[4] = *in++; + mem[5] = Vm[0]; + mem[6] = Vm[1]; + *out1 += mem[7]; + + /* Upper branch */ + Vu[0] = mem[0] + filt_coeff[0] * ( *in - mem[1] ); + Vu[1] = mem[1] + filt_coeff[1] * ( Vu[0] - mem[2] ); + mem[3] = mem[2] + filt_coeff[2] * ( Vu[1] - mem[3] ); + + mem[0] = *in++; + mem[1] = Vu[0]; + mem[2] = Vu[1]; + *out1++ += mem[3]; + } + + return; +} + +/*-------------------------------------------------------------------* + * interpolate_3_over_1_allpass() + * + * Interpolate 3/1 using allpass iir polyphase filter. Delay 4 samples @48k + *-------------------------------------------------------------------*/ + +void interpolate_3_over_1_allpass( + const float *input, /* i : input signal */ + const short len, /* i : number of input samples */ + float *out, /* o : output signal */ + float *mem, /* i/o: memory */ + const float *filt_coeff /* i : filter coefficients */ +) +{ + short i; + float Vu[2], Vm[2], Vl[2]; /* Outputs of three cascaded allpass stages (upper, middle, and lower) */ + float * out1; + float mem_temp; + out1 = &out[0]; + + for (i = 0; i < len; i++ ) + { + /* Upper branch */ + Vu[0] = mem[0] + filt_coeff[0] * ( input[i] - mem[1] ); + Vu[1] = mem[1] + filt_coeff[1] * ( Vu[0] - mem[2] ); + mem[3] = mem[2] + filt_coeff[2] * ( Vu[1] - mem[3] ); + + mem[1] = Vu[0]; + mem[2] = Vu[1]; + *out1++ = mem[3]; + + /* Middle branch */ + Vm[0] = mem[0] + filt_coeff[3] * (input[i]-mem[4]); + Vm[1] = mem[4] + filt_coeff[4] * (Vm[0]-mem[5]); + mem[6] = mem[5] + filt_coeff[5] * (Vm[1]-mem[6]); + + mem[4] = Vm[0]; + mem[5] = Vm[1]; + *out1++ = mem[6]; + + /* Lower branch */ + Vl[0] = mem[0] + filt_coeff[6] * (input[i]-mem[7]); + Vl[1] = mem[7] + filt_coeff[7] * (Vl[0]-mem[8]); + mem[9] = mem[8] + filt_coeff[8] * (Vl[1]-mem[9]); + + mem[0] = input[i]; + mem[7] = Vl[0]; + mem[8] = Vl[1]; + *out1++ = mem[9]; + } + + /*LPF*/ + for(i = 0; i < len*3; i++) + { + mem_temp = out[i]; + out[i] = (((0.572769f)*(mem[12]+mem[11]))-((0.074005f)*(mem_temp+mem[10]))); + mem[10] = mem[11]; + mem[11] = mem[12]; + mem[12] = mem_temp; + } + + return; +} + + +/*-------------------------------------------------------------------* + * retro_interp4_5() + * + * + *-------------------------------------------------------------------*/ + +void retro_interp4_5( + const float *syn, + float *pst_old_syn +) +{ + float *pf5, *pf4; + short c; + + /* resample st->pst_old_syn in a reverse way to preserve time-alignment */ + pf4 = (float*) &pst_old_syn[58]; + pf5 = (float*) pst_old_syn; + for (c=0; c<57; c++) + { + *pf5++ = pf4[0]; + *pf5++ = 0.2f * pf4[0] + 0.8f * pf4[1]; + *pf5++ = 0.4f * pf4[1] + 0.6f * pf4[2]; + *pf5++ = 0.6f * pf4[2] + 0.4f * pf4[3]; + *pf5++ = 0.8f * pf4[3] + 0.2f * pf4[4]; + pf4+=4; + } + *pf5++ = pf4[0]; + *pf5++ = 0.2f * pf4[0] + 0.8f * pf4[1]; + *pf5++ = 0.4f * pf4[1] + 0.6f * pf4[2]; + *pf5++ = 0.6f * pf4[2] + 0.4f * pf4[3]; + *pf5++ = 0.8f * pf4[3] + 0.2f * syn[0]; + /* all samples processed: NBPSF_PIT_MAX = 290 = (58*5) */ + + return; +} + + +/*-------------------------------------------------------------------* + * retro_interp5_4() + * + * + *-------------------------------------------------------------------*/ + +void retro_interp5_4( float *pst_old_syn ) +{ + float *pf5, *pf4; + short c; + + /* resample st->pst_old_syn in a reverse way to preserve time-alignment */ + pf4 = (float*) &pst_old_syn[NBPSF_PIT_MAX-1]; + pf5 = pf4; + for (c=0; c<58; c++) + { + *pf4-- = 0.75f * pf5[0] + 0.25f * pf5[-1]; + *pf4-- = 0.50f * pf5[-1] + 0.50f * pf5[-2]; + *pf4-- = 0.25f * pf5[-2] + 0.75f * pf5[-3]; + *pf4-- = pf5[-4]; + pf5-=5; + } + /* all samples processed: NBPSF_PIT_MAX = 290 = (58*5) */ + + return; +} diff --git a/lib_com/move.h b/lib_com/move.h new file mode 100644 index 000000000..09219dd1c --- /dev/null +++ b/lib_com/move.h @@ -0,0 +1,86 @@ +/****************************************************************************************************** + + (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#ifndef _MOVE_H +#define _MOVE_H + +/* BASOP -> FLC brigde: data move counting */ + +static __inline void move16( void ) +{ +#ifdef WMOPS + multiCounter[currCounter].move16++; +#endif +} + +static __inline void move32( void ) +{ +#ifdef WMOPS + multiCounter[currCounter].move32++; +#endif +} + +static __inline void test( void ) +{ +#ifdef WMOPS + multiCounter[currCounter].Test++; +#endif +} + +static __inline void logic16( void ) +{ +#ifdef WMOPS + multiCounter[currCounter].Logic16++; +#endif +} + +static __inline void logic32( void ) +{ +#ifdef WMOPS + multiCounter[currCounter].Logic32++; +#endif +} + +/*-------- legacy ----------*/ +#define data_move() move16() +#define L_data_move() move32() +#define data_move_external() move16() +#define compare_zero() test() +/*-------- end legacy ----------*/ + +#define cast16 move16 + +#endif /* _MOVE_H */ diff --git a/lib_com/mslvq_com.c b/lib_com/mslvq_com.c new file mode 100644 index 000000000..f381e64a8 --- /dev/null +++ b/lib_com/mslvq_com.c @@ -0,0 +1,734 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*-----------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------*/ + +static void make_offset_scale(int j, const unsigned int tab_no_cv[], const int no_ld[], short no_scl, unsigned int offset_scale[][MAX_NO_SCALES+1]); +static void init_offset( unsigned int offset_scale1[][MAX_NO_SCALES+1], unsigned int offset_scale2[][MAX_NO_SCALES+1], unsigned int offset_scale1_p[][MAX_NO_SCALES+1], + unsigned int offset_scale2_p[][MAX_NO_SCALES+1], short no_scales[][2], short no_scales_p[][2]); +static void decode_comb( int index, float *cv, int idx_lead ); +static void decode_sign_pc1( float *c, int idx_sign, int parity ); +static void put_value( float *cv, int *p, float val, int dim, int no_new_val ); +static void decode_leaders( int index, int idx_lead, float *cv ); +static void idx2c( int n, int *p, int k, int val ); +static void divide_64_32( short *x, unsigned int y, unsigned int *result, unsigned int *rem ); +static short decode_indexes( short *index, int no_bits, const float *p_scales, short *p_no_scales, + unsigned int *p_offset_scale1, unsigned int *p_offset_scale2, float *x_lvq, short mode_glb ); + +/*-----------------------------------------------------------------* + * permute() + * used in CNG-LP coding + *-----------------------------------------------------------------*/ + +void permute( + float *pTmp1, /* i/o: vector whose components are to be permuted */ + const short *perm /* i : permutation info (indexes that should be interchanged), max two perms */ +) +{ + int p1, p2; + float tmp; + + p1 = perm[0]; + p2 = perm[1]; + tmp = pTmp1[p1]; + pTmp1[p1] = pTmp1[p2]; + pTmp1[p2] = tmp; + p1 = perm[2]; + + if ( p1 > -1 ) + { + p2 = perm[3]; + tmp = pTmp1[p1]; + pTmp1[p1] = pTmp1[p2]; + pTmp1[p2] = tmp; + } + + return; +} + +/*-----------------------------------------------------------------* + * init_lvq() + * + *-----------------------------------------------------------------*/ + +void init_lvq( + unsigned int offset_scale1[][MAX_NO_SCALES+1], + unsigned int offset_scale2[][MAX_NO_SCALES+1], + unsigned int offset_scale1_p[][MAX_NO_SCALES+1], + unsigned int offset_scale2_p[][MAX_NO_SCALES+1], + short no_scales[][2], + short no_scales_p[][2] +) +{ + short i, j; + /* safety-net mode */ + for(i=0; i0 )) + { + j++; + } + no_scales[i][0] = j; + j = MAX_NO_SCALES; + while ((j0 )) + { + j++; + } + no_scales[i][1] = j-MAX_NO_SCALES; + } + /* predictive mode */ + for(i=0; i0 )) + { + j++; + } + no_scales_p[i][0] = j; + j = MAX_NO_SCALES; + while ((j0 )) + { + j++; + } + no_scales_p[i][1] = j-MAX_NO_SCALES; + } + /* index offsets for each truncation */ + init_offset( offset_scale1, offset_scale2, offset_scale1_p, offset_scale2_p, no_scales, no_scales_p ); +} + +/*-----------------------------------------------------------------* + * make_offset_scale() + * + *-----------------------------------------------------------------*/ +static +void make_offset_scale( + int j, + const unsigned int tab_no_cv[], + const int no_ld[], + short no_scl, + unsigned int offset_scale[][MAX_NO_SCALES+1] +) +{ + int i; + + offset_scale[j][0] = 1; + for( i=1; i<=no_scl; i++ ) + { + offset_scale[j][i] = offset_scale[j][i-1] + tab_no_cv[no_ld[i-1]]; + } + + return; +} + +/*-----------------------------------------------------------------* + * init_offset() + * + *-----------------------------------------------------------------*/ +static +void init_offset( + unsigned int offset_scale1[][MAX_NO_SCALES+1], + unsigned int offset_scale2[][MAX_NO_SCALES+1], + unsigned int offset_scale1_p[][MAX_NO_SCALES+1], + unsigned int offset_scale2_p[][MAX_NO_SCALES+1], + short no_scales[][2], + short no_scales_p[][2] +) +{ + int j; + /* safety-net */ + for( j=0; j 0 ) + { + divide_64_32( index, (unsigned int)p_offset_scale2[mode_glb*no_modes+p_no_scales[mode_glb*2+1]], &index1, &index2 ); + } + else + { + index1 = (unsigned int)(index[0]); /* this is for very low bitrates, so there is no loss in truncation */ + index2 = 0; + } + + if ( index1 == 0 ) + { + for( i=0; i= p_offset_scale1[mode_glb*no_modes+p_no_scales[mode_glb*2]] ) + { + /* safety check in case of bit errors */ + set_f( x_lvq, 0.0f, 2*LATTICE_DIM ); + return 1; + } + + /* find idx_scale */ + i = 1; + while( (short)i <= p_no_scales[mode_glb*2] && index1 >= p_offset_scale1[mode_glb*no_modes +i] ) + { + i++; + } + + idx_scale = i-1; + index1 -= p_offset_scale1[mode_glb*no_modes+idx_scale]; + + /* find idx_leader */ + i = 1; + while( index1 >= table_no_cv[i] ) + { + i++; + } + decode_comb(index1-table_no_cv[i-1], x_lvq, i-1 ); + scale = p_scales[mode_glb*len_scales+idx_scale]; + for( i=0; i= p_offset_scale2[mode_glb*no_modes+i] ) + { + i++; + } + + idx_scale = i-1; + index2 -= p_offset_scale2[mode_glb*no_modes+idx_scale]; + /* find the index of the leader vector */ + i = 1; + while ( index2 >= table_no_cv[i] ) + { + i++; + } + + decode_comb( index2-table_no_cv[i-1], &x_lvq[LATTICE_DIM], i-1 ); + + scale = p_scales[mode_glb*len_scales+MAX_NO_SCALES+idx_scale]; + for( i=LATTICE_DIM; i<2*LATTICE_DIM; i++ ) + { + x_lvq[i] *= scale; + } + } + + return 0; +} + +/*-----------------------------------------------------------------* + * deindex_lvq() + * + *-----------------------------------------------------------------*/ + +short deindex_lvq( + short *index, /* i : index to be decoded, as an array of 3 short */ + float *x_lvq, /* o : decoded codevector */ + short mode, /* i : LVQ coding mode (select scales & no_lead ), or idx_cv */ + short sf_flag, /* i : safety net flag */ + short no_bits, /* i : number of bits for lattice */ + unsigned int *p_offset_scale1, /* i : offset for first subvector */ + unsigned int *p_offset_scale2, /* i : offset for the second subvector */ + short *p_no_scales +) +{ + int i; + const float * p_scales; + short mode_glb; + short ber_flag; + + if ( sf_flag == 1 ) + { + mode_glb = offset_lvq_modes_SN[mode] + offset_in_lvq_mode_SN[mode][no_bits-min_lat_bits_SN[mode]]; + p_scales = &scales[0][0]; + } + else + { + mode_glb = offset_lvq_modes_pred[mode] + offset_in_lvq_mode_pred[mode][no_bits-min_lat_bits_pred[mode]]; + p_scales = &scales_p[0][0]; + } + + /* decode the lattice index into the lattice codevectors for the two subvectors */ + ber_flag = decode_indexes( index, no_bits, p_scales, p_no_scales, p_offset_scale1, p_offset_scale2, x_lvq, mode_glb ); + + if ( sf_flag == 1 ) + { + for( i=0; i<2*LATTICE_DIM; i++ ) + { + x_lvq[i] *= sigma_MSLVQ[mode][i]; + } + } + else + { + for( i=0; i<2*LATTICE_DIM; i++ ) + { + x_lvq[i] *= sigma_p[mode][i]; + } + } + + return ber_flag; +} + +/*------------------------------------------------------------------------------------------------------------* + * deindex_lvq_cng() + * + * Note: + * The sampling frequency for the LVQ CNG decoder frame can be determined by checking the fully decoded + * value of the highest order LSF coefficient. Thus sampling rate information, nor extra codebooks are + * not needed for deindex_lvq_cng(), since it is embedded inside the LSF codebooks. + *------------------------------------------------------------------------------------------------------------*/ + +short deindex_lvq_cng( + short *index, /* i : index to be decoded, as an array of 3 short */ + float *x_lvq, /* o : decoded codevector */ + short idx_cv, /* i : relative mode_lvq, wrt START_CNG */ + int no_bits, /* i : number of bits for lattice */ + unsigned int * p_offset_scale1, + unsigned int * p_offset_scale2, + short * p_no_scales +) +{ + int i; + const float *p_scales; + short mode_glb, mode; + short ber_flag; + + mode_glb = START_CNG + idx_cv; + mode = LVQ_COD_MODES + idx_cv; + + p_scales = &scales[0][0]; + ber_flag = decode_indexes( index, no_bits, p_scales, p_no_scales, p_offset_scale1, p_offset_scale2, x_lvq, mode_glb ); + + for( i=0; i<2*LATTICE_DIM; i++ ) + { + x_lvq[i] *= sigma_MSLVQ[mode][i]; + } + + /* check if permutting needed */ + if ( cng_sort[idx_cv] ) + { + permute( x_lvq, perm_MSLVQ[idx_cv] ); + } + + return ber_flag; +} + + + +/*-----------------------------------------------------------------* + * decode_comb() + * + * combinatorial deindexing of a codevector including the signs +* + *-----------------------------------------------------------------*/ +static void decode_comb( + int index, /* i : index to be decoded */ + float *cv, /* o : decoded codevector */ + int idx_lead /* i : leader class index */ +) +{ + int idx_sign; + + idx_sign = (int)(index/pi0[idx_lead]); + index -= idx_sign*pi0[idx_lead]; + decode_leaders((int)index, idx_lead, cv); + decode_sign_pc1(cv, idx_sign, pl_par[idx_lead]); + + return; +} + +/*-----------------------------------------------------------------* + * decode_leaders() + * + * decode index of a codevector from the leader class idx_lead +*-----------------------------------------------------------------*/ + +static void decode_leaders( + int index, /* i : index to be decoded */ + int idx_lead, /* i : leader class index */ + float *cv /* o : decoded codevector */ +) +{ + int i, no_vals_loc, no_vals_last, p[LATTICE_DIM], index1, dim_loc, n_crt; + float val_crt; + + no_vals_loc = no_vals[idx_lead]; + val_crt = vals[idx_lead][no_vals_loc-1]; + no_vals_last = no_vals_ind[idx_lead][no_vals_loc-1]; + + for( i=0; i 0) + { + if (idx_sign % 2) + { + c[i] = -c[i]; + cnt_neg = -cnt_neg; + } + idx_sign >>= 1; + } + } + + if ( len < LATTICE_DIM ) + { + if (cnt_neg != parity) + { + c[len] = -c[len]; + } + } + + return; +} + +/*-----------------------------------------------------------------* + * extract_low() + * + * (!!!!! function for int64 !!!!) + *-----------------------------------------------------------------*/ + +static unsigned int extract_low( + unsigned int x +) +{ + return (x&(0xffff)); +} + +/*-----------------------------------------------------------------* + * extract_high() + * + * (!!!!! function for int64 !!!!) + *-----------------------------------------------------------------*/ + +static unsigned int extract_high( + unsigned int x +) +{ + return (x>>16); +} + +/*-----------------------------------------------------------------* + * multiply32_32_64() + * + * (!!!!! function for int64 !!!!) + *-----------------------------------------------------------------*/ + +void multiply32_32_64( + unsigned int x, + unsigned int y, + unsigned int *res +) +{ + unsigned int tmp, x_tmp[2], y_tmp[2]; + unsigned int high = 0; + + x_tmp[0] = extract_low(x); /* lowest 16 bits */ + x_tmp[1] = extract_high(x); + y_tmp[0] = extract_low(y); + y_tmp[1] = extract_high(y); + tmp = x_tmp[0]*y_tmp[0]; + high = extract_high(tmp); + res[0] = extract_low(tmp); + tmp = x_tmp[1]*y_tmp[0]+ x_tmp[0]*y_tmp[1] + high; /* x and y are not using all 32 bits */ + high = extract_high(tmp); + res[0] += (extract_low(tmp)<<16); + tmp = x_tmp[1]*y_tmp[1]+high; + res[1] = tmp; + + return; +} + +/*-----------------------------------------------------------------* + * get_no_bits() + * + * (!!!!! function for int64 !!!!) + *-----------------------------------------------------------------*/ + +static int get_no_bits( + unsigned int x +) +{ + int nb = 0; + + while( x > 0 ) + { + x >>= 1; + nb++; + } + + return nb; +} + +/*-----------------------------------------------------------------* + * divide_64_32() + * + * (!!!!! function for int64 !!!!) + *-----------------------------------------------------------------*/ + +static void divide_64_32( + short *xs, /* i : denominator as array of two int32 */ + unsigned int y, /* i : nominator on 32 bits */ + unsigned int *result, /* o : integer division result on 32 bits */ + unsigned int *rem /* o : integer division reminder on 32 bits */ +) +{ + int nb_x1; + unsigned int r, q, q1, x_tmp, x[2]; + + x[0] = (((unsigned int)xs[2]&((1<<2)-1))<<(LEN_INDICE*2)) + (xs[1]<>2; + + /* find number of bits of x[0] and x[1] */ + nb_x1 = get_no_bits(x[1]); + + /* take the first 32 bits */ + if ( nb_x1 > 0 ) + { + x_tmp = (x[1]<<(32-nb_x1)) + (x[0]>>nb_x1); + q = (unsigned int)(x_tmp/y+0.5); + r = x_tmp-q*y; /* this is the first reminder */ + r = (r< +#include "wmc_auto.h" +#include "math.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * dequantize_uvg() + * + * Dequantize unvoiced gains + *--------------------------------------------------------------------*/ + +float dequantize_uvg( + int iG1, /* i: gain 1 index */ + int *iG2, /* i: gain 2 index */ + float *G, /* o: quantized gain */ + short bwidth +) +{ + short i, k; + const float (*UVG1CB)[2] = NULL; + const float (*UVG2CB1)[5] = NULL; + const float (*UVG2CB2)[5] = NULL; + + if ( bwidth == NB ) + { + UVG1CB = UVG1CB_NB; + UVG2CB1 = UVG2CB1_NB; + UVG2CB2 = UVG2CB2_NB; + } + + else if ( bwidth == WB || bwidth == SWB ) + { + UVG1CB = UVG1CB_WB; + UVG2CB1 = UVG2CB1_WB; + UVG2CB2 = UVG2CB2_WB; + } + + for( i=0; i<2; i++) + { + for (k=0; k<5; k++) + { + if(i==0) + { + G[i*5+k] = (float) pow(10.0, UVG1CB[iG1][i]) * UVG2CB1[iG2[i]][k]; + } + else if (i==1) + { + G[i*5+k] = (float) pow(10.0, UVG1CB[iG1][i]) * UVG2CB2[iG2[i]][k]; + } + } + } + return(0.0); +} + +/*-------------------------------------------------------------------* + * generate_nelp_excitation() + * + * Generate excitation for NELP coding. + *--------------------------------------------------------------------*/ + +void generate_nelp_excitation( + short *seed, /* i/o: random number seed */ + float *Gains, /* i : excitation gains */ + float *output, /* o : excitation output */ + float gain_fac /* i : gain factor */ +) +{ + short i,len,j; + float tmp[31], tmp1[31], tmpf; + short k1,k2, I[31], tmpi; + + for (i=0; i<10; i++) + { + if (i==9) + { + len=31; + } + else + { + len=25; + } + + for (j=0; jtmp1[k1]) + { + tmpi=I[k2]; + tmpf=tmp1[k2]; + tmp1[k2]=tmp1[k1]; + I[k2]=I[k1]; + tmp1[k1]=tmpf; + I[k1]=tmpi; + } + } + } + + /*using a factor of 1.37 to compensate for the ~ 2.5 ( or 2.73) dB diff between this scheme and EVS-UV */ + for (j=0; j<(short) rint_new(len/4.0f); j++) + { + output[i*25+I[j]]=(float) (Gains[i]*sqrt(3.0f)*tmp[I[j]]*gain_fac); + } + for (; j + + +#define WMC_TOOL_SKIP + + +/********************************/ +/* Helper functions */ +/********************************/ + +/** Put nBits long encoded value from *pStream into bitstream. Using the function EncodeValue for encoding. */ +static int PutIntoBitstream(int const ** pStream, TEncodeValue EncodeValue, int index, Encoder_State *st, int nBits) +{ + int const value = *(*pStream)++; + int const codedValue = EncodeValue(value, index); + /* Variable initialization */ + push_next_indice(st, codedValue, nBits); + + return value; +} + +/** Get nBits long value from bitstream into *pStream. */ +static int GetFromBitstream(Decoder_State *st, TDecodeValue DecodeValue, int index, int nFixedBits, int ** pStream) +{ + int value = 0; + if (DecodeValue != NULL) + { + DecodeValue(st, index, &value); + } + else + { + value = get_next_indice(st, nFixedBits); + } + *(*pStream)++ = value; + + return value; +} + +static int FixedWidthEncoding(int value, int index) +{ + (void)index; + return value; +} + +/********************************/ +/* Interface functions */ +/********************************/ + +void GetParameters(ParamsBitMap const * paramsBitMap, int nArrayLength, void const * pParameter, int ** pStream, int * pnSize, int * pnBits) +{ + int index; + int iParam, nParams; + int value; + void const * pSubStruct; + + + assert((paramsBitMap != NULL) && (nArrayLength > 0) && (pParameter != NULL) && (pStream != NULL) && (pnSize != NULL) && (pnBits != NULL)); + nParams = paramsBitMap->nParams; + for (index = 0; index < nArrayLength; index++) + { + for (iParam = 0; iParam < nParams; iParam++) + { + ParamBitMap const * const param = & paramsBitMap->params[iParam]; /* WMOPS: Just a shortcut */ + + pSubStruct = param->GetParamValue(pParameter, index, &value); + /* If a function for encoding/decoding value is defined than it should take care of 0 */ + if (param->fZeroAllowed || (param->EncodeValue != NULL)) + { + *(*pStream)++ = value; + } + else + { + *(*pStream)++ = value - 1; + } + ++*pnSize; + *pnBits += (param->nBits != 0) ? param->nBits : param->GetNumberOfBits(value, index); + if ((param->pSubParamBitMap != NULL) && (value > 0)) + { + GetParameters(param->pSubParamBitMap, value, (pSubStruct != NULL) ? pSubStruct : pParameter, pStream, pnSize, pnBits); + } + } + } +} + +void SetParameters(ParamsBitMap const * paramsBitMap, int nArrayLength, void * pParameter, int const ** pStream, int * pnSize) +{ + int index; + int iParam, nParams; + int value; + void * pSubStruct; + 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 * const param = & paramsBitMap->params[iParam]; /* WMOPS: Just a shortcut */ + /* If a function for encoding/decoding value is defined than it should take care of 0 */ + + value = *(*pStream)++ + (param->fZeroAllowed || (param->EncodeValue != NULL) ? 0 : 1); + pSubStruct = param->SetParamValue(pParameter, index, value); + ++*pnSize; + if ((param->pSubParamBitMap != NULL) && (value > 0)) + { + SetParameters(param->pSubParamBitMap, value, (pSubStruct != NULL) ? pSubStruct : pParameter, pStream, pnSize); + } + } + } +} + +void WriteToBitstream(ParamsBitMap const * paramsBitMap, int nArrayLength, int const ** pStream, int * pnSize, Encoder_State *st, int * pnBits) +{ + int index; + int 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 * const param = & paramsBitMap->params[iParam]; /* WMOPS: Just a shortcut */ + int nBits; + /* If a function for encoding/decoding value is defined than it should take care of 0 */ + int fShiftValue; + TEncodeValue EncodeValue; + int value; + + nBits = (param->nBits != 0) ? param->nBits : param->GetNumberOfBits(**pStream, index); + fShiftValue = !param->fZeroAllowed && (param->EncodeValue == NULL); + EncodeValue = (param->EncodeValue == NULL) ? &FixedWidthEncoding : param->EncodeValue; + value = PutIntoBitstream(pStream, EncodeValue, index, st, nBits) + (fShiftValue ? 1 : 0); + ++*pnSize; + *pnBits += nBits; + if ((param->pSubParamBitMap != NULL) && (value > 0)) + { + WriteToBitstream(param->pSubParamBitMap, value, pStream, pnSize, st, pnBits); + } + } + } +} + +void ReadFromBitstream(ParamsBitMap const * paramsBitMap, int nArrayLength, Decoder_State *st, int ** pStream, int * pnSize) +{ + int index; + int iParam, nParams; + int fShiftValue; + int value; + assert((paramsBitMap != NULL) && (nArrayLength > 0) && (pStream != NULL) && (pnSize != NULL) && (st != NULL)); + nParams = paramsBitMap->nParams; + for (index = 0; index < nArrayLength; index++) + { + for (iParam = 0; iParam < nParams; iParam++) + { + ParamBitMap const * param = & paramsBitMap->params[iParam]; /* WMOPS: Just a shortcut */ + /* If a function for encoding/decoding value is defined than it should take care of 0 */ + + fShiftValue = !param->fZeroAllowed && (param->EncodeValue == NULL); + value = GetFromBitstream(st, param->DecodeValue, index, param->nBits, pStream) + (fShiftValue ? 1 : 0); + if ((param->pSubParamBitMap != NULL) && (value > 0)) + { + ReadFromBitstream(param->pSubParamBitMap, value, st, pStream, pnSize); + } + } + } + *pnSize += nParams*nArrayLength; +} diff --git a/lib_com/phase_dispersion.c b/lib_com/phase_dispersion.c new file mode 100644 index 000000000..e3a1bd735 --- /dev/null +++ b/lib_com/phase_dispersion.c @@ -0,0 +1,124 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + + +/*-----------------------------------------------------------------------* + * phase_dispersion() + * + * Post-processing to enhance noise at low bitrate + *-----------------------------------------------------------------------*/ + +void phase_dispersion( + const float gain_code, /* i : gain of code */ + const float gain_pit, /* i : gain of pitch */ + float code[], /* i/o: code vector */ + const short mode, /* i : level, 0=hi, 1=lo, 2=off */ + float disp_mem[] /* i/o: static memory (size = 8) */ +) +{ + short i, j, state; + float *prev_gain_pit, *prev_gain_code, *prev_state; + float code2[2*L_SUBFR]; + float h_disp[L_SUBFR], *code2_real, *code2_imag, *code_real, *code_imag, *h_real, *h_imag; + + prev_state = disp_mem; + prev_gain_code = disp_mem+1; + prev_gain_pit = disp_mem+2; + + state = 2; + if (gain_pit < 0.6f) + { + state = 0; + } + else if (gain_pit < 0.9f) + { + state = 1; + } + + for (i=5; i>0; i--) + { + prev_gain_pit[i] = prev_gain_pit[i-1]; + } + prev_gain_pit[0] = gain_pit; + + if (gain_code - 3.0f * *prev_gain_code > 0.0f) + { + if (state < 2) + { + state++; + } + } + else + { + j=0; + for (i=0; i<6; i++) + { + if (prev_gain_pit[i] < 0.6f) + { + j++; + } + } + + if (j > 2) + { + state = 0; + } + + if ((state - (short)*prev_state) > 1) + { + state--; + } + } + + *prev_gain_code = gain_code; + *prev_state = (float)state; + + /*-----------------------------------------------------------------* + * Circular convolution + *-----------------------------------------------------------------*/ + + state += mode; /* level of dispersion */ + if( state < 2 ) + { + fft_rel( code, L_SUBFR, 6 ); + + if (state == 0) + { + mvr2r( low_H, h_disp, L_SUBFR ); + } + + if (state == 1) + { + mvr2r( mid_H, h_disp, L_SUBFR ); + } + + code2_real = code2; + code2_imag = code2 + L_SUBFR - 1; + code_real = code; + code_imag = code + L_SUBFR - 1; + h_real = h_disp; + h_imag = h_disp + L_SUBFR - 1; + *code2_real++ = *code_real++ **h_real++; + + for (i=1; i +#include "cnst.h" +#include "options.h" +#include "prot.h" +#include "rom_com.h" +#include "wmc_auto.h" + + +/*-------------------------------------------------------------------* + * Interpol_delay() + * + * Interpolation of pitch lag + *--------------------------------------------------------------------*/ + +void Interpol_delay( + float *out, /* o : pitch interpolation output */ + float *last, /* i : last frame pitch lag */ + float *current, /* i : current frame pitch lag */ + short SubNum, /* i : subframe number */ + const float *frac /* i : interpolation constant */ +) +{ + out[0] = (1.0f - frac[SubNum]) **last + frac[SubNum] **current; + out[1] = (1.0f - frac[SubNum + 1]) **last + frac[SubNum + 1] **current; + out[2] = (1.0f - frac[SubNum + 2]) **last + frac[SubNum + 2] **current; + + return; +} + + +/*-------------------------------------------------------------------* + * deemph_lpc() + * + * De-emphasis of LP coefficients + * convolve LPC with [1 -PREEMPH_FAC] to de-emphasise LPC + *--------------------------------------------------------------------*/ + +void deemph_lpc( + float *p_Aq_curr, /* i : LP coefficients current frame */ + float *p_Aq_old, /* i : LP coefficients previous frame */ + float *LPC_de_curr, /* o : De-emphasized LP coefficients current frame */ + float *LPC_de_old /* o : De-emphasized LP coefficients previous frame */ + ,short deemph_old + +) +{ + short k; + float b[M+2]; + float a[2] = {-PREEMPH_FAC,1.0}; + + b[0] = 1.0; + for(k = 0; k < M; k++) + { + b[k+1] = p_Aq_curr[k]; + } + b[M+1] = 0.0; + + for(k = 0; k <= M; k++) + { + LPC_de_curr[k] = a[0]*b[k] + a[1]*b[k+1]; + } + + if ( deemph_old == 1) + { + /* ignoring the 1st value which is 1.0 in this case */ + b[0] = 1.0; + for(k = 0; k < M; k++) + { + b[k+1] = p_Aq_old[k+1]; + } + b[M+1] = 0.0; + + for(k = 0; k <= M; k++) + { + LPC_de_old[k] = a[0]*b[k] + a[1]*b[k+1]; + } + } + + return; +} diff --git a/lib_com/pred_lt4.c b/lib_com/pred_lt4.c new file mode 100644 index 000000000..cad503d57 --- /dev/null +++ b/lib_com/pred_lt4.c @@ -0,0 +1,126 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + + +/*-------------------------------------------------------------------* + * pred_lt4() + * + * Compute the result of long term prediction with fractionnal + * interpolation of resolution 1/4. + * + * On return, exc[0..L_subfr-1] contains the interpolated signal + * (adaptive codebook excitation) + *-------------------------------------------------------------------*/ + +void pred_lt4( + const float excI[], /* i : input excitation buffer */ + float excO[], /* o : output excitation buffer */ + const short T0, /* i : integer pitch lag */ + short frac, /* i : fraction of lag */ + const short L_subfr, /* i : subframe size */ + const float *win, /* i : interpolation window */ + const short nb_coef, /* i : nb of filter coef */ + const short up_sample /* i : up_sample */ +) +{ + short i, j; + float s; + const float *x1, *x2, *x0, *c1, *c2; + + x0 = &excI[-T0]; + frac = -frac; + + if (frac < 0) + { + frac += up_sample; + x0--; + } + + for (j=0; j0; i--) + { + signal[i] = signal[i] - mu*signal[i-1]; + } + + signal[0] = signal[0] - mu*(*mem); + *mem = temp; + + return; +} diff --git a/lib_com/prot.h b/lib_com/prot.h new file mode 100644 index 000000000..7a5d0ec94 --- /dev/null +++ b/lib_com/prot.h @@ -0,0 +1,9773 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#ifndef PROT_H +#define PROT_H + +#include +#include +#include "options.h" +#include "typedef.h" +#include "stat_enc.h" +#include "stat_dec.h" +#include "stat_com.h" +#include "cnst.h" +#include "stl.h" + + + +/*----------------------------------------------------------------------------------* + * Prototypes of global macros + *----------------------------------------------------------------------------------*/ + +#ifndef min +#define min(x,y) ((x)<(y)?(x):(y)) +#endif + +#ifndef max +#define max(x,y) ((x)>(y)?(x):(y)) +#endif + +#define log_base_2(x) ((double)log((double)(x))*1.4426950408889634074f) +#define round_f(x) (((x)>0)?(int)((x)+0.5f):(-(int)((-x)+0.5f))) + +#ifndef ABSVAL +#define ABSVAL(a) ((a)>=0?(a):(-(a))) +#endif + +#ifndef SQR +#define SQR(a) ((a)*(a)) +#endif + +#ifndef SWAP +#define SWAP(a,b) {tempr=(a); (a)=(b); (b)=tempr;} +#endif + +#ifndef swap +#define swap(x,y,type) {type u__p; u__p=x; x=y; y=u__p;} +#endif + +#define set_max(a, b) { if ((b) > *a) { *a = (b); } } /* If the first argument is already the highes or lowest, nothing is done. */ +#define set_min(a, b) { if ((b) < *a) { *a = (b); } } /* Otherwise, the 2nd arg is stored at the address of the first arg. */ + +static __inline Word16 L_Extract_lc(const Word32 L_32, Word16 *p_hi) +{ + *p_hi = extract_h(L_32); + return lshr(extract_l(L_32), 1); +} + +/*----------------------------------------------------------------------------------* + * MODE1 prototypes + *----------------------------------------------------------------------------------*/ + +float inv_sqrt( /* o : inverse square root of input value */ + const float x /* i : input value */ +); + +short own_random( /* o : output random value */ + short *seed /* i/o: random seed */ +); + +float sign( /* o : sign of x (+1/-1) */ + const float x /* i : input value of x */ +); + +float log2_f( /* o : logarithm2 of x */ + const float x /* i : input value of x */ +); + +short norm_ul( + unsigned int UL_var1 +); +short sum_s( /* o : sum of all vector elements */ + const short *vec, /* i : input vector */ + const short lvec /* i : length of input vector */ +); + +float sum_f( /* o : sum of all vector elements */ + const float *vec, /* i : input vector */ + const short lvec /* i : length of input vector */ +); + +float sum2_f( /* o : sum of all squared vector elements */ + const float *vec, /* i : input vector */ + const short lvec /* i : length of input vector */ +); + +void set_c( + char y[], /* i/o: Vector to set */ + const char a, /* i : Value to set the vector to */ + const short N /* i : Lenght of the vector */ +); + +void set_s( + short y[], /* i/o: Vector to set */ + const short a, /* i : Value to set the vector to */ + const short N /* i : Lenght of the vector */ +); + +void set_i( + int y[], /* i/o: Vector to set */ + const int a, /* i : Value to set the vector to */ + const short N /* i : Lenght of the vector */ +); + +void set_f( + float y[], /* i/o: Vector to set */ + const float a, /* i : Value to set the vector to */ + const short N /* i : Lenght of the vector */ +); + +void set_zero( + float *vec, /* o : input vector */ + int lvec /* i : length of the vector */ +); + +void mvr2r( + const float x[], /* i : input vector */ + float y[], /* o : output vector */ + const short n /* i : vector size */ +); + +void mvs2s( + const short x[], /* i : input vector */ + short y[], /* o : output vector */ + const short n /* i : vector size */ +); + +unsigned int mvr2s( + const float x[], /* i : input vector */ + short y[], /* o : output vector */ + const short n /* i : vector size */ +); + +void mvs2r( + const short x[], /* i : input vector */ + float y[], /* o : output vector */ + const short n /* i : vector size */ +); + +void mvi2i( + const int x[], /* i : input vector */ + int y[], /* o : output vector */ + const int n /* i : vector size */ +); +void AGC_dec( + float x[], + float mem[], + const short n +); + +short maximum( /* o : index of the maximum value in the input vector */ + const float *vec, /* i : input vector */ + const short lvec, /* i : length of input vector */ + float *max /* o : maximum value in the input vector */ +); + +short minimum( /* o : index of the minimum value in the input vector */ + const float *vec, /* i : input vector */ + const short lvec, /* i : length of input vector */ + float *min /* o : minimum value in the input vector */ +); + +short emaximum( /* o : return index with max energy value in vector */ + const float *vec, /* i : input vector */ + const short lvec, /* i : length of input vector */ + float *ener_max /* o : maximum energy value */ +); + +float mean( /* o : vector mean */ + const float *vec, /* i : input vector */ + const short lvec /* i : length of input vector */ +); + +float dotp( /* o : dot product of x[] and y[] */ + const float x[], /* i : vector x[] */ + const float y[], /* i : vector y[] */ + const short n /* i : vector length */ +); + +void conv( + const float x[], /* i : input vector */ + const float h[], /* i : impulse response (or second input vector) */ + float y[], /* o : output vetor (result of convolution) */ + const short L /* i : vector size */ +); + +void fir( + const float x[], /* i : input vector */ + const float h[], /* i : impulse response of the FIR filter */ + float y[], /* o : output vector (result of filtering) */ + float mem[], /* i/o: memory of the input signal (M samples) */ + const short L, /* i : input vector size */ + const short K, /* i : order of the FIR filter (M+1 coefs.) */ + const short upd /* i : 1 = update the memory, 0 = not */ +); + +void v_add( + const float x1[], /* i : Input vector 1 */ + const float x2[], /* i : Input vector 2 */ + float y[], /* o : Output vector that contains vector 1 + vector 2 */ + const short N /* i : Vector lenght */ +); + +void v_sub( + const float x1[], /* i : Input vector 1 */ + const float x2[], /* i : Input vector 2 */ + float y[], /* o : Output vector that contains vector 1 - vector 2 */ + const short N /* i : Vector lenght */ +); + +void v_mult( + const float x1[], /* i : Input vector 1 */ + const float x2[], /* i : Input vector 2 */ + float y[], /* o : Output vector that contains vector 1 .* vector 2 */ + const short N /* i : Vector lenght */ +); + +void v_multc( + const float x[], /* i : Input vector */ + const float c, /* i : Constant */ + float y[], /* o : Output vector that contains c*x */ + const short N /* i : Vector lenght */ +); + +int squant( /* o: index of the winning codeword */ + const float x, /* i: scalar value to quantize */ + float *xq, /* o: quantized value */ + const float cb[], /* i: codebook */ + const int cbsize /* i: codebook size */ +); + +int vquant( /* o: index of the winning codevector */ + float x[], /* i: vector to quantize */ + const float x_mean[], /* i: vector mean to subtract (0 if none) */ + float xq[], /* o: quantized vector */ + const float cb[], /* i: codebook */ + const int dim, /* i: dimension of codebook vectors */ + const int cbsize /* i: codebook size */ +); + +int w_vquant( /* o: index of the winning codevector */ + float x[], /* i: vector to quantize */ + const float x_mean[], /* i: vector mean to subtract (0 if none) */ + const short weights[], /* i: error weights */ + float xq[], /* o: quantized vector */ + const float cb[], /* i: codebook */ + const int dim, /* i: dimension of codebook vectors */ + const int cbsize, /* i: codebook size */ + const short reverse /* i: reverse codebook vectors */ +); + +short usquant( /* o: index of the winning codeword */ + const float x, /* i: scalar value to quantize */ + float *xq, /* o: quantized value */ + const float qlow, /* i: lowest codebook entry (index 0) */ + const float delta, /* i: quantization step */ + const short cbsize /* i: codebook size */ +); + +float usdequant( /* o: dequanzited gain */ + const int idx, /* i: quantizer index */ + const float qlow, /* i: lowest codebook entry (index 0) */ + const float delta /* i: quantization step */ +); + +void v_sort( + float *r, /* i/o: Vector to be sorted in place */ + const short lo, /* i : Low limit of sorting range */ + const short up /* i : High limit of sorting range */ +); + +float var( /* o: variance of vector */ + const float *x, /* i: input vector */ + const int len /* i: length of inputvector */ +); + +float std_dev( /* o: standard deviation */ + const float *x, /* i: input vector */ + const int len /* i: length of the input vector */ +); + +float dot_product_mat( /* o : the dot product x'*A*x */ + const float *x, /* i : vector x */ + const float *A, /* i : matrix A */ + const short m /* i : vector length */ +); + +float root_a( + float a +); + +float root_a_over_b( + float a, + float b +); + +void polezero_filter ( + const float *in, /* i : input vector */ + float *out, /* o : output vector */ + const short N, /* i : input vector size */ + const float *b, /* i : numerator coefficients */ + const float *a, /* i : denominator coefficients */ + const short order, /* i : filter order */ + float *mem /* i/o: filter memory */ +); + +double rint_new( + double x /* i/o: Round to the nearest integer with mid point exception */ +); + +double anint( + double x /* i/o: Round to the nearest integer */ +); +short is_numeric_float( /* o : Output either 1 if Numeric, 0 if NaN or Inf */ + float x /* i : Input value which is checked if numeric or not */ +); + +void push_indice( + Encoder_State *st, /* i/o: encoder state structure */ + short id, /* i : ID of the indice */ + unsigned short value, /* i : value of the quantized indice */ + short nb_bits /* i : number of bits used to quantize the indice */ +); + +void push_next_indice( + Encoder_State *st, /* i/o: encoder state structure */ + unsigned short value, /* i : value of the quantized indice */ + short nb_bits /* i : number of bits used to quantize the indice */ +); + +void push_next_bits( + Encoder_State *st, /* i/o: encoder state structure */ + int bits[], /* i : bit buffer to pack, sequence of single bits */ + short nb_bits /* i : number of bits to pack */ +); + +unsigned short get_next_indice( /* o : value of the indice */ + Decoder_State *st, /* i/o: decoder state structure */ + short nb_bits /* i : number of bits that were used to quantize the indice */ +); + +unsigned short get_next_indice_1( /* o : value of the indice */ + Decoder_State *st /* i/o: decoder state structure */ +); + +void get_next_indice_tmp( + Decoder_State *st, /* o : decoder state structure */ + short nb_bits /* i : number of bits that were used to quantize the indice */ +); + +unsigned short get_indice( /* o : value of the indice */ + Decoder_State *st, /* i/o: decoder state structure */ + short pos, /* i : absolute position in the bitstream */ + short nb_bits /* i : number of bits that were used to quantize the indice */ +); + +unsigned short get_indice_1( /* o : value of the indice */ + Decoder_State *st, /* i/o: decoder state structure */ + short pos /* i : absolute position in the bitstream */ +); + +void reset_indices_enc( + Encoder_State *st /* i/o: encoder state structure */ +); + +void reset_indices_dec( + Decoder_State *st /* i/o: decoder state structure */ +); + +void write_indices( + Encoder_State *st, /* 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] */ +); + +short read_indices( /* o : 1 = OK, 0 = something wrong */ + Decoder_State *st, /* i/o: decoder state structure */ + FILE *file, /* i : bitstream file */ + const short rew_flag /* i : rewind flag (rewind file after reading) */ +); + +Word16 read_indices_mime( /* o : 1 = reading OK, 0 = problem */ + Decoder_State *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 *st, /* i: encoder state structure */ + UWord8 *pFrame, /* o: byte array with bit packet and byte aligned coded speech data */ + Word16 *pFrame_size +); + +void indices_to_serial_generic( + const Indice *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 /* o: size of the binary encoded access unit [bits] */ +); + +void evs_dec_previewFrame( + unsigned char *bitstream, /* i : bitstream pointer */ + int bitstreamSize, /* i : bitstream size */ + short *partialCopyFrameType, /* o : frame type of the partial copy */ + short *partialCopyOffset /* o : offset of the partial copy relative to the primary copy */ +); + +void read_indices_from_djb( + Decoder_State *st, /* i/o: decoder state structure */ + unsigned char *pt_stream, /* i : bitstream file */ + int nbits /* i : number of bits */ + , Word16 isAMRWB_IOmode + , Word16 core_mode + , Word16 qbit + ,short partialframe /* i : partial frame information */ + ,short next_coder_type /* i : next coder type information */ +); + +void getPartialCopyInfo( + Decoder_State *st, /* i : decoder state structure */ + short *coder_type, + short *sharpFlag +); + +void get_NextCoderType( + unsigned char *bitsteam, /* i : bitstream */ + short *next_coder_type /* o : next coder type */ +); + +int print_disclaimer ( + FILE *fPtr +); + +void autocorr( + const float *x, /* i : input signal */ + float *r, /* o : autocorrelations vector */ + const short m, /* i : order of LP filter */ + const short len, /* i : window size */ + const float *wind, /* i : window */ + const short rev_flag, /* i : flag to reverse window */ + const short sym_flag, /* i : symmetric window flag */ + const short no_thr /* i : flag to avoid thresholding */ +); + +short lev_dur( /* o: energy of prediction error */ + float *a, /* o: LP coefficients (a[0] = 1.0) */ + const float *r, /* i: vector of autocorrelations */ + const short m, /* i: order of LP filter */ + float epsP[] /* o: prediction error energy */ +); + +float get_delay( /* o : delay value in ms */ + const short what_delay, /* i : what delay? (ENC or DEC) */ + const int io_fs /* i : input/output sampling frequency */ +); + +void decision_matrix_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const short sp_aud_decision1, /* i : 1st stage speech/music classification */ + const short sp_aud_decision2, /* i : 2nd stage speech/music classification */ + const short coder_type, /* i : coder type */ + const short vad_flag, + short *hq_core_type /* o : HQ core type */ +); + +void signalling_enc( + Encoder_State *st, /* i : encoder state structure */ + const short coder_type, /* i : coder type */ + const short sharpFlag /* i : formant sharpening flag */ +); + +short signalling_mode1_tcx20_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const short push /* i : flag to push indice */ +); + +void decision_matrix_dec( + Decoder_State *st, /* i/o: decoder state structure */ + short *coder_type, /* o : coder type */ + short *sharpFlag, /* o : formant sharpening flag */ + short *hq_core_type, /* o : HQ core type */ + short *core_switching_flag /* o : ACELP->HQ switching frame flag */ +); + +float lsf_stab( /* o : LP filter stability */ + const float *lsf, /* i : LSF vector */ + const float *lsfold, /* i : old LSF vector */ + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short L_frame /* i : frame lenght */ +); + +void hf_synth_amr_wb_init( + float *prev_r, /* o : 1 sample memory for preemphasis/deemphasis*/ + float *fmerit_w_sm, /* o : 1 sample memory fmerit_w param*/ + float mem_syn_hf[], /* o : HF LPC synthesis filter initialization */ + short *frame_count, /* o : frame counter initialization */ + float *ne_min, /* o : minimum Noise gate - short-term energy initialization*/ + float *fmerit_m_sm, /* o : 1 sample memory fmerit_m param */ + float *voice_fac, /* o : voice factor initialization */ + float *unvoicing, /* o : unvoiced parameter */ + float *unvoicing_sm, /* o : smoothed unvoiced parameter */ + short *unvoicing_flag, /* o : unvoiced flag */ + short *voicing_flag, /* o : voiced flag */ + short *start_band_old, /* o : previous start point for copying frequency band */ + float *OptCrit_old /* o : previous criterion value for deciding the start point */ +); + +void hf_synth_amr_wb_reset( + short *seed2, /* i/o: random seed for HF noise gen */ + float mem_syn_hf[], /* o : HF synthesis memory */ + float mem_hp_interp[], /* o : interpol. memory */ + float *prev_r, /* o : 1 sample memory for deemphasis */ + float *fmerit_w_sm, /* o : 1 sample memory fmerit_w param */ + float delay_syn_hf[], /* o : HF synthesis memory */ + short *frame_count, /* o : frame counter memory */ + float *ne_min, /* o : minimum Noise gate - short-term energy memory */ + float *fmerit_m_sm, /* o : 1 sample memory fmerit_m param */ + float *voice_fac, /* o : voice factor memory */ + float *unvoicing, /* o : unvoiced parameter */ + float *unvoicing_sm, /* o : smoothed unvoiced parameter */ + short *unvoicing_flag, /* o : unvoiced flag */ + short *voicing_flag, /* o : voiced flag */ + short *start_band_old, /* o : previous start point for copying frequency band */ + float *OptCrit_old /* o : previous criterion value for deciding the start point */ +); + +void hf_synth_amr_wb( + const long core_brate, /* i : core bitrate */ + const short output_frame, /* i : output frame length */ + const float *Aq, /* i : quantized Az */ + const float *exc, /* i : excitation at 12.8 kHz */ + float *synth, /* i/o: synthesis signal at 12.8 kHz */ + float *mem_syn_hf, /* i/o: HF synthesis memory */ + float *delay_syn_hf, /* i/o: HF synthesis memory */ + float *prev_r, /* i/o: preemphasis/deemphasis filter memory */ + float *fmerit_w_sm, /* i/o: smoothed fmerit_w */ + short *amr_io_class, /* i : signal class (determined by FEC algorithm) */ + float *mem_hp_interp, /* i/o: interpol. memory */ + float *synth_out, /* i/o: synthesis signal at output Fs */ + float fmerit, /* i : classify parameter from FEC */ + const short *hf_gain, /* i : decoded HF gain */ + const float *voice_factors, /* i : voicing factors */ + const float pitch_buf[], /* i : pitch buffer */ + const float ng_ener_ST, /* i : Noise gate - short-term energy */ + const float *lsf_new, /* i : ISF vector */ + short *frame_count, /* i/o: frame counter */ + float *ne_min, /* i/o: minimum Noise gate */ + float *fmerit_m_sm, /* i/o: smoothed fmerit_m */ + float *voice_facor_sm, /* i/o: voice factor memory */ + float *unvoicing, /* i/o: unvoiced parameter */ + float *unvoicing_sm, /* i/o: smoothed unvoiced parameter */ + short *unvoicing_flag, /* i/o: unvoiced flag */ + short *voicing_flag, /* i/o: voiced flag */ + short *start_band_old, /* i/o: previous start point for copying frequency band */ + float *OptCrit_old /* i/o: previous criterion value for deciding the start point */ +); + +void hf_cod_init( + float *mem_hp400_enc, /* o: memory of hp 400 Hz filter */ + float *mem_hf1_enc, /* o: HF band-pass filter memory */ + float *mem_syn_hf_enc, /* o: HF synthesis memory */ + float *mem_hf2_enc, /* o: HF band-pass filter memory */ + float *gain_alpha /* o: smoothing gain for transitions between active and inactive frames */ +); + +void hf_cod( + const long core_brate, /* i : core bitrate */ + const float *speech16k, /* i : original speech at 16 kHz */ + const float Aq[], /* i : quantized Aq */ + const float exc[], /* i : excitation at 12.8 kHz */ + float synth[], /* i : 12.8kHz synthesis signal */ + short *seed2_enc, /* i/o: random seed for HF noise gen */ + float *mem_hp400_enc, /* i/o: memory of hp 400 Hz filter */ + float *mem_syn_hf_enc, /* i/o: HF synthesis memory */ + float *mem_hf1_enc, /* i/o: HF band-pass filter memory */ + float *mem_hf2_enc, /* i/o: HF band-pass filter memory */ + const short *dtxHangoverCount, + float *gain_alpha, /* i/o: smoothing gain for transitions between active and inactive frames */ + short *hf_gain /* o : HF gain to be transmitted to decoder */ +); + +void hf_synth_init( + float mem_hp400[], /* o: 400 Hz high pass filter memory initialization */ + float mem_hf[] /* o: band pass 6kHz to 7kHz FIR filter initialization */ +); + +void hf_synth_reset( + short *seed2, /* i/o: random seed for HF noise gen */ + float mem_hf[], /* o : HF band-pass filter memory */ + float mem_syn_hf[], /* o : HF synthesis memory */ + float mem_hp400[], /* o : memory of hp 400 Hz filter */ + float mem_hp_interp[], /* o : interpol. memory */ + float delay_syn_hf[] /* o : HF synthesis memory */ +); + +void hf_synth( + const long core_brate, /* i : core bitrate */ + const short output_frame, /* i : output frame length */ + const float *Aq, /* i : quantized Az */ + const float *exc, /* i : excitation at 12.8 kHz */ + float *synth, /* i/o: 12.8kHz synthesis signal */ + float *synth16k, /* i/o: 16kHz synthesis signal */ + short *seed2, /* i/o: random seed for HF noise gen */ + float *mem_hp400, /* i/o: memory of hp 400 Hz filter */ + float *mem_syn_hf, /* i/o: HF synthesis memory */ + float *mem_hf, /* i/o: HF band-pass filter memory */ + float *delay_syn_hf, /* i/o: HF synthesis memory */ + float *mem_hp_interp /* i/o: interpol. memory */ +); + +short lsp_convert_poly( + float w[], /* i/o: LSP or ISP parameters */ + const short L_frame, /* i : flag for up or down conversion */ + const short Opt_AMRWB /* i : flag for the AMR-WB IO mode */ +); + +short findpulse( /* o : pulse position */ + const short L_frame, /* i : length of the frame */ + const float res[], /* i : residual signal */ + const short T0, /* i : integer pitch */ + const short enc_dec, /* i : flag enc/dec, 0 - enc, 1 - dec */ + short *sign /* i/o: sign of the maximum */ +); + +void fft_rel( + float x[], /* i/o: input/output vector */ + const short n, /* i : vector length */ + const short m /* i : log2 of vector length */ +); + +void ifft_rel( + float io[], /* i/o: input/output vector */ + const short n, /* i : vector length */ + const short m /* i : log2 of vector length */ +); + +void preemph( + float *signal, /* i/o: signal */ + const float mu, /* i : preemphasis factor */ + const short L, /* i : vector size */ + float *mem /* i/o: memory (x[-1]) */ +); + +void cb_shape( + const short preemphFlag, /* i : flag for pre-emphasis */ + const short pitchFlag, /* i : flag for pitch sharpening */ + const short scramblingFlag, /* i : flag for phase scrambling */ + const short formantFlag, /* i : flag for formant sharpening */ + const short formantTiltFlag, /* i : flag for formant tilt */ + const float g1, /* i : formant sharpening numerator weighting */ + const float g2, /* i : formant sharpening denominator weighting */ + const float *p_Aq, /* i : LP filter coefficients */ + float *code, /* i/o: signal to shape */ + const float tilt_code, /* i : tilt of code */ + const float pt_pitch /* i : pointer to current subframe fractional pitch*/ +); + +void isp2a( + const float *isp, /* i : ISP vector (in the cosine domain) */ + float *a, /* o : LP filter coefficients */ + const short m /* i : order of LP analysis */ +); + +void isp2isf( + const float isp[], /* i : isp[m] (range: -1<=val<1) */ + float isf[], /* o : isf[m] normalized (range: 0<=val<=fs/2) */ + const short m, /* i : LPC order */ + const float fs /* i : sampling frequency */ +); + +void isf2isp( + const float isf[], /* i : isf[m] normalized (range: 0<=val<=fs/2) */ + float isp[], /* o : isp[m] (range: -1<=val<1) */ + const short m, /* i : LPC order */ + const float fs /* i : sampling frequency */ +); + +void reorder_isf( + float *isf, /* i/o: vector of isfs in the frequency domain (0..0.5)*/ + const float min_dist, /* i : minimum required distance */ + const short n, /* i : LPC order */ + const float fs /* i : sampling frequency */ +); + +void lsp2lsf( + const float lsp[], /* i : isp[m] (range: -1<=val<1) */ + float lsf[], /* o : isf[m] normalized (range: 0<=val<=fs/2) */ + const short m, /* i : LPC order */ + const float fs /* i : sampling frequency */ +); + +void lsf2lsp( + const float lsf[], /* i : isf[m] normalized (range: 0<=val<=fs/2) */ + float lsp[], /* o : isp[m] (range: -1<=val<1) */ + const short m, /* i : LPC order */ + const float fs /* i : sampling frequency */ +); + +void lsp2isp( + const float *lsp, /* i : LSP vector */ + float *isp, /* o : ISP filter coefficients */ + float *stable_isp, /* i/o: ISP filter coefficients */ + const short m /* i : order of LP analysis */ +); + +void isp2lsp( + const float *isp, /* i : LSP vector */ + float *lsp, /* o : ISP filter coefficients */ + float *stable_lsp, /* i/o: stable LSP filter coefficients */ + const short m /* i : order of LP analysis */ +); + +void reorder_lsf( + float *lsf, /* i/o: vector of lsfs in the frequency domain (0..0.5)*/ + const float min_dist, /* i : minimum required distance */ + const short n, /* i : LPC order */ + const float fs /* i : sampling frequency */ +); + +void CNG_exc( + const long core_brate, /* i : core bitrate */ + const short L_frame, /* i : length of the frame */ + float *Enew, /* i/o: decoded SID energy */ + short *seed, /* i/o: random generator seed */ + float exc[], /* o : current non-enhanced excitation */ + float exc2[], /* o : current enhanced excitation */ + float *lp_ener, /* i/o: LP filtered E */ + const long last_core_brate, /* i : previous frame core bitrate */ + short *first_CNG, /* i/o: first CNG frame flag for energy init. */ + short *cng_ener_seed, /* i/o: random generator seed for CNG energy */ + float bwe_exc[], /* o : excitation for SWB TBE */ + const short allow_cn_step, /* i : allow CN step */ + short *last_allow_cn_step, /* i/o: last CN_step */ + const short num_ho, /* i : number of selected hangover frames */ + float q_env[], + float *lp_env, + float *old_env, + float *exc_mem, + float *exc_mem1, + short *sid_bw, + short *cng_ener_seed1, + float exc3[], + short Opt_AMR_WB +); + +void cng_params_upd( + const float lsp_new[], /* i : LSP aprameters */ + const float exc2[], /* i : current enhanced excitation */ + const short L_frame, /* i : frame length */ + short *ho_circ_ptr, /* i/o: pointer for CNG averaging buffers */ + float ho_ener_circ[], /* o : energy buffer for CNG averaging */ + short *ho_circ_size, /* i/o: size of DTX hangover history buffer for averaging */ + float ho_lsp_circ[], /* o : old LSP buffer for CNG averaging */ + const short enc_dec_flag, /* i : Flag indicating encoder or decoder (ENC,DEC) */ + float ho_env_circ[], /* i/o: Envelope buffer */ + short *cng_buf_cnt, /* i/o: Counter of postponed FFT-processing instances */ + float cng_exc2_buf[], /* i/o: Excitation buffer */ + long cng_brate_buf[], /* i/o: last_active_brate buffer */ + const long last_active_brate /* i : Last active bit rate */ +); + +void cng_params_postupd( + const short ho_circ_ptr, /* i : pointer for CNG averaging buffers */ + short *cng_buf_cnt, /* i/o: counter for CNG store buffers */ + const float *const cng_exc2_buf, /* i : Excitation buffer */ + const long *const cng_brate_buf, /* i : bit rate buffer */ + float ho_env_circ[] /* i/o: Envelope buffer */ +); + +void disf_ns_28b( + short *indice, /* i : quantized indices (use indice[0] = -1 in the decoder) */ + float *isf_q /* o : ISF in the frequency domain (0..6400) */ +); + +void limit_T0( + const short L_frame, /* i : length of the frame */ + const short delta, /* i : Half the close-loop searched interval */ + const short pit_flag, /* i : selecting absolute(0) or delta(1) pitch quantization */ + const short limit_flag, /* i : flag for limits (0=restrained, 1=extended) */ + const short T0, /* i : rough pitch estimate around which the search is done */ + const short T0_frac, /* i : pitch estimate fractional part */ + short *T0_min, /* o : lower pitch limit */ + short *T0_max /* o : higher pitch limit */ +); + +float interpolation( /* o : interpolated value */ + const float *x, /* i : input vector */ + const float *win, /* i : interpolation window */ + const short frac, /* i : fraction */ + const short up_samp, /* i : upsampling factor */ + const short nb_coef /* i : nb of filter coef */ +); + +void deemph( + float *signal, /* i/o: signal */ + const float mu, /* i : deemphasis factor */ + const short L, /* i : vector size */ + float *mem /* i/o: memory (y[-1]) */ +); + +float est_tilt( /* o : tilt of the code */ + const float *adpt_exc, /* i : adaptive excitation vector */ + const float gain_pit, /* i : adaptive gain */ + const float *fixe_exc, /* i : algebraic exctitation vector */ + const float gain_code, /* i : algebraic code gain */ + float *voice_fac, /* o : voicing factor */ + const short L_subfr, /* i : subframe size */ + const short flag_tilt /* i : flag for special tilt */ +); + +void weight_a( + const float *a, /* i : LP filter coefficients */ + float *ap, /* o : weighted LP filter coefficients */ + const float gamma, /* i : weighting factor */ + const short m /* i : order of LP filter */ +); + +void weight_a_subfr( + const short nb_subfr, /* i : number of subframes */ + const float *a, /* i : LP filter coefficients */ + float *ap, /* o : weighted LP filter coefficients */ + const float gamma, /* i : weighting factor */ + const short m /* i : order of LP filter */ +); + +void syn_12k8( + const short L_frame, /* i : length of the frame */ + const float *Aq, /* i : LP filter coefficients */ + const float *exc, /* i : input signal */ + float *synth, /* o : output signal */ + float *mem, /* i/o: initial filter states */ + const short update_m /* i : update memory flag: 0 --> no memory update */ +); /* 1 --> update of memory */ + +void syn_filt( + const float a[], /* i : LP filter coefficients */ + const short m, /* i : order of LP filter */ + const float x[], /* i : input signal */ + float y[], /* o : output signal */ + const short l, /* i : size of filtering */ + float mem[], /* i/o: initial filter states */ + const short update_m /* i : update memory flag: 0 --> no memory update */ +); /* 1 --> update of memory */ +void synth_mem_updt2( + const short L_frame, /* i : frame length */ + const short last_L_frame, /* i : frame length */ + float old_exc[], /* i/o : excitation buffer */ + float mem_syn_r[], /* i/o: synthesis filter memory */ + float mem_syn2[], /* o : synthesis filter memory for find_target */ + float mem_syn[], /* o : synthesis filter memory for find_target */ + const short dec /* i: flag for decoder indication */ +); + +void int_lsp( + const short L_frame, /* i : length of the frame */ + const float lsp_old[], /* i : LSPs from past frame */ + const float lsp_new[], /* i : LSPs from present frame */ + float *Aq, /* o : LP coefficients in both subframes */ + const short m, /* i : order of LP filter */ + const float *int_coeffs, /* i : interpolation coefficients */ + const short Opt_AMR_WB /* i : flag indicating AMR-WB IO mode */ +); + +void int_lsp4( + const short L_frame, /* i : length of the frame */ + const float lsp_old[], /* i : previous end-frame LSPs */ + const float lsp_mid[], /* i : current mid-frame LSPs */ + const float lsp_new[], /* i : current end-frame LSPs */ + float *Aq, /* o : LP coefficients in both subframes */ + const short m, /* i : order of LP filter */ + short relax_prev_lsf_interp /* i : relax prev frame lsf interp after erasure */ +); + +short modify_Fs( /* o : length of output */ + const float sigIn[], /* i : signal to decimate */ + short lg, /* i : length of input */ + const int fin, /* i : frequency of input */ + float sigOut[], /* o : decimated signal */ + const int fout, /* i : frequency of output */ + float mem[] /* i/o: filter memory */ + ,int nblp /* i : flag indicating if NB low-pass is applied */ +); + +void pred_lt4( + const float excI[], /* i : input excitation buffer */ + float excO[], /* o : output excitation buffer */ + const short T0, /* i: integer pitch lag */ + short frac, /* i: fraction of lag */ + const short L_subfr, /* i: subframe size */ + const float *win, /* i: interpolation window */ + const short nb_coef, /* i : nb of filter coef */ + const short up_sample /* i : up_sample */ +); + +void pred_lt4_tc( + float exc[], /* i: excitation buffer */ + const short T0, /* i: integer pitch lag */ + short frac, /* i: fraction of lag */ + const float *win, /* i : interpolation window */ + const short imp_pos, /* i: glottal impulse position */ + const short i_subfr /* i: subframe index */ +); + +void residu( + const float *a, /* i : LP filter coefficients */ + const short m, /* i : order of LP filter */ + const float *x, /* i : input signal (usually speech) */ + float *y, /* o : output signal (usually residual) */ + const short l /* i : size of filtering */ +); + +void calc_residu( + const float *speech, /* i : weighted speech signal */ + float *res, /* o : residual signal */ + const float *p_Aq, /* i : quantized LP filter coefficients */ + const short L_frame /* i : size of frame */ +); + +float enr_1_Az( /* o : impulse response energy */ + const float Aq[], /* i : LP filter coefs */ + const short len /* i : impulse response length */ +); + + +void Es_pred_enc( + float *Es_pred, /* o : predicited scaled innovation energy */ + int *Es_pred_indice, /* o : indice corresponding to above parameter */ + const short L_frame, /* i : length of the frame */ + const short L_subfr, /* i : length of the subframe */ + const float *res, /* i : residual signal */ + const float *voicing, /* i : normal. correlattion in three 1/2frames */ + const short nb_bits, /* i : allocated number of bits */ + const short no_ltp /* i : no_ltp flag */ +); + +void init_lvq( + unsigned int offset_scale1[][MAX_NO_SCALES+1], + unsigned int offset_scale2[][MAX_NO_SCALES+1], + unsigned int offset_scale1_p[][MAX_NO_SCALES+1], + unsigned int offset_scale2_p[][MAX_NO_SCALES+1], + short no_scales[][2], + short no_scales_p[][2] +); + +float mslvq ( + float *pTmp, /* i : M-dimensional input vector */ + float *quant, /* o : quantized vector */ + float *cv_out, /* o : corresponding 8-dim lattice codevectors (without the scaling) */ + int *idx_lead, /* o : leader index for each 8-dim subvector */ + int *idx_scale, /* o : scale index for each subvector */ + float *w, /* i : weights for LSF quantization */ + short mode, /* i : number indicating the coding type (V/UV/G...)*/ + short mode_glb, /* i : LVQ coding mode */ + int pred_flag, /* i : prediction flag (0: safety net, 1 - predictive )*/ + short no_scales[][2] +); + +void permute( + float *pTmp1, /* (i/o): vector whose components are to be permuted */ + const short *perm /* (i) : permutation info (indexes that should be interchanged), max two perms */ +); + +float mslvq_cng( + short idx_cv, /* (i): index of cv from previous stage */ + float *pTmp, /* (i): 16 dimensional input vector */ + float *quant, /* (o): quantized vector */ + float *cv_out, /* (o): corresponding 8-dim lattice codevectors (without the scaling) */ + int *idx_lead, /* (o): leader index for each 8-dim subvector */ + int *idx_scale, /* (o): scale index for each subvector */ + const float *w, /* (i): weights for LSF quantization */ + short * no_scales +); + +short deindex_lvq_cng( + short *index, /* i : index to be decoded, as an array of 3 short */ + float *x_lvq, /* o : decoded codevector */ + short idx_cv, /* i : relative mode_lvq, wrt START_CNG */ + int no_bits, /* i : number of bits for lattice */ + unsigned int * p_offset_scale1, + unsigned int * p_offset_scale2, + short * p_no_scales +); + +void multiply32_32_64( + unsigned int x, /* (i): operand 1 */ + unsigned int y, /* (i): operand 2 */ + unsigned int *res /* (o): result as array of two uint32 */ +); + +short deindex_lvq( + short *index, /* (i): index to be decoded, as an array of 3 short */ + float *x_lvq, /* (o): decoded codevector */ + short mode, /* (i): LVQ coding mode (select scales & no_lead ), or idx_cv */ + short sf_flag, /* (i): safety net flag */ + short no_bits, /* (i): number of bits for lattice */ + unsigned int *p_offset_scale1, /* i : offset for first subvector */ + unsigned int *p_offset_scale2, /* i : offset for the second subvector */ + short * p_no_scales +); +short vq_dec_lvq ( + short sf_flag, /* i : safety net flag */ + float x[], /* o : Decoded vector */ + short indices[], /* i : Indices */ + short stages, /* i : Number of stages */ + short N, /* i : Vector dimension */ + short mode, /* i : lvq coding type */ + short no_bits, /* i : no. bits for lattice */ + unsigned int * p_offset_scale1, + unsigned int * p_offset_scale2, + unsigned int * p_offset_scale1_p, + unsigned int * p_offset_scale2_p, + short * p_no_scales, + short * p_no_scales_p +); + +void index_lvq ( + float *quant, /* i : codevector to be indexed (2 8-dim subvectors)*/ + int *idx_lead, /* i : leader class index for each subvector */ + int *idx_scale, /* i : scale index for each subvector */ + int mode, /* i : integer signalling the quantizer structure for the current bitrate */ + short *index, /* o : encoded index (represented on 3 short each with 15 bits ) */ + unsigned int * p_offset_scale1, + unsigned int * p_offset_scale2, + short * p_no_scales +); + +short qlsf_ARSN_tcvq_Dec_16k ( + float *y, /* o : Quantized LSF vector */ + short *indice, /* i : Indices */ + const short nBits /* i : number of bits */ +); + +int lsf_bctcvq_encprm( + Encoder_State *st, + int *param_lpc, + short *bits_param_lpc, + short no_indices +); + +int lsf_bctcvq_decprm( + Decoder_State *st, + int *param_lpc +); + +void lsf_allocate( + const short nBits, /* i : Number of bits to use for quantization */ + const short framemode, /* i : ISF quantizer mode */ + const short framemode_p, /* i : ISF quantizer mode */ + short *stages0, /* o : Number of stages for safety-net quantizer */ + short *stages1, /* o : Number of stages for predictive quantizer */ + short levels0[], /* o : Number of vectors for each stage for SFNET */ + short levels1[], /* o : Number of vectors for each stage for pred */ + short bits0[], /* o : Number of bits for each stage safety net */ + short bits1[] /* o : Number of bits for each stage predictive */ +); + +void disf_2s_36b( + short *indice, /* i : quantized indices (use indice[0] = -1 in the decoder) */ + float *isf_q, /* o : quantized ISFs in the cosine domain */ + float *mem_AR, /* i/o: quantizer memory for AR model */ + float *mem_MA /* i/o: quantizer memory for MA model */ +); + +void disf_2s_46b( + short *indice, /* i : quantized indices (use indice[0] = -1 in the decoder) */ + float *isf_q, /* o : quantized ISFs in the cosine domain */ + float *mem_AR, /* o : quantizer memory for AR model */ + float *mem_MA /* i/o: quantizer memory for MA model */ +); + +void re8_k2y( + const int *k, /* i : Voronoi index k[0..7] */ + const int m, /* i : Voronoi modulo (m = 2^r = 1<=2) */ + int *y /* o : 8-dimensional point y[0..7] in RE8 */ +); + +void re8_PPV( + float x[], /* i : point in R^8 */ + int y[] /* o : point in RE8 (8-dimensional integer vector) */ +); + +void enhancer( + const short codec_mode, /* i : flag indicating Codec Mode */ + const long core_brate, /* i : core bitrate */ + const short cbk_index, /* i : */ + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short coder_type, /* i : coding type */ + const short L_frame, /* i : frame size */ + const float voice_fac, /* i : subframe voicing estimation */ + const float stab_fac, /* i : LP filter stablility measure */ + const float norm_gain_code, /* i : normalized innovative cb. gain */ + const float gain_inov, /* i : gain of the unscaled innovation */ + float *gc_threshold, /* i/o: code threshold */ + float *code, /* i/o: innovation */ + float *exc2, /* i/o: adapt. excitation/total exc. */ + const float gain_pit, /* i : Quantized pitch gain */ + float *dispMem /* i/o: Phase dispersion algorithm memory */ +); + +void phase_dispersion( + const float gain_code, /* i : gain of code */ + const float gain_pit, /* i : gain of pitch */ + float code[], /* i/o: code vector */ + const short mode, /* i : level, 0=hi, 1=lo, 2=off */ + float disp_mem[] /* i/o: static memory (size = 8) */ +); + +void re8_vor( + int y[], /* i : point in RE8 (8-dimensional integer vector) */ + int *n, /* o : codebook number n=0,2,3,4,... (scalar integer) */ + int k[], /* o : Voronoi index (integer vector of dimension 8) used only if n>4 */ + int c[], /* o : codevector in Q0, Q2, Q3, or Q4 if n<=4, y=c */ + int *ka /* o : identifier of absolute leader (needed to index c)*/ +); + +void edct( + const float *x, /* i : input signal */ + float *y, /* o : output transform */ + short length /* i : length */ +); + +void edst( + const float *x, /* i : input signal */ + float *y, /* o : output transform */ + short length /* i : length */ +); + +void iedct_short( + const float *in, /* i : input vector */ + float *out, /* o : output vector */ + const short segment_length /* i : length */ +); + + +void DoRTFT480( + float *x, /* i/o : real part of input and output data */ + float *y /* i/o : imaginary part of input and output data */ +); + +void DoRTFT320( + float *x, /* i/o : real part of input and output data */ + float *y /* i/o : imaginary part of input and output data */ +); + +void DoRTFT160( + float *x, /* i/o : real part of input and output data */ + float *y /* i/o : imaginary part of input and output data */ +); + +void DoRTFT128( + float *x, /* i/o : real part of input and output data */ + float *y /* i/o : imaginary part of input and output data */ +); + +void DoRTFT120( + float *x, /* i/o : real part of input and output data */ + float *y /* i/o : imaginary part of input and output data */ +); + +void DoRTFT80( + float *x, /* i/o : real part of input and output data */ + float *y /* i/o : imaginary part of input and output data */ +); + +void DoRTFT20( + float *x, /* i/o : real part of input and output data */ + float *y /* i/o : imaginary part of input and output data */ +); + +void DoRTFT40( + float *x, /* i/o : real part of input and output data */ + float *y /* i/o : imaginary part of input and output data */ +); + +void DoRTFTn( + float *x, /* i/o : real part of input and output data */ + float *y, /* i/o : imaginary part of input and output data */ + const short n /* i : size of the FFT n=(2^k) up to 1024 */ +); + +void BASOP_cfft( + Word32 *re, /* i/o: real part */ + Word32 *im, /* i/o: imag part */ + Word16 s, /* i : stride real and imag part */ + Word16 *scale /* i : scalefactor */ +); + +void sinq( + const float tmp, /* i : sinus factor cos(tmp*i+phi) */ + const float phi, /* i : sinus phase cos(tmp*i+phi) */ + const short N, /* i : size of output */ + float x[] /* o : output vector */ +); + +void edct2( + short n, + short isgn, + float *in, + float *a, + const short *ip, + const float *w +); + +void stat_noise_uv_mod( + const short coder_type, /* i : coding type */ + float noisiness, /* i : noisiness parameter */ + const float *isp_old, /* i : old ISP vector at 4th sfr */ + const float *isp_new, /* i : ISP vector at 4th sfr */ + const float *isp_mid, /* i : ISP vector at 2nd sfr */ + float *Aq, /* o : A(z) quantized for the 4 subframes */ + float *exc2, /* o : excitation buffer */ + const short bfi, /* i : bad frame indicator */ + float *ge_sm, /* i/o: ???? */ + short *uv_count, /* i/o: unvoiced counter */ + short *act_count, /* i/o: activation counter */ + float lspold_s[], /* i/o: old LSP */ + short *noimix_seed, /* i/o: mixture seed */ + float *st_min_alpha, /* i/o: minimum alpha */ + float *exc_pe, /* i/o: scale Q_stat_noise */ + const long bitrate, /* i : core bitrate */ + const short bwidth /* i : Bandwidth */ +); + +void SWB_TBE_describe_envelope( /* Function to represent energies in MDCT frequency bands */ + const float *yos, /* i : MDCT coefficients of weighted original */ + float *SWB_env_gain /* i/o: energy of SWB envelope */ +); + +void dct2( + const float in[], /* i : time domain input */ + float out[] /* o : transform domain output */ +); + +void idct2( + const float in[], /* i : transform domain input */ + float out[] /* o : time domain output */ +); + +void pre_echo_att( + float *Last_frame_ener, /* i/o: Energy of the last frame */ + float *exc, /* i/o: Excitation of the current frame */ + const short attack_flag, /* i : flag signalling attack encoded by AC mode (GSC) */ + const short last_coder_type /* i : Last coder type */ +); + +void hq_swb_harmonic_calc_norm_envelop( + float *SWB_signal, /* i : input signal */ + float *envelope, /* o : output envelope */ + int L_swb_norm, /* i : length of normaliztion */ + int SWB_flength /* i : length of input signal */ +); + +void limit_band_noise_level_calc( + short *wnorm, /* i : reordered norm of sub-vectors */ + short *limit, /* o : highest band of bit allocation */ + long core_brate, /* o : bit rate */ + float *noise_level /* o : noise level */ +); + +short peak_avrg_ratio( + const long total_brate, + const float *input_hi, /* i : input signal */ + const short N, /* i : number of coefficients */ + short *mode_count, /* i/o: HQ_HARMONIC mode count */ + short *mode_count1 /* i/o: HQ_NORMAL mode count */ +); + +short build_nf_codebook( /* o : Number of coefficients in nf codebook */ + const short flag_32K_env_ho, /* i : Envelope attenuation hangover flag */ + const float *coeff, /* i : Coded spectral coefficients */ + const short *sfm_start, /* i : Subband start indices */ + const short *sfmsize, /* i : Subband widths */ + const short *sfm_end, /* i : Subband end indices */ + const short nb_sfm, /* i : Number of subbands */ + const short *R, /* i : Per-band bit allocation */ + float *CodeBook, /* o : Noise-fill codebook */ + float *CodeBook_mod /* o : Densified noise-fill codebook */ +); + +void apply_noisefill_HQ( + const short *R, /* i : bit allocation */ + const short length, /* i : input frame length */ + const short flag_32K_env_ho, /* i : envelope stability hangover flag */ + const long core_brate, /* i : core bit rate */ + const short last_sfm, /* i : last coded subband */ + const float *CodeBook, /* i : Noise-fill codebook */ + const float *CodeBook_mod, /* i : Densified noise-fill codebook */ + const short cb_size, /* i : Codebook length */ + const short *sfm_start, /* i : Subband start coefficient */ + const short *sfm_end, /* i : Subband end coefficient */ + const short *sfmsize, /* i : Subband band width */ + float *coeff /* i/o: coded/noisefilled spectrum */ +); + +void harm_bwe_fine( + const short *R, /* i : bit allocation */ + const short last_sfm, /* i : last coded subband */ + const short high_sfm, /* i : higher transition band to BWE */ + const short num_sfm, /* i : total number of bands */ + const short *norm, /* i : quantization indices for norms */ + const short *sfm_start, /* i : Subband start coefficient */ + const short *sfm_end, /* i : Subband end coefficient */ + short *prev_L_swb_norm, /* i/o: last normalize length */ + float *coeff, /* i/o: coded/noisefilled normalized spectrum */ + float *coeff_out, /* o : coded/noisefilled spectrum */ + float *coeff_fine /* o : BWE fine structure */ +); + +void hvq_bwe_fine( + const short last_sfm, /* i : last coded subband */ + const short num_sfm, /* i : total number of bands */ + const short *sfm_end, /* i : Subband end coefficient */ + const short *peak_idx, /* i : Peak index */ + const short Npeaks, /* i : Number of peaks */ + short *peak_pos, /* i/o: Peak positions */ + short *prev_L_swb_norm, /* i/o: last normalize length */ + float *coeff, /* i/o: coded/noisefilled normalized spectrum */ + short *bwe_peaks, /* o : Positions of peaks in BWE */ + float *coeff_fine /* o : HVQ BWE fine structure */ +); + +void hq_fold_bwe( + const short last_sfm, /* i : last coded subband */ + const short *sfm_end, /* i : Subband end coefficient */ + const short num_sfm, /* i : Number of subbands */ + float *coeff /* i/o: coded/noisefilled normalized spectrum */ +); + +void apply_nf_gain( + const short nf_idx, + const short last_sfm, /* i : last coded subband */ + const short *R, /* i : bit allocation */ + const short *sfm_start, /* i : Subband start coefficient */ + const short *sfm_end, /* i : Subband end coefficient */ + float *coeff /* i/o: coded/noisefilled normalized spectrum */ + +); + +void hq_generic_fine( + float *coeff, /* i : coded/noisefilled normalized spectrum */ + const short last_sfm, /* i : Last coded band */ + const short *sfm_start, /* i : Subband start coefficient */ + const short *sfm_end, /* i : Subband end coefficient */ + short *bwe_seed, /* i/o: random seed for generating BWE input */ + float *coeff_out1 /* o : HQ GENERIC input */ +); + +void harm_bwe( + const float *coeff_fine, /* i : fine structure for BWE */ + const float *coeff, /* i : coded/noisefilled normalized spectrum */ + const short num_sfm, /* i : Number of subbands */ + const short *sfm_start, /* i : Subband start coefficient */ + const short *sfm_end, /* i : Subband end coefficient */ + const short last_sfm, /* i : last coded subband */ + const short high_sfm, /* i : */ + const short *R, /* i : bit allocation */ + const short prev_hq_mode, /* i : previous hq mode */ + short *norm, /* i/o: quantization indices for norms */ + float *noise_level, /* i/o: noise levels for harmonic modes */ + float *prev_noise_level, /* i/o: noise factor in previous frame */ + short *bwe_seed, /* i/o: random seed for generating BWE input */ + float *coeff_out /* o : coded/noisefilled spectrum */ +); + +void hvq_bwe( + const float *coeff, /* i : coded/noisefilled spectrum */ + const float *coeff_fine, /* i : BWE fine structure */ + const short *sfm_start, /* i : Subband start coefficient */ + const short *sfm_end, /* i : Subband end coefficient */ + const short *sfm_len, /* i : Subband length */ + const short last_sfm, /* i : last coded subband */ + const short prev_hq_mode, /* i : previous hq mode */ + const short *bwe_peaks, /* i : HVQ bwe peaks */ + const short bin_th, /* i : HVQ transition bin */ + const short num_sfm, /* i : Number of bands */ + const long core_brate, /* i : Core bit-rate */ + const short *R, /* i : Bit allocation */ + short *norm, /* i/o: quantization indices for norms */ + float *noise_level, /* i/o: noise levels for harmonic modes */ + float *prev_noise_level, /* i/o: noise factor in previous frame */ + short *bwe_seed, /* i/o: random seed for generating BWE input */ + float *coeff_out /* o : coded/noisefilled spectrum */ +); + +void hvq_concat_bands +( + const short pvq_bands, /* i : Number of bands in concatenated PVQ target */ + const short *sel_bnds, /* i : Array of selected high bands */ + const short n_sel_bnds, /* i : Number of selected high bands */ + short *hvq_band_start, /* i : Band start indices */ + short *hvq_band_width, /* i : Band widths */ + short *hvq_band_end /* i : Band end indices */ +); + +void hq_generic_bwe( + const short HQ_mode, /* i : HQ mode */ + float *coeff_out1, /* i/o: BWE input & temporary buffer */ + const float *hq_generic_fenv, /* i : SWB frequency envelopes */ + float *coeff_out, /* o : SWB signal in MDCT domain */ + const short hq_generic_offset, /* i : frequency offset for representing hq generic*/ + short *prev_L_swb_norm, /* i/o: last normalize length */ + const short hq_generic_exc_clas, /* i : hf excitation class */ + const short *sfm_end, /* i : End of bands */ + const short num_sfm, + const short num_env_bands, + const short *R +); + +void logqnorm_2( + const float *env_fl, /* o : index */ + const short L, /* i : codebook length */ + const short n_env_band, /* i : sub-vector size */ + const short nb_sfm, /* i : sub-vector size */ + short *ynrm, + short *normqlg2, + const float *thren /* i : quantization thresholds */ +); + +void map_hq_generic_fenv_norm( + const short hqswb_clas, + const float *hq_generic_fenv, + short *ynrm, + short *normqlg2, + const short num_env_bands, + const short nb_sfm, + const short hq_generic_offset +); + +short calc_nor_delta_hf( + Encoder_State *st, + const float *t_audio, + short *ynrm, + short *Rsubband, + const short num_env_bands, + const short nb_sfm, + const short *sfmsize, + const short *sfm_start, + const short core_sfm +); + +short get_nor_delta_hf( + Decoder_State *st, + short *ynrm, + short *Rsubband, + const short num_env_bands, + const short nb_sfm, + const short core_sfm +); + +void hq_wb_nf_bwe( + const float *coeff, /* i : coded/noisefilled normal. spectrum */ + const short is_transient, + const short prev_bfi, /* i : previous bad frame indicator */ + const float *normq_v, + const short num_sfm, /* i : Number of subbands */ + const short *sfm_start, /* i : Subband start coefficient */ + const short *sfm_end, /* i : Subband end coefficient */ + const short *sfmsize, /* i : Subband band width */ + const short last_sfm, /* i : last coded subband */ + const short *R, /* i : bit allocation */ + const short prev_is_transient, /* i : previous transient flag */ + float *prev_normq, /* i/o: previous norms */ + float *prev_env, /* i/o: previous noise envelopes */ + short *bwe_seed, /* i/o: random seed for generating BWE input*/ + float *prev_coeff_out, /* i/o: decoded spectrum in previous frame */ + short *prev_R, /* i/o: previous frame bit allocation info. */ + float *coeff_out /* o : coded/noisefilled spectrum */ +); + +short encode_envelope_indices( /* o : Number of bits */ + Encoder_State *st, /* i/o: encoder state structure */ + const short num_sfm, /* i : Number of subbands */ + const short numnrmibits, /* i : Bitrate of fall-back coding mode */ + short *difidx, /* i/o: Diff indices/encoded diff indices */ + short *LCmode, /* o : Coding mode */ + const short flag_pack, /* i : indicator of packing or estimating bits */ + const short flag_HQ2 /* i : indicator of HQ2 core */ + ,const short is_transient +); + +void diff_envelope_coding( + const short is_transient, /* i : transient indicator */ + const short num_env_bands, /* i : number of envelope bands to code */ + const short start_norm, /* i : start of envelope coding */ + short *ynrm, /* i/o: quantization indices for norms */ + short *normqlg2, /* i/o: quantized norms */ + short *difidx /* o : differential code */ +); + +short decode_envelope_indices( /* o : Number of bits */ + Decoder_State *st, /* i/o: decoder state structure */ + const short start_norm, /* i : First SDE encoded norm */ + const short num_sfm, /* i : Number of norms */ + const short numnrmibits, /* i : Bitrate of fall-back coding mode */ + short *ynrm, /* o : Decoded norm indices */ + const short flag_HQ2 /* i : indicator of HQ2 core */ + ,const short is_transient +); + +void dequantize_norms( /* o : Number of bits */ + Decoder_State *st, /* i/o: decoder state structure */ + const short start_norm, /* i : First SDE encoded norm */ + const short num_sfm, /* i : Number of norms */ + const short is_transient, /* i : Transient flag */ + short *ynrm, /* o : Decoded norm indices */ + short *normqlg2 /* o : Log2 of decoded norms */ +); + +void hq_configure( + const short length, /* i : Frame length */ + const short hqswb_clas, /* i : HQ SWB class */ + const long brate, /* i : Codec bitrate */ + short *num_sfm, /* o : Total number of subbands */ + short *nb_sfm, /* o : Total number of coded bands */ + short *start_norm, /* o : First norm to be SDE encoded */ + short *num_sde_norm, /* o : Number of norms for SDE encoding */ + short *numnrmibits, /* o : Number of bits in fall-back norm encoding */ + short *hq_generic_offset, /* o : Freq offset for HQ GENERIC */ + short const **sfmsize, /* o : Subband bandwidths */ + short const **sfm_start, /* o : Subband start coefficients */ + short const **sfm_end /* o : Subband end coefficients */ +); + +short hvq_enc( /* o : Consumed bits */ + Encoder_State *st, /* i/o: encoder state structure */ + const long brate, /* i : Total bit rate */ + const short hvq_bits, /* i : HVQ bit budget */ + const short Npeaks, /* i : Number of peaks */ + const short *ynrm, /* i : Envelope coefficients */ + short *R, /* i/o: Bit allocation/updated bit allocation */ + short *peaks, /* i : Peak pos. / Encoded peak pos. */ + float *nf_gains, /* i/o: Noise fill gains / Quant. nf gains */ + float *noise_level, /* o : Quantized noise level */ + const float *pe_gains, /* i : Peak gains */ + const float *coefs, /* i : spectrum coefficients */ + float *coefs_out /* o : encoded spectrum coefficients */ +); + +short hq_classifier_enc( /* o : Consumed bits */ + Encoder_State *st, /* i/o: encoder state structure */ + const short length, /* i : Frame length */ + const float *coefs, /* i : Spectral coefficients */ + const short is_transient, /* i : Transient flag */ + short *Npeaks, /* o : Number of identified peaks */ + short *peaks, /* o : Peak indices */ + float *pe_gains, /* o : Peak gains */ + float *nf_gains, /* o : Noise-fill gains */ + short *hqswb_clas /* o : HQ class */ +); + +short hq_classifier_dec( /* o : Consumed bits */ + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : Core bit rate */ + const short length, /* i : Frame length */ + short *is_transient, /* o : Transient flag */ + short *hqswb_clas /* o : HQ class */ +); + + +void hq_bit_allocation( + const long core_brate, /* i : Core bit-rate */ + const short length, /* i : Frame length */ + const short hqswb_clas, /* i : HQ class */ + short *num_bits, /* i/o: Remaining bit budget */ + const short *normqlg2, /* i : Quantized norms */ + const short nb_sfm, /* i : Number sub bands to be encoded */ + const short *sfmsize, /* i : Sub band bandwidths */ + float *noise_level, /* o : HVQ noise level */ + short *R, /* o : Bit allocation per sub band */ + short *Rsubband, /* o : Fractional bit allocation (Q3) */ + short *sum, /* o : Sum of allocated shape bits */ + short *core_sfm, /* o : Last coded band in core */ + const short num_env_bands +); + +void enforce_zero_for_min_envelope( + const short hqswb_clas, /* i : HQ coding mode */ + const short *ynrm, /* i : Envelope indices */ + float *coefsq, /* i/o: Quantized spectrum/zeroed spectrum */ + short nb_sfm, /* i : Number of coded sub bands */ + const short *sfm_start, /* i : Sub band start indices */ + const short *sfm_end /* i : Sub band end indices */ +); + +short assign_gain_bits( /* o : Number of assigned gain bits */ + const short core, /* i : HQ core */ + const short BANDS, /* i : Number of bands */ + const short *band_width, /* i : Sub band bandwidth */ + short *Rk, /* i/o: Bit allocation/Adjusted bit alloc. (Q3)*/ + short *gain_bits_array, /* o : Assigned gain bits */ + short *Rcalc /* o : Bit budget for shape quantizer (Q3)*/ +); + +void apply_envelope( + const float *coeff, /* i/o: Coded/noisefilled normalized spectrum */ + const short *norm, /* i : Envelope */ + const float *norm_adj, /* i : Envelope adjustment */ + const short num_sfm, /* i : Total number of bands */ + const short last_sfm, /* i : Last coded band */ + const short HQ_mode, /* i : HQ mode */ + const short length, /* i : Frame length */ + const short *sfm_start, /* i : Sub band start indices */ + const short *sfm_end, /* i : Sub band end indices */ + float *normq_v, /* o : Envelope with adjustment */ + float *coeff_out, /* o : coded/noisefilled spectrum */ + float *coeff_out1 /* o : noisefilled spectrum for HQ SWB BWE */ +); + +PvqEntry mpvq_encode_vec( /* o : Leading_sign_index, index, size, k_val */ + const short* vec_in, /* i : Signed pulse train */ + short dim_in, /* i : Dimension */ + short k_val_local /* i : Num unit pulses */ +); + +PvqEntry get_size_mpvq_calc_offset( /* o : Size, dim, k_val */ + short dim_in, /* i : Dimension */ + short k_val_in, /* i : Num unit pulses */ + unsigned int* h_mem /* o : Offsets */ +); + +void mpvq_decode_vec( + const PvqEntry* entry, /* i : Sign_ind, index, dim, k_val */ + unsigned int* h_mem, /* i : A/U offsets */ + short* vec_out /* o : Pulse train */ +); + +unsigned int UMult_32_32( + unsigned int UL_var1, + unsigned int UL_var2 +); + +unsigned int UL_inverse( + const unsigned int UL_val, + short *exp +); + +Word16 ratio( + const Word32 numer, + const Word32 denom, + Word16 *expo +); + +Word16 atan2_fx( /* o: Angle between 0 and EVS_PI/2 radian (Q14) */ + const Word32 y, /* i: Argument must be positive (Q15) */ + const Word32 x /* i: Q15 */ +); + +void encode_energies( + Encoder_State *st, + const float *coefs, + short Np, + short *dim_part, + float *E_part, + short *bits_part, + short *g_part, + short qband, + short *bits_left, + float enr, + short n, + const short strict_bits +); + +void decode_energies( + Decoder_State *st, + short Np, + short *dim_part, + short *bits_part, + short *g_part, + short qband, + short *bits_left, + short n, + const short strict_bits +); + +void pvq_encode_frame( + Encoder_State *st, + const float *coefs_norm, /* i : normalized coefficients to encode */ + float *coefs_quant, /* o : quantized coefficients */ + float *gopt, /* o : optimal shape gains */ + short *npulses, /* o : number of pulses per band */ + short *pulse_vector, /* o : non-normalized pulse shapes */ + const short *sfm_start, /* i : indices of first coefficients in the bands */ + const short *sfm_end, /* i : indices of last coefficients in the bands */ + const short *sfmsize, /* i : band sizes */ + const short nb_sfm, /* i : total number of bands */ + const short *R, /* i : bitallocation per band (Q3)*/ + const short pvq_bits, /* i : number of bits avaiable */ + const short core /* i : core */ +); + +void pvq_decode_frame( + Decoder_State *st, + float *coefs_quant, /* o : quantized coefficients */ + short *npulses, /* o : number of pulses per band */ + short *pulse_vector, /* o : non-normalized pulse shapes */ + const short *sfm_start, /* i : indices of first coefficients in the bands */ + const short *sfm_end, /* i : indices of last coefficients in the bands */ + const short *sfmsize, /* i : band sizes */ + const short nb_sfm, /* i : total number of bands */ + const short *R, /* i : bitallocation per band (Q3) */ + const short pvq_bits, /* i : number of bits avaiable */ + const short core /* i : core */ +); + + + +void srt_vec_ind ( + const short *linear, /* linear input */ + short *srt, /* sorted output*/ + short *I, /* index for sorted output */ + short length +); +void srt_vec_ind_f( + const float *linear, /* linear input */ + float *srt, /* sorted output*/ + short *I, /* index for sorted output */ + short length /* length of vector */ +); + + +unsigned int floor_sqrt_exact( + unsigned int input +); + + + + +void fine_gain_quant( + Encoder_State *st, + const short *ord, /* i : Indices for energy order */ + const short num_sfm, /* i : Number of bands */ + const short *gain_bits, /* i : Gain adjustment bits per sub band */ + float *fg_pred, /* i/o: Predicted gains / Corrected gains */ + const float *gopt /* i : Optimal gains */ +); + +void apply_gain( + const short *ord, /* i : Indices for energy order */ + const short *band_start, /* i : Sub band start indices */ + const short *band_end, /* i : Sub band end indices */ + const short num_sfm, /* i : Number of bands */ + const float *gains, /* i : Band gain vector */ + float *xq /* i/o: Float synthesis / Gain adjusted synth */ +); + +void fine_gain_pred( + const short *sfm_start, /* i : Sub band start indices */ + const short *sfm_end, /* i : Sub band end indices */ + const short *sfm_size, /* i : Sub band bandwidths */ + const short *i_sort, /* i : Energy sorting indices */ + const short *K, /* i : Number of pulses per band */ + const short *maxpulse, /* i : Maximum pulse per band */ + const short *R, /* i : Bits per sub band (Q3) */ + const short num_sfm, /* i : Number of sub bands */ + float *xq, /* i/o: Quantized vector /quantized vector with finegain adj */ + short *y, /* i/o: Quantized vector (int) */ + float *fg_pred, /* o : Predicted fine gains */ + const short core /* i : Core */ +); + +void fine_gain_dec( + Decoder_State *st, + const short *ord, /* i : Indices for energy order */ + const short num_sfm, /* i : Number of bands */ + const short *gain_bits, /* i : Gain adjustment bits per sub band */ + float *fg_pred /* i/o: Predicted gains / Corrected gains */ +); + +void get_max_pulses( + const short *band_start, /* i : Sub band start indices */ + const short *band_end, /* i : Sub band end indices */ + const short *k_sort, /* i : Indices for sorting by energy */ + const short *npulses, /* i : Pulses per sub band */ + const short BANDS, /* i : Number of bands */ + short *inp_vector, /* i/o: Encoded shape vectors (int)*/ + short *maxpulse /* o : Maximum pulse height per band */ +); + +Word32 ar_div( + Word32 num, + Word32 denum +); + +void ar_encoder_start( + PARCODEC arInst, + PBITSTREAM bsInst, + int max_bits +); + +void ar_decoder_start( + PARCODEC arInst, + PBITSTREAM bsInst +); + +void ar_encoder_done( + PARCODEC arInst +); + +void ar_decoder_done( + PARCODEC arInst +); + +float GetISCScale( + float *quants, + int size, + Word32 bits_fx, + float *magn, + float *qscale, + Word32 *surplus_fx, + float *pulses, + int* savedstates, + int noTCQ, + int *nzpout, + short *bcount, + float *abuffer, + float *mbuffer, + float *sbuffer +); + +Word32 Mult_32_16( + Word32 a, + Word16 b +); + +Word32 Mult_32_32( + Word32 a, + Word32 b +); + +void decode_position_ari_fx( + PARCODEC pardec, + Word16 size, + Word16 npulses, + Word16 *nz, + Word32 *position +); + +void decode_magnitude_usq_fx( + ARCODEC *pardec, + Word16 size, + Word16 npulses, + Word16 nzpos, + Word32 *positions, + Word32 *out +); + +void decode_mangitude_tcq_fx( + ARCODEC *pardec, + Word16 size, + Word16 npulses, + Word16 nzpos, + Word32 *positions, + Word32 *out, + Word32 *surplus_fx +); + +void decode_signs_fx( + ARCODEC *pardec, + Word16 size, + Word32 *out +); + +void srt_vec_ind_fx( + const Word32 *linear, + Word32 *srt, + Word16 *I, + Word16 length +); + +Word16 GetScale_fx( + Word16 blen, + Word32 bits_fx/*Q16*/, + Word32 *surplus_fx/*Q16*/ +); + +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 +); + +Word32 encode_position_ari_fx( + PARCODEC parenc, + float *quants, + Word16 size, + Word32 *est_bits_frame_fx +); + +Word32 encode_magnitude_tcq_fx( + ARCODEC *parenc, + float *magn_fx, + Word16 size, + Word16 npulses, + Word16 nzpos, + Word32 *savedstates, + Word32 *est_frame_bits_fx +); + +Word32 encode_signs_fx( + ARCODEC *parenc, + float *magn, + Word16 size, + Word16 npos, + Word32 *est_frame_bits_fx +); + +Word32 encode_magnitude_usq_fx( + ARCODEC *parenc, + float *magn_fx, + Word16 size, + Word16 npulses, + Word16 nzpos, + Word32 *est_frame_bits_fx +); + +void tcq_core_LR_enc( + Encoder_State *st, + int inp_vector[], + const float coefs_norm[], + float coefs_quant[], + const short bit_budget, /* number of bits */ + const short nb_sfm, + const short *sfm_start, + const short *sfm_end, + const short *sfmsize, + Word32 *Rk_fx, + int *npulses, + short *k_sort, + const short *p2a_flags, + const short p2a_bands, + const short *last_bitalloc, + const short input_frame, + const short adjustFlag, + const short is_transient +); + +void tcq_core_LR_dec( + Decoder_State *st, + int *inp_vector, + const short bit_budget, + const short bands, + const short *band_start, + const short *band_width, + Word32 *Rk_fx, + int *npulses, + short *k_sort, + const short *p2a_flags, + const short p2a_bands, + const short *last_bitalloc, + const short input_frame, + const short adjustFlag, + const short *is_transient +); + +void InitLSBTCQ( + short *bcount +); + +void TCQLSB( + short bcount, + float *abuffer, + float *mbuffer, + float *sbuffer, + short *dpath +); + +void RestoreTCQ( + float * magn, + int size, + short *bcount, + float *mbuffer +); + +void SaveTCQdata( + PARCODEC arInst, + short *dpath, + short bcount +); + +void LoadTCQdata( + PARCODEC arInst, + short *dpath, + short bcount +); + +void RestoreTCQdec( + int * magn, + int size, + short *bcount, + float *mbuffer +); + +void TCQLSBdec( + short *dpath, + float *mbuffer, + short 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 io_ini_enc( + 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 */ + short *quietMode, /* o : limit printouts */ + short *noDelayCmp, /* o : turn off delay compensation */ + Encoder_State *st /* o : state structure */ +); + +void read_next_rfparam( + short *rf_fec_offset, /* o: rf offset */ + short *rf_fec_indicator, /* o: rf FEC indicator */ + FILE *f_rf /* i: file pointer to read parameters */ +); + +void read_next_brate( + long *total_brate, /* i/o: total bitrate */ + const int last_total_brate, /* i : last total bitrate */ + FILE *f_rate, /* i : bitrate switching profile (0 if N/A) */ + int input_Fs, /* i : input sampling frequency */ + short *Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + short *Opt_SC_VBR, /* i/o: SC-VBR flag */ + short *codec_mode /* i/o: Mode 1 or 2 */ +); + +void read_next_bwidth( + short *max_bwidth, /* i/o: maximum encoded bandwidth */ + FILE *f_bwidth, /* i : bandwidth switching profile (0 if N/A) */ + long *bwidth_profile_cnt, /* i/o: counter of frames for bandwidth switching profile file */ + int input_Fs /* i : input sampling rate */ +); + + +void init_encoder( + Encoder_State *st /* i/o: state structure */ +); + +void destroy_encoder( + Encoder_State *st /* i/o: state structure */ +); + +void evs_enc( + Encoder_State *st, /* i/o: state structure */ + const short *data, /* i : input signal */ + const short n_samples /* i : number of input samples */ +); + +void amr_wb_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const short *data, /* i : input signal */ + const short n_samples /* i : number of input samples */ +); + +void pre_proc( + Encoder_State *st, /* i/o: encoder state structure */ + const short input_frame, /* i : frame length */ + const float signal_in[], /* i : new samples */ + float old_inp_12k8[], /* i/o: buffer of old input signal */ + float old_inp_16k[], /* i/o: buffer of old input signal @ 16kHz */ + float **inp, /* o : ptr. to inp. signal in the current frame */ + short *sp_aud_decision1, /* o : 1st stage speech/music classification */ + short *sp_aud_decision2, /* o : 2nd stage speech/music classification */ + float fr_bands[2*NB_BANDS], /* o : energy in frequency bands */ + short *vad_flag, + short *localVAD, + float *Etot, /* o : total energy, correlation shift */ + float *ener, /* o : residual energy from Levinson-Durbin */ + short pitch[3], /* o : open-loop pitch values for quantiz. */ + float voicing[3], /* o : OL maximum normalized correlation */ + float A[NB_SUBFR16k*(M+1)], /* o : A(z) unquantized for the 4 subframes */ + float Aw[NB_SUBFR16k*(M+1)], /* o : weighted A(z) unquantized for subframes */ + float epsP[M+1], /* o : LP prediction errors */ + float lsp_new[M], /* o : LSPs at the end of the frame */ + float lsp_mid[M], /* o : LSPs in the middle of the frame */ + short *coder_type, /* o : coder type */ + short *sharpFlag, /* o : formant sharpening flag */ + short *vad_hover_flag, + short *attack_flag, /* o : flag signalling attack encoded by AC mode (GSC) */ + float *new_inp_resamp16k, /* o : new input signal @16kHz, non pre-emphasised, used by the WB TBE/BWE */ + short *Voicing_flag, /* o : voicing flag for HQ FEC */ + float realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o : real buffer */ + float imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o : imag buffer */ + short *hq_core_type /* o : HQ core type */ +); + +short mdct_classifier( /* o: Class decision, 0 = Mode 1, 1 = Mode 2 */ + const float *Y, /* i: FFT spectrum from fft_rel */ + Encoder_State *st, /* i/o: Encoder state variable */ + short vadflag + ,float *cldfbBuf_Ener +); + +void MDCT_selector( + Encoder_State *st, /* i/o: Encoder State */ + float sp_floor, /* i : Noise floor estimate */ + float Etot, /* i : Total energy */ + float cor_map_sum, /* i : harmonicity factor */ + const float voicing[], /* i : voicing factors */ + const float enerBuffer[], /* i : CLDFB buffers */ + short vadflag +); + +void MDCT_selector_reset( + Encoder_State *st /* i/o: Encoder State */ +); + +void acelp_core_enc( + Encoder_State *st, /* i/o: encoder state structure */ + LPD_state *mem, /* i/o: acelp memories */ + const float inp[], /* i : input signal of the current frame */ + const short vad_flag, + const float ener, /* i : residual energy from Levinson-Durbin*/ + const short pitch[3], /* i : open-loop pitch values for quantiz. */ + const float voicing[3], /* i : Open-loop pitch gains */ + float A[NB_SUBFR16k*(M+1)], /* i : A(z) unquantized for the 4 subframes*/ + float Aw[NB_SUBFR16k*(M+1)], /* i : weighted A(z) unquant. for subframes*/ + const float epsP[M+1], /* i : LP prediction errors */ + float lsp_new[M], /* i : LSPs at the end of the frame */ + float lsp_mid[M], /* i : LSPs in the middle of the frame */ + short coder_type, /* i : coding type */ + const short sharpFlag, /* i : formant sharpening flag */ + short vad_hover_flag, + const short attack_flag, /* i : flag signalling attack encoded by AC mode (GSC) */ + float bwe_exc_extended[], /* i/o: bandwidth extended excitation */ + float *voice_factors, /* o : voicing factors */ + float old_syn_12k8_16k[], /* o : ACELP core synthesis at 12.8kHz or 16kHz to be used by SWB BWE */ + float pitch_buf[NB_SUBFR16k], /* o : floating pitch for each subframe */ + short *unbits /* o : number of unused bits */ +); + +void acelp_core_switch_dec_bfi( + Decoder_State *st, /* i/o: decoder state structure */ + float synth_out[], /* o : synthesis */ + const short coder_type /* i : coder type */ +); + +void acelp_core_switch_enc( + Encoder_State *st, /* i/o: encoder state structure */ + LPD_state *mem, /* i/o: encoder memories */ + const float inp12k8[], /* i : input signal @12.8 kHz */ + const float inp16k[], /* i : input signal @16 kHz */ + const short T_op[2], /* i : open-loop pitch values for quantiz. */ + const float voicing[3], /* i : Open-loop pitch gains */ + const float A[NB_SUBFR16k*(M+1)] /* i : A(z) unquantized for the 4 subframes */ +); + +short modify_Fs_intcub3m_sup( /* o : length of output */ + const float sigIn[], /* i : signal to decimate with memory of 2 samples (indexes -2 & -1) */ + const short lg, /* i : length of input */ + const int fin, /* i : frequency of input */ + float sigOut[], /* o : decimated signal */ + const int fout, /* i : frequency of output */ + short *delayout /* o : delay of output */ +); + +void core_switching_OLA( + const float *mem_over_hp, /* i : upsampling filter memory */ + const short last_L_frame, /* i : last L_frame lengthture */ + const int output_Fs, /* i : output sampling rate */ + float *synth, /* i/o: synthesized signal from HQ core */ + const float *synth_subfr_out, /* i : synthesized signal from ACELP core */ + float *synth_subfr_bwe, /* i : synthesized BWE from ACELP core */ + const short output_frame, /* i : output frame length */ + const short bwidth /* i : output bandwidth */ +); + +void retro_interp4_5( + const float *syn, + float *pst_old_syn +); + +void retro_interp5_4( + float *pst_old_syn +); + +void core_switching_hq_prepare_enc( + Encoder_State *st, /* i/o: encoder state structure */ + short *num_bits, /* i/o: bit budget update */ + const short input_frame, /* i : input frame length */ + float *wtda_audio, + const float *audio +); + +void core_switching_hq_prepare_dec( + Decoder_State *st, /* i/o: encoder state structure */ + short *num_bits, /* i/o: bit budget update */ + const short input_frame /* i : input frame length */ +); + +void acelp_core_switch_dec( + Decoder_State *st, /* i/o: decoder structure */ + float *synth_subfr_out, /* o : synthesized ACELP subframe */ + float *tmp_synth_bwe, /* o : synthesized ACELP subframe BWE */ + const short output_frame, /* i : input frame length */ + const short core_switching_flag, /* i : core switching flag */ + float *mem_synth /* o : synthesis to overlap */ +); + +void space_lsfs( + float *lsfs, + const short order +); + +void lsp2a( + float *pc_in, + float *freq, + const short order +); + +void lsp_weights( + const float *lsps, + float *weight, + const short order +); + +void a2lsp_stab( + const float *a, /* i: LP filter coefficients */ + float *lsp, /* o: Line spectral pairs */ + const float *old_lsp /* i: LSP vector from past frame */ +); + +void lsp2a_stab( + const float *lsp, /* i : LSF vector (in the cosine domain) */ + float *a, /* o : LP filter coefficients */ + const short m /* i : order of LP analysis */ +); + +void isf2lsf( + const float *isf, /* i : ISF vector */ + float *lsf, /* o : LSF vector */ + float *stable_lsp, /* i/o: LSF vector */ + const short m, /* i : order of LP analysis */ + const float int_fs +); + +void lsf2isf( + const float *lsf, /* i : LSF vector */ + float *isf, /* o : ISF vector */ + float *stable_isp, /* i/o: ISP vector */ + const short m, /* i : order of LP analysis */ + const float int_fs +); + +short a2lsp( + float *freq, /* o : LSP vector */ + const float *a, /* i : predictor coefficients */ + const short order /* i : order of LP analysis */ +); + +void ResetSHBbuffer_Enc( + Encoder_State *st /* i/o: encoder state structure */ +); + +void ResetSHBbuffer_Dec( + Decoder_State *st /* i/o: decoder state structure */ +); + +void calc_st_filt( + const float *apond2, /* i : coefficients of numerator */ + const float *apond1, /* i : coefficients of denominator */ + float *parcor0, /* o : 1st parcor calcul. on composed filter */ + float *sig_ltp_ptr, /* i/o: input of 1/A(gamma1) : scaled by 1/g0 */ + float *mem_zero, /* i/o: All zero memory */ + const short L_subfr, /* i : the length of subframe */ + const short extl /* i : extension layer info */ +); + +void scale_st( + const float *sig_in, /* i : postfilter input signal */ + float *sig_out, /* i/o: postfilter output signal */ + float *gain_prec, /* i/o: last value of gain for subframe */ + const short L_subfr, /* i : the length of subframe */ + const short extl /* i : extension layer info */ +); + +void filt_mu( + const float *sig_in, /* i : signal (beginning at sample -1) */ + float *sig_out, /* o : output signal */ + const float parcor0, /* i : parcor0 (mu = parcor0 * gamma3) */ + const short L_subfr, /* i : the length of subframe */ + const short extl /* i : extension layer info */ +); + +void PostShortTerm( + float *sig_in, /* i : input signal (ptr. to current subframe */ + float *lpccoeff, /* i : LPC coefficients for current subframe */ + float *sig_out, /* o : postfiltered output */ + float *mem_stp, /* i/o: postfilter memory */ + float *ptr_mem_stp, /* i/o: pointer to postfilter memory */ + float *ptr_gain_prec, /* i/o: for gain adjustment */ + float *mem_zero, /* i/o: null memory to compute h_st */ + const float formant_fac /* i : Strength of post-filter [0,1] */ +); + +float swb_formant_fac( /* o : Formant filter strength [0,1] */ + const float lpc_shb2, /* i : 2nd HB LPC coefficient */ + float *tilt_mem /* i/o: Tilt smoothing memory */ +); + +void GenShapedSHBExcitation( + float *excSHB, /* o : synthesized shaped shb exctiation */ + const float *lpc_shb, /* i : lpc coefficients */ + float *exc16kWhtnd, /* o : whitened synthesized shb excitation */ + float *mem_csfilt, /* i/o: memory */ + float *mem_genSHBexc_filt_down_shb,/* i/o: memory */ + float *state_lpc_syn, /* i/o: memory */ + const short coder_type, /* i : coding type */ + const float *bwe_exc_extended, /* i : bandwidth extended excitation */ + short bwe_seed[], /* i/o: random number generator seed */ + float voice_factors[], /* i : voicing factor */ + const short extl, /* i : extension layer */ + float *tbe_demph, /* i/o: de-emphasis memory */ + float *tbe_premph, /* i/o: pre-emphasis memory */ + float *lpc_shb_sf, /* i : LP coefficients */ + float *shb_ener_sf, /* i : SHB subframe energies */ + float *shb_res_gshape, /* i : SHB LP residual gain shape */ + float *shb_res, /* i : SHB residual used in encoder only */ + short *vf_ind, /* i/o: Mixing factor index */ + const float formant_fac, /* i : Formant sharpening factor [0..1] */ + float fb_state_lpc_syn[], /* i/o: memory */ + float *fb_tbe_demph, /* i/o: fb de-emphasis memory */ + const long bitrate, /* i : overall bitrate */ + const short prev_bfi /* i : previous frame was lost flag */ +); + +void GenSHBSynth( + const float *shb_target_speech, /* i : input synthesized speech */ + float *shb_syn_speech_32k, /* o : output highband component */ + float Hilbert_Mem[], /* i/o: memory */ + float state_lsyn_filt_shb_local[],/* i/o: memory */ + const short L_frame, /* i : ACELP Frame length */ + short *syn_dm_phase +); + +void ScaleShapedSHB( + const short length, /* i : SHB overlap length */ + float *synSHB, /* i/o: synthesized shb signal */ + float *overlap, /* i/o: buffer for overlap-add */ + const float *subgain, /* i : subframe gain */ + const float frame_gain, /* i : frame gain */ + const float *win, /* i : window */ + const float *subwin /* i : subframes window */ +); + +void Interpolate_allpass_steep ( + const float *in, /* i : input array of size N */ + float *state, /* i/o: memory */ + const short N, /* i : number of input samples */ + float *out /* o : output array of size 2*N */ +); + +void Decimate_allpass_steep ( + const float *in, /* i : input array of size N */ + float *state, /* i/o: memory */ + const short N, /* i : number of input samples */ + float *out /* o : output array of size N/2 */ +); + +void interpolate_3_over_2_allpass( + const float *input, /* i : input signal */ + const short len, /* i : number of input samples */ + float *out, /* o : output signal */ + float *mem, /* i/o: memory */ + const float *filt_coeff /* i : filter coefficients */ +); + +void decimate_2_over_3_allpass( + const float *input, /* i : input signal */ + const short len, /* i : number of input samples */ + float *out, /* o : output signal */ + float *mem, /* i/o: memory */ + const float *filt_coeff, /* i : filter coefficients */ + const float *lp_num, + const float *lp_den, + float *lp_mem +); + +void interpolate_3_over_1_allpass( + const float *input, /* i : input signal */ + const short len, /* i : number of input samples */ + float *out, /* o : output signal */ + float *mem, /* i/o: memory */ + const float *filt_coeff /* i : filter coefficients */ +); + +void InitSWBencBuffer( + Encoder_State *st /* i/o: encoder state structure */ +); + +void swb_tbe_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const short coder_type, /* i : coding type */ + float *new_speech, /* i : original input signal */ + const float *bwe_exc_extended, /* i : bandwidth extended exciatation */ + const float voice_factors[], /* i : voicing factors */ + float *White_exc16k, /* o : shaped white excitation for the FB TBE */ + const float voicing[], /* i : OL maximum normalized correlation */ + const float pitch_buf[] /* i : pitch for each subframe */ +); + +void InitSWBdecBuffer( + Decoder_State *swb_dnc /* i/o: SHB decoder structure */ +); + +void swb_tbe_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const short coder_type, /* i : coding type */ + const float *bwe_exc_extended, /* i : bandwidth extended exciatation */ + const float voice_factors[], /* i : voicing factors */ + const float old_syn_12k8_16k[], + float *White_exc16k, /* o : shaped white excitation for the FB TBE */ + float *synth, /* i/o: ACELP core synthesis/final synthesis */ + float *pitch_buf +); + +void flip_and_downmix_generic( + float input[], /* i : input spectrum */ + float output[], /* o : output spectrum */ + const short length, /* i : length of spectra */ + float mem1_ext[HILBERT_ORDER1], /* i/o: Hilbert filter memory */ + float mem2_ext[2*HILBERT_ORDER2], /* i/o: memory */ + float mem3_ext[2*HILBERT_ORDER2], /* i/o: memory */ + short *phase_state /* i/o: Phase state in case frequency isn't multiple of 50 Hz */ +); + +void non_linearity( + const float input[], /* i : input signal */ + float output[], /* i : output signal */ + float old_bwe_exc_extended[], /* i/o: memory bugffer */ + const short length, /* i : input length */ + float *prev_scale /* i/o: memory */ + ,short coder_type, /* i : Coder Type */ + float *voice_factors, /* i : Voice Factors */ + const short L_frame /* i : ACELP frame length */ +); + +void interp_code_5over2( + const float inp_code[], /* i : input vector */ + float interp_code[], /* o : output vector */ + const short inp_length /* i : length of the input vector */ +); + +void interp_code_4over2( + const float inp_code[], /* i : input vector */ + float interp_code[], /* o : output vector */ + const short inp_length /* i : length of the input vector */ +); + +void flip_spectrum_and_decimby4( + const float input[], /* i : input spectrum */ + float output[], /* o : output spectrum */ + const short length, /* i : vector length */ + float mem1[], /* i/o: memory */ + float mem2[], /* i/o: memory */ + const short ramp_flag /* i : flag to trigger slow ramp-up of output */ +); + +void GenShapedWBExcitation( + float *excSHB, /* o : synthesized shaped shb exctiation */ + const float *lpc_shb, /* i : lpc coefficients */ + float *exc4kWhtnd, /* o : whitened synthesized shb excitation */ + float *mem_csfilt, /* i/o : memory */ + float *mem_genSHBexc_filt_down1, /* i/o : memory */ + float *mem_genSHBexc_filt_down2, /* i/o : memory */ + float *mem_genSHBexc_filt_down3, /* i/o : memory */ + float *state_lpc_syn, /* i/o : memory */ + const short coder_type, /* i : coding type */ + const float *bwe_exc_extended, /* i : bandwidth extended exciatation */ + short bwe_seed[], /* i/o : random number generator seed */ + const float voice_factors[], /* i : voicing factor */ + const short uv_flag, /* i : unvoiced flag */ + const short igf_flag +); + +void GenWBSynth( + const float *input_synspeech, /* i : input synthesized speech */ + float *shb_syn_speech_16k, /* o : output highband compnent */ + float *state_lsyn_filt_shb1, /* i/o: memory */ + float *state_lsyn_filt_shb2 /* i/o: memory */ +); + +void wb_tbe_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const short coder_type, /* i : coding type */ + const float *hb_speech, /* i : HB target signal (6-8kHz) at 16kHz */ + const float *bwe_exc_extended, /* i : bandwidth extended exciatation */ + const float voice_factors[], /* i : voicing factors */ + const float pitch_buf[], /* i : pitch for each subframe */ + const float voicing[] /* o : OL maximum normalized correlation */ +); + +void wb_tbe_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const short coder_type, /* i : coding type */ + const float *bwe_exc_extended, /* i : bandwidth extended exciatation */ + const float voice_factors[], /* i : voicing factors */ + float *synth /* i/o: ACELP core synthesis/final synthesis */ +); + +void tbe_write_bitstream( + Encoder_State *st /* i/o: encoder state structure */ +); + +void tbe_read_bitstream( + Decoder_State *st /* i/o: decoder state structure */ +); + +void GenTransition( + const float *input, /* i : gain shape overlap buffer */ + const float *old_hb_synth, /* i : synthesized HB from previous frame */ + short length, /* i : targeted length of transition signal */ + float *output, /* o : synthesized transitions signal */ + float Hilbert_Mem[], /* i/o: memory */ + float state_lsyn_filt_shb_local[],/* i/o: memory */ + float mem_resamp_HB_32k[], /* i/o: memory */ + short *syn_dm_phase, + int output_Fs, + float *up_mem, + int rf_flag + , int bitrate +); + +void GenTransition_WB( + const float *input, /* i : gain shape overlap buffer */ + const float *old_hb_synth, /* i : synthesized HB from previous frame */ + short length, /* i : targeted length of transition signal */ + float *output, /* o : synthesized transitions signal */ + float state_lsyn_filt_shb1[], + float state_lsyn_filt_shb2[], + int output_Fs, + float *up_mem +); + +void TBEreset_enc( + Encoder_State *st, /* i/o: encoder state structure */ + short bandwidth /* i : bandwidth mode */ +); + +void TBEreset_dec( + Decoder_State *st, /* i/o: decoder state structure */ + short bandwidth /* i : bandwidth mode */ +); + +short get_tbe_bits( /* o : TBE bit consumption per frame */ + short bitrate, /* i : overall bitrate */ + short bandwidth, /* i : bandwidht mode */ + short rf_mode /* i : channel aware mode */ +); + +void fb_tbe_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const float new_input[], /* i : input speech at 48 kHz sample rate */ + const float fb_exc[] /* i : FB excitation from the SWB part */ +); + +void fb_tbe_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const float fb_exc[], /* i : FB excitation from the SWB part */ + float *hb_synth /* i/o: high-band synthesis */ +); + +void calc_tilt_bwe( + const float *sp, /* i : input signal */ + float *tilt, /* o : signal tilt */ + const short N /* i : signal length */ +); + +void wtda_BWE( + const float *new_audio, /* i : input audio */ + float *old_wtda, /* i/o: windowed audio from previous frame */ + const short L /* i : length */ +); + +void swb_pre_proc( + Encoder_State *st, /* i/o: encoder state structure */ + const float *input, /* i : original input signal */ + float *new_swb_speech, /* o : original input signal at 32kHz */ + float *shb_speech, /* o : SHB target signal (6-14kHz) at 16kHz */ + float realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : real buffer */ + float imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] /* i : imag buffer */ +); + +void wb_pre_proc( + Encoder_State *st, /* i/o: encoder state structure */ + const float *new_inp_resamp16k, /* i : original input signal */ + float *hb_speech /* o : HB target signal (6-8kHz) at 16kHz */ +); + +void wb_bwe_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const float *new_wb_speech, /* i : original input signal at 16kHz */ + short coder_type /* i : coding type */ +); + +void wb_bwe_dec( + float *synth, /* i/o: ACELP core synthesis/final synthesis */ + float *hb_synth, /* o : SHB synthesis/final synthesis */ + const short output_frame, /* i : frame length */ + Decoder_State *st, /* i/o: decoder state structure */ + short coder_type, /* i : coding type */ + float *voice_factors, /* i : voicing factors */ + const float pitch_buf[] /* i : pitch buffer */ +); + +void swb_bwe_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const float *old_input_12k8, /* i : input signal @12.8kHz for SWB BWE */ + const float *old_input_16k, /* i : input signal @16kHz for SWB BWE */ + const float *old_syn_12k8_16k, /* i : ACELP core synthesis at 12.8kHz or 16kHz*/ + const float *new_swb_speech, /* i : original input signal at 32kHz */ + const float *shb_speech, /* i : SHB target signal (6-14kHz) at 16kHz */ + const short coder_type /* i : coding type */ +); + +void swb_bwe_enc_hr( + Encoder_State *st, /* i/o: encoder state structure */ + const float *new_input, /* i : input signal */ + const short input_frame, /* i : frame length */ + const short coder_type, /* i : coding type */ + const short unbits /* i : number of core unused bits */ +); + +void swb_bwe_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const float *synth, /* i : ACELP core synthesis/final synthesis */ + float *hb_synth, /* o : SHB synthesis/final synthesis */ + const short output_frame /* i : frame length */ + ,short coder_type /* i : coding type */ +); + +void swb_bwe_dec_hr( + Decoder_State *st, /* i/o: decoder state structure */ + const float *syn_12k8_16k, /* i : ACELP core synthesis @16kHz */ + float *hb_synth, /* o : SHB synthesis */ + const short output_frame, /* i : frame length */ + const short unbits, /* i : number of core unused bits */ + const float pitch_buf[] /* i : pitch buffer */ +); + +void swb_hr_noise_fill( + const short is_transient, /* i : transient flag */ + const short spect_start, /* i : spectrum start point */ + const short spect_end, /* i : spectrum end point */ + const float tilt_wb, /* i : tilt of wideband signal */ + const float pitch, /* i : pitch value */ + const short nq[], /* i : AVQ nq index */ + short Nsv, /* i : number of subband */ + short *bwe_highrate_seed, /* i/o: seed of random noise */ + float *t_audio /* i/o: mdct spectrum */ +); + +float td_postprocess( /* o : gain */ + float hb_synth[], /* i/o: high-band synthesis */ + const short input_frame, /* i : frame length */ + const short last_extl /* i : last extension layer */ +); + +void calc_normal_length( + const short core, /* i : core */ + const float *sp, /* i : input signal */ + const short mode, /* i : input mode */ + const short extl, /* i : extension layer */ + short *L_swb_norm, /* o : normalize length */ + short *prev_L_swb_norm /* i/o: last normalize length */ +); + +void calc_norm_envelop( + const float SWB_signal[], /* i : SWB spectrum */ + float *envelope, /* o : normalized envelope */ + const short L_swb_norm, /* i : length of envelope */ + const short SWB_flength, /* i : Length of input/output */ + const short st_offset /* i : offset */ +); + +void time_envelop_shaping( + float werr[], /* i/o: SHB synthesis */ + float SWB_tenv[], /* i/o: frequency envelope */ + const short L /* i : frame length */ +); + +void time_reduce_pre_echo( + const float *synth, /* i : ACELP core synthesis */ + float *error, /* o : SHB BWE synthesis */ + float prev_td_energy, /* o : last td energy */ + const short L /* i : subframe length */ +); + +short WB_BWE_gain_pred( + float *WB_fenv, /* o : WB frequency envelopes */ + const float *core_dec_freq, /* i : Frequency domain core decoded signal */ + const short coder_type, /* i : coding type */ + short prev_code_type, /* i : coding type of last frame */ + float prev_WB_fenv, /* i : envelope for last frame */ + float *voice_factors, /* i : voicing factors */ + const float pitch_buf[], /* i : pitch buffer */ + long last_core_brate, /* i : previous frame core bitrate */ + float last_wb_bwe_ener /* i : previous frame wb bwe signal energy */ + ,short last_extl /* i : extl. layer for last frame */ + ,float tilt +); + +void WB_BWE_decoding( + const float *core_dec_freq, /* i : Frequency domain core decoded signal */ + float *WB_fenv, /* i : WB frequency envelopes */ + float *WB_signal, /* o : WB signal in MDCT domain */ + const short WB_flength, /* i : Length of input/output */ + const short mode, /* i : classification for WB signal */ + const short last_extl, /* i : extl. layer for last frame */ + float *prev_Energy, /* i/o: energy for last frame */ + float *prev_WB_fenv, /* i/o: envelope for last frame */ + short *prev_L_wb_norm, /* i/o: length for last frame wb norm */ + const short extl, /* i : extension layer */ + const short coder_type, /* i : coding type */ + const long total_brate, /* i : core layer bitrate */ + short *Seed, /* i/o: random generator seed */ + short *prev_flag, /* i/o: attenu flag of last frame */ + short prev_coder_type /* i : coding type of last frame */ +); + +void SWB_BWE_decoding( + const float *core_dec_freq, /* i : Frequency domain core decoded signal */ + float *SWB_fenv, /* i/o: SWB frequency envelopes */ + float *SWB_signal, /* o : SWB signal in MDCT domain */ + const short SWB_flength, /* i : Length of input/output */ + const short mode, /* i : classification for SWB signal */ + short *frica_flag, /* o : fricative signal flag */ + float *prev_Energy, /* i/o: energy for last frame */ + float *prev_SWB_fenv, /* i/o: envelope for last frame */ + short *prev_L_swb_norm, /* i/o: length for last frame wb norm */ + const float tilt_nb, /* i : tilt of synthesis wb signal */ + short *Seed, /* i/o: random generator seed */ + const short st_offset, /* i : offset value due to different core */ + float *prev_weight, /* i/o: excitation weight value of last frame */ + const short extl /* i : extension layer */ + ,const short last_extl /* i : extension layer of last frame */ +); + +void CNG_reset_enc( + Encoder_State *st, /* i/o: encoder state structure */ + LPD_state *mem, /* i/o: encoder memories */ + float *pitch_buf, /* o : floating pitch for each subframe */ + float *voice_factors /* o : voicing factors */ + ,short VBR_cng_reset_flag +); + +void a2isp( + const float *a, /* i : LP filter coefficients */ + float *isp, /* o : Immittance spectral pairs */ + const float *old_isp /* i : ISP vector from past frame */ +); + +void a2isf( + float *a, + float *isf, + const float *old_isf, + short lpcOrder); + +void a2rc ( + const float *a, /* i : LPC coefficients */ + float *refl, /* o : Reflection co-efficients */ + const short lpcorder /* i : LPC order */ +); + +short lp_filt_exc_enc( + const short codec_mode, /* i : codec mode */ + const long core_brate, /* i : core bitrate */ + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short coder_type, /* i : coding type */ + const short i_subfr, /* i : subframe index */ + float *exc, /* i/o: pointer to excitation signal frame */ + const float *h1, /* i : weighted filter input response */ + const float *xn, /* i : target vector */ + float *y1, /* o : zero-memory filtered adaptive excitation */ + float *xn2, /* o : target vector for innovation search */ + const short L_subfr, /* i : length of vectors for gain quantization */ + const short L_frame, /* i : frame size */ + float *g_corr, /* o : ACELP correlation values */ + const short clip_gain, /* i : adaptive gain clipping flag */ + float *gain_pit, /* o : adaptive excitation gain */ + short *lp_flag /* i/o : mode selection */ +); + +void updt_tar( + const float *x, /* i : old target (for pitch search) */ + float *x2, /* o : new target (for codebook search) */ + const float *y, /* i : filtered adaptive codebook vector */ + const float gain, /* i : adaptive codebook gain */ + const short L /* i : subframe size */ +); + +void analy_sp( + float *speech, /* i : speech buffer */ + float *Bin_E, /* o : per bin log energy spectrum */ + float *Bin_E_old, /* o : per bin log energy spectrum for mid-frame */ + float *fr_bands, /* o : per band energy spectrum (2 analyses) */ + float lf_E[], /* o : per bin E for first VOIC_BINS bins (without DC) */ + float *Etot, /* o : total input energy */ + const short min_band, /* i : minimum critical band */ + const short max_band, /* i : maximum critical band */ + float *band_ener, /* o: energy in critical frequency bands without minimum noise floor E_MIN */ + float *PS /* o : Per bin energy spectrum */ + ,float *fft_buff /* o : FFT coefficients */ +); + +void CNG_enc( + Encoder_State *st, /* i/o: State structure */ + const short L_frame, /* i : length of the frame */ + float Aq[], /* o : LP coefficients */ + const float *speech, /* i : pointer to current frame input speech buffer */ + float enr, /* i : frame energy output from Levinson recursion */ + float *lsp_new, /* i/o: current frame LSPs */ + float *lsf_new, /* i/o: current frame LSFs */ + short *allow_cn_step, /* o : allow CN step */ + short burst_ho_cnt, /* i : hangover frames at end of speech burst */ + float *q_env, + short *sid_bw, + float *exc_mem2 +); + +void swb_CNG_enc( + Encoder_State *st, /* i/o: State structure */ + const float *shb_speech, /* i : SHB target signal (6-14kHz) at 16kHz */ + const float *syn_12k8_16k /* i : ACELP core synthesis at 12.8kHz or 16kHz */ +); + +void lsf_enc( + Encoder_State *st, /* i/o: state structure */ + const short L_frame, /* i : length of the frame */ + const short coder_type, /* i : coding type */ + float *lsf_new, /* o : quantized LSF vector */ + float *lsp_new, /* i/o: LSP vector to quantize/quantized */ + float *lsp_mid, /* i : mid-frame LSP vector */ + float *Aq, /* o : quantized A(z) for 4 subframes */ + float *stab_fac, /* o : ISF stability factor */ + const short Nb_ACELP_frames +); + +void isf_enc_amr_wb( + Encoder_State *st, /* i/o: state structure */ + float *isf_new, /* o : quantized ISF vector */ + float *isp_new, /* i/o: ISP vector to quantize/quantized */ + float *Aq, /* o : quantized A(z) for 4 subframes */ + float *stab_fac /* o : ISF stability factor */ +); + +void find_targets( + const float *speech, /* i : pointer to the speech frame */ + const float *mem_syn, /* i : memory of the synthesis filter */ + const short i_subfr, /* i : subframe index */ + float *mem_w0, /* i/o: weighting filter denominator memory */ + const float *p_Aq, /* i : interpolated quantized A(z) filter */ + const float *res, /* i : residual signal */ + const short L_subfr, /* i : length of vectors for gain quantization */ + const float *Ap, /* i : unquantized A(z) filter with bandwidth expansion */ + const float tilt_fac, /* i : tilt factor */ + float *xn, /* o : Close-loop Pitch search target vector */ + float *cn, /* o : target vector in residual domain */ + float *h1 /* o : impulse response of weighted synthesis filter */ +); + +void inov_encode( + Encoder_State *st, /* i/o: encoder state structure */ + const long core_brate, /* i : core bitrate */ + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short L_frame, /* i : length of the frame */ + const short last_L_frame, /* i : length of the last frame */ + const short coder_type, /* i : coding type */ + const short bwidth, /* i : input signal bandwidth */ + const short sharpFlag, /* i : formant sharpening flag */ + const short i_subfr, /* i : subframe index */ + short const tc_subfr, /* i : TC subframe index */ + const float *p_Aq, /* i : LP filter coefficients */ + const float gain_pit, /* i : adaptive excitation gain */ + float *cn, /* i/o: target vector in residual domain */ + const float *exc, /* i : pointer to excitation signal frame */ + float *h1, /* i/o: weighted filter input response */ + const float tilt_code, /* i : tilt of of the excitation of previous subframe */ + const float pt_pitch, /* i : pointer to current subframe fractional pitch */ + const float *xn2, /* i : target vector for innovation search */ + float *code, /* o : algebraic excitation */ + float *y2, /* o : zero-memory filtered algebraic excitation */ + short *unbits /* o : number of unused bits for EVS_PI */ +); + +void acelp_1t64( + Encoder_State *st, /* i/o: encoder state structure */ + const float dn[], /* i : corr. between target and h[]. */ + const float h[], /* i : impulse response of weighted synthesis filter */ + float code[], /* o : algebraic (fixed) codebook excitation */ + float y[] /* o : filtered fixed codebook excitation */ +); + +void acelp_2t32( + Encoder_State *st, /* i/o: encoder state structure */ + const float dn[], /* i : corr. between target and h[]. */ + const float h[], /* i : impulse response of weighted synthesis filter */ + float code[], /* o : algebraic (fixed) codebook excitation */ + float y[] /* o : filtered fixed codebook excitation */ +); + +short acelp_4t64( + Encoder_State *st, /* i/o: encoder state structure */ + float dn[], /* i : corr. between target and h[]. */ + const float cn[], /* i : residual after long term prediction */ + const float H[], /* i : impulse response of weighted synthesis filter */ + float R[], /* i : autocorrelation values */ + const short acelpautoc, /* i : autocorrealtion flag */ + float code[], /* o : algebraic (fixed) codebook excitation */ + float y[], /* o : filtered fixed codebook excitation */ + short nbbits, /* i : number of bits per codebook */ + const short cmpl_flag, /* i : coomplexity reduction flag */ + const short Opt_AMR_WB /* i : flag indicating AMR-WB IO mode */ +); + +void corr_xh( + const float *x, /* i : target signal */ + float *y, /* o : correlation between x[] and h[] */ + const float *h, /* i : impulse response of weighted synthesis filter */ + const int L_subfr /* i : length of the subframe */ +); + +void find_tilt( + const float fr_bands[], /* i : energy in frequency bands */ + const float bckr[], /* i : per band background noise energy estimate */ + float ee[2], /* o : lf/hf E ration for present frame */ + const short pitch[3], /* i : open loop pitch values for 3 half-frames */ + const float voicing[3], /* i : normalized correlation for 3 half-frames */ + const float *lf_E, /* i : per bin energy for low frequencies */ + const float corr_shift, /* i : normalized correlation correction */ + const short bwidth, /* i : input signal bandwidth */ + const short max_band, /* i : maximum critical band */ + float hp_E[], /* o : energy in HF */ + const short codec_mode, /* i : Mode 1 or 2 */ + float *bckr_tilt_lt, /* i/o: lf/hf E ratio of background noise */ + short Opt_vbr_mode +); + +void init_gp_clip( + float mem[] /* o : memory of gain of pitch clipping algorithm */ +); + +short gp_clip( + const long core_brate, /* i : core bitrate */ + const float *voicing, /* i : normalized correlations (from OL pitch) */ + const short i_subfr, /* i : subframe index */ + const short coder_type, /* i : coding type */ + const float xn[], /* i : target vector */ + float mem[] /* i/o: memory of gain of pitch clipping algorithm */ +); + +void gp_clip_test_lsf( + const long core_brate, /* i : core bitrate */ + const float lsf[], /* i : LSF vector */ + float mem[], /* i/o: memory of gain of pitch clipping algorithm */ + const short Opt_AMR_WB /* i : flag indicating AMR-WB IO mode */ +); + +void gp_clip_test_gain_pit( + const long core_brate, /* i : core bitrate */ + const float gain_pit, /* i : gain of quantized pitch */ + float mem[] /* i/o: memory of gain of pitch clipping algorithm */ +); + +void analy_lp( + const float speech[], /* i : pointer to the denoised speech frame */ + const short L_frame, /* i : length of the frame */ + const short L_look, /* i : look-ahead length */ + float *ener, /* o : residual signal energy */ + float A[], /* o : A(z) filter coefficients */ + float epsP[], /* o : LP analysis residual energies for each iteration */ + float lsp_new[], /* o : current frame ISPs */ + float lsp_mid[], /* o : current mid-frame ISPs */ + float lsp_old[], /* i/o: previous frame unquantized ISPs */ + const short Top[2], /* i : open loop pitch lag */ + const float Tnc[2], /* i : open loop pitch gain */ + const float sr_core /* i : internal sampling rate */ +); + +void analy_lp_AMR_WB( + const float speech[], /* i : pointer to the speech frame */ + float *ener, /* o : residual energy from Levinson-Durbin */ + float A[], /* o : A(z) filter coefficients */ + float epsP[], /* o : LP analysis residual energies for each iteration */ + float isp_new[], /* o : current frame ISPs */ + float isp_old[], /* i/o: previous frame unquantized ISPs */ + float isf_new[], /* o : current frame ISFs */ + const int Top, /* i : open loop pitch lag */ + const float Tnc /* i : open loop pitch gain */ +); + +void noise_est_init( + float *totalNoise, /* o : noise estimate over all critical bands */ + short *first_noise_updt, /* o : noise update initialization flag */ + float bckr[], /* o : per band background noise energy estimate */ + float enrO[], /* o : per band old input energy */ + float ave_enr[], /* o : per band long-term average energies */ + short *pitO, /* o : open-loop pitch values from preceed. frame */ + short *aEn, /* o : noise adaptation hangover counter */ + short *st_harm_cor_cnt, /* o : harm and correlation timer */ + short *bg_cnt, /* o : pause length counter */ + float *lt_tn_track, + float *lt_tn_dist, + float *lt_Ellp_dist, + float *lt_haco_ev, + short *low_tn_track_cnt + ,float *Etot_st_est, + float *Etot_sq_st_est + +); + +void long_enr( + Encoder_State *st, /* i/o: encoder state structure */ + const float Etot, /* i : total channel energy */ + const short localVAD_HE_SAD, /* i : HE-SAD flag without hangover */ + short high_lpn_flag +); + +void noise_est_pre( + const float Etot, /* i : Energy of current frame */ + const short ini_frame, /* i : Frame number (init) */ + float *Etot_l, /* i/o: Track energy from below */ + float *Etot_h, /* i/o: Track energy from above */ + float *Etot_l_lp, /* i/o: Smoothed low energy */ + float *Etot_last, /* i/o: Energy of last frame */ + float *Etot_v_h2, /* i/o: Energy variations */ + float *sign_dyn_lp, /* i/o: Smoother signal dynamics */ + short harm_cor_cnt, + float *Etot_lp +); + +void noise_est_down( + const float fr_bands[], /* i : per band input energy (contains 2 vectors) */ + float bckr[], /* i/o: per band background noise energy estimate */ + float tmpN[], /* o : temporary noise update */ + float enr[], /* o : averaged energy over both subframes */ + const short min_band, /* i : minimum critical band */ + const short max_band, /* i : maximum critical band */ + float *totalNoise, /* o : noise estimate over all critical bands */ + const float Etot, /* i : Energy of current frame */ + float *Etot_last, /* i/o: Energy of last frame */ + float *Etot_v_h2 /* i/o: Energy variaions of noise frames */ +); + +void noise_est( + Encoder_State *st, /* i/o: encoder state structure */ + const float tmpN[], /* i : temporary noise update */ + const short *pitch, /* i : open-loop pitch values for each half-frame */ + const float *voicing, /* i : normalized correlation for all half-frames */ + const float *epsP, /* i : LP prediction error energies */ + const float Etot, /* i : total channel E */ + const float relE, /* i : relative frame energy */ + const float corr_shift, /* i : normalized correlation correction */ + const float enr[], /* i : averaged energy over both subframes */ + float fr_bands[], /* i : spectrum per critical bands of the current frame */ + float *cor_map_sum, /* o : sum of correlation map from mult-harm analysis */ + float *sp_div, /* o : soectral diversity feature */ + float *non_staX, /* o : non-stationarity for sp/mus classifier */ + short *loc_harm, /* o : multi-harmonicity flag for UV classifier */ + const float *lf_E, /* i : per bin energy for low frequencies */ + short *st_harm_cor_cnt, /* i : 1st harm correlation timer */ + const float Etot_l_lp, /* i : Smoothed low energy */ + float *sp_floor /* o : noise floor estimate */ +); + +void vad_param_updt( + Encoder_State *st, /* i/o: encoder state structure */ + const short pitch[3], /* i : open loop pitch lag for each half-frame */ + const float voicing[3], /* i : maximum normalized correlation for each half-frame */ + const short old_pitch1, /* i : OL pitch value from last frame */ + const float corr_shift, /* i : correlation shift */ + const float A[] /* i : A(z) unquantized for the 4 subframes */ +); + +short multi_harm( /* o : frame multi-harmonicity (1-harmonic, 0-not) */ + const float Bin_E[], /* i : log energy spectrum of the current frame */ + float old_S[], /* i/o: prev. log-energy spectrum w. subtracted floor */ + float cor_map_LT[], /* i/o: LT correlation map */ + float *multi_harm_limit, /* i/o: multi harminic threshold */ + const long total_brate, /* i : total bitrate */ + const short bwidth, /* i : input signal bandwidth */ + short *cor_strong_limit, /* i/o: HF correlation indicator */ + float *st_mean_avr_dyn, /* i/o: long term average dynamic */ + float *st_last_sw_dyn, /* i/o: last dynamic */ + float *cor_map_sum, + float *sp_floor /* o : noise floor estimate */ +); + +void lp_gain_updt( + const short i_subfr, /* i : subframe number */ + const float gain_pit, /* i : Decoded gain pitch */ + const float norm_gain_code, /* i : Normalised gain code */ + float *lp_gainp, /* i/o: LP-filtered pitch gain(FEC) */ + float *lp_gainc, /* i/o: LP-filtered code gain (FEC) */ + const short L_frame /* i : length of the frame */ +); + +void enc_pit_exc( + Encoder_State *st, /* i/o: state structure */ + LPD_state *mem, /* i/o: encoder memories */ + const float *speech, /* i : Input speech */ + const float Aw[], /* i : weighted A(z) unquantized for subframes */ + const float *Aq, /* i : 12k8 Lp coefficient */ + const float Es_pred, /* i : predicted scaled innov. energy */ + const short *T_op, /* i : open loop pitch */ + const float *voicing, /* i : voicing */ + const float *res, /* i : residual signal */ + float *synth, /* i/o: core synthesis */ + float *exc, /* i/o: current non-enhanced excitation */ + short *T0, /* i/o: close loop integer pitch */ + short *T0_frac, /* i/o: close-loop pitch period - fractional part */ + float *pitch_buf, /* i/o: Fractionnal per subframe pitch */ + const short nb_subfr, /* i : Number of subframe considered */ + float *gpit /* o : pitch gain per subframe */ +); + +void encod_audio( + Encoder_State *st, /* i/o: state structure */ + LPD_state *mem, /* i/o: encoder memories */ + const float speech[], /* i : input speech */ + const float Aw[], /* i : weighted A(z) unquantized for subframes */ + const float Aq[], /* i : 12k8 Lp coefficient */ + const short T_op[], /* i : open loop pitch */ + const float voicing[], /* i : voicing */ + const float *res, /* i : residual signal */ + float *synth, /* i/o: core synthesis */ + float *exc, /* i/o: current non-enhanced excitation */ + float *pitch_buf, /* i/o: floating pitch values for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *bwe_exc, /* o : excitation for SWB TBE */ + const short attack_flag, /* i : Flag that point to an attack coded with AC mode (GSC) */ + const short coder_type, /* i : core coding type */ + float *lsf_new, /* i : current frame ISF vector */ + float *tmp_noise /* o : long-term noise energy */ +); + +short Pit_exc_contribution_len( /* o : index of the last band where pitch contribution is significant */ + Encoder_State *st, /* i/o: state structure */ + const float *dct_res, /* i : DCT of residual */ + float *dct_pitex, /* i/o: DCT of pitch contribution */ + float *pitch_buf, /* i/o: Pitch per subframe */ + short *hangover, /* i : Hangover for the time contribution switching */ + const short coder_type /* i : coding type */ +); + +short stab_est( + float etot, /* i : Total energy of the current frame */ + float *lt_diff_etot, /* i/o: Long term total energy variation */ + float *mem_etot, /* i/o: Total energy memory */ + short *nb_thr_3, /* i/o: Number of consecutives frames of level 3 */ + short *nb_thr_1, /* i/o: Number of consecutives frames of level 1 */ + float *thresh, /* i/o: Detection thresold */ + short *last_music_flag, /* i/o: Previous music detection ouptut */ + short vad_flag +); + +float gsc_gainQ( + Encoder_State *st, /* i/o: encoder state structure */ + const float y_gain4[], /* i : gain per band */ + float y_gainQ[], /* o : quantized gain per band */ + const long core_brate, /* i : Core rate */ + const short coder_type, /* i : coding type */ + const short bwidth /* i : input signal bandwidth */ +); + +void Ener_per_band_comp( + const float exc_diff[], /* i : gain per band */ + float y_gain4[], /* o : gain per band to quantize */ + const short Mband, /* i : Max band */ + const short Eflag /* i : flag of highest band */ +); + +void Comp_and_apply_gain( + float exc_diffQ[], /* i/o: gain per band */ + float Ener_per_bd_iQ[], /* o : Quant Ener per band */ + float Ener_per_bd_yQ[], /* o : Ener per band for quantize y */ + short Mbands_gn, /* i : number of bands */ + const short ReUseGain /* i : Reuse the gain in Ener_per_bd_yQ */ +); + +void bands_and_bit_alloc( + const short cor_strong_limit, /* i : HF correlation */ + const short noise_lev, /* i : dwn scaling factor */ + const long core_brate, /* i : core bit rate */ + const short Diff_len, /* i : Lenght of the difference signal (before pure spectral)*/ + const short bits_used, /* i : Number of bit used before frequency Q */ + short *bit, /* i/o: Number of bit allowed for frequency quantization */ + float *ener_vec, /* i/o: Quantized energy vector */ + short *max_ener_band, /* o : Sorted order */ + short *bits_per_bands_s, /* i/o: Number of bit allowed per allowed subband (Q3) */ + short *nb_subbands, /* o : Number of subband allowed */ + const float *exc_diff, /* i : Difference signal to quantize (encoder side only) */ + float *concat_in, /* o : Concatened PVQ's input vector (encoder side only) */ + short *pvq_len, /* o : Number of bin covered with the PVQ */ + const short coder_type, /* i : coding type */ + const short bwidth, /* i : input signal bandwidth */ + const short GSC_noisy_speech /* i : GSC noisy speech flag */ +); + +float gsc_gaindec( /* o : average frequency gain */ + Decoder_State *st, /* i/o: decoder state structure */ + float y_gainQ[], /* o : quantized gain per band */ + const long core_brate, /* i : core used */ + float old_y_gain[], /* i/o: AR gain quantizer for low rate */ + const short coder_type, /* i : coding type */ + const short bwidth /* i : input signal bandwidth */ +); + +void freq_dnw_scaling( + const short cor_strong_limit, /* i : HF correlation */ + const short coder_type, /* i : coder type */ + const short noise_lev, /* i : Noise level */ + const long core_brate, /* i : Core bitrate */ + float fy_norm[] /* i/o: Frequency quantized parameter */ +); + +void decod_audio( + Decoder_State *st, /* i/o: decoder static memory */ + float dct_epit[], /* o : GSC excitation in DCT domain */ + const float *Aq, /* i : LP filter coefficient */ + const short coder_type, /* i : coding type */ + float *tmp_noise, /* o : long term temporary noise energy */ + float *pitch_buf, /* o : floating pitch values for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *exc_dct_in, /* i/o: adapt. excitation exc */ + float *exc2, /* i/o: adapt. excitation/total exc */ + float *bwe_exc, /* o : excitation for SWB TBE */ + float *lsf_new, /* i : current frame ISF vector */ + float *gain_buf +); + +void gsc_dec( + Decoder_State *st, /* i/o: State structure */ + float exc_dct_in[], /* i/o: dct of pitch-only/total excitation */ + const short pit_band_idx, /* i : pitch band index */ + const short Diff_len, /* i : */ + const short bits_used, /* i : total number of bits used */ + const short nb_subfr, /* i : Number of subframe considered */ + const short coder_type, /* i : coding type */ + short *last_bin, /* i : last bin of bit allocation */ + float *lsf_new, /* i : ISFs at the end of the frame */ + float *exc_wo_nf, /* o : excitation (in f domain) without noisefill*/ + float *tmp_noise /* o : long-term noise energy */ +); + +void dec_pit_exc( + Decoder_State *st, /* i/o: decoder static memory */ + const short L_frame, /* i : length of the frame */ + const float *Aq, /* i : LP filter coefficient */ + const float Es_pred, /* i : predicted scaled innov. energy */ + float *pitch_buf, /* o : floating pitch values for each subframe */ + float *code, /* o : innovation */ + float *exc, /* i/o: adapt. excitation exc */ + const short nb_subfr, /* i : Number of subframe considered */ + float *gain_buf +); + +void highband_exc_dct_in( + const long core_brate, /* i : core bitrate */ + const short *mfreq_bindiv_loc, /* i : bin per bands tables */ + short last_bin, /* i : last bin of bit allocation */ + short Diff_len, /* i : number of bin before cut-off frequency */ + short noise_lev, /* i : pulses dynamic */ + short pit_band_idx, /* i : bin position of the cut-off frequency */ + float *exc_diffQ, /* i : frequency coefficients of per band */ + short *seed_tcx, /* i : Seed for noise */ + float *Ener_per_bd_iQ, /* i : Quantized energy of targeted vector */ + short nb_subfr, /* i : Number of subframe considered */ + float *exc_dct_in, /* o : dct of residual signal */ + short last_coder_type, /* i : coding type of last frame */ + short *bitallocation_band, /* i : bit allocation flag of each band */ + float *lsf_new, /* i : ISFs at the end of the frame */ + float *last_exc_dct_in, /* i : dct of residual signal of last frame */ + float *last_ener, /* i : frequency energy of last frame */ + short *last_bitallocation_band, /* i : bit allocation flag of each band of last frame */ + short *bitallocation_exc, /* i : flag of decoded coefficients */ + short bfi, /* i : bad frame indicator */ + const short coder_type, /* i : coder type */ + short bwidth, + float *exc_wo_nf, /* o : excitation (in f domain) without noisefill */ + const short GSC_noisy_speech + ,float *lt_ener_per_band_fx /* i/o: Average per band energy */ +); + +void inact_switch_ematch( + float exc2[], /* i/o: CELP/GSC excitation buffer */ + float dct_exc_tmp[], /* i : GSC excitation in DCT domain */ + float lt_ener_per_band[], /* i/o: long-term energy per band */ + const short coder_type, /* i : coding mode */ + const short L_frame, /* i : frame lenght */ + const long core_brate /* i : core bit rate */ + ,const short bfi, /* i : frame lost indicator */ + const short last_core, /* i : Last core used */ + const short last_codec_mode /* i : Last codec mode */ +); + +void LD_music_post_filter( + const float dtc_in[], /* i : input synthesis */ + float dtc_out[], /* o : output synthesis */ + const long core_brate, /* i : core bitrate */ + short *last_music_flag, /* i/o: Previous music detection ouptut */ + float *thresh, /* i/o: Detection thresold */ + short *nb_thr_1, /* i/o: Number of consecutives frames of level 1 */ + short *nb_thr_3, /* i/o: Number of consecutives frames of level 3 */ + float *lt_diff_etot, /* i/o: Long term total energy variation */ + float *mem_etot, /* i/o: Total energy memory */ + const float min_ns_gain, /* i : minimum gain for inter-harm noise red. */ + float bckr[], /* i/o: per band bckgnd. noise energy estimate */ + float lf_EO[], /* i/o: old per bin E for previous half frame */ + float lp_gbin[], /* i/o: smoothed suppression gain, per FFT bin */ + float *filt_lfE, /* i : post filter weighting coefficient */ + short *last_nonfull_music, /* i : Coder type : -1 in case of IO */ + const short coder_type /* i : Coder type : -1 in case of IO */ + ,const short Last_coder_type /* i : last Coder type */ +); + +void Post_music_postP( + float dct_buffer_in[], /* i/o: excitation buffer */ + float exc_buffer_out[], /* o : DCT output buffer */ + float *exc2, /* i/o: Current excitation to be overwriten */ + const float *mem_tmp, /* i : previous frame synthesis memory */ + float *st_mem_syn2, /* i/o: current frame synthesis memory */ + const float *Aq, /* i : LPC filter coefficients */ + float *syn /* i/o: 12k8 synthesis */ +); + +void Prep_music_postP( + float exc_buffer_in[], /* i/o: excitation buffer */ + float dct_buffer_out[], /* o : DCT output buffer */ + float filt_lfE[], /* i/o: long term spectrum energy */ + const short last_core, /* i : last core */ + const float *pitch_buf, /* i : current frame pitch information */ + float *LDm_enh_lp_gbin /* o : smoothed suppression gain, per bin FFT */ +); + +void speech_music_classif( + Encoder_State *st, /* i/o: encoder state structure */ + short *sp_aud_decision0, /* o : 1st stage speech/music decision */ + short *sp_aud_decision1, /* o : 1st stage speech/music decision */ + short *sp_aud_decision2, /* o : 2nd stage speech/music decision */ + const float *new_inp, /* i : new input signal */ + const float *inp, /* i : input signal to locate attach position */ + const short vad_flag, + const short localVAD, + const short localVAD_HE_SAD, /* i : HE-SAD flag without hangover */ + const short pitch[3], /* i : open-loop pitch estimate in three subframes */ + const float voicing[3], /* i : voicing estimate in three subframes */ + const float lsp_new[M], /* i : LSPs in current frame */ + const float cor_map_sum, /* i : correlation map sum (from multi-harmonic anal.) */ + const float epsP[M+1], /* i : LP prediciton error */ + const float PS[], /* i : energy spectrum */ + const float Etot, /* i : total frame energy */ + const float old_cor, /* i : max correlation from previous frame */ + short *coder_type, /* i/o: coding type */ + short *attack_flag, /* o : flag to indicate if attack is to be treated by TC or GSC */ + const float non_staX, /* i : unbound non-stationarity for sp/mus classifier */ + const float relE, /* i : relative frame energy */ + short *high_lpn_flag, + const short flag_spitch /* i : flag to indicate very short stable pitch */ +); + +void find_wsp( + const short L_frame, /* i : length of the frame */ + const short L_subfr, /* i : length of subframe */ + const short nb_subfr, /* i : number of subframes */ + const float *A, /* i : A(z) filter coefficients */ + float *Aw, /* o : weighted A(z) filter coefficients */ + const float *speech, /* i : pointer to the denoised speech frame */ + const float tilt_fact, /* i : tilt factor */ + float *wsp, /* o : poitnter to the weighted speech frame */ + float *mem_wsp, /* i/o: W(Z) denominator memory */ + const float gamma, /* i : weighting factor */ + const short L_look /* i : look-ahead */ +); + +void pitch_ol_init( + float *old_thres, /* o : threshold for reinforcement of past pitch influence */ + short *old_pitch, /* o : pitch of the 2nd half-frame of previous frame */ + short *delta_pit, /* o : pitch evolution extrapolation */ + float *old_corr /* o : correlation */ +); + +void pitch_ol( + short pitch[3], /* o : open loop pitch lag for each half-frame */ + float voicing[3], /* o : maximum normalized correlation for each half-frame */ + short *old_pitch, /* i/o: OL pitch of the 2nd half-frame of the last frame */ + float *old_corr, /* i/o: correlation */ + float corr_shift, /* i : normalized correlation correction */ + float *old_thres, /* i/o: maximum correlation weighting with respect to past frame pitch */ + short *delta_pit, /* i/o: old pitch extrapolation correction (added to old pitch) */ + float *st_old_wsp2, /* i/o: weighted speech memory */ + const float *wsp, /* i : weighted speech for current frame and look-ahead */ + float mem_decim2[3], /* i/o: wsp decimation filter memory */ + const float relE, /* i : relative frame energy */ + const short L_look, /* i : look-ahead */ + const short last_class, /* i : frame classification of last frame */ + const short bwidth, /* i : bandwidth */ + const short Opt_SC_VBR /* i : SC-VBR flag */ +); + +void pitch_ol2( + const short pit_min, /* i : pit_min value */ + const short pitch_ol, /* i : pitch to be improved */ + float *pitch_fr, /* o : adjusted 1/4 fractional pitch */ + float *voicing_fr, /* o : adjusted 1/4 fractional voicing */ + const short pos, /* i : position in frame where to calculate the improv. */ + const float *wsp, /* i : weighted speech for current frame and look-ahead */ + const short delta /* i : delta for pitch search */ +); + +void StableHighPitchDetect( + short *flag_spitch, /* o : flag to indicate very short stable pitch */ + short pitch[], /* i/o: OL pitch buffer */ + const float voicing[], /* i : OL pitch gains */ + const float Bin_E[], /* i : per bin log energy spectrum */ + const float wsp[], /* i : weighted speech */ + const short localVAD, + float *voicing_sm, /* i/o: smoothed open-loop pitch gains */ + float *voicing0_sm, /* i/o: smoothed high pitch gains */ + float *LF_EnergyRatio_sm, /* i/o: smoothed [0, 300Hz] relative peak energy */ + short *predecision_flag, /* i/o: predecision flag */ + float *diff_sm, /* i/o: smoothed pitch frequency difference */ + float *energy_sm /* i/o: smoothed energy around pitch frequency */ +); + +void pitchDoubling_det( + float *wspeech, + short *pitch_ol, + float *pitch_fr, + float *voicing_fr +); + +void gain_enc_amr_wb( + Encoder_State *st, /* i/o: encoder state structure */ + const float *xn, /* i : target vector */ + const float *y1, /* i : zero-memory filtered adaptive excitation */ + const float *y2, /* i : zero-memory filtered algebraic codebook excitation */ + const float *code, /* i : algebraic excitation */ + const long core_brate, /* i : core bitrate */ + float *gain_pit, /* i/o: Pitch gain / Quantized pitch gain */ + float *gain_code, /* o : Quantized codebook gain */ + float *gain_inov, /* o : innovation gain */ + float *norm_gain_code, /* o : norm. gain of the codebook excitation */ + float *coeff, /* i/o: correlations , -2,, -2 and 2 */ + const short clip_gain, /* i : gain pitch clipping flag (1 = clipping) */ + float *past_qua_en /* i/o: gain quantization memory (4 words) */ + +); + +void gain_enc_lbr( + Encoder_State *st, /* i/o: encoder state structure */ + const long core_brate, /* i : core bitrate */ + const short coder_type, /* i : coding type */ + const short i_subfr, /* i : subframe index */ + const float *xn, /* i : target vector */ + const float *y1, /* i : zero-memory filtered adaptive excitation */ + const float *y2, /* i : zero-memory filtered algebraic codebook excitation */ + const float *code, /* i : algebraic excitation */ + float *gain_pit, /* o : quantized pitch gain */ + float *gain_code, /* o : quantized codebook gain */ + float *gain_inov, /* o : gain of the innovation (used for normalization) */ + float *norm_gain_code, /* o : norm. gain of the codebook excitation */ + float *g_corr, /* i/o: correlations , -2,, -2 and 2 */ + float gains_mem[], /* i/o: pitch gain and code gain from previous subframes */ + const short clip_gain /* i : gain pitch clipping flag (1 = clipping) */ +); + +void gain_enc_mless( + Encoder_State *st, /* i/o: encoder state structure */ + const long core_brate, /* i : core bitrate */ + const short L_frame, /* i : length of the frame */ + const short coder_type, /* i : coding type */ + const short i_subfr, /* i : subframe index */ + const short tc_subfr, /* i : TC subframe index */ + const float *xn, /* i : target vector */ + const float *y1, /* i : zero-memory filtered adaptive excitation */ + const float *y2, /* i : zero-memory filtered algebraic codebook excitation */ + const float *code, /* i : algebraic excitation */ + const float Es_pred, /* i : predicted scaled innovation energy */ + float *gain_pit, /* o : quantized pitch gain */ + float *gain_code, /* o : quantized codebook gain */ + float *gain_inov, /* o : innovation gain */ + float *norm_gain_code, /* o : norm. gain of the codebook excitation */ + float *coeff, /* i/o: correlations , -2,, -2 and 2 */ + const short clip_gain /* i : gain pitch clipping flag (1 = clipping) */ +); + +void gain_enc_SQ( + Encoder_State *st, /* i/o: encoder state structure */ + const long core_brate, /* i : core bitrate */ + const short coder_type, /* i : coding type */ + const short i_subfr, /* i : subframe index */ + const short tc_subfr, /* i : TC subframe index */ + const float *xn, /* i : target vector */ + const float *yy1, /* i : zero-memory filtered adaptive excitation */ + const float *y2, /* i : zero-memory filtered algebraic codebook excitation */ + const float *code, /* i : algebraic excitation */ + const float Es_pred, /* i : predicted scaled innovation energy */ + float *gain_pit, /* o : quantized pitch gain */ + float *gain_code, /* o : quantized codebook gain */ + float *gain_inov, /* o : gain of the innovation (used for normalization) */ + float *norm_gain_code, /* o : norm. gain of the codebook excitation */ + float *g_corr, /* i/o: correlations , -2,, -2 and 2 */ + const short clip_gain /* i : gain pitch clipping flag (1 = clipping) */ +); + +short gain_enc_gaus( /* o : Return index of quantization */ + float *gain, /* i/o: Code gain to quantize */ + const short bits, /* i : number of bits to quantize */ + const float lowBound, /* i : lower bound of quantizer (dB) */ + const float topBound /* i : upper bound of quantizer (dB) */ +); + +void E_corr_xy2( + const float xn[], /* i : target vector */ + const float y1[], /* i : filtered excitation components 1 */ + const float y2[], /* i : filtered excitation components 2 */ + float g_corr[], /* o : correlations between x, y1, y2, y3, y4 */ + const short L_subfr /* i : subframe size */ +); + +float pit_encode( /* o : Floating pitch for each subframe */ + Encoder_State *st, /* i/o: encoder state structure */ + const long core_brate, /* i : core bitrate */ + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short L_frame, /* i : length of the frame */ + const short coder_type, /* i : coding type */ + short *limit_flag, /* i/o: restrained(0) or extended(1) Q limits */ + const short i_subfr, /* i : subframe index */ + float *exc, /* i/o: pointer to excitation signal frame */ + const short L_subfr, /* i : subframe length */ + const short *T_op, /* i : open loop pitch estimates in current frame */ + short *T0_min, /* i/o: lower limit for close-loop search */ + short *T0_max, /* i/o: higher limit for close-loop search */ + short *T0, /* i/o: close loop integer pitch */ + short *T0_frac, /* i/o: close loop fractional part of the pitch */ + const float *h1, /* i : weighted filter input response */ + const float *xn /* i : target vector */ +); + +short find_uv( /* o : coding type */ + Encoder_State *st, /* i/o: encoder state structure */ + const float *pitch_fr, /* i : pointer to adjusted fractional pitch (4 val.) */ + const float *voicing_fr, /* i : refined correlation for each subframes */ + const float *voicing, /* i : correlation for 3 half-frames */ + const float *speech, /* i : pointer to speech signal for E computation */ + const short localVAD, /* i : vad without hangover */ + const float *ee, /* i : lf/hf Energy ratio for present frame */ + const float corr_shift, /* i : normalized correlation correction in noise */ + const float relE, /* i : relative frame energy */ + const float Etot, /* i : total energy */ + const float hp_E[], /* i : energy in HF */ + short *flag_spitch, /* i/o: flag to indicate very short stable pitch and high correlation */ + float voicing_sm /* i/o: smoothed open-loop pitch gains */ + , const short last_core_orig /* i : original last core */ +); + +short signal_clas( /* o : classification for current frames */ + Encoder_State *st, /* i/o: encoder state structure */ + short *coder_type, /* i/o: coder type */ + const float voicing[3], /* i : normalized correlation for 3 half-frames */ + const float *speech, /* i : pointer to speech signal for E computation */ + const short localVAD, /* i : vad without hangover */ + const short pit[3], /* i : open loop pitch values for 3 half-frames */ + const float *ee, /* i : lf/hf E ration for 2 half-frames */ + const float relE, /* i : frame relative E to the long term average */ + const short L_look, /* i : look-ahead */ + short *uc_clas /* o : flag for unvoiced class used in sp/mus classifier */ +); + +void wb_vad_init( + short *nb_active_frames, /* o : nb of consecutive active speech frames */ + short *hangover_cnt, + float *lp_speech, /* o : long-term active speech level */ + short *nb_active_frames_he, /* o : nb of consecutive active speech frames */ + short *hangover_cnt_he, + float *bcg_flux, /* o : background noise fluctuation */ + short *soft_hangover, /* o : soft hangover counter */ + short *voiced_burst, /* o : consecutive voiced speech counter */ + short *bcg_flux_init, /* o : initialization period for noise fluctuation estimation */ + short *nb_active_frames_he1, /* o : nb of consecutive active speech frames 1 */ + short *hangover_cnt_he1, + long *vad_flag_reg_H, + long *vad_flag_reg_L, /* o : lower 31 bits */ + long *vad_prim_reg, + short *vad_flag_cnt_50, + short *vad_prim_cnt_16, + short *hangover_cnt_dtx, + short *flag_noisy_speech_snr + ,short *hangover_cnt_music /* o : counter of VAD DTX Music hangover frames */ +); + +short dtx_hangover_addition( + Encoder_State *st, /* i/o: encoder state structure */ + const short localVAD, /* i : Primary vad decision */ + const short vad_flag, + const float snr, /* i : input single SNR estimate */ + const short cldfb_subtraction, /* i : */ + short *vad_hover_flag +); + +short wb_vad( + Encoder_State *st, /* i/o: encoder state structure */ + const float fr_bands[], /* i : per band input energy (contains 2 vectors) */ + short *localVAD, + short *noisy_speech_HO, /* o : SC-VBR noisy speech HO flag */ + short *clean_speech_HO, /* o : SC-VBR clean speech HO flag */ + short *NB_speech_HO, /* o : SC-VBR NB speech HO flag */ + float *snr_sum_he, /* i : voicing metric from SAD */ + short *localVAD_HE_SAD, /* o : HE_SAD decision without hangovers */ + short *flag_noisy_speech_snr /* o : */ +); + +void bw_detect( + Encoder_State *st, /* i/o: Encoder State */ + const float signal_in[], /* i : input signal */ + const short localVAD, + float *enerBuffer +); + +float gaus_encode( + Encoder_State *st, /* i/o: encoder state structure */ + const short i_subfr, /* i : subframe index */ + const float *h1, /* i : weighted filter input response */ + const float *xn, /* i : target vector */ + float *exc, /* o : pointer to excitation signal frame */ + float *mem_w0, /* o : weighting filter denominator memory */ + float *gp_clip_mem, /* o : memory of gain of pitch clipping algorithm */ + float *tilt_code, /* o : synthesis excitation spectrum tilt */ + float *code, /* o : algebraic excitation */ + float *gain_code, /* o : Code gain. */ + float *y2, /* o : zero-memory filtered adaptive excitation */ + float *gain_inov, /* o : innovation gain */ + float *voice_fac, /* o : voicing factor */ + float *gain_pit, /* o : adaptive excitation gain */ + float *norm_gain_code, /* o : normalized innovative cb. gain */ + const long core_brate /* i : core bitrate */ +); + +void dtx( + Encoder_State *st, /* i/o: encoder state structure */ + const short vad, /* i : vad flag */ + const float speech[] /* i : Pointer to the speech frame */ +); + +void dtx_hangover_control( + Encoder_State *st, /* i/o: encoder state structure */ + const float lsp_new[M] /* i : current frame LSPs */ +); + +void updt_enc( + Encoder_State *st, /* i/o: state structure */ + const short L_frame, /* i : length of the frame */ + const short coder_type, /* i : coding type */ + const float *old_exc, /* i : buffer of excitation */ + const float *pitch_buf, /* i : Floating pitch for each subframe */ + const float Es_pred, /* i : predicited scaled innovation energy */ + const float *Aq, /* i : A(z) quantized for all subframes */ + const float *lsf_new, /* i : current frame LSF vector */ + const float *lsp_new, /* i : current frame LSP vector */ + const float *old_bwe_exc /* o : buffer of excitation for SWB TBE */ +); + +void updt_IO_switch_enc( + Encoder_State *st, /* i/o: state structure */ + const short input_frame /* i : input frame length */ +); + +void transition_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const long core_brate, /* i : core bitrate */ + const short L_frame, /* i : length of the frame */ + const short coder_type, /* i : coding type */ + const short i_subfr, /* i : subframe index */ + short *tc_subfr, /* i/o: TC subframe index */ + short *Jopt_flag, /* i : joint optimization flag */ + short *position, /* i/o: maximum of residual signal index */ + const float voicing[], /* i : normalized correlations (from OL pitch) */ + const short T_op[], /* i : open loop pitch estimates in current frame */ + short *T0, /* i/o: close loop integer pitch */ + short *T0_frac, /* i/o: close loop fractional part of the pitch */ + short *T0_min, /* i/o: lower limit for close-loop search */ + short *T0_max, /* i/o: higher limit for close-loop search */ + float *exc, /* i/o: pointer to excitation signal frame */ + float *y1, /* o : zero-memory filtered adaptive excitation */ + const float *res, /* i : pointer to the LP residual signal frame */ + const float *h1, /* i : weighted filter input response */ + const float *xn, /* i : target vector */ + float *xn2, /* o : target vector for innovation search */ + float *gp_cl, /* i/o: memory of gain of pitch clipping algorithm */ + float *gain_pit, /* o : adaptive excitation gain */ + float *g_corr, /* o : ACELP correlation values */ + short *clip_gain, /* i/o: adaptive gain clipping flag */ + float **pt_pitch, /* o: floating pitch values */ + float *bwe_exc /* i/o: excitation for SWB TBE */ +); + +void set_impulse( + const float xn[], /* i : target signal */ + const float h_orig[], /* i : impulse response of weighted synthesis filter */ + float exc[], /* o : adaptive codebook excitation */ + float y1[], /* o : filtered adaptive codebook excitation */ + short *imp_shape, /* o : adaptive codebook index */ + short *imp_pos, /* o : position of the glotal impulse center index */ + float *gain_trans /* o : transition gain */ +); + +void gain_enc_tc( + Encoder_State *st, /* i/o: encoder state structure */ + const long core_brate, /* i : core bitrate */ + const short L_frame, /* i : length of the frame */ + const short i_subfr, /* i : subframe index */ + const short tc_subfr, /* i : TC subframe index */ + const float xn[], /* i : target vector */ + const float y2[], /* i : zero-memory filtered algebraic codebook excitation */ + const float code[], /* i : algebraic excitation */ + const float Es_pred, /* i : predicted scaled innovation energy */ + float *gain_pit, /* o : pitch gain / Quantized pitch gain */ + float *gain_code, /* o : quantized codebook gain */ + float *gain_inov, /* o : innovation gain */ + float *norm_gain_code /* o : norm. gain of the codebook excitation */ +); + +float corr_xy1( /* o : pitch gain (0..GAIN_PIT_MAX) */ + const float xn[], /* i : target signal */ + const float y1[], /* i : filtered adaptive codebook excitation */ + float g_corr[], /* o : correlations and -2 */ + const short L_subfr, + const short norm_flag /* i : flag for constraining pitch contribution */ +); + +void norm_corr( + const float exc[], /* i : excitation buffer */ + const float xn[], /* i : target signal */ + const float h[], /* i : weighted synthesis filter impulse response */ + const short t_min, /* i : minimum value of searched range */ + const short t_max, /* i : maximum value of searched range */ + float corr_norm[], /* o : normalized correlation */ + const short L_subfr /* i : subframe size */ +); + +short pitch_fr4( /* o : chosen integer pitch lag */ + const float exc[], /* i : excitation buffer */ + const float xn[], /* i : target signal */ + const float h[], /* i : weighted synthesis filter impulse response */ + const short t0_min, /* i : minimum value in the searched range. */ + const short t0_max, /* i : maximum value in the searched range. */ + short *pit_frac, /* o : chosen fraction (0, 1, 2 or 3) */ + const short i_subfr, /* i : flag to first subframe */ + const short limit_flag, /* i : flag for limits (0=restrained, 1=extended) */ + const short t0_fr2, /* i : minimum value for resolution 1/2 */ + const short t0_fr1, /* i : minimum value for resolution 1 */ + const short L_frame, /* i : length of the frame */ + const short L_subfr /* i : size of subframe */ +); + +void pit_Q_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short nBits, /* i : # of Q bits */ + const short delta, /* i : Half the CL searched interval */ + const short pit_flag, /* i : absolute(0) or delta(1) pitch Q */ + const short limit_flag, /* i : restrained(0) or extended(1) Q limits */ + const short T0, /* i : integer pitch lag */ + const short T0_frac, /* i : pitch fraction */ + short *T0_min, /* i/o: delta search min */ + short *T0_max /* o : delta search max */ +); + +void pit16k_Q_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const short nBits, /* i : # of Q bits */ + const short limit_flag, /* i : restrained(0) or extended(1) Q limits */ + const short T0, /* i : integer pitch lag */ + const short T0_frac, /* i : pitch fraction */ + short *T0_min, /* i/o: delta search min */ + short *T0_max /* o : delta search max */ +); + +short abs_pit_enc( /* o : pitch index */ + const short fr_steps, /* i : fractional resolution step */ + const short limit_flag, /* i : restrained(0) or extended(1) limits */ + const short T0, /* i : integer pitch lag */ + const short T0_frac /* i : pitch fraction */ +); + +short delta_pit_enc( /* o : pitch index */ + const short fr_steps, /* i : fractional resolution steps (2 or 4) */ + const short T0, /* i : integer pitch lag */ + const short T0_frac, /* i : pitch fraction */ + const short T0_min /* i : delta search min */ +); + +float AVQ_cod( /* o: comfort noise gain factor */ + const float xri[], /* i: vector to quantize */ + int xriq[], /* o: quantized normalized vector (assuming the bit budget is enough) */ + const short nb_bits, /* i: number of allocated bits */ + const short Nsv /* i: number of subvectors (lg=Nsv*8) */ +); + +void AVQ_encmux( + Encoder_State *st, /* i/o: encoder state structure */ + const short extl, /* i : extension layer */ + int xriq[], /* i/o: rounded subvectors [0..8*Nsv-1] followed */ + /* by rounded bit allocations [8*Nsv..8*Nsv+Nsv-1] */ + short *nb_bits, /* i/o: number of allocated bits */ + const short Nsv, /* i: number of subvectors */ + short nq[] /* o : AVQ nq index */ +); + +void re8_cod( + int x[], /* i : point in RE8 (8-dimensional integer vector) */ + int *n, /* i : codebook number (*n is an integer defined in {0,2,3,4,..,n_max}) */ + long *I, /* o : index of c (pointer to unsigned 16-bit word) */ + int k[] /* o : index of v (8-dimensional vector of binary indices) = Voronoi index */ +); + +void pre_exc( + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short L_frame, /* i : frame length */ + const float *speech, /* i : input speech */ + const float *p_Aq, /* i : 12k8 Lp coefficient */ + const float *p_A, /* i : unquantized A(q) filter with bandwidth expansion */ + const short coder_type, /* i : coding type */ + const short i_subfr, /* i : current sub frame indicator */ + float *Ap, /* o : weighted LP filter coefficients */ + const float *res, /* i : residual signal */ + float *h1, /* o : impulse response of weighted synthesis filter */ + float *xn, /* o : close-loop Pitch search target vector */ + float *cn, /* o : target vector in residual domain */ + float *mem_syn, /* i/o: memory of the synthesis filter */ + float *mem_w0, /* i/o: weighting filter denominator memory */ + const short L_subfr /* i : subframe length */ +); + +void encod_unvoiced( + Encoder_State *st, /* i/o: state structure */ + LPD_state *mem, /* i/o: encoder memories */ + const float *speech, /* i : input speech */ + const float Aw[], /* i : weighted A(z) unquantized for subframes */ + const float *Aq, /* i : LP coefficients */ + const short vad_flag, + const float *res, /* i : residual signal */ + float *syn, /* o : core synthesis */ + float *tmp_noise, /* o : long-term noise energy */ + float *exc, /* i/o: current non-enhanced excitation */ + float *pitch_buf, /* o : floating pitch values for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *bwe_exc /* i/o: excitation for SWB TBE */ +); + +void encod_gen_voic( + Encoder_State *st, /* i/o: state structure */ + LPD_state *mem, /* i/o: encoder memories */ + const short L_frame, /* i : length of the frame */ + const short sharpFlag, /* i : formant sharpening flag */ + const float speech[], /* i : input speech */ + const float Aw[], /* i : weighted A(z) unquantized for subframes */ + const float Aq[], /* i : LP coefficients */ + const short coder_type, /* i : coding type */ + const float Es_pred, /* i : predicted scaled innov. energy */ + const short T_op[], /* i : open loop pitch */ + const float voicing[], /* i : voicing */ + const float *res, /* i : residual signal */ + float *syn, /* o : core synthesis */ + float *exc, /* i/o: current non-enhanced excitation */ + float *exc2, /* i/o: current enhanced excitation */ + float *pitch_buf, /* o : floating pitch values for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *bwe_exc, /* i/o: excitation for SWB TBE */ + short *unbits /* i/o: number of unused bits */ +); + +short encod_tran( + Encoder_State *st, /* i/o: state structure */ + LPD_state *mem, /* i/o: encoder memories */ + const short L_frame, /* i : length of the frame */ + const float speech[], /* i : input speech */ + const float Aw[], /* i : weighted A(z) unquantized for subframes */ + const float Aq[], /* i : LP coefficients */ + const short coder_type, /* i : coding type */ + const float Es_pred, /* i : predicted scaled innov. energy */ + const short T_op[], /* i : open loop pitch */ + const float voicing[], /* i : voicing */ + const float *res, /* i : residual signal */ + float *syn, /* o : synthesis */ + float *exc, /* i/o: current non-enhanced excitation */ + float *exc2, /* i/o: current enhanced excitation */ + float *pitch_buf, /* o : floating pitch values for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *bwe_exc, /* i/o: excitation for SWB TBE */ + const short attack_flag, /* i : Flag to indicate when attack is deal with TM */ + short *unbits, /* i/o: number of unused bits */ + const short sharpFlag /* i : formant sharpening flag */ +); + +void encod_amr_wb( + Encoder_State *st, /* i/o: state structure */ + LPD_state *mem, /* i/o: encoder state structure */ + const float speech[], /* i : input speech */ + const float Aw[], /* i : weighted A(z) unquantized for subframes */ + const float Aq[], /* i : 12k8 Lp coefficient */ + const short pitch[3], /* i : open-loop pitch values for quantiz. */ + const float voicing[], /* i : voicing */ + const float *res, /* i : residual signal */ + float *syn, /* i/o: core synthesis */ + float *exc, /* i/o: current non-enhanced excitation */ + float *exc2, /* i/o: current enhanced excitation */ + float *pitch_buf, /* i/o: floating pitch values for each subframe */ + short *hf_gain, /* o : decoded HF gain */ + const float *speech16k /* i : input speech @16kHz */ +); + +void stat_noise_uv_enc( + Encoder_State *st, /* i/o: state structure */ + const short coder_type, /* i : coding type */ + const float *epsP, /* i : LP prediction errors */ + float *lsp_new, /* i : end-frame LSP vector */ + float *lsp_mid, /* i : mid-frame LSP vector */ + float *Aq, /* i : A(z) quantized for the 4 subframes */ + float *exc2 /* i/o: excitation buffer */ +); + +void re8_compute_base_index( + const int *x, /* i : Elemen of Q2, Q3 or Q4 */ + const int ka, /* i : Identifier of the absolute leader related to x */ + long *I /* o : index */ +); + +void transf_cdbk_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const long core_brate, /* i : core bitrate */ + const short extl, /* i : extension layer */ + const short coder_type, /* i : coding type */ + const short harm_flag_acelp, /* i : harmonic flag for higher rates ACELP */ + const short i_subfr, /* i : subframe index */ + const short tc_subfr, /* i : TC subframe index */ + float cn[], /* i/o: target vector in residual domain */ + float exc[], /* i/o: pointer to excitation signal frame */ + const float *p_Aq, /* i : 12k8 Lp coefficient */ + const float Ap[], /* i : weighted LP filter coefficients */ + const float h1[], /* i : weighted filter input response */ + float xn[], /* i/o: target vector */ + float xn2[], /* i/o: target vector for innovation search */ + float y1[], /* i/o: zero-memory filtered adaptive excitation */ + const float y2[], /* i : zero-memory filtered innovative excitation */ + const float Es_pred, /* i : predicited scaled innovation energy */ + float *gain_pit, /* i/o: adaptive excitation gain */ + const float gain_code, /* i : innovative excitation gain */ + float g_corr[], /* o : ACELP correlation values */ + const short clip_gain, /* i : adaptive gain clipping flag */ + float *mem_deemp, /* i/o: prequantizer deemhasis memory */ + float *mem_preemp, /* i/o: prequantizer preemhasis memory */ + float *gain_preQ, /* o : prequantizer excitation gain */ + float code_preQ[], /* o : prequantizer excitation */ + short *unbits /* i/o: number of AVQ unused bits */ +); + +short gain_quant( /* o: quantization index */ + float *gain, /* i/o: quantized gain */ + const float min, /* i: value of lower limit */ + const float max, /* i: value of upper limit */ + const short bits /* i: number of bits to quantize */ +); + +void deemph_lpc( + float *p_Aq_cuerr, /* i : LP coefficients current frame */ + float *p_Aq_old, /* i : LP coefficients previous frame */ + float *LPC_de_curr, /* o : De-emphasized LP coefficients current frame */ + float *LPC_de_old /* o : De-emphasized LP coefficients previous frame */ + ,short deemph_old +); + +void Interpol_delay( + float *out, /* o : pitch interpolation output */ + float *last, /* i : last frame pitch lag */ + float *current, /* i : current frame pitch lag */ + short SubNum, /* i : subframe number */ + const float *frac /* i : interpolation constant */ +); + +float dequantize_uvg( + int iG1, /* i: gain 1 index */ + int *iG2, /* i: gain 2 index */ + float *G, /* o: quantized gain */ + short bwidth +); + +void generate_nelp_excitation( + short *seed, /* i/o: random number seed */ + float *Gains, /* i : excitation gains */ + float *output, /* o : excitation output */ + float gain_fac /* i : gain factor */ +); + +void nelp_encoder( + Encoder_State *st, /* i/o: encoder state */ + float *in, /* i : residual signal */ + float *exc /* o : NELP quantized excitation signal */ + ,short reduce_gains +); + +void encod_nelp( + Encoder_State *st, /* i/o: state structure */ + LPD_state *mem, /* i/o: encoder memories */ + const float *speech, /* i : input speech */ + const float Aw[], /* i : weighted A(z) unquantized for subframes */ + const float *Aq, /* i : 12k8 Lp coefficient */ + float *res, /* o : residual signal */ + float *synth, /* o : core synthesis */ + float *tmp_noise, /* o : long-term noise energy */ + float *exc, /* i/o: current non-enhanced excitation */ + float *exc2, /* i/o: current enhanced excitation */ + float *pitch_buf, /* o : floating pitch values for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *bwe_exc /* o : excitation for SWB TBE */ +); + +void realft( + float *data, /* i/o: data array .......... */ + short n, /* i : length of data array */ + short isign /* i : sign +1 or -1 */ +); + +DTFS_STRUCTURE *DTFS_new( + void +); + +void DTFS_copy( + DTFS_STRUCTURE *Xout, /* o: DTFS */ + DTFS_STRUCTURE Xinp /* i: DTFS */ +); + +DTFS_STRUCTURE DTFS_sub( + DTFS_STRUCTURE X1, /* i: X1 DTFS */ + DTFS_STRUCTURE X2 /* i: X2 DTFS */ + /* o: X1 - X2 */ +); + +void DTFS_to_fs( + const float *x, /* i: Time domain signal */ + int N, /* i: Length of input vector */ + DTFS_STRUCTURE *X, /* o: DTFS structure with a, b, lag */ + short Fs, + short FR_flag /* i: FR flag */ +); + +void DTFS_fs_inv( + DTFS_STRUCTURE *X, /* i : DTFS */ + float *x, /* o : time domain sig */ + int N, /* i : Output length */ + float ph0 /* i : Input phase */ +); + +void DTFS_fast_fs_inv( + DTFS_STRUCTURE *X1_DTFS, /* i : X1 DTFS */ + float *out, /* o : time domain */ + int N /* i : Number of output samples */ +); + +void DTFS_car2pol( + DTFS_STRUCTURE *X /* i/o : DTFS structure a, b, lag */ + /* input in Cartesion, output in Polar */ +); + +void DTFS_pol2car( + DTFS_STRUCTURE *X /* i/o : DTFS structure a, b, lag */ + /* input in Polar, output in Cartesian */ +); + +float DTFS_setEngyHarm( + float f1, /* i : lower band freq of input to control energy */ + float f2, /* i : upper band freq of input to control energy */ + float g1, /* i : lower band freq of output to control energy */ + float g2, /* i : upper band freq of output to control energy */ + float en2, /* i : Target Energy to set the DTFS to */ + DTFS_STRUCTURE *X /* i/o: DTFS to adjust the energy of */ + /* o : Return Input RMS between f1/f2 b4 scaling */ +); + +void DTFS_to_erb( + DTFS_STRUCTURE X, /* i : DTFS input */ + float *out /* o : ERB output */ +); + +void DTFS_zeroPadd( + int N, /* i : Target lag */ + DTFS_STRUCTURE *X /* i/o: DTFS */ +); + +float DTFS_getEngy( + DTFS_STRUCTURE X /* i : DTFS to compute energy of */ + /* o : Energy */ +); + +float DTFS_getEngy_band( + DTFS_STRUCTURE X, /* i : DTFS to compute energy of */ + float lband, /* i : low end of band of interest */ + float hband /* i : high end of band of interest */ +); + +float DTFS_getEngy_band_wb( + DTFS_STRUCTURE X, /* i : DTFS to compute energy of */ + float lband, /* i : low end of band of interest */ + float hband /* i : high end of band of interest */ +); + +double DTFS_freq_corr( + DTFS_STRUCTURE X1, /* i : X1 DTFS */ + DTFS_STRUCTURE X2, /* i : X2 DTFS */ + float lband, /* i : low cutoff */ + float hband /* i : high cutoff */ + /* o : Correlation */ +); + +float DTFS_setEngy( + DTFS_STRUCTURE *X_DTFS, /* i/o: DTFS structure to set engy */ + float en2 /* i : Energy to set to */ +); + +void DTFS_adjustLag( + DTFS_STRUCTURE *X_DTFS, /* i/o: DTFS to adjust lag for */ + int N /* i : Target lag */ +); + +void DTFS_poleFilter( + DTFS_STRUCTURE *X, /* i/o: DTFS to poleFilter inplace */ + const float *LPC, /* i : LPCs */ + int N /* i : LPCORDER */ +); + +void DTFS_zeroFilter( + DTFS_STRUCTURE *X, /* i/o: DTFS to zeroFilter inplace */ + const float *LPC, /* i : LPCs */ + int N /* i : LPCORDER */ +); + +float DTFS_alignment_full( + DTFS_STRUCTURE X1_DTFS, /* i : reference DTFS */ + DTFS_STRUCTURE X2_DTFS, /* i : DTFS to shift */ + int num_steps /* i : resolution */ +); + +float DTFS_alignment_extract( + DTFS_STRUCTURE refX1_DTFS, /* i : X1 the reference DTFS to keep fixed */ + DTFS_STRUCTURE X2_DTFS, /* i : X2 the test DTFS to shift to find best match */ + float Eshift, /* i : Expected shift - coarse value */ + const float *LPC2 /* i : LPC to filter to find correlation in speech */ + /* o : shift value to shift X2 by */ +); + +float DTFS_alignment_weight( + DTFS_STRUCTURE refX1_DTFS, /* i : X1 the reference DTFS to keep fixed */ + DTFS_STRUCTURE X2_DTFS, /* i : X2 the test DTFS to shift to find best match */ + float Eshift, /* i : Expected shift - coarse value */ + const float *LPC1, /* i : LPC to filter to find correlation in spch */ + const float *LPC2 /* i : LPC to filter to find correlation in spch */ + /* o : shift value to shift X2 by */ +); + +float DTFS_alignment_fine_new( + DTFS_STRUCTURE X1_DTFS, /* i : X1 the reference DTFS to keep fixed */ + DTFS_STRUCTURE X2_DTFS, /* i : X2 the test DTFS to shift to find best match */ + float Eshift /* i : Expected shift - coarse value */ + /* o : shift value to shift X2 by */ +); + +void DTFS_phaseShift( + DTFS_STRUCTURE *X, /* i : DTFS to shift */ + float ph /* i : phase to shift */ +); + +void DTFS_erb_inv( + float *in, /* i : ERB inpt */ + int *slot, /* i : ERB slots filled based on lag */ + float *mfreq, /* i : erb frequence edges */ + DTFS_STRUCTURE * X, /* o : DTFS after erb-inv */ + short num_erb /* i : Number of ERB bands */ +); + +short DTFS_quant_cw( + DTFS_STRUCTURE *X, /* i/o: DTFS unquant inp, quant out */ + int pl, /* i : Previous lag */ + const float *curr_lpc, /* i : LPC */ + int *POWER_IDX, /* o : Power index */ + int *AMP_IDX, /* o : Amplitude index */ + float *lastLgainE, /* i/o: last frame lowband gain */ + float *lastHgainE, /* i/o: last frame highband gain */ + float *lasterbE /* i/o: last frame ERB vector */ + /* Flag - amp quant performance pass/fail */ +); + +void DTFS_dequant_cw( + int pl, /* i : Previous lag */ + int POWER_IDX, /* i : POWER index */ + const int *AMP_IDX, /* i : Amp Shape index */ + float *lastLgainD, /* i/o: low band last gain */ + float *lastHgainD, /* i/o: high band last gain */ + float *lasterbD, /* i/o: last frame ERB vector */ + DTFS_STRUCTURE *X, /* o : DTFS structure dequantized */ + short num_erb /* i : Number of ERB bands */ +); + +void DTFS_transform( + DTFS_STRUCTURE X, /* i : Starting DTFS to use in WI */ + DTFS_STRUCTURE X2, /* i : Ending DTFS to use in WI */ + const float *phase, /* i : Phase contour */ + float *out, /* o : Output time domain waveform */ + int N, /* i : Number of samples to generate */ + short FR_flag /* i : Flag to indicate called in FR context */ +); + +float DTFS_getSpEngyFromResAmp( + DTFS_STRUCTURE X, /* i : DTFS */ + float lband, /* i : Low band end to get energy from */ + float hband, /* i : High band end to get energy from */ + const float *curr_lsp /* i : LPCs */ + /* o : speech energy */ +); + +void DTFS_peaktoaverage( + DTFS_STRUCTURE X, /* i : DTFS */ + float *pos, /* o : positive peak to ave */ + float *neg /* o : negative peak to ave */ +); + +short ppp_extract_pitch_period( + const float *in, /* i : input residual */ + float *out, /* o : output residual */ + int l, /* i : lag */ + short *out_of_bound /* o : out of bound flag */ +); + +short ppp_quarter_encoder( + Encoder_State *st, /* i/o: encoder state structure */ + DTFS_STRUCTURE *CURRCW_Q, /* o : Quantized (amp/phase) DTFS */ + DTFS_STRUCTURE *TARGETCW, /* o : DTFS with quant phase but unquant Amp */ + int prevCW_lag, /* i : previous lag */ + DTFS_STRUCTURE vCURRCW_NQ, /* i : Unquantized DTFS */ + const float *curr_lpc, /* i : LPCS */ + float *lastLgainE, /* i/o: last low band gain */ + float *lastHgainE, /* i/o: last high band gain */ + float *lasterbE, /* i/o: last ERB vector */ + DTFS_STRUCTURE PREV_CW_E /* i : past DTFS */ +); + +void WIsyn( + DTFS_STRUCTURE PREVCW, /* i : Prev frame DTFS */ + DTFS_STRUCTURE *CURR_CW_DTFS, /* i/o: Curr frame DTFS */ + const float *curr_lpc, /* i : LPC */ + float *ph_offset, /* i/o: Phase offset to line up at end of frame */ + float *out, /* o : Waveform Interpolated time domain signal */ + int N, /* i : Number of samples of output to generate */ + int FR_flag /* i : called for post-smoothing in FR */ +); + +void set_ppp_mode( + Encoder_State *st, /* i/o: encoder state structure */ + short *coder_type, /* i/o: coder type */ + const short noisy_speech_HO, /* i : SC-VBR noisy speech HO flag */ + const short clean_speech_HO, /* i : SC-VBR clean speech HO flag */ + const short NB_speech_HO, /* i : SC-VBR NB speech HO flag */ + const short localVAD, + const short localVAD_he, /* i : HE-SAD flag without hangover */ + short *vad_flag, + short T_op[], /* i :open loop pitch lag */ + short sp_aud_decision1 /* i : Speech Audio Decision */ +); + +void lsf_syn_mem_backup( + Encoder_State *st, /* i: state structure */ + LPD_state* LPDmem, /* i: LPD state memory structure */ + float *btilt_code, /* i: tilt code */ + float *bgc_threshold, /* i: */ + float *clip_var_bck, /* o: */ + short *next_force_sf_bck, /* o: */ + float *lsp_new, /* i: LSP vector to quantize */ + float *lsp_mid, /* i: mid-frame LSP vector */ + float *clip_var, /* o: pitch clipping state var */ + float *mem_AR, /* o: quantizer memory for AR model */ + float *mem_MA, /* o: quantizer memory for AR model */ + float *lsp_new_bck, /* o: LSP vector to quantize- backup */ + float *lsp_mid_bck, /* o: mid-frame LSP vector - backup */ + short *mCb1, /* o: counter for stationary frame after a transition frame */ + float *Bin_E, /* o: FFT Bin energy 128 *2 sets */ + float *Bin_E_old, /* o: FFT Bin energy 128 sets */ + float *mem_syn_bck, /* o: synthesis filter memory */ + float *mem_w0_bck, /* o: memory of the weighting filter */ + float *streaklimit, + short *pstreaklen +); + +void lsf_syn_mem_restore( + Encoder_State *st, /* o: state structure */ + LPD_state* LPDmem, /* o: LPD_state vewctor */ + float btilt_code, /* i: */ + float gc_threshold, /* i: */ + float *clip_var_bck, /* i: */ + short next_force_sf_bck, /* i: */ + float *lsp_new, /* o: LSP vector to quantize */ + float *lsp_mid, /* o: mid-frame LSP vector */ + float clip_var, /* i: pitch clipping state var */ + float *mem_AR, /* i: quantizer memory for AR model */ + float *mem_MA, /* i: quantizer memory for AR model */ + float *lsp_new_bck, /* i: LSP vector to quantize- backup */ + float *lsp_mid_bck, /* i: mid-frame LSP vector - backup */ + short mCb1, /* i: counter for stationary frame after a transition frame */ + float *Bin_E, /* i: FFT Bin energy 128 *2 sets */ + float *Bin_E_old, /* i: FFT Bin energy 128 sets */ + float *mem_syn_bck, /* i: synthesis filter memory */ + float mem_w0_bck, /* i: memory of the weighting filter */ + float streaklimit, + short pstreaklen +); +void ppp_voiced_encoder( + Encoder_State *st, /* i/o: state structure */ + float *in, /* i : residual signal */ + float *out, /* o : Quantized residual signal */ + short delay, /* i : open loop pitch */ + float *lpc1, /* i : prev frame de-emphasized LPC */ + float *lpc2, /* i : current frame de-emphasized LPC */ + float *exc, /* i : previous frame quantized excitation */ + float *pitch, /* o : floating pitch values for each subframe */ + float vadsnr /* i : current frame SNR */ +); + +void encod_ppp( + Encoder_State *st, /* i/o: state structure */ + LPD_state *mem, /* i/o: encoder memories */ + const float speech[], /* i : input speech */ + const float Aw[], /* i : weighted A(z) unquantized for subframes */ + const float Aq[], /* i : 12k8 Lp coefficient */ + short *coder_type, /* i/o: coding type */ + const short sharpFlag, /* i : formant sharpening flag */ + const short T_op[], /* i : open loop pitch */ + const float voicing[], /* i : voicing */ + float *res, /* i/o: residual signal */ + float *synth, /* i/o: core synthesis */ + float *exc, /* i/o: current non-enhanced excitation */ + float *exc2, /* i/o: current enhanced excitation */ + float *pitch_buf, /* i/o: floating pitch values for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *bwe_exc /* o : excitation for SWB TBE */ +); + +void reset_rf_indices( + Encoder_State *st /* i: state structure - contains partial RF indices */ +); + +void signalling_enc_rf( + Encoder_State *st /* i/o: encoder state structure */ +); + +void acelp_core_dec( + Decoder_State *st, /* i/o: Decoder state structure */ + float synth_out[], /* o : synthesis */ + float bwe_exc_extended[], /* i/o: bandwidth extended excitation */ + float *voice_factors, /* o : voicing factors */ + float old_syn_12k8_16k[], /* o : intermediate ACELP synthesis at 12.8kHz or 16kHz to be used by SWB BWE */ + short coder_type, /* i : coder type */ + short sharpFlag, /* i : formant sharpening flag */ + float pitch_buf[NB_SUBFR16k], /* o : floating pitch for each subframe */ + short *unbits, /* o : number of unused bits */ + short *sid_bw /* o : 0-NB/WB, 1-SWB SID */ +); + +void bass_psfilter_init( + float old_syn[], /* o : Old synthesis buffer 1 */ + float *mem_deemph_err, /* o : Error deemphasis memory */ + float *lp_ener /* o : long_term error signal energy */ +); + +void bass_psfilter( + const short Opt_AMR_WB, /* i : AMR-WB IO flag */ + const float synth_in[], /* i : synthesis (at 16kHz) */ + const short L_frame, /* i : length of the last frame */ + const float pitch_buf[], /* i : pitch for every subfr [0,1,2,3] */ + float old_syn[], /* i/o: NBPSF_PIT_MAX */ + float *mem_deemph_err, /* o : Error deemphasis memory */ + float *lp_ener, /* o : long_term error signal energy */ + const short bpf_off, /* i : do not use BPF when set to 1 */ + float v_stab, /* i : stability factor */ + float *v_stab_smooth, /* i : smoothed stability factor */ + float *mem_mean_pit, /* i/o: average pitch memory */ + short *Track_on_hist, /* i/o: History of half frame usage */ + short *vibrato_hist, /* i/o: History of frames declared as vibrato*/ + float *psf_att, /* i/o: Post filter attenuation factor */ + const short coder_type, /* i : coder_type */ + float bpf_noise_buf[] /* o : BPF error signal (at int_fs) */ +); + +void CNG_reset_dec( + Decoder_State *st, /* i/o: decoder state structure */ + float *pitch_buf, /* o : floating pitch for each subframe */ + float *voice_factors /* o : voicing factors */ +); + +void updt_dec( + Decoder_State *st, /* i/o: state structure */ + const short L_frame, /* i : length of the frame */ + const short coder_type, /* i : coding type */ + const float *old_exc, /* i : buffer of excitation */ + const float *pitch_buf, /* i : floating pitch values for each subframe */ + const float Es_pred, /* i : predicited scaled innovation energy */ + const float *Aq, /* i : A(z) quantized for all subframes */ + const float *lsf_new, /* i : current frame LSF vector */ + const float *lsp_new, /* i : current frame LSP vector */ + const float voice_factors[], /* i : voicing factors */ + const float *old_bwe_exc, /* i : buffer of excitation */ + const float *gain_buf +); + +void updt_IO_switch_dec( + const short output_frame, /* i : output frame length */ + Decoder_State *st /* i/o: state structure */ +); + +void updt_dec_common( + Decoder_State *st, /* i/o: decoder state structure */ + const short hq_core_type, /* i : HQ core type */ + const float *synth /* i : decoded synthesis */ +); + +void CNG_dec( + Decoder_State *st, /* i/o: State structure */ + const short L_frame, /* i : length of the frame */ + float Aq[], /* o : LP coefficients */ + const long core_brate, /* i : core bitrate */ + float *lsp_new, /* i/o: current frame LSPs */ + float *lsf_new, /* i/o: current frame LSFs */ + short *allow_cn_step, /* o : allow cn step */ + short *sid_bw, /* o : 0-NB/WB, 1-SWB SID */ + float *q_env +); + +void swb_CNG_dec( + Decoder_State *st, /* i/o: State structure */ + const float *synth, /* i : ACELP core synthesis at 32kHz */ + float *shb_synth, /* o : high-band CNG synthesis */ + const short sid_bw /* i : 0-NB/WB, 1-SWB SID */ +); + +void lsf_dec( + Decoder_State *st, /* i/o: State structure */ + const short tc_subfr, /* i : TC subframe index */ + const short L_frame, /* i : length of the frame */ + const short coder_type, /* i : coding type */ + const short bwidth, /* i : input signal bandwidth */ + float *Aq, /* o : quantized A(z) for 4 subframes */ + short *LSF_Q_prediction, /* o : LSF prediction mode */ + float *lsf_new, /* o : de-quantized LSF vector */ + float *lsp_new, /* o : de-quantized LSP vector */ + float *lsp_mid /* o : de-quantized mid-frame LSP vector */ +); + +void isf_dec_amr_wb( + Decoder_State *st, /* i/o: State structure */ + float *Aq, /* o : quantized A(z) for 4 subframes */ + float *isf_new, /* o : de-quantized ISF vector */ + float *isp_new /* o : de-quantized ISP vector */ +); + +void Es_pred_dec( + float *Es_pred, /* o : predicited scaled innovation energy */ + const int enr_idx, /* i : indice */ + const short nb_bits, /* i : number of bits */ + const short no_ltp /* i : no LTP flag */ +); + +void gaus_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : core bitrate */ + const short i_subfr, /* i : subframe index */ + float *code, /* o : gaussian excitation */ + float *norm_gain_code, /* o : gain of the normalized gaussian excitation */ + float *lp_gainp, /* i/o: lp filtered pitch gain(FER) */ + float *lp_gainc, /* i/o: lp filtered code gain (FER) */ + float *gain_inov, /* o : unscaled innovation gain */ + float *tilt_code, /* o : synthesis excitation spectrum tilt */ + float *voice_fac, /* o : estimated voicing factor */ + float *gain_pit, /* o : reset pitch gain */ + float *pt_pitch, /* o : reset floating pitch buffer */ + float *exc, /* o : excitation signal frame */ + float *gain_code, /* o : gain of the gaussian excitation */ + float *exc2 /* o : scaled excitation signal frame */ +); + +void gain_dec_amr_wb( + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : core bitrate */ + float *gain_pit, /* o : Quantized pitch gain */ + float *gain_code, /* o : Quantized codeebook gain */ + float *past_qua_en, /* i/o: gain quantization memory (4 words) */ + float *gain_inov, /* o : unscaled innovation gain */ + const float *code, /* i : algebraic code excitation */ + float *norm_gain_code /* o : norm. gain of the codebook excitation */ +); + +void gain_dec_lbr( + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : core bitrate */ + const short coder_type, /* i : coding type */ + const short i_subfr, /* i : subframe index */ + const float *code, /* i : algebraic excitation */ + float *gain_pit, /* o : quantized pitch gain */ + float *gain_code, /* o : quantized codebook gain */ + float *gain_inov, /* o : gain of the innovation (used for normalization) */ + float *norm_gain_code, /* o : norm. gain of the codebook excitation */ + float gains_mem[] /* i/o: pitch gain and code gain from previous subframes */ +); + +void gain_dec_mless( + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : core bitrate */ + const short L_frame, /* i : length of the frame */ + const short coder_type, /* i : coding type */ + const short i_subfr, /* i : subframe number */ + const short tc_subfr, /* i : TC subframe index */ + const float *code, /* i : algebraic code excitation */ + const float Es_pred, /* i : predicted scaled innov. energy */ + float *gain_pit, /* o : Quantized pitch gain */ + float *gain_code, /* o : Quantized codeebook gain */ + float *gain_inov, /* o : unscaled innovation gain */ + float *norm_gain_code /* o : norm. gain of the codebook excitation */ +); + +void gain_dec_SQ( + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : core bitrate */ + const short coder_type, /* i : coding type */ + const short i_subfr, /* i : subframe number */ + const short tc_subfr, /* i : TC subframe index */ + const float *code, /* i : algebraic code excitation */ + const float Es_pred, /* i : predicted scaled innov. energy */ + float *gain_pit, /* o : Quantized pitch gain */ + float *gain_code, /* o : Quantized codeebook gain */ + float *gain_inov, /* o : unscaled innovation gain */ + float *norm_gain_code /* o : norm. gain of the codebook excitation */ +); + +float gain_dec_gaus( /* o : quantized codebook gain */ + const short index, /* i : quantization index */ + const short bits, /* i : number of bits to quantize */ + const float lowBound, /* i : lower bound of quantizer (dB) */ + const float topBound, /* i : upper bound of quantizer (dB) */ + const float gain_inov, /* i : unscaled innovation gain */ + float *norm_gain_code /* o : gain of normalized gaus. excit. */ +); + +float pit_decode( /* o : floating pitch value */ + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : core bitrate */ + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short L_frame, /* i : length of the frame */ + short i_subfr, /* i : subframe index */ + const short coder_type, /* i : coding type */ + short *limit_flag, /* i/o: restrained(0) or extended(1) Q limits */ + short *T0, /* o : close loop integer pitch */ + short *T0_frac, /* o : close loop fractional part of the pitch */ + short *T0_min, /* i/o: delta search min for sf 2 & 4 */ + short *T0_max, /* i/o: delta search max for sf 2 & 4 */ + const short L_subfr /* i : subframe length */ +); + +void abs_pit_dec( + const short fr_steps, /* i : fractional resolution steps (0, 2, 4) */ + short pitch_index, /* i : pitch index */ + const short limit_flag, /* i : restrained(0) or extended(1) Q limits */ + short *T0, /* o : integer pitch lag */ + short *T0_frac /* o : pitch fraction */ +); + +void delta_pit_dec( + const short fr_steps, /* i : fractional resolution steps (0, 2, 4) */ + const short pitch_index, /* i : pitch index */ + short *T0, /* o : integer pitch lag */ + short *T0_frac, /* o : pitch fraction */ + const short T0_min /* i : delta search min */ +); + +void pit_Q_dec( + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short pitch_index, /* i : pitch index */ + const short nBits, /* i : # of Q bits */ + const short delta, /* i : Half the CL searched interval */ + const short pit_flag, /* i : absolute(0) or delta(1) pitch Q */ + const short limit_flag, /* i : restrained(0) or extended(1) Q limits */ + short *T0, /* o : integer pitch lag */ + short *T0_frac, /* o : pitch fraction */ + short *T0_min, /* i/o: delta search min */ + short *T0_max /* i/o: delta search max */ + ,short *BER_detect /* o : BER detect flag */ +); + +void pit16k_Q_dec( + const short pitch_index, /* i : pitch index */ + const short nBits, /* i : # of Q bits */ + const short limit_flag, /* i : restrained(0) or extended(1) Q limits */ + short *T0, /* o : integer pitch lag */ + short *T0_frac, /* o : pitch fraction */ + short *T0_min, /* i/o: delta search min */ + short *T0_max /* i/o: delta search max */ + ,short *BER_detect /* o : BER detect flag */ +); + +void lp_filt_exc_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const short codec_mode, /* i : codec mode */ + const long core_brate, /* i : core bitrate */ + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short coder_type, /* i : coding type */ + const short i_subfr, /* i : subframe index */ + const short L_subfr, /* i : subframe size */ + const short L_Frame, /* i : frame size */ + short lp_flag, /* i : operation mode signalling */ + float *exc /* i/o: pointer to the excitation signal frame */ +); + +void inov_decode( + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : core bitrate */ + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short L_frame, /* i : length of the frame */ + const short coder_type, /* i : coding type */ + const short sharpFlag, /* i : formant sharpening flag */ + const short i_subfr, /* i : subframe index */ + const short tc_subfr, /* i : TC subframe index */ + const float *p_Aq, /* i : LP filter coefficients */ + const float tilt_code, /* i : tilt of of the excitation of previous subframe */ + const float pt_pitch, /* i : pointer to current subframe fractional pitch */ + float *code /* o : algebraic excitation */ +); + +void dec_acelp_1t64( + Decoder_State *st, /* i/o: decoder state structure */ + float code[] /* o : algebraic (fixed) codebook excitation */ +); + +void dec_acelp_2t32( + Decoder_State *st, /* i/o: decoder state structure */ + float code[] /* o : algebraic (fixed) codebook excitation */ +); + +void dec_acelp_4t64( + Decoder_State *st, /* i/o: decoder state structure */ + short nbbits, /* i : number of bits per codebook */ + float code[], /* o : algebraic (fixed) codebook excitation */ + const short Opt_AMR_WB /* i : flag indicating AMR-WB IO mode */ +); + +unsigned int syn_output( + float *synth, /* i/o: float synthesis signal */ + const short output_frame, /* i : output frame length */ + short *synth_out /* o : integer 16 bits synthesis signal */ +); + +void FEC_exc_estim( + Decoder_State *st, /* i/o: Decoder static memory */ + const short L_frame, /* i : length of the frame */ + float *old_exc, /* i/o: excitation buffer */ + float *exc2, /* o : excitation buffer (for synthesis) */ + float *exc_dct_in, /* o : GSC excitation in DCT domain */ + float *pitch_buf, /* o : Floating pitch for each subframe */ + float *tmp_tc, /* o : FEC pitch */ + float *voice_factors, /* o : voicing factors */ + float *bwe_exc, /* i/o: excitation for SWB TBE */ + float *lsf_new, /* i : ISFs at the end of the frame */ + float *tmp_noise /* o : long-term noise energy */ +); + +void FEC_lsf2lsp_interp( + Decoder_State *st, /* i/o: Decoder static memory */ + const short L_frame, /* i : length of the frame */ + float *Aq, /* o : calculated A(z) for 4 subframes */ + float *lsf, /* o : estimated LSF vector */ + float *lsp /* o : estimated LSP vector */ +); + +void FEC_lsf_estim_enc( + Encoder_State *st, /* i : Encoder static memory */ + const short L_frame, /* i : length of the frame */ + float *lsf /* o : estimated LSF vector */ +); + +float frame_energy( + const short L_frame, /* i : length of the frame */ + const float *pitch, /* i : pitch values for each subframe */ + const float *speech, /* i : pointer to speech signal for E computation */ + const float lp_speech, /* i : long term active speech energy average */ + float *frame_ener /* o : pitch-synchronous energy at frame end */ +); + +void FEC_SinOnset( + float *exc, /* i/o : exc vector to modify */ + short puls_pos, /* i : Last pulse position desired */ + short T0, /* i : decoded first frame pitch */ + float enr_q, /* i : energy provide by the encoder */ + float *Aq, /* i : Lsp coefficient */ + const short L_frame /* i : Frame lenght */ +); + +short FEC_enhACB( + const short L_frame, /* i : Frame lenght */ + const short last_L_frame, /* i : frame length of last frame */ + float *exc_io, /* i/o : Adaptive codebook memory */ + const short new_pit, /* i : decoded first frame pitch */ + const short puls_pos, /* i : decoder position of the last glottal pulses decoded in the previous frame */ + const float bfi_pitch /* i : Pitch used for concealment */ +); + +void FEC_scale_syn( + const short L_frame, /* i : length of the frame */ + short clas, /* i/o: frame classification */ + const short last_good, /* i : last good frame classification */ + float *synth, /* i/o: synthesized speech at Fs = 12k8 Hz */ + const float *pitch, /* i : pitch values for each subframe */ + float enr_old, /* i : energy at the end of prvious frame */ + float enr_q, /* i : transmitted energy for current frame */ + const short coder_type, /* i : coding type */ + const short LSF_Q_prediction, /* i : LSF prediction mode */ + short *scaling_flag, /* i/o: flag to indicate energy control of syn */ + float *lp_ener_FEC_av, /* i/o: averaged voiced signal energy */ + float *lp_ener_FEC_max, /* i/o: averaged voiced signal energy */ + const short bfi, /* i: current frame BFI */ + const long total_brate, /* i: total bitrate */ + const short prev_bfi, /* i : previous frame BFI */ + const long last_core_brate, /* i : previous frame core bitrate */ + float *exc, /* i/o: excitation signal without enhancement */ + float *exc2, /* i/o: excitation signal with enhancement */ + const float Aq[], /* i : LP filter coefs */ + float *old_enr_LP, /* i/o: LP filter E of last good voiced frame */ + const float *mem_tmp, /* i : temp. initial synthesis filter states */ + float *mem_syn /* o : initial synthesis filter states */ + , int avoid_lpc_burst_on_recovery /* i : if true the excitation energy is limited if LP has big gain */ + , short force_scaling /* i: force scaling */ +); + +void FEC_pitch_estim( + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short last_core, /* i : last core */ + const short L_frame, /* i : length of the frame */ + const short clas, /* i : current frame classification */ + const short last_good, /* i : last good clas information */ + const float pitch_buf[], /* i : Floating pitch for each subframe */ + const float old_pitch_buf[], /* i : buffer of old subframe pitch values */ + float *bfi_pitch, /* i/o: update of the estimated pitch for FEC */ + short *bfi_pitch_frame, /* o : frame length when pitch was updated */ + short *upd_cnt, /* i/o: update counter */ + const short coder_type +); + +void FEC_encode( + Encoder_State *st, /* i/o: encoder state structure */ + const float *synth, /* i : pointer to synthesized speech for E computation */ + const short coder_type, /* i : type of coder */ + short clas, /* i : signal clas for current frame */ + const float *fpit, /* i : close loop fractional pitch buffer */ + const float *res, /* i : LP residual signal frame */ + short *last_pulse_pos, /* i/o: Position of the last pulse */ + const short L_frame, /* i : Frame length */ + const long total_brate, /* i : total codec bitrate */ + const long core_brate /* i : core codec bitrate */ +); + +short FEC_pos_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const short coder_type, /* i : coder type */ + const short last_good, /* i : Last good classfication */ + short *last_pulse_pos, /* o : Last glotal pulse position in the lost ACB */ + short *clas, /* o : Decoded classification */ + float *enr_q, /* o : Decoded energy */ + const long core_brate /* i : Decoded bitrate */ +); + +void improv_amr_wb_gs( + const short clas, /* i : bitrate allocated to the core */ + const short coder_type, /* i : coder_type */ + const long core_brate, /* i : bitrate allocated to the core */ + short *seed_tcx, /* i/o: Seed used for noise generation */ + float *old_Aq, /* i/o: old LPC filter coefficient */ + float *mem_syn2, /* i/o: synthesis memory */ + const float lt_voice_fac, /* i/o: long term voice factor */ + const short locattack, /* i : Flag for a detected attack */ + float *Aq, /* i/o: Decoded LP filter coefficient */ + float *exc2, /* i/o: Decoded complete excitation */ + float *mem_tmp, /* i/o: synthesis temporary memory */ + float *syn, /* i/o: Decoded synthesis to be updated */ + const float *pitch_buf, /* i : Decoded pitch buffer */ + const float Last_ener /* i : Last energy */ + ,const short rate_switching_reset /* i : rate switching reset flag */ + ,const short last_coder_type /* i : Last coder_type */ +); + +short tc_classif( + Decoder_State *st, /* i/o: decoder state structure */ + const short L_frame /* i : length of the frame */ +); + +void transition_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : core bitrate */ + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short L_frame, /* i : length of the frame */ + const short i_subfr, /* i : subframe index */ + const short coder_type, /* i : coding type */ + const short tc_subfr, /* i : TC subframe index */ + short *Jopt_flag, /* i : joint optimization flag */ + float *exc, /* i/o: current frame excitation signal */ + short *T0, /* o : close loop integer pitch */ + short *T0_frac, /* o : close loop fractional part of the pitch */ + short *T0_min, /* i/o: delta search min for sf 2 & 4 */ + short *T0_max, /* i/o: delta search max for sf 2 & 4 */ + float **pt_pitch, /* o : floating pitch values */ + short *position, /* i/o: first glottal impulse position in frame */ + float *bwe_exc /* i/o: excitation for SWB TBE */ +); + +void gain_dec_tc( + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : core bitrate */ + const short L_frame, /* i : length of the frame */ + const short i_subfr, /* i : subframe number */ + const short tc_subfr, /* i : TC subframe index */ + const float Es_pred, /* i : predicted scaled innov. energy */ + const float *code, /* i : algebraic code excitation */ + float *gain_pit, /* o : pitch gain */ + float *gain_code, /* o : Quantized codeebook gain */ + float *gain_inov, /* o : unscaled innovation gain */ + float *norm_gain_code /* o : norm. gain of the codebook excit. */ +); + +void stat_noise_uv_dec( + Decoder_State *st, /* i/o: decoder static memory */ + const short coder_type, /* i : coding type */ + float *lsp_new, /* i : end-frame LSP vector */ + float *lsp_mid, /* i : mid-frame LSP vector */ + float *Aq, /* o : A(z) quantized for the 4 subframes */ + float *exc2 /* i/o: excitation buffer */ +); + +void decod_nelp( + Decoder_State *st, /* i/o: decoder static memory */ + const short coder_type, /* i : coding type */ + float *tmp_noise, /* o : long term temporary noise energy */ + float *pitch_buf, /* o : floating pitch values for each subframe */ + float *exc, /* o : adapt. excitation exc */ + float *exc2, /* o : adapt. excitation/total exc */ + float *voice_factors, /* o : voicing factors */ + float *bwe_exc, /* o : excitation for SWB TBE */ + const short bfi, /* i : bad frame indicator */ + float *gain_buf +); + +void nelp_decoder( + Decoder_State *st, /* i/o: decoder static memory */ + float *exc_nelp, /* o : adapt. excitation/total exc */ + float *exc, /* o : adapt. excitation exc */ + short bfi, /* i : frame error rate */ + const short coder_type, /* i : coding type */ + float *gain_buf +); + +void decod_ppp( + Decoder_State *st, /* i/o: state structure */ + const float Aq[], /* i : 12k8 Lp coefficient */ + float *pitch_buf, /* i/o: floating pitch values for each subframe */ + float *exc, /* i/o: current non-enhanced excitation */ + float *exc2, /* i/o: current enhanced excitation */ + float *voice_factors, /* o : voicing factors */ + float *bwe_exc, /* o : excitation for SWB TBE */ + float *gain_buf + , short bfi +); + +void ppp_quarter_decoder( + Decoder_State *st, /* i/o: decoder state structure */ + DTFS_STRUCTURE *CURRCW_Q_DTFS, /* i/o: Current CW DTFS */ + int prevCW_lag, /* i : Previous lag */ + float *lastLgainD, /* i/o: Last gain lowband */ + float *lastHgainD, /* i/o: Last gain highwband */ + float *lasterbD, /* i/o: Last ERB vector */ + short bfi, /* i : FER flag */ + DTFS_STRUCTURE PREV_CW_D /* i : Previous DTFS */ +); + +void ppp_voiced_decoder( + Decoder_State *st, /* i/o: state structure */ + float *out, /* o : residual signal */ + const float *lpc2, /* i : current frame LPC */ + float *exc, /* i : previous frame excitation */ + float *pitch /* o : floating pitch values for each subframe */ + ,short bfi +); + +void AVQ_demuxdec( + Decoder_State *st, /* i/o: decoder state structure */ + int xriq[], /* o: decoded subvectors [0..8*Nsv-1] */ + short *nb_bits, /* i/o: number of allocated bits */ + const short Nsv, /* i: number of subvectors */ + short nq_out[] /* i/o: AVQ nq index */ +); + +void re8_dec( + int nq, + long I, + int kv[], + int y[] +); + +void re8_decode_base_index( + int n, /* i : codebook number (*n is an integer defined in {0,2,3,4,..,n_max}) */ + long I, /* i : index of c (pointer to unsigned 16-bit word) */ + int *x /* o : point in RE8 (8-dimensional integer vector) */ +); + +void Init_post_filter( + PFSTAT *pfstat /* i : post-filter state memories */ +); + +void nb_post_filt( + const short L_frame, /* i : frame length */ + const short L_subfr, /* i : sub-frame length */ + PFSTAT *pfstat, /* i/o: Post filter related memories */ + float *lp_noise, /* i/o: long term noise energy */ + const float tmp_noise, /* i : noise energy */ + float *synth, /* i/o: synthesis */ + const float *Aq, /* i : LP filter coefficient */ + const float *pitch_buf, /* i : Floating pitch for each subframe */ + const short coder_type, /* i : coder_type -> deactivated in AUDIO */ + const short BER_detect, /* i : BER detect flag */ + const short disable_hpf /* i : flag to diabled HPF */ +); + +void decod_unvoiced( + Decoder_State *st, /* i/o: decoder static memory */ + const float *Aq, /* i : LP filter coefficient */ + const short coder_type, /* i : coding type */ + float *tmp_noise, /* o : long term temporary noise energy */ + float *pitch_buf, /* o : floating pitch values for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *exc, /* o : adapt. excitation exc */ + float *exc2, /* o : adapt. excitation/total exc */ + float *bwe_exc, /* i/o: excitation for SWB TBE */ + float *gain_buf +); + +void decod_tran( + Decoder_State *st, /* i/o: decoder static memory */ + const short L_frame, /* i : length of the frame */ + const short tc_subfr, /* i : TC subframe index */ + const float *Aq, /* i : LP filter coefficient */ + const short coder_type, /* i : coding type */ + const float Es_pred, /* i : predicted scaled innov. energy */ + float *pitch_buf, /* o : floating pitch values for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *exc, /* i/o: adapt. excitation exc */ + float *exc2, /* i/o: adapt. excitation/total exc */ + float *bwe_exc, /* i/o: excitation for SWB TBE */ + short *unbits, /* i/o: number of unused bits */ + const short sharpFlag, /* i : formant sharpening flag */ + float *gain_buf +); + +void decod_gen_voic( + Decoder_State *st, /* i/o: decoder static memory */ + const short L_frame, /* i : length of the frame */ + const short sharpFlag, /* i : formant sharpening flag */ + const float *Aq, /* i : LP filter coefficient */ + const short coder_type, /* i : coding type */ + const float Es_pred, /* i : predicted scaled innov. energy */ + const short do_WI, /* i : FEC fast recovery flag */ + float *pitch_buf, /* o : floating pitch for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *exc, /* i/o: adapt. excitation exc */ + float *exc2, /* i/o: adapt. excitation/total exc */ + float *bwe_exc, /* i/o: excitation for SWB TBE */ + short *unbits, /* i/o: number of unused bits */ + float *gain_buf +); + +void decod_amr_wb( + Decoder_State *st, /* i/o: decoder static memory */ + const float *Aq, /* i : LP filter coefficients */ + float *pitch_buf, /* o : floating pitch values for each subframe */ + float *exc, /* i/o: adapt. excitation exc */ + float *exc2, /* i/o: adapt. excitation/total exc */ + short *hf_gain, /* o : decoded HF gain */ + float *voice_factors, /* o : voicing factors */ + float *gain_buf +); + +void io_ini_dec( + 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 */ + short *quietMode, /* o : limited printouts */ + short *noDelayCmp, /* o : turn off delay compensation */ + Decoder_State *st, /* o : Decoder static variables structure */ +#ifdef SUPPORT_JBM_TRACEFILE + char **jbmTraceFileName, /* o : VOIP tracefilename */ +#endif + char **jbmFECoffsetFileName /* o : Output file for Optimum FEC offset */ +); + +void init_decoder( + Decoder_State *st /* o : Decoder static variables structure */ +); + +void destroy_decoder( + Decoder_State *st /* o : Decoder static variables structure */ +); + +void evs_dec( + Decoder_State *st, /* i/o: Decoder state structure */ + float *output, /* o : output synthesis signal */ + frameMode frameMode /* i : Decoder frame mode */ +); + +int decodeVoip( + Decoder_State *st, + FILE *f_stream, + FILE *f_synth, +#ifdef SUPPORT_JBM_TRACEFILE + const char *jbmTraceFileName, +#endif + const char *jbmFECoffsetFileName, /* : Output file for Optimum FEC offset */ + const short quietMode +); + +void get_next_frame_parameters( + Decoder_State *st /* i/o: Decoder state structure */ +); + +void amr_wb_dec( + Decoder_State *st, /* i/o: decoder state structure */ + float *output_sp /* o : synthesis output */ +); + +void transf_cdbk_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : core bitrate */ + const short coder_type, /* i : coding type */ + const short harm_flag_acelp, /* i : harmonic flag for higher rates ACELP */ + const short i_subfr, /* i : subframe index */ + const short tc_subfr, /* i : TC subframe index */ + const float Es_pred, /* i : predicited scaled innovation energy */ + const float gain_code, /* i : innovative excitation gain */ + float *mem_preemp_preQ, /* i/o: prequantizer preemhasis memory */ + float *gain_preQ, /* o : prequantizer excitation gain */ + float *norm_gain_preQ, /* o : normalized prequantizer excitation gain */ + float code_preQ[], /* o : prequantizer excitation */ + short *unbits /* o : number of AVQ unused bits */ +); + +float gain_dequant( /* o: decoded gain */ + short index, /* i: quantization index */ + const float min, /* i: value of lower limit */ + const float max, /* i: value of upper limit */ + const short bits /* i: number of bits to dequantize */ +); + +void hq_core_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const float *audio, /* i : input audio signal */ + const short input_frame, /* i : frame length */ + const short hq_core_type, /* i : HQ core type */ + const short Voicing_flag +); + +short detect_transient( + const float *in, /* i : input signal */ + Encoder_State *st, /* i/o: encoder state structure */ + const short L, /* i : length */ + const short coder_type /* i : coding type */ +); + +void wtda( + const float *new_audio, /* i : input audio */ + float *wtda_audio, /* o : windowed audio */ + float *old_wtda, /* i/o: windowed audio from previous frame */ + const short left_mode, + const short right_mode, /* window overlap of current frame (0: full, 2: none, or 3: half) */ + const short L /* i : length */ +); + + +void tcx_get_windows_mode1( + const short left_mode, /* i: overlap mode of left window half */ + const short right_mode, /* i: overlap mode of right window half */ + float *left_win, /* o: left overlap window */ + float *right_win, /* o: right overlap window */ + float *left_win_int, /* o: left overlap window */ + float *right_win_int, /* o: right overlap window */ + short const L +); + +void direct_transform( + const float *in32, /* i : input signal */ + float *out32, /* o : output transformation */ + const short is_transient, /* i : transient flag */ + const short L /* i : length */ +); + +short noise_adjust( /* o : index of noise attenuation */ + const float *coeffs_norm, /* i : normalized coefficients */ + const short *bitalloc, /* i : bit allocation */ + const short *sfm_start, /* i : Start of bands */ + const short *sfm_end, /* i : End of bands */ + const short core_sfm /* i : index of the end band for core */ +); + +void interleave_spectrum( + float *coefs, /* i/o: input and output coefficients */ + const short length /* i : length of spectrum */ +); + +void hq_hr_enc( + Encoder_State *st, /* i/o: encoder state structure */ + float *coefs, /* i/o: transform-domain coefficients */ + const short length, /* i : length of spectrum */ + short *num_bits, /* i : number of available bits */ + const short is_transient /* i : transient flag */ +); + +void logqnorm( + const float *x, /* i : coefficient vector */ + short *k, /* o : index */ + const short L, /* i : codebook length */ + const short N, /* i : sub-vector size */ + const float *thren +); + +void huff_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const short N, /* i : Number of codewords to decode */ + const short buffer_len, /* i : Number of bits to read */ + const short num_lengths, /* i : Number of different huffman codeword lengths */ + const short *thres, /* i : Threshold of first codeword of each length */ + const short *offset, /* i : Offset for first codeword */ + const short *huff_tab, /* i : Huffman table order by codeword lengths */ + short *index /* o : Decoded index */ +); + +void calc_norm( + const float *x, /* i : Input vector. */ + short *norm, /* o : Quantization indices for norms */ + short *normlg, /* o : Quantized norms in log2 */ + const short start_band, /* i : Indice of band to start coding */ + const short num_bands, /* i : Number of bands */ + const short *band_len, /* i : Length of bands */ + const short *band_start /* i : Start of bands */ +); + +void reordernorm( + const short *ynrm, /* i : quantization indices for norms */ + const short *normqlg2, /* i : quantized norms */ + short *idxbuf, /* o : reordered quantization indices */ + short *normbuf, /* o : reordered quantized norms */ + const short nb_sfm /* i : number of bands */ +); + +void diffcod( + const short N, /* i : number of sub-vectors */ + short *y, /* i/o: indices of quantized norms */ + short *difidx /* o : differential code */ +); + +void diffcod_lrmdct( + const short N, + const int be_ref, + int *y, + int *difidx, + const short is_transient +); + +void normalizecoefs( + float *coefs, /* i/o: MDCT coefficients */ + const short *ynrm, /* i : quantization indices for norms */ + const short num_bands, /* i : Number of bands */ + const short *band_start, /* i : Start of bands */ + const short *band_end /* i : End of bands */ +); + +void bitallocsum( + short *R, /* i : bit-allocation vector */ + const short nb_sfm, /* i : number of sub-vectors */ + short *sum, /* o : total number of bits allocated */ + short *Rsubband, /* o : rate per subband (Q3) */ + const short v, /* i : bit rate */ + const short length, /* i : length of spectrum */ + const short *sfmsize /* i : Length of bands */ +); + +void hq_generic_hf_encoding( + const float *coefs, /* i : MDCT coefficients of weighted original */ + float *hq_generic_fenv, /* i/o: energy of SWB envelope */ + const short hq_generic_offset, /* i : frequency offset for extracting energy */ + Encoder_State *st, /* i/o: encoder state structure */ + short *hq_generic_clas /* o : bwe excitation class */ +); + +short swb_bwe_gain_deq( /* o : BWE class */ + Decoder_State *st, /* i/o: decoder state structure */ + const short core, /* i : core */ + float *SWB_tenv, /* o : time-domain BWE envelope */ + float *SWB_fenv, /* o : frequency-domain BWE envelope */ + const short hr_flag, /* i : high rate flag */ + const short hqswb_clas /* i : HQ BWE class */ +); + +void save_old_syn( + const short L_frame, /* i : frame length */ + const float syn[], /* i : ACELP synthesis */ + float old_syn[], /* o : old synthesis buffer */ + float old_syn_12k8_16k[], /* i/o: old synthesis buffer */ + const float preemph_fac, /* i : preemphasis factor */ + float *mem_deemph /* i/o: deemphasis filter memory */ +); + +void hq_generic_hf_decoding( + const short HQ_mode, /* i : HQ mode */ + float *coeff_out1, /* i/o : BWE input & temporary buffer */ + const float *hq_generic_fenv, /* i : SWB frequency envelopes */ + float *coeff_out, /* o : SWB signal in MDCT domain */ + const short hq_generic_offset, /* i : frequency offset for representing hq swb bwe*/ + short *prev_L_swb_norm, /* i/o: last normalize length */ + const short hq_swb_bwe_exc_clas, /* i : bwe excitation class */ + const short *R +); + +void hq_core_dec( + Decoder_State *st, /* i/o: decoder state structure */ + float out[], /* o : output synthesis */ + const short output_frame, /* i : output frame length */ + const short hq_core_type, /* i : HQ core type */ + const short core_switching_flag /* i : ACELP->HQ switching frame flag */ +); + +void hq_hr_dec( + Decoder_State *st, /* i/o: decoder state structure */ + float *coefsq, /* o : transform-domain coefficients */ + const short length, /* i : frame length */ + short num_bits, /* i : number of available bits */ + short *ynrm, /* o : norm quantization index vector */ + short *is_transient, /* o : transient flag */ + short *hqswb_clas, /* o : HQ SWB class */ + float *SWB_fenv /* o : SWB frequency envelopes */ +); + +void hdecnrm_context( + Decoder_State *st, /* i/o: decoder state structure */ + const short N, /* i : number of norms */ + short *index, /* o : indices of quantized norms */ + short *n_length /* o : decoded stream length */ +); + +void hdecnrm_tran( + Decoder_State *st, /* i/o: decoder state structure */ + const short N, + short *index +); + +void hdecnrm_resize( + Decoder_State *st, /* i/o: decoder state structure */ + const short N, /* i :number of SFMs */ + short *index /* o : norm quantization index vector */ +); + +void hdecnrm( + Decoder_State *st, /* i/o: decoder state structure */ + const short N, /* i : number of norms */ + short *index /* o : indices of quantized norms */ +); + +short find_last_band( /* o : index of last band */ + const short *bitalloc, /* i : bit allocation */ + const short nb_sfm /* i : number of possibly coded bands */ +); + +void fill_spectrum( + float *coeff, /* i/o: normalized MLT spectrum / nf spectrum */ + short *R, /* i : number of pulses per band */ + const short is_transient, /* i : transient flag */ + short norm[], /* i : quantization indices for norms */ + const float *hq_generic_fenv, /* i : HQ GENERIC envelope */ + const short hq_generic_offset, /* i : HQ GENERIC offset */ + const short nf_idx, /* i : noise fill index */ + const short length, /* i : Length of spectrum (32 or 48 kHz) */ + const float env_stab, /* i : Envelope stability measure [0..1] */ + short *no_att_hangover, /* i/o: Frame counter for attenuation hangover */ + float *energy_lt, /* i/o: Long-term energy measure for transient detection */ + short *bwe_seed, /* i/o: random seed for generating BWE input */ + const short hq_generic_exc_clas, /* i : HF excitation class */ + const short core_sfm, /* i : index of the end band for core */ + short HQ_mode, /* i : HQ mode */ + float noise_level[], /* i : noise level for harmonic modes */ + long core_brate, /* i : target bit-rate */ + float prev_noise_level[], /* i/o: noise factor in previous frame */ + short *prev_R, /* i/o: bit allocation info. in previous frame */ + float *prev_coeff_out, /* i/o: decoded spectrum in previous frame */ + const short *peak_idx, /* i : peak positions */ + const short Npeaks, /* i : number of peaks */ + const short *npulses, /* i : Number of assigned pulses per band */ + short prev_is_transient, + float *prev_normq, + float *prev_env, + short prev_bfi, + const short *sfmsize, /* i : Length of bands */ + const short *sfm_start, /* i : Start of bands */ + const short *sfm_end, /* i : End of bands */ + short *prev_L_swb_norm, + short prev_hq_mode, + const short num_sfm, + const short num_env_bands +); + +void env_stab_transient_detect( + const short is_transient, /* i: Transient flag */ + const short length, /* i : Length of spectrum (32 or 48 kHz) */ + const short norm[], /* i : quantization indices for norms */ + short *no_att_hangover, /* i/o: Frame counter for attenuation hangover */ + float *energy_lt, /* i/o: Long-term energy measure for transient detection */ + const short HQ_mode, /* i : HQ coding mode */ + const short bin_th, /* i : HVQ cross-over frequency bin */ + const float *coeff /* i : Coded spectral coefficients */ +); + +void de_interleave_spectrum( + float *coefs, /* i/o: input and output coefficients */ + short length /* i : length of spectrum */ +); + +void inverse_transform( + const float *InMDCT, /* i : input MDCT vector */ + float *Out, /* o : output vector */ + const short IsTransient, /* i : transient flag */ + const short L, /* i : output frame length */ + const short L_inner /* i : length of the transform */ +); + +void window_ola( + const float *ImdctOut, /* i : input */ + float *auOut, /* o : output audio */ + float *OldauOut, /* i/o: audio from previous frame */ + const short L, /* i : length */ + const short left_mode, + const short right_mode, /* window overlap of current frame (0: full, 2: none, or 3: half) */ + const short use_bfi_win, /* i : use BFI windowing */ + const short oldHqVoicing, /* i : previous HqVoicing */ + float *oldgapsynth /* i : previous gapsynth */ +); + +void map_quant_weight( + const short normqlg2[], /* i : quantized norms */ + short wnorm[], /* o : weighted norm */ + const short is_transient /* i : transient flag */ +); + +void recovernorm( + short *idxbuf, /* i : reordered quantization indices */ + short *ynrm, /* o : recovered quantization indices */ + short *normqlg2, /* o : recovered quantized norms */ + short nb_sfm /* i : number of SFMs */ +); + +void reordvct( + short *y, /* i/o: vector to rearrange */ + short N, /* i : dimensions */ + short *idx /* o : reordered vector index */ +); + +void bitalloc( + short *y, /* i : reordered norm of sub-vectors */ + short *idx, /* i : reordered sub-vector indices */ + short sum, /* i : number of available bits */ + short N, /* i : number of norms */ + short K, /* i : maximum number of bits per dimension */ + short *r, /* o : bit-allacation vector */ + const short *sfmsize, /* i : Length of bands */ + const short hqswb_clas /* i : signal classification flag */ +); + +short BitAllocF( + short *y, /* i : norm of sub-vectors */ + long bit_rate, /* i : bitrate */ + short B, /* i : number of available bits */ + short N, /* i : number of sub-vectors */ + short *R, /* o : bit-allocation indicator */ + short *Rsubband, /* o : sub-band bit-allocation vector (Q3) */ + const short hqswb_clas, /* i : hq swb class */ + const short num_env_bands /* i : Number sub bands to be encoded for HQ_SWB_BWE */ +); + +short BitAllocWB( + short *y, + short B, + short N, + short *R, + short *Rsubband +); + +short hvq_pvq_bitalloc( + short num_bits, /* i/o: Number of available bits (including gain bits) */ + const short brate, /* i : bitrate */ + const short bwidth, /* i : Encoded bandwidth */ + const short *ynrm, /* i : Envelope coefficients */ + const int manE_peak, /* i : Peak energy mantissa */ + const short expE_peak, /* i : Peak energy exponent */ + short *Rk, /* o : bit allocation for concatenated vector */ + short *R, /* i/o: Global bit allocation */ + short *sel_bands, /* o : Selected bands for encoding */ + short *n_sel_bands /* o : No. of selected bands for encoding */ +); + +void floating_point_add( + int *mx, /* io: mantissa of the addend Q31 */ + short *ex, /* io: exponent of the addend Q0 */ + const int my, /* i: mantissa of the adder Q31 */ + const short ey /* i: exponent of the adder Q0 */ +); + +short rc_get_bits2( /* o: Number of bits needed */ + const short N, /* i: Number of bits currently used */ + const unsigned int range /* i: Range of range coder */ +); + + + +void rc_enc_init( + Encoder_State *st, /* i/o: Encoder state */ + short tot_bits /* i : Total bit budget */ +); + +void rc_encode( + Encoder_State *st, /* i/o: Encoder state */ + unsigned int cum_freq, /* i : Cumulative frequency up to symbol */ + unsigned int sym_freq, /* i : Symbol probability */ + unsigned int tot /* i : Total cumulative frequency */ +); + +void rc_enc_finish( + Encoder_State *st /* i/o: Encoder state */ +); + +void rc_enc_bits( + Encoder_State *st, /* i/o: Encoder state */ + unsigned int value, /* i : Value to encode */ + short bits /* i : Number of bits used */ +); + +void rc_enc_uniform( + Encoder_State *st, /* i/o: Encoder state */ + unsigned int value, /* i : Value to encode */ + unsigned int tot /* i : Maximum value */ +); + +void rc_dec_init( + Decoder_State *st, /* i/o: Decoder State */ + short tot_bits /* i : Total bit budget */ +); + +unsigned int rc_decode( /* o : Decoded cumulative frequency */ + Decoder_State *st, /* i/o: Decoder State */ + unsigned int tot /* i : Total cumulative frequency */ +); + +void rc_dec_update( + Decoder_State *st, /* i/o: Decoder State */ + unsigned int cum_freq, /* i : Cumulative frequency */ + unsigned int sym_freq /* i : Symbol frequency */ +); + +unsigned int rc_dec_bits( /* i : Decoded value */ + Decoder_State *st, /* i/o: Decoder State */ + short bits /* i : Number of bits */ +); + +unsigned int rc_dec_uniform( /* i : Decoded value */ + Decoder_State *st, /* i/o: Decoder State */ + unsigned int tot /* i : Maximum value */ +); + +void rc_dec_finish( + Decoder_State *st /* i/o: deocder state structure */ +); + +short pvq_core_enc ( + Encoder_State *st, + float coefs_norm[], + float coefs_quant[], + short bit_budget, /* number of bits */ + short nb_sfm, + const short *sfm_start, + const short *sfm_end, + const short *sfmsize, + short *R, + short *Rs, + short *npulses, + short *maxpulse, + const short core +); + +short pvq_core_dec ( + Decoder_State *st, + const short *band_start, + const short *band_end, + const short *band_width, + float coefs_quant[], /* o : output MDCT */ + short bits_tot, + short nb_sfm, + short *R, + short *Rs, + short *npulses, + short *maxpulse, + const short core +); + +void pvq_encode( + Encoder_State *st, + const float *x, /* i: vector to quantize */ + short *y, /* o: quantized vector (non-scaled int)*/ + float *xq, /* o: quantized vector (scaled float) */ + const short pulses, /* i: number of allocated pulses */ + const short N, /* i: Length of vector */ + const float gain /* i: Gain */ +); + +void pvq_decode( + Decoder_State *st, + float *xq, /* o: decoded vector (scaled float) */ + short *y, /* o: decoded vector (non-scaled short)*/ + const short K, /* i: number of allocated pulses */ + const short N, /* i: Length of vector */ + const float gain /* i: Gain */ +); + + +void rangeCoderFinalizationFBits( + short Brc, + unsigned int INTrc, + short *FBits +); + +void bandBitsAdjustment( + short Brc, + unsigned int INTrc, + short Bavail, + short Nbands, + short D, + short L, + short Bband, + short Breserv, + short *Bband_adj, /* o */ + short *Brem, /* o */ + short *Breservplus /* o */ +) ; +void conservativeL1Norm( + short L, + short Qvec, + short Fcons, + short Qavail, + short Qreserv, + short Dspec, + short *Dvec, /*o*/ + short *Qspare, /*o*/ + short *Qreservplus, /*o*/ + short *Dspecplus /*o*/ +); + +void NearOppSplitAdjustment( + short qband, + short qzero, + const short Qac, + const unsigned int INTac, + short qglobal, + short FlagCons, + short Np, + short Nhead, + short Ntail, + short Nnear, + short Nopp, + short oppRQ3, + short *qnear, + short *qopp, + short *qglobalupd +) ; +void dsDirac2Dirac( + short dsDiracIndex, + short *diracs +); +int intLimCDivPos( + int NUM, + short DEN +) ; + +int intLimCDivSigned( + int NUM, + short DEN +) ; + + +short shrtCDivSignedApprox( + const short num, + const short den +); + +void dsDiracPerQuanta(short td, + short t_quanta, + short dsm, + const unsigned char* const *frQuanta, + short *DsIdx + ); +void QuantaPerDsDirac( + short td, + short dsDiracIndex, + const unsigned char* const* dimFrQuanta, + short *Quanta +) ; + +void Ratio_rQ3( + short opp, + short near, + short *result +); + +void obtainEnergyQuantizerDensity( + short L, + short R, + short *Density +) ; + +void densityAngle2RmsProjDec( + short D, /* i: density */ + short indexphi, /* i: decoded index from AR dec */ + short *oppQ15, /* o: proj*/ + short *nearQ15, /* o: */ + short *oppRatioQ3 /* o: */ +) ; + +void densityAngle2RmsProjEnc ( + short D, + short phiQ14uq, + short *indexphi, /* o: index to send to AR */ + short *oppQ15, /* o: proj*/ + short *nearQ15, + short *oppRatioQ3 +) ; + + +void subband_gain_bits( + const short *Rk, /* i : bit allocation per band (Q3)*/ + const short N, /* i : number of bands */ + short *bits, /* o : gain bits per band */ + const short *sfmsize /* i : Size of bands */ +); + +void env_adj( + const short *pulses, /* i : number of pulses per band */ + const short length, /* i : length of spectrum */ + const short last_sfm, /* i : Index of last band */ + float *adj, /* o : Adjustment factors for the envelope */ + const float env_stab, + const short *sfmsize /* i : Length of bands */ +); + +float env_stability( + const short *ynrm, /*i : Norm vector for current frame */ + const short nb_sfm, /*i : Number of sub-bands */ + short *mem_norm, /*i/o: Norm vector memory from past frame */ + short *mem_env_delta /*i/o: Envelope stability memory for smoothing (Q12)*/ +); + +float env_stab_smo( + float env_stab, /*i : env_stab value */ + float *env_stab_state_p, /*i/o: env_stab state probabilities */ + short *ho_cnt /*i/o: hangover counter for speech state */ +); + +void core_switching_pre_enc( + Encoder_State *st, /* i/o: encoder state structure */ + LPD_state *mem, /* i/o: encoder state structure */ + const float *old_inp_12k8, /* i : old input signal @12.8kHz */ + const float *old_inp_16k /* i : old input signal @16kHz */ +); + +void core_switching_post_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const float *old_inp_12k8, /* i : old input signal @12.8kHz */ + const float *old_inp_16k, /* i : old input signal @16kHz */ + const short pitch[3], /* i : open-loop pitch values for quantiz. */ + const float voicing[3], /* i : Open-loop pitch gains */ + const float A[] /* i : unquant LP filter coefs. */ +); + +void core_switching_post_dec( + Decoder_State *st, /* i/o: decoder state structure */ + float *synth, /* i/o: output synthesis */ + const short output_frame, /* i : frame length */ + const short core_switching_flag, /* i : ACELP->HQ switching frame flag */ + const short coder_type +); + +void core_switching_pre_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const short output_frame /* i : frame length */ +); + +void bandwidth_switching_detect( + Decoder_State *st /* i/o: encoder state structure */ +); + +void bw_switching_pre_proc( + Decoder_State *st, /* i/o: decoder state structure */ + const float *old_syn_12k8_16k /* i : ACELP core synthesis @ 12.8kHz or 16kHz */ +); + +void updt_bw_switching( + Decoder_State *st, /* i/o: decoder state structure */ + const float *synth /* i : float synthesis signal */ +); + +void swb_tbe_reset( + float mem_csfilt[], + float mem_genSHBexc_filt_down_shb[], + float state_lpc_syn[], + float syn_overlap[], + float state_syn_shbexc[], + float *tbe_demph, + float *tbe_premph, + float mem_stp_swb[], + float *gain_prec_swb +); + +void swb_tbe_reset_synth( + float genSHBsynth_Hilbert_Mem[], + float genSHBsynth_state_lsyn_filt_shb_local[] +); + + +void fb_tbe_reset_enc( + float elliptic_bpf_2_48k_mem[][4], + float *prev_fb_energy +); + +void fb_tbe_reset_synth( + float fbbwe_hpf_mem[][4], + float *prev_fbbwe_ratio +); + +void wb_tbe_extras_reset( + float mem_genSHBexc_filt_down_wb2[], + float mem_genSHBexc_filt_down_wb3[] +); + +void wb_tbe_extras_reset_synth( + float state_lsyn_filt_shb[], + float state_lsyn_filt_dwn_shb[], + float mem_resamp_HB[] +); + +void prep_tbe_exc( + const short L_frame, /* i : length of the frame */ + const short i_subfr, /* i : subframe index */ + const float gain_pit, /* i : Pitch gain */ + const float gain_code, /* i : algebraic codebook gain */ + const float code[], /* i : algebraic excitation */ + const float voice_fac, /* i : voicing factor */ + float *voice_factors, /* o : TBE voicing factor */ + float bwe_exc[], /* i/o: excitation for TBE */ + const float gain_preQ, /* i : prequantizer excitation gain */ + const float code_preQ[], /* i : prequantizer excitation */ + const short T0, /* i : integer pitch variables */ + const short coder_type, /* i : coding type */ + const long core_brate /* i : core bitrate */ +); + +void synthesise_fb_high_band( + const float excitation_in[], /* i : full band excitation */ + float output[], /* o : high band speech - 14.0 to 20 kHz */ + const float fb_exc_energy, /* i : full band excitation energy */ + const float ratio, /* i : energy ratio */ + const short L_frame, /* i : ACELP frame length */ + const short bfi, /* i : fec flag */ + float *prev_fbbwe_ratio, /* o : previous frame energy for FEC */ + float bpf_memory[][4] /* i/o: memory for elliptic bpf 48k */ +); + +void elliptic_bpf_48k_generic( + const float input[], /* i : input signal */ + float output[], /* o : output signal */ + float memory[][4], /* i/o: 4 arrays for memory */ + const float full_band_bpf[][5] /* i : filter coefficients b0,b1,b2,a0,a1,a2 */ +); + +void HQ_FEC_processing( + Decoder_State *st, /* i/o: decoder state structure */ + float *t_audio_q, /* o : MDCT coeffs. (for synthesis) */ + short is_transient, /* i : Old flag for transient */ + float ynrm_values[][MAX_PGF], /* i : Old average Norm values for each group of bands */ + float r_p_values[][MAX_ROW], /* i : Computed y-intercept and slope by Regression */ + short num_Sb, /* i : Number of sub-band group */ + short nb_sfm, /* i : Number of sub-band */ + short *Num_bands_p, /* i : Number of coeffs. for each sub-band */ + short output_frame, /* i : Frame size */ + const short *sfm_start, /* i : Start of bands */ + const short *sfm_end /* i : End of bands */ +); + +void HQ_FEC_Mem_update( + Decoder_State *st, /* i/o: decoder state structure */ + float *t_audio_q, + float *normq, + short *ynrm, + short *Num_bands_p, + short is_transient, + short hqswb_clas, + short c_switching_flag, + short nb_sfm, + short num_Sb, + float *mean_en_high, + short hq_core_type, /* i : normal or low-rate MDCT(HQ) core */ + short output_frame +); + +void time_domain_FEC_HQ( + Decoder_State *st, /* i : Decoder State */ + float *wtda_audio, /* i : input */ + float *out, /* o : output audio */ + float mean_en_high, /* i : transient flag */ + const short output_frame +); + +void Next_good_after_burst_erasures( + const float *ImdctOut, /* i : input */ + float *auOut, /* o : output audio */ + float *OldauOut, /* i/o: audio from previous frame */ + const short ol_size /* i : overlap size */ +); + +void update_average_rate( + Encoder_State *st /* i/o: encoder state structure */ +); + +void reset_preecho_dec( + Decoder_State *st /* i/o: decoder state structure */ +); + +void preecho_sb( + const long brate, /* i : core bit-rate */ + const float wtda_audio[], /* i : imdct signal */ + float *rec_sig, /* i : reconstructed signal, output of the imdct transform */ + const short output_frame, /* i : output frame length */ + float *memfilt_lb, /* i/o: memory */ + float *mean_prev_hb, /* i/o: memory */ + float *smoothmem, /* i/o: memory */ + float *mean_prev, /* i/o: memory */ + float *mean_prev_nc, /* i/o: memory */ + float *wmold_hb, /* i/o: memory */ + short *prevflag, /* i/o: flag */ + short *pastpre, /* i/o: flag */ + const short bwidth +); + +void hq2_core_configure( + const short frame_length, /* i : frame length */ + const short num_bits, /* i : number of bits */ + const short is_transient, /* i : transient flag */ + short *bands, + short *length, + short band_width[], + short band_start[], + short band_end[], + Word32 *L_qint, /* o : Q29 */ + Word16 *eref_fx, /* o : Q10 */ + Word16 *bit_alloc_weight_fx, /* o : Q13 */ + short *gqlevs, + short *Ngq, + short *p2a_bands, + float *p2a_th, + float *pd_thresh, + float *ld_slope, + float *ni_coef, + float *ni_pd_th, + long bwe_br +); + +void hq_lr_enc( + Encoder_State *st, /* i/o: encoder state structure */ + float t_audio[], /* i/o: transform-domain coefs. */ + const short inner_frame, /* i : inner frame length */ + short *num_bits, /* i/o: number of available bits */ + const short is_transient /* i : transient flag */ +); + +void hq_lr_dec( + Decoder_State *st, /* i/o: decoder state structure */ + float yout[], /* o : transform-domain output coefs. */ + const short inner_frame, /* i : inner frame length */ + short num_bits, /* i : number of available bits */ + short *is_transient /* o : transient flag */ +); + +void hq2_bit_alloc ( + const float band_energy[], /* i : band energy of each subband */ + const short bands, /* i : total number of subbands in a frame */ + Word32 L_Rk[], /* i/o: Bit allocation/Adjusted bit alloc. */ + short *bit_budget, /* i/o: bit bugdet */ + short *p2a_flags, /* i : HF tonal indicator */ + const Word16 weight_fx, /* i : weight (Q13) */ + const short band_width[], /* i : Sub band bandwidth */ + const short num_bits, /* i : available bits */ + const short hqswb_clas, /* i : HQ2 class information */ + const short bwidth, /* i : input bandwidth */ + const short is_transient /* i : indicator HQ_TRANSIENT or not */ +); + +void hq2_noise_inject( + float y2hat[], + const short band_start[], + const short band_end[], + const short band_width[], + float Ep[], + float Rk[], + const int npulses[], + short ni_seed, + const short bands, + const short ni_start_band, + const short bw_low, + const short bw_high, + const float enerL, + const float enerH, + float last_ni_gain[], + float last_env[], + short *last_max_pos_pulse, + short *p2a_flags, + short p2a_bands, + const short hqswb_clas, + const short bwidth, + const long bwe_br +); + +void mdct_spectrum_denorm( + const int inp_vector[], + float y2[], + const short band_start[], + const short band_end[], + const short band_width[], + const float band_energy[], + const int npulses[], + const short bands, + const float ld_slope, + const float pd_thresh +); + +void reverse_transient_frame_energies( + float band_energy[], /* o : band energies */ + const short bands /* i : number of bands */ +); + +short peak_vq_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const float *coefs, /* i : Input coefficient vector */ + float *coefs_out, /* o : Quantized output vector */ + const short brate, /* i : Core bitrate */ + const short num_bits, /* i : Number of bits for HVQ */ + const short vq_peaks, /* i : Number of identified peaks */ + const short *ynrm, /* i : Envelope coefficients */ + short *R, /* i/o: Bit allocation/updated bit allocation */ + short *vq_peak_idx, /* i : Peak index vector */ + float *nf_gains /* i : Estimated noise floor gains */ +); + +void hvq_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const short num_bits, /* i : Number of available bits */ + const long core_brate, /* i : Core bit-rate */ + const short *ynrm, /* i : Envelope coefficients */ + short *R, /* i/o: Bit allocation/updated bit allocation */ + float *noise_level, /* o : Noise level */ + short *peak_idx, /* o : Peak position vector */ + short *Npeaks, /* o : Total number of peaks */ + float *coefsq_norm, /* o : Output vector */ + const short core +); + +void hq_configure_bfi( + short *nb_sfm, /* o : Number of sub bands */ + short *num_Sb, /* o : Number of FEC sub bands ? */ + short *num_bands_p, /* o : FEC sub bands */ + short const **sfmsize, /* o : Subband bandwidths */ + short const **sfm_start, /* o : Subband start coefficients */ + short const **sfm_end /* o : Subband end coefficients */ +); + +void peak_vq_dec( + Decoder_State *st, /* i/o: decoder state structure */ + float *coefs_out, /* o : Output coefficient vetor */ + const short brate, /* i : Core bitrate */ + const short num_bits, /* i : Number of bits for HVQ */ + const short *ynrm, /* i : Envelope coefficients */ + short *R, /* i/o: Bit allocation/updated bit allocation */ + short *vq_peak_idx, /* o : Peak position vector */ + short *Npeaks, /* o : Number of peaks */ + const short core /* i : Core type */ +); + +void swb_bwe_enc_lr( + Encoder_State *st, /* i/o: encoder state structure */ + const float m_core[], /* i : core synthesis (MDCT) */ + const float m_orig[], /* i/o: scaled orig signal (MDCT) */ + float m[], /* o : output, SWB part (MDCT) */ + const long total_brate, /* i : total bitrate for selecting subband pattern */ + short BANDS, + short *band_start, + short *band_end, + float *band_energy, + short *p2a_flags, + const short hqswb_clas, + short lowlength, + short highlength, + short *prev_frm_index, + const short har_bands, + short *prev_frm_hfe2, + short *prev_stab_hfe2, + short band_width[], + const float y2_ni[], + short *ni_seed +); + +void swb_bwe_dec_lr( + Decoder_State *st, /* i/o: decoder state structure */ + const float m_core[], /* i : lowband synthesis */ + float m[], /* o : highband synthesis with lowband zeroed */ + const long total_brate, /* i : total bitrate for selecting subband pattern */ + short BANDS, + short *band_start, + short *band_end, + float *band_energy, + short *p2a_flags, + const short hqswb_clas, + short lowlength, + short highlength, + const short har_bands, + short *prev_frm_hfe2, + short *prev_stab_hfe2, + short band_width[], + const float y2_ni[], + short *ni_seed +); + +int get_usebit_npswb( + short hqswb_clas +); + +void GetPredictedSignal( + const float *predBuf, /* i : prediction buffer */ + float *outBuf, /* o : output buffer */ + const short lag, /* i : prediction buffer offset */ + const short fLen, /* i : length of loop (output) */ + const float gain /* i : gain to be applied */ +); + +void convert_lagIndices_pls2smp( + short lagIndices_in[], + short nBands_search, + short lagIndices_out[], + const float sspectra[], + const short sbWidth[], + const short fLenLow +); + +void FindNBiggest2_simple( + const float *inBuf, /* i : input buffer (searched) */ + GainItem *g, /* o : N biggest components found */ + const short nIdx, /* i : search length */ + short *n, /* i : number of components searched (N biggest) */ + short N_NBIGGESTSEARCH +); + +void updat_prev_frm( + float y2[], + float t_audio[], + long bwe_br, + short length, + const short inner_frame, + short bands, + short bwidth, + const short is_transient, + short hqswb_clas, + short *prev_hqswb_clas, + short *prev_SWB_peak_pos, + short prev_SWB_peak_pos_tmp[], + short *prev_frm_hfe2, + short *prev_stab_hfe2, + short bws_cnt +); + +void hf_parinitiz( + const long total_brate, + const short hqswb_clas, + short lowlength, + short highlength, + short wBands[], + const short **subband_search_offset, + const short **subband_offsets, + short *nBands, + short *nBands_search, + short *swb_lowband, + short *swb_highband +); + +float spectrumsmooth_noiseton( + float spectra[], + const float spectra_ni[], + float sspectra[], + float sspectra_diff[], + float sspectra_ni[], + const short fLenLow, + short *ni_seed +); + +void noiseinj_hf( + float xSynth_har[], + float th_g[], + float band_energy[], + float *prev_En_sb, + const short p2a_flags[], + short BANDS, + short band_start[], + short band_end[], + const short fLenLow +); + +void noise_extr_corcod( + float spectra[], + const float spectra_ni[], + float sspectra[], + float sspectra_diff[], + float sspectra_ni[], + const short fLenLow, + short prev_hqswb_clas, + float *prev_ni_ratio +); + +void genhf_noise( + float noise_flr[], + float xSynth_har[], + float *predBuf, + short bands, /* i : total number of subbands in a frame */ + short harmonic_band, /* i : Number of LF harmonic frames */ + short har_freq_est2, + short pos_max_hfe2, + short *pul_res, + GainItem pk_sf[], + const short fLenLow, + const short fLenHigh, + const short sbWidth[], + const short lagIndices[], + const short subband_offsets[], + const short subband_search_offset[] +); + +void ton_ene_est( + float xSynth_har[], + float be_tonal[], + float band_energy[], + short band_start[], + short band_end[], + short band_width[], + const short fLenLow, + const short fLenHigh, + short bands, + short har_bands, + float ni_lvl, + GainItem pk_sf[], + short *pul_res +); + +void Gettonl_scalfact( + float *outBuf, /* o : synthesized spectrum */ + const float *codbuf, /* i : core coder */ + const short fLenLow, /* i : lowband length */ + const short fLenHigh, /* i : highband length */ + short harmonic_band, /* i : Number of LF harmonic frames */ + short bands, /* i : total number of subbands in a frame */ + float *band_energy, /* i : band energy of each subband */ + short *band_start, /* i : subband start indices */ + short *band_end, /* i : subband end indices */ + const short p2aflags[], + float be_tonal[], + GainItem *pk_sf, + short *pul_res +); + +void SpectrumSmoothing_nss( + float *inBuf, + float *outBuf, + int fLen +); + +void SpectrumSmoothing( + float *inBuf, + float *outBuf, + const short fLen, + const float th_cut +); + +void hq2_bit_alloc_har ( + float *y, /* i : band energy of sub-vectors */ + int B, /* i : number of available bits */ + short N, /* i : number of sub-vectors */ + Word32 *L_Rsubband, + short p2a_bands, + long core_brate, /* i : core bit rate */ + short p2a_flags[], + short band_width[] +); + +void GetSynthesizedSpecThinOut( + const float *predBuf, + float *outBuf, + const short nBands, + const short *sbWidth, + const short *lagIndices, + const float *lagGains, + const short predBufLen +); + +void return_bits_normal2( + short *bit_budget, + const short p2a_flags[], + const short bands, + const short bits_lagIndices[] +); + +void GetlagGains( + const float *predBuf, + const float *band_energy, + const short nBands, + const short *sbWidth, + const short *lagIndices, + const short predBufLen, + float *lagGains +); + +void preset_hq2_swb( + const short hqswb_clas, + const short band_end[], + short *har_bands, + short p2a_bands, + const short length, + const short bands, + short *lowlength, + short *highlength, + float m[] +); + +void post_hq2_swb( + const float m[], + const short lowlength, + const short highlength, + const short hqswb_clas, + const short har_bands, + const short bands, + const short p2a_flags[], + const short band_start[], + const short band_end[], + float y2[], + int npulses[] +); + +void har_denorm_pulcnt( + float spectra[], /* i/o: MDCT domain spectrum */ + short band_start[], /* i : Number subbands/Frame */ + short band_end[], /* i : Band Start of each SB */ + float band_energy[], /* i : Band end of each SB */ + short band_width[], + int npulses[], + const short har_bands /* i: No. of harmonic bands */ +); + +short har_est( + float spectra[], + short N, + short *har_freq_est1, + short *har_freq_est2, + short *flag_dis, + short *prev_frm_hfe2, + const short subband_search_offset[], + const short sbWidth[], + short *prev_stab_hfe2 +); + +void spt_shorten_domain_pre( + const short band_start[], + const short band_end[], + const short prev_SWB_peak_pos[], + const short BANDS, + const long bwe_br, + short new_band_start[], + short new_band_end[], + short new_band_width[] +); + +void spt_shorten_domain_band_save( + const short bands, + const short band_start[], + const short band_end[], + const short band_width[], + short org_band_start[], + short org_band_end[], + short org_band_width[] +); + +void spt_shorten_domain_band_restore( + const short bands, + short band_start[], + short band_end[], + short band_width[], + const short org_band_start[], + const short org_band_end[], + const short org_band_width[] +); + +void spt_swb_peakpos_tmp_save( + const float y2[], + const short bands, + const short band_start[], + const short band_end[], + short prev_SWB_peak_pos_tmp[] +); + +void hq_ecu( + const float *prevsynth, /* i : buffer of previously synthesized signal */ + float *ecu_rec, /* o : reconstructed frame in tda domain */ + short *time_offs, /* i/o: Sample offset for consecutive frame losses*/ + float *X_sav, /* i/o: Stored spectrum of prototype frame */ + short *num_p, /* i/o: Number of identified peaks */ + short *plocs, /* i/o: Peak locations */ + float *plocsi, /* i/o: Interpolated peak locations */ + const float env_stab, /* i : Envelope stability parameter */ + short *last_fec, /* i/o: Flag for usage of pitch dependent ECU */ + const short ph_ecu_HqVoicing, /* i : HQ Voicing flag */ + short *ph_ecu_active, /* i : Phase ECU active flag */ + float *gapsynth, /* o : Gap synthesis */ + const short prev_bfi, /* i : indicating burst frame error */ + const short old_is_transient[2], /* i : flags indicating previous transient frames*/ + float *mag_chg_1st, /* i/o: per band magnitude modifier for transients*/ + float Xavg[LGW_MAX], /* i/o: Frequency group average gain to fade to */ + float *beta_mute, /* o : Factor for long-term mute */ + const short output_frame, /* i : frame length */ + Decoder_State *st /* i/o: decoder state structure */ +); + +void hq_timedomain_conc( + float *ecu_rec, /* o : reconstructed frame in tda domain */ + float *gapsynth, /* o : Gap synthesis */ + const short output_frame, /* i : frame length */ + const float *prevsynth, /* i : buffer of previously synthesized signal */ + Decoder_State *st /* i/o: decoder state structure */ +); + +void fft3( + const float X[], /* i : input frame */ + float Y[], /* o : DFT of input frame */ + const short n /* i : block length (must be radix 3) */ +); + +void ifft3( + const float X[], /* i : input frame */ + float Y[], /* o : iDFT of input frame */ + const short n /* i : block length (must be radix 3) */ +); + +void minimumStatistics( /* return: updated estimate of background noise */ + float* noiseLevelMemory, /* internal state */ + int* noiseLevelIndex, /* internal state */ + int* currLevelIndex, /* internal state (circular buffer) */ + float* noiseEstimate, /* previous estimate of background noise */ + float* lastFrameLevel, /* level of the last frame */ + float currentFrameLevel, /* level of the current frame */ + float const minLev, /* minimum level */ + int const buffSize /* buffer size */ +); + +void E_LPC_int_lpc_tcx( + const float lsf_old[], /* input : LSFs from past frame */ + const float lsf_new[], /* input : LSFs from present frame */ + float a[] /* output: interpolated LP coefficients */ +); + +Word32 E_GAIN_closed_loop_search( + Float32 exc[], + Float32 xn[], + Float32 h[], + Word32 t0_min, + Word32 t0_min_frac, + Word32 t0_max, + Word32 t0_max_frac, + Word32 t0_min_max_res, + Word32 *pit_frac, + Word32 *pit_res, + Word32 pit_res_max, + Word32 i_subfr, + Word32 pit_min, + Word32 pit_fr2, + Word32 pit_fr1, + Word32 L_subfr +); + +void E_ACELP_toeplitz_mul( + float R[], + float c[], + float d[] +); + +void acelp_pulsesign( + const float cn[], + float dn[], + float dn2[], + float sign[], + float vec[], + float alp +); + +void E_ACELP_4tsearch( + Float32 dn[], + const Float32 cn[], + const Float32 H[], + float code[], + PulseConfig *config, + Word16 ind[], + Float32 y[] +); + +void E_ACELP_4tsearchx( + Float32 dn[], + const Float32 cn[], + Float32 Rw[], + float code[], + PulseConfig *config, + Word16 ind[] +); + +short E_ACELP_indexing( + Float32 code[], + PulseConfig config, + int num_tracks, + int prm[] +); + +void acelp_findcandidates( + float dn2[], + short dn2_pos[], + short pos_max[], + int L_subfr, + int tracks +); + +void E_ACELP_innovative_codebook( + float *exc, /* i : pointer to the excitation frame */ + int T0, /* i : integer pitch lag */ + int T0_frac, /* i : fraction of lag */ + int T0_res, /* i : pitch resolution */ + float pitch_gain, /* i : adaptive codebook gain */ + float tilt_code, /* i : tilt factor */ + int mode, /* i : innovative codebook mode */ + int pre_emphasis,/* i : use pre_emphasis */ + int pitch_sharpening, /* i : use pitch sharpening */ + int phase_scrambling, /* i : use phase scrambling */ + int formant_enh, /* i : use formant enhancement */ + int formant_tilt,/* i : use tilt of formant enhancement */ + float formant_enh_num, /* i : formant enhancement numerator weighting factor*/ + float formant_enh_den, /* i : formant enhancement denominator weighting factor*/ + const short i_subfr, /* i : subframe index */ + const float *Aq, /* i : quantized LPC coefficients */ + float *h1, /* i : impulse response of weighted synthesis filter */ + float *xn, /* i : Close-loop Pitch search target vector */ + float *cn, /* i : Innovative codebook search target vector */ + float *y1, /* i : zero-memory filtered adaptive excitation */ + float *y2, /* o : zero-memory filtered algebraic excitation */ + int acelpautoc, /* i : autocorrelation mode enabled */ + int **pt_indice, /* i/o: quantization indices pointer */ + float *code /* o : innovative codebook */ + ,const short L_frame, /* i : length of the frame */ + const short last_L_frame,/* i : length of the last frame */ + const long total_brate /* i : total bit-rate */ +); + +short E_ACELP_code43bit( + const float code[], + long unsigned *ps, + int *p, + unsigned short idxs[] +); + +void fcb_pulse_track_joint( + unsigned short *idxs, + int wordcnt, + unsigned long *index_n, + int *pulse_num, + int track_num +); + +void D_ACELP_indexing( + Float32 code[], + PulseConfig config, + int num_tracks, + int prm[], + short *BER_detect +); + +void D_ACELP_decode_43bit( + unsigned short idxs[], + float code[], + int *pulsestrack +); + +void fcb_pulse_track_joint_decode( + unsigned short *idxs, + int wordcnt, + long unsigned *index_n, + int *pulse_num, + int track_num +); + +void lag_wind( + float r[], /* i/o: autocorrelations */ + const short m, /* i : order of LP filter */ + const int sr, /* i : sampling rate */ + const short strength /* i : LAGW_WEAK, LAGW_MEDIUM, or LAGW_STRONG */ +); + +void adapt_lag_wind( + float r[], /* i/o: autocorrelations */ + int m, /* i : order of LP filter */ + const int Top, /* i : open loop pitch lags from curr. frame (or NULL if n/a) */ + const float Tnc, /* i : open loop pitch gains from curr. frame (NULL if n/a) */ + int sr /* i : sampling rate */ +); + +void hp20( + Float32 signal[], + Word32 lg, + Float32 mem[], + Word32 fs +); + +void ham_cos_window( + float *fh, + int n1, + int n2 +); + +float correlation_shift( /* o : noise dependent voicing correction */ + const float totalNoise /* i : noise estimate over all critical bands */ +); + +void init_coder_ace_plus( + Encoder_State *st /* i/o: encoder state structure */ +); + +void core_coder_reconfig( + Encoder_State *st /* i/o: encoder state structure */ +); + +void core_coder_mode_switch( + Encoder_State *st, /* i/o: encoder state structure */ + int bandwidth_in, /* i : bandwidth */ + int bitrate /* i : bitrate */ +); + +void enc_acelp_tcx_main( + const float new_samples[], /* i : new samples */ + Encoder_State *st, /* i/o: encoder state structure */ + const short coder_type, /* i : coding type */ + const short pitch[3], /* i : open-loop pitch values for quantiz. */ + const float voicing[3], /* i : open-loop pitch gains */ + float Aw[NB_SUBFR16k*(M+1)], /* i : weighted A(z) unquant. for subframes*/ + const float lsp_new[M], /* i : LSPs at the end of the frame */ + const float lsp_mid[M], /* i : LSPs at the middle of the frame */ + HANDLE_FD_CNG_ENC hFdCngEnc, /* i/o: CNG handle */ + float bwe_exc_extended[], /* i/o: bandwidth extended excitation */ + float *voice_factors, /* o : voicing factors */ + float pitch_buf[], /* o : floating pitch for each subframe */ + short vad_hover_flag, + short vad_flag_dtx +); + +void pitch_pred_linear_fit( + const short nbLostCmpt, /* i: bfi counter */ + const short last_good, /* i: last classification type */ + float *old_pitch_buf, /* i: pitch lag buffer */ + float *old_fpitch, /* i/o: pitch used for initial ACB generation */ + float *T0_out, /* o: estimated close loop pitch */ + int pit_min, /* i: Minimum pitch lag */ + int pit_max, /* i: Maximum pitch lag */ + float *mem_pitch_gain, /* i: lag pitch gain [0] is the most recent subfr lag */ + int limitation, + short plc_use_future_lag, /* i: number of subframes to predict */ + short *extrapolationFailed /* o: flag if extrap decides not to change the pitch */ + ,int nb_subfr /* i: number of ACELP subframes */ +); + +void get_subframe_pitch( + int nSubframes, /* i: number of subframes */ + float pitchStart, /* i: starting pitch lag (in subframe -1) */ + float pitchEnd, /* i: ending pitch lag (in subframe nSubframes-1) */ + float *pitchBuf /* o: interpolated pitch lag per subframe */ +); + + +void core_encode_openloop( + Encoder_State *st, /* i/o: encoder state structure */ + const short coder_type, /* i : coding type */ + const short pitch[3], /* i : open-loop pitch values for quantiz. */ + const float voicing[3], /* i : open-loop pitch gains */ + const float Aw[NB_SUBFR16k*(M+1)], /* i : weighted A(z) unquant. for subframes*/ + const float lsp_new[M], /* i : LSPs at the end of the frame */ + const float lsp_mid[M], /* i : LSPs at the middle of the frame */ + float *pitch_buf, /* i/o: floating pitch values for each subfr*/ + float *voice_factors, /* o : voicing factors */ + float *bwe_exc, /* o : excitation for SWB TBE */ + const short vad_hover_flag, + const short vad_flag_dtx +); + +void core_acelp_tcx20_switching( + Encoder_State *st, /* i/o: encoder state structure */ + const short vad_flag, + short sp_aud_decision0, + float non_staX, + short *pitch, /* i : open-loop pitch values for quantiz. */ + float *pitch_fr, /* i/o: fraction pitch values */ + float *voicing_fr, /* i/o: fractional voicing values */ + const float currTempFlatness, /* i : flatness */ + const float lsp_mid[M], /* i : LSPs at the middle of the frame */ + const float stab_fac /* i : LP filter stability */ +); + +void core_encode_twodiv( + const float new_samples[], /* i : new samples */ + Encoder_State *st, /* i/o: encoder state structure */ + const short coder_type, /* i : coding type */ + const short pitch[3], /* i : open-loop pitch values for quantiz. */ + const float voicing[3], /* i : open-loop pitch gains */ + float Aw[NB_SUBFR16k*(M+1)] /* i : weighted A(z) unquant. for subframes*/ +); + +void core_encode_update( + Encoder_State *st /* i/o: encoder state structure */ +); + +void core_encode_update_cng( + Encoder_State *st, /* i/o: encoder state structure */ + float *timeDomainBuffer, + float *A, + const float Aw[] /* i : weighted A(z) unquant. for subframes*/ +); + +void core_signal_analysis_high_bitrate( + const float *new_samples, + const short T_op[3], /* i : open-loop pitch values for quantiz. */ + const float voicing[3], /* i : open-loop pitch gains */ + const short pitch_12k8[2], /* i : open-loop pitch @12.8kHz for adapt. lag windowing */ + float lsp[], + float lsp_mid[], + Encoder_State *st, + int pTnsSize[], + int pTnsBits[], + int param_core[], + int *ltpBits, + int L_frame + ,int L_frameTCX +); + + +float get_gain( /* output: codebook gain (adaptive or fixed) */ + float x[], /* input : target signal */ + float y[], /* input : filtered codebook excitation */ + int n, /* input : segment length */ + float *en_y /* output: energy of y (sum of y[]^2, optional) */ +); + +void encode_acelp_gains( + float *code, + int gains_mode, + float mean_ener_code, + short clip_gain, + ACELP_CbkCorr *g_corr, + float *gain_pit, + float *gain_code, + int **pt_indice, + float *past_gcode, + float *gain_inov, + int L_subfr, + float *code2, + float *gain_code2, + short noisy_speech_flag +); + +int Mode2_gain_enc_mless( + const float *code, /* i : algebraic excitation */ + int lcode, /* i : Subframe size */ + float *gain_pit, /* o : quantized pitch gain */ + float *gain_code, /* o : quantized codebook gain */ + ACELP_CbkCorr *coeff, /* i/o: correlations , -2,, -2 and 2 */ + float mean_ener, /* i : mean_ener defined in open-loop (3 bits) */ + const short clip_gain, /* i : gain pitch clipping flag (1 = clipping) */ + float *past_gcode, /* i/o: past gain of code */ + float *gain_inov, /* o : unscaled innovation gain */ + const short coder_type /* i : type of coder */ +); + +void decode_acelp_gains( + float *code, + int gains_mode, + float mean_ener_code, + float *gain_pit, + float *gain_code, + int **pt_indice, + float *past_gpit, + float *past_gcode, + float *gain_inov, + int L_subfr, + float *code2, + float *gain_code2 +); + +void Es_pred_dec( + float *Es_pred, /* o : predicited scaled innovation energy */ + const int enr_idx, /* i : indice */ + const short nb_bits, /* i : number of bits */ + const short no_ltp /* i : no LTP flag */ +); + +void Mode2_pit_encode( + short coder_type, /* i : coding model */ + short i_subfr, /* i : subframe index */ + int **pt_indice, /* i/o: quantization indices pointer */ + float *exc, /* i/o: pointer to excitation signal frame */ + const short *T_op, /* i : open loop pitch estimates in current frame */ + int *T0_min, /* i/o: lower limit for close-loop search */ + int *T0_min_frac, /* i/o: lower limit for close-loop search */ + int *T0_max, /* i/o: higher limit for close-loop search */ + int *T0_max_frac, /* i/o: higher limit for close-loop search */ + int *T0, /* i/o: close loop integer pitch */ + int *T0_frac, /* i/o: close loop fractional part of the pitch */ + int *T0_res, /* i/o: close loop pitch resolution */ + float *h1, /* i : weighted filter impulse response */ + float *xn, /* i : target vector */ + int pit_min, + int pit_fr1, + int pit_fr1b, + int pit_fr2, + int pit_max, + int pit_res_max +); + +void limit_T0_voiced( + int nbits, + int res, + int T0, /* i : rough pitch estimate around which the search is done */ + int T0_frac, /* i : pitch estimate fractional part */ + int T0_res, /* i : pitch resolution */ + int *T0_min, /* o : lower pitch limit */ + int *T0_min_frac, /* o : lower pitch limit */ + int *T0_max, /* o : higher pitch limit */ + int *T0_max_frac, /* o : higher pitch limit */ + int pit_min, /* i : Minimum pitch lag */ + int pit_max /* i : Maximum pitch lag */ +); + +void Mode2_abs_pit_enc( + short T0, /* i : integer pitch lag */ + int T0_frac, /* i : pitch fraction */ + int **pt_indice, /* i/o: pointer to Vector of Q indexes */ + short pit_min, + short pit_fr1, + short pit_fr2, + short pit_res_max +); + +void Mode2_delta_pit_enc( + short T0, /* i : integer pitch lag */ + int T0_frac, /* i : pitch fraction */ + int T0_res, /* i : pitch resolution */ + short T0_min, /* i/o: delta search min */ + short T0_min_frac, /* i/o: delta search min */ + int **pt_indice /* i/o: pointer to Vector of Q indexes */ +); + +float Mode2_pit_decode( /* o: floating pitch value */ + const short coder_type, /* i: coding model */ + short i_subfr, /* i: subframe index */ + int L_subfr, + int **pt_indice, /* i/o: quantization indices pointer */ + int *T0, /* o: close loop integer pitch */ + int *T0_frac, /* o: close loop fractional part of the pitch */ + int *T0_res, /* i/o: pitch resolution */ + int *T0_min, /* i/o: lower limit for close-loop search */ + int *T0_min_frac, /* i/o: lower limit for close-loop search */ + int *T0_max, /* i/o: higher limit for close-loop search */ + int *T0_max_frac, /* i/o: higher limit for close-loop search */ + int pit_min, + int pit_fr1, + int pit_fr1b, + int pit_fr2, + int pit_max, + int pit_res_max +); + +void Mode2_abs_pit_dec( + int *T0, /* o: integer pitch lag */ + int *T0_frac, /* o: pitch fraction */ + int *T0_res, /* o: pitch resolution */ + int **pt_indice, /* i/o: pointer to Vector of Q indexes */ + int pit_min, + int pit_fr1, + int pit_fr2, + int pit_res_max +); + +void Mode2_delta_pit_dec( + int *T0, /* o: integer pitch lag */ + int *T0_frac, /* o: pitch fraction */ + int T0_res, /* i: pitch resolution */ + int *T0_min, /* i: delta search min */ + int *T0_min_frac, /* i: delta search min */ + int **pt_indice /* i/o: pointer to Vector of Q indexes */ +); + +void formant_post_filt( + PFSTAT *pfstat, /* i/o: Post filter related memories */ + float *synth_in, /* i : 12k8 synthesis */ + const float *Aq, /* i : LP filter coefficient */ + float *synth_out, /* i/o: input signal */ + const short L_frame, /* i : frame length */ + const short L_subfr, /* i : sub-frame length */ + const float lp_noise, /* i : background noise energy */ + const long rate, /* i : bit-rate */ + const short off_flag /* i : Off flag */ +); + +void qlpc_avq( + const float *lsp, /* (i) Input LSF vectors */ + const float *lspmid, + float *lsf_q, /* (o) Quantized LFS vectors */ + float *lsfmid_q, + int *index, /* (o) Quantization indices */ + int *nb_indices, /* (o) Number of quantization indices */ + int *nbbits, /* (o) Number of quantization bits */ + int core, + float sr_core +); + +int encode_lpc_avq( + Encoder_State *st, + int numlpc, + int *param_lpc, + int mode +); + +int dlpc_avq( + int *index, /* (i) Quantization indices */ + float *LSF_Q, /* (o) Quantized LSF vectors */ + int numlpc, /* (i) Number of sets of lpc */ + float sr_core +); + +int decode_lpc_avq( Decoder_State *st, int numlpc, int *param_lpc ); + +int vlpc_1st_cod( /* output: codebook index */ + const float *lsf, /* input: vector to quantize */ + float *lsfq, /* i/o: i:prediction o:quantized lsf */ + float sr_core + ,float *w /* o: lsf weights */ +); + +int vlpc_2st_cod( /* output: number of allocated bits */ + const float *lsf, /* input: normalized vector to quantize */ + float *lsfq, /* i/o: i:1st stage o:1st+2nd stage */ + int *indx, /* output: index[] (4 bits per words) */ + int mode, /* input: 0=abs, >0=rel */ + float sr_core +); + +void vlpc_2st_dec( + float *lsfq, /* i/o: i:1st stage o:1st+2nd stage */ + int *indx, /* input: index[] (4 bits per words) */ + int mode, /* input: 0=abs, >0=rel */ + float sr_core +); + +void lsf_weight_2st( + const float *lsfq, + float *w, + int mode, + float sr_core +); + +void mdct_window_sine( + float *window, + int n +); + +void mdct_window_aldo( + float *window1, + float *window2, + int n +); + +void AVQ_cod_lpc( + const float nvec[], /* i: vector to quantize */ + int nvecq[], /* o: quantized normalized vector (assuming the bit budget is enough) */ + int *indx, /* o: index[] (4 bits per words) */ + const short Nsv /* i: number of subvectors (lg=Nsv*8) */ +); + +void AVQ_dec_lpc( + const int indx[], /* i : index[] (4 bits per words) */ + int nvecq[], /* o : vector quantized */ + const short Nsv /* i : number of subvectors (lg=Nsv*8) */ +); + +void vlpc_1st_dec( + int index, /* input: codebook index */ + float *lsfq, /* i/o: i:prediction o:quantized lsf */ + float sr_core +); + +void WindowSignal( + TCX_config const *tcx_cfg, /* input: configuration of TCX */ + int offset, /* input: left folding point offset relative to the input signal pointer */ + const short left_overlap_mode, /* input: overlap mode of left window half */ + const short right_overlap_mode, /* input: overlap mode of right window half */ + int * left_overlap_length, /* output: TCX window left overlap length */ + int * right_overlap_length, /* output: TCX window right overlap length */ + float const in[], /* input: input signal */ + int * L_frame, /* input/output: frame length */ + float out[], /* output: output windowed signal */ + int fullband /* input: fullband flag */ +); + +void HBAutocorrelation( + TCX_config *tcx_cfg, /* input: configuration of TCX */ + int left_mode, /* input: overlap mode of left window half */ + int right_mode, /* input: overlap mode of right window half */ + float speech[], /* input: speech */ + int L_frame_glob, /* input: frame length */ + float *r, /* output: autocorrelations vector */ + int m /* input : order of LP filter */ +); + +void TNSAnalysis( + TCX_config *tcx_cfg, /* input: configuration of TCX */ + int L_frame, /* input: frame length */ + int L_spec, + const short tcxMode, /* input: TCX mode for the frame/subframe - TCX20 | TCX10 | TCX 5 (meaning 2 x TCX 5) */ + int isAfterACELP, /* input: Flag indicating if the last frame was ACELP. For the second TCX subframe it should be 0 */ + float spectrum[], /* input: MDCT spectrum of the subframe */ + STnsData * pTnsData, /* output: Tns data */ + int * pfUseTns, /* output: Flag indicating if TNS is used */ + float* predictionGain +); + +void ShapeSpectrum( + TCX_config *tcx_cfg,/*input: configuration of TCX*/ + float A[], /* input: quantized coefficients NxAz_q[M+1] */ + float gainlpc[], /* output: MDCT gains for the previous frame */ + int L_frame_glob, /* input: frame length */ + int L_spec, + float spectrum[], /* i/o: MDCT spectrum */ + int fUseTns, /* output: Flag indicating if TNS is used */ + Encoder_State *st +); + +void QuantizeSpectrum( + TCX_config *tcx_cfg,/*input: configuration of TCX*/ + float A[], /* input: quantized coefficients NxAz_q[M+1] */ + Word16 Aqind[], /* input: frame-independent quantized coefficients (M+1) */ + float gainlpc[], /* input: MDCT gains of the previous frame */ + float synth[], + int L_frame_glob, /* input: frame length */ + int L_frameTCX_glob, + int L_spec, + int nb_bits, /*input: bit budget*/ + int tcxonly, /*input: only TCX flag*/ + float spectrum[], /* i/o: MDCT spectrum, input is shaped MDCT spectrum */ + STnsData * pTnsData,/* input: Tns data */ + int fUseTns, /* input: Flag indicating if TNS is used */ + int tnsSize, /* input: number of tns parameters put into prm */ + LPD_state *LPDmem, /*i/o: memories*/ + int prm[], /* output: tcx parameters */ + int frame_cnt, /* input: frame counter in the super_frame */ + Encoder_State *st, + CONTEXT_HM_CONFIG *hm_cfg +); + +/* Returns: index of next coefficient */ +int get_next_coeff_mapped( + int ii[2], /* i/o: coefficient indexes */ + int *pp, /* o : peak(1)/hole(0) indicator */ + int *idx, /* o : index in unmapped domain */ + CONTEXT_HM_CONFIG *hm_cfg /* i : HM configuration */ +); + +/* Returns: index of next coefficient */ +int get_next_coeff_unmapped( + int *ii, /* i/o: coefficient index */ + int *idx /* o : index in unmapped domain */ +); + +int update_mixed_context( + int ctx, + int a +); + +void ACcontextMapping_encode2_no_mem_s17_LC( + Encoder_State *st, + int *x, + int nt, + int lastnz, + int nbbits, + int resQMaxBits, + CONTEXT_HM_CONFIG *hm_cfg +); + +long ACcontextMapping_decode2_no_mem_s17_LC( + Decoder_State *st, /* i/o: decoder state */ + int *x, /* o: decoded spectrum */ + long nt, /* i: size of spectrum */ + int nbbits, /* i: bit budget */ + int resQMaxBits, /* i: residual coding maximum bits */ + CONTEXT_HM_CONFIG *hm_cfg /* i: context-based harmonic model configuration*/ +); + +int ACcontextMapping_encode2_estimate_no_mem_s17_LC( + const int *x, + int nt, + int *lastnz, + int *nEncoded, + int target, + int *stop, + CONTEXT_HM_CONFIG *hm_cfg +); + +void tcx_windowing_analysis( + float const *signal, /* i: signal vector */ + int L_frame, /* i: frame length */ + int left_overlap, /* i: left overlap length */ + float const *left_win, /* i: left overlap window */ + int right_overlap, /* i: right overlap length */ + float const *right_win, /* i: right overlap window */ + float *output /* o: windowed signal vector */ +); + +void tcx_windowing_synthesis_current_frame( + float *signal, /* i/o: signal vector */ + float *window, /* i: TCX window vector */ + float *window_half, /* i: TCX window vector for half-overlap window */ + float *window_min, /* i: TCX minimum overlap window */ + int window_length, /* i: TCX window length */ + int window_half_length, /* i: TCX half window length */ + int window_min_length, /* i: TCX minimum overlap length */ + int left_rect, /* i: left part is rectangular */ + int left_mode, /* i: overlap mode of left window half */ + float *acelp_zir, /* i: acelp ZIR */ + float *old_syn, /* i: old synthesis */ + float *syn_overl, /* i: overlap synthesis */ + float *A_zir, + float *window_trans, /* i: window for transition from ACELP */ + int acelp_zir_len, + int acelp_mem_len, + int last_core_bfi, /* i : last mode */ + int last_is_cng, + int fullbandScale +); + +void tcx_windowing_synthesis_past_frame( + float *signal, /* i/o: signal vector */ + float *window, /* i: TCX window vector */ + float *window_half, /* i: TCX window vector for half-overlap window */ + float *window_min, /* i: TCX minimum overlap window */ + int window_length, /* i: TCX window length */ + int window_half_length, /* i: TCX half window length */ + int window_min_length, /* i: TCX minimum overlap length */ + int right_mode /* i: overlap mode (left_mode of current frame) */ +); + +/* tcx_utils_enc.c */ +void ProcessIGF( + IGF_ENC_INSTANCE_HANDLE const hInstance, /**< in: instance handle of IGF Encoder */ + Encoder_State *st, /**< in: Encoder state */ + float *pMDCTSpectrum, /**< in: MDCT spectrum */ + float *pPowerSpectrum, /**< in: MDCT^2 + MDST^2 spectrum, or estimate */ + int isTCX20, /**< in: flag indicating if the input is TCX20 or TCX10/2xTCX5 */ + int isTNSActive, /**< in: flag indicating if the TNS is active */ + int isTransition, /**< in: flag indicating if the input is the transition from from ACELP to TCX20/TCX10 */ + int frameno /**< in: flag indicating index of current subframe */ +); + +/* tcx_utils_enc.c */ +void AnalyzePowerSpectrum( + Encoder_State *st, /* i/o: encoder states */ + int L_frame, /* input: frame length */ + int L_frameTCX, /* input: full band frame length */ + int left_overlap, /* input: left overlap length */ + int right_overlap, /* input: right overlap length */ + float const mdctSpectrum[], /* input: MDCT spectrum */ + float const signal[], /* input: windowed signal corresponding to mdctSpectrum */ + float powerSpec[] /* output: Power spectrum */ +); + +void lpc2mdct( + float *lpcCoeffs, + int lpcOrder, + float *mdct_gains +); + +void mdct_preShaping( + float x[], + int lg, + const float gains[] +); + +void mdct_noiseShaping( + float x[], + int lg, + const float gains[] +); + +void mdct_noiseShaping_interp( + float x[], + int lg, + const float gains[] +); + +void AdaptLowFreqEmph( + float x[], + int xq[], + float invGain, + short tcx_lpc_shaped_ari, + const float lpcGains[], + const int lg +); + +void PsychAdaptLowFreqEmph( + float x[], + const float lpcGains[] +); + +void PsychAdaptLowFreqDeemph( + float x[], + const float lpcGains[], + float lf_deemph_factors[] +); + +void AdaptLowFreqDeemph( + float x[], + short tcx_lpc_shaped_ari, + const float lpcGains[], + const int lg, + float lf_deemph_factors[] +); + +float SQ_gain( /* output: SQ gain */ + float x[], /* input: vector to quantize */ + int nbitsSQ, /* input: number of bits targeted */ + int lg /* input: vector size (2048 max) */ +); + +void tcx_scalar_quantization( + float *x, /* i: input coefficients */ + int *xq, /* o: quantized coefficients */ + int L_frame, /* i: frame length */ + float gain, /* i: quantization gain */ + float offset, /* i: rounding offset (deadzone) */ + int *memQuantZeros, /* o: coefficients set to 0 */ + const int alfe_flag +); + +int tcx_scalar_quantization_rateloop( + float *x, /* i : input coefficients */ + int *xq, /* o : quantized coefficients */ + int L_frame, /* i : frame length */ + float *gain, /* i/o: quantization gain */ + float offset, /* i : rounding offset (deadzone) */ + int *memQuantZeros, /* o : coefficients set to 0 */ + int *lastnz_out, /* i/o: last nonzero coeff index */ + int target, /* i : target number of bits */ + int *nEncoded, /* o : number of encoded coeff */ + int *stop, /* i/o: stop param */ + int sqBits_in_noStop, /* i : number of sqBits as determined in prev. quant. stage, w/o using stop mechanism (ie might exceed target bits) */ + int sqBits_in, /* i : number of sqBits as determined in prev. quant. stage, using stop mechanism (ie always <= target bits) */ + int tcxRateLoopOpt, /* i : turns on/off rateloop optimization */ + const int tcxonly, + CONTEXT_HM_CONFIG *hm_cfg +); + +void QuantizeGain( + int n, + float * pGain, + int * pQuantizedGain +); + +void tcx_noise_factor( + float *x_orig, /* i: unquantized mdct coefficients */ + float *sqQ, /* i: quantized mdct coefficients */ + int iFirstLine, /* i: first coefficient to be considered */ + int lowpassLine, /* i: last nonzero coefficients after low-pass */ + int nMinHoleSize, /* i: minimum size of hole to be checked */ + int L_frame, /* i: frame length */ + float gain_tcx, /* i: tcx gain */ + float tiltCompFactor, /* i: LPC tilt compensation factor */ + float *fac_ns, /* o: noise factor */ + int *quantized_fac_ns /* o: quantized noise factor */ +); + +void tcx_noise_filling( + float *Q, + const int noiseFillSeed, + const int iFirstLine, + const int lowpassLine, + const int nTransWidth, + const int L_frame, + float tiltCompFactor, + float fac_ns, + unsigned char *infoTCXNoise +); + +void tcx_encoder_memory_update( + const float *wsig, /* i : target weighted signal */ + float *xn_buf, /* i/o: mdct output buffer/TD weigthed synthesis */ + int L_frame_glob, /* i: global frame length */ + const float *Ai, /* i: Unquantized (interpolated) LPC coefficients */ + float *A, /* i: Quantized LPC coefficients */ + float preemph, /* i: preemphasis factor*/ + LPD_state *LPDmem, /* i/o: coder memory state */ + Encoder_State *st, + int m, + float *synth +); + +void tcx_decoder_memory_update( + float *xn_buf, /* i: mdct output buffer */ + float *synth, /* i/o: synth */ + int L_frame_glob, /* i: global frame length */ + float *A, /* i: Quantized LPC coefficients */ + Decoder_State *st, /* i/o : decoder memory state */ + float *syn /* o: st->syn */ +); + + + +int tcx_ari_res_Q_spec( /* Returns: number of bits used (including "bits") */ + const float x_orig[], /* i: original spectrum */ + const int signs[], /* i: signs (x_orig[.]<0) */ + float x_Q[], /* i/o: quantized spectrum */ + int L_frame, /* i: number of lines */ + float gain, /* i: TCX gain */ + int prm[], /* o: bit-stream */ + int target_bits, /* i: number of bits available */ + int bits, /* i: number of bits used so far */ + float deadzone, /* i: quantizer deadzone */ + const float x_fac[] /* i: spectrum post-quantization factors */ +); + +int tcx_ari_res_invQ_spec(/* Returns: number of bits used (including "bits") */ + float x_Q[], /* i/o: quantized spectrum */ + int L_frame, /* i: number of lines */ + const int prm[], /* i: bit-stream */ + int target_bits, /* i: number of bits available */ + int bits, /* i: number of bits used so far */ + float deadzone, /* i: quantizer deadzone */ + const float x_fac[] /* i: spectrum post-quantization factors */ +); + +int tcx_res_Q_gain( + float sqGain, + float *gain_tcx, + int *prm, + int sqTargetBits +); + +int tcx_res_Q_spec( + float *x_orig, + float *x_Q, + int L_frame, + float sqGain, + int *prm, + int sqTargetBits, + int bits, + float sq_round, + const float lf_deemph_factors[] +); + +int tcx_res_invQ_gain( + float *gain_tcx, + const int *prm, + int resQBits +); + +int tcx_res_invQ_spec( + float *x, + int L_frame, + const int *prm, + int resQBits, + int bits, + float sq_round, + const float lf_deemph_factors[] +); + +void InitTnsConfigs( + int nSampleRate, + int L_frame, + STnsConfig tnsConfig[2][2], + int igfStopFreq, + int bitrate +); + +void SetTnsConfig( + TCX_config * tcx_cfg, + int isTCX20, + int isAfterACELP +); + +void ari_copy_states( + Tastat *source, + Tastat *dest +); + +long mul_sbc_14bits( + long r, + long c +); + +void ari_start_encoding_14bits( + Tastat *s +); + +long ari_encode_14bits( + short *ptr, + long bp, + Tastat *s, + long symbol, + unsigned short *cum_freq +); + +long ari_encode_14bits_ext( + int *ptr, + long bp, + Tastat *s, + long symbol, + const unsigned short *cum_freq +); + +long ari_done_encoding_14bits( + int *ptr, + long bp, + Tastat *s +); + +short ari_encode_check_budget_14bits( + long bp, + Tastat *s, + long nb_bits +); + +void ari_start_decoding_14bits( + Decoder_State *st, + Tastat *s +); + +long ari_start_decoding_14bits_prm( + const int *ptr, + long bp, + Tastat *s +); + +void ari_decode_14bits_s17_ext( + Decoder_State *st, + int *res, + Tastat *s, + const unsigned short *cum_freq +); + +void ari_decode_14bits_s27_ext( + Decoder_State *st, + int *res, + Tastat *s, + const unsigned short *cum_freq +); + +void ari_decode_14bits_bit_ext( + Decoder_State *st, + int *res, + Tastat *s +); + +Word16 expfp( /* o: Q15 */ + Word16 x, /* i: mantissa Q15-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 */ +); + +long ari_encode_14bits_range( + int *ptr, + long bp, + long bits, + Tastat *s, + unsigned short cum_freq_low, + unsigned short cum_freq_high +); + +long ari_encode_14bits_sign( + int *ptr, + long bp, + long bits, + Tastat *s, + long sign +); + +long ari_done_cbr_encoding_14bits( + int *ptr, + long bp, + long bits, + Tastat *s +); + +long ari_decode_14bits_pow( + const int *ptr, + long bp, + long bits, + int *res, + Tastat *s, + unsigned base +); + +long ari_decode_14bits_sign( + const int *ptr, + long bp, + long bits, + int *res, + Tastat *s +); + +void tcx_arith_encode_envelope( + float spectrum[], /* i/o: MDCT coefficients */ + int signs[], /* o: signs (spectrum[.]<0) */ + int L_frame, /* i: frame or MDCT length */ + int L_frame_orig, /* i: length w/o BW limitation */ + Encoder_State *st, /* i/o: coder state */ + const Word16 A_ind[], /* i: quantised LPC coefficients */ + int target_bits, /* i: number of available bits */ + int prm[], /* o: bitstream parameters */ + int use_hm, /* i: use HM in current frame? */ + int prm_hm[], /* o: HM parameter area */ + short tcxltp_pitch, /* i: TCX LTP pitch in FD, -1 if n/a*/ + int *arith_bits, /* o: bits used for ari. coding */ + int *signaling_bits /* o: bits used for signaling */ + ,int low_complexity /* i: low-complexity flag */ +); + +void tcx_arith_decode_envelope( + float q_spectrum[], /* o: quantised MDCT coefficients */ + int L_frame, /* i: frame or MDCT length */ + int L_frame_orig, /* i: length w/o BW limitation */ + Decoder_State *st, /* i/o: coder state */ + const short coder_type, /* i : coder type */ + const Word16 A_ind[], /* i: quantised LPC coefficients */ + float tcxltp_gain, /* i: TCX LTP gain */ + int target_bits, /* i: number of available bits */ + const int prm[], /* i: bitstream parameters */ + int use_hm, /* i: use HM in current frame? */ + const int prm_hm[], /* i: HM parameter area */ + short tcxltp_pitch, /* i: TCX LTP pitch in FD, -1 if n/a*/ + int *arith_bits, /* o: bits used for ari. coding */ + int *signaling_bits /* o: bits used for signaling */ + ,int low_complexity /* i: low-complexity flag */ +); + +void UnmapIndex( + int PeriodicityIndex, + int Bandwidth, + short LtpPitchLag, + int SmallerLags, + int *FractionalResolution, + int *Lag +); + +int SearchPeriodicityIndex( /* Returns: PeriodicityIndex */ + const float Mdct[], /* (I) Coefficients, Mdct[0..NumCoeffs-1] */ + const float UnfilteredMdct[], /* (I) Unfiltered coefficients, UnfilteredMdct[0..NumCoeffs-1] */ + int NumCoeffs, /* (I) Number of coefficients */ + int TargetBits, /* (I) Target bit budget (excl. Done flag) */ + short LtpPitchLag, + float LtpGain, /* (I) LTP gain */ + float *RelativeScore /* (O) Energy concentration factor */ +); + +void ConfigureContextHm( + int NumCoeffs, /* (I) Number of coefficients */ + int TargetBits, /* (I) Target bit budget (excl. Done flag) */ + int PeriodicityIndex, /* (I) Pitch related index */ + short LtpPitchLag, /* (I) TCX-LTP pitch in F.D. */ + CONTEXT_HM_CONFIG *hm_cfg /* (O) Context-based harmonic model configuration */ +); + +int EncodeIndex( + int Bandwidth, /* 0: NB, 1: (S)WB */ + int PeriodicityIndex, + Encoder_State *st +); + +int CountIndexBits( + int Bandwidth, /* 0: NB, 1: (S)WB */ + int PeriodicityIndex +); + +int DecodeIndex( + Decoder_State *st, + int Bandwidth, /* 0: NB, 1: (S)WB */ + int *PeriodicityIndex +); + + +#define GET_ADJ(T,L) GET_ADJ2(T,L,*FractionalResolution) +#define GET_ADJ2(T,L,F) (((L) << (F)) - (T)) + +int tcx_hm_render( + int lag, /* i: pitch lag */ + int fract_res, /* i: fractional resolution of the lag */ + float LtpGain, /* i: LTP gain */ + Word16 p[] /* o: harmonic model (Q13) */ +); + +void tcx_hm_modify_envelope( + Word16 gain, /* i: HM gain (Q11) */ + int lag, + int fract_res, + Word16 p[], /* i: harmonic model (Q13) */ + Word32 env[], /* i/o: envelope (Q16) */ + int L_frame /* i: number of spectral lines */ +); + +void tcx_hm_analyse( + const float abs_spectrum[], /* i: absolute spectrum */ + int L_frame, /* i: number of spectral lines */ + Word32 env[], /* i/o: envelope shape (Q16) */ + int targetBits, /* i: target bit budget */ + int coder_type, /* i: GC/VC mode */ + int prm_hm[], /* o: HM parameters */ + short LtpPitchLag, /* i: LTP pitch lag or -1 if none */ + float LtpGain, /* i: LTP gain */ + int *hm_bits /* o: bit consumption */ +); + +void tcx_hm_decode( + int L_frame, /* i: number of spectral lines */ + Word32 env[], /* i/o: envelope shape (Q16) */ + int targetBits, /* i: target bit budget */ + int coder_type, /* i: GC/VC mode */ + const int prm_hm[], /* i: HM parameters */ + short LtpPitchLag, /* i: LTP pitch lag or -1 if none */ + float LtpGain , /* i: LTP gain */ + int *hm_bits /* o: bit consumption */ +); + +void coder_tcx( + int n, + TCX_config *tcx_cfg, /* input: configuration of TCX */ + float A[], /* input: quantized coefficients NxAz_q[M+1] */ + Word16 Aqind[], /* input: frame-independent quantized coefficients (M+1) */ + float synth[], + int L_frame_glob, /* input: frame length */ + int L_frameTCX_glob, + int L_spec, + int nb_bits, /* input: bit budget */ + int tcxonly, /* input: only TCX flag */ + float spectrum[], /* i/o: MDCT spectrum */ + LPD_state *LPDmem, /* i/o: memories */ + int prm[], /* output: tcx parameters */ + Encoder_State *st, + CONTEXT_HM_CONFIG *hm_cfg +); + +void coder_tcx_post( + Encoder_State *st, + LPD_state *LPDmem, + TCX_config *tcx_cfg, + float *synth, + float *A, + const float *Ai, + float *wsig +); + +void decoder_tcx( + TCX_config *tcx_cfg, /* input: configuration of TCX */ + int prm[], /* input: parameters */ + float A[], /* input: coefficients NxAz[M+1] */ + Word16 Aind[], /* input: frame-independent coefficients Az[M+1] */ + int L_frame, /* input: frame length */ + int L_frameTCX, + int L_spec, + float synth[], /* in/out: synth[-M..lg] */ + float synthFB[], + Decoder_State *st, /* i/o : coder memory state */ + const short coder_type, + int bfi, /* input: Bad frame indicator */ + int frame_cnt, /* input: frame counter in the super_frame */ + float stab_fac /* input: stability of isf */ +); + +void decoder_tcx_post( + Decoder_State *st, + float *synth, + float *synthFB, + float *A, + int bfi +); + +void coder_acelp( + ACELP_config *acelp_cfg, /* i/o: configuration of the ACELP */ + const short coder_type, /* i : coding type */ + const float A[], /* i : coefficients 4xAz[M+1] */ + const float Aq[], /* i : coefficients 4xAz_q[M+1] */ + const float speech[], /* i : speech[-M..lg] */ + float synth[], /* o : synthesis */ + LPD_state *LPDmem, /* i/o: ACELP memories */ + const float voicing[], /* i : open-loop LTP gain */ + const short T_op[], /* i : open-loop LTP lag */ + int *prm, /* o : acelp parameters */ + const float stab_fac, + Encoder_State *st, /* i/o : coder memory state */ + HANDLE_PLC_ENC_EVS hPlc_Ext, + const short target_bits, + float *gain_pitch_buf,/* o : gain pitch values */ + float *gain_code_buf, /* o : gain code values */ + float *pitch_buf, /* o : pitch values for each subfr.*/ + float *voice_factors, /* o : voicing factors */ + float *bwe_exc /* o : excitation for SWB TBE */ +); + +void coder_acelp_rf( + const short target_bits, /* i: target bits */ + const float speech[], /* i : speech[-M..lg] */ + const short coder_type, /* i : coding type */ + const short rf_frame_type, /* i : rf_frame_type */ + const float A[], /* i : coefficients 4xAz[M+1] */ + const float Aq[], /* i : coefficients 4xAz_q[M+1] */ + const float voicing[], /* i : open-loop LTP gain */ + const short T_op[], /* i : open-loop LTP lag */ + const float stab_fac, /* i : LP stability factor */ + Encoder_State *st, /* i/o: coder memory state */ + ACELP_config *acelp_cfg, /* i/o: configuration of the ACELP */ + float *exc_rf, /* i/o: pointer to RF excitation */ + float *syn_rf /* i/o: pointer to RF synthesis */ +); + +void decoder_acelp( + Decoder_State *st, /* i/o: coder memory state */ + const short coder_type, /* i : coder type */ + int prm[], /* i : parameters */ + const float A[], /* i : coefficients NxAz[M+1] */ + ACELP_config acelp_cfg, /* i : ACELP config */ + float synth[], /* i/o: synthesis */ + int *pT, /* o : pitch for all subframe */ + float *pgainT, /* o : pitch gain for all subfr */ + const float stab_fac /* i : stability of isf */ + ,float *pitch_buffer /* o : pitch values for each subfr.*/ + ,float *voice_factors /* o : voicing factors */ + ,const short LSF_Q_prediction/* i : LSF prediction mode */ + ,float *bwe_exc /* o : excitation for SWB TBE */ +); + +void enc_prm( + const short coder_type, /* i : coding type */ + int param[], /* i : parameters */ + int param_lpc[], /* i : LPC parameters */ + Encoder_State *st, /* i/o: quantization Analysis values*/ + const short L_Frame, /* i : frame length */ + CONTEXT_HM_CONFIG hm_cfg[], + short * bits_param_lpc, + short no_param_lpc +); + +void enc_prm_rf( + Encoder_State *st, + const short rf_frame_type, + const short fec_offset +); + +void dec_prm( + short *coder_type, /* o : coder type */ + int param[], /* (o) : decoded parameters */ + int param_lpc[], /* (i) : LPC parameters */ + Word16 *total_nbbits, /* i/o : number of bits / decoded bits */ + Decoder_State *st, /* i/o: decoder memory state */ + const int L_frame, + short * bitsRead +); + +void dec_prm_core( + Decoder_State *st +); + +void gauss_L2( + const float h[], /* i : weighted LP filter impulse response */ + float code[], /* o : gaussian excitation */ + float y2[], /* i : zero-memory filtered code. excitation */ + float y11[], /* o : zero-memory filtered gauss. excitation */ + float *gain, /* o : excitation gain */ + float g_corr[], /* i/o : correlation structure for gain coding */ + float gain_pit, /* i : unquantized gain of code */ + float tilt_code, /* i : tilt of code */ + const float *Aq, /* i : quantized LPCs */ + float formant_enh_num, /* i: formant enhancement factor */ + short *seed_acelp /*i/o: random seed */ +); + +void gaus_L2_dec( + float *code, /* o: decoded gaussian codevector */ + float tilt_code, + const float *A, + float formant_enh_num, + short *seed_acelp /*i/o: random seed */ +); + +float interpolation( /* o: interpolated value */ + const float *x, /* i: input vector */ + const float *win, /* i: interpolation window */ + const short frac, /* i: fraction */ + const short up_samp, /* i: upsampling factor */ + const short nb_coef /* i: nb of filter coef */ +); + +void predict_signal( + const float excI[], /* i : input excitation buffer */ + float excO[], /* o : output excitation buffer */ + const short T0, /* i : integer pitch lag */ + short frac, /* i : fraction of lag */ + const short frac_max,/* i : max fraction */ + const short L_subfr /* i : subframe size */ +); + +void tcx_ltp_encode( + int tcxltp_on, + int tcxOnly, + int tcxMode, + int L_frame, + int L_subfr, + float *speech, + float *speech_ltp, + float *wsp, + int Top, + int *ltp_param, + int *ltp_bits, + int *pitch_int, + int *pitch_fr, + float *gain, + int *pitch_int_past, + int *pitch_fr_past, + float *gain_past, + float *norm_corr_past, + int last_core, + int pitmin, + int pitfr1, + int pitfr2, + int pitmax, + int pitres, + struct TransientDetection const * pTransientDetection, + int SideInfoOnly, + float *A, + int lpcorder +); + +void tcx_ltp_post( int tcxltp_on, + short core, + int L_frame, + int L_frame_core, + int delay, + float *sig, + float *tcx_buf, + short tcx_buf_len, + int bfi, + int pitch_int, + int pitch_fr, + float gain, + int *pitch_int_past, + int *pitch_fr_past, + float *gain_past, + int *filtIdx_past, + int pitres, + int *pitres_past, + float damping, + int SideInfoOnly, + float *mem_in, + float *mem_out, + int bitrate + ); + +int tcx_ltp_decode_params( + int *ltp_param, + int *pitch_int, + int *pitch_fr, + float *gain, + int pitmin, + int pitfr1, + int pitfr2, + int pitmax, + int pitres +); + + +int enc_lsf_tcxlpc( + int **indices, /* i : Ptr to VQ indices */ + Encoder_State *st /* i/o: Encoder state */ +); + +void msvq_enc +( + const float *const *cb, /* i : Codebook (indexed cb[*stages][levels][p]) */ + const int dims[], /* i : Dimension of each codebook stage (NULL: full dim.) */ + const int offs[], /* i : Starting dimension of each codebook stage (NULL: 0) */ + float u[], /* i : Vector to be encoded (prediction and mean removed) */ + const int *levels, /* i : Number of levels in each stage */ + int maxC, /* i : Tree search size (number of candidates kept from */ + /* one stage to the next == M-best) */ + int stages, /* i : Number of stages */ + float w[], /* i : Weights */ + int N, /* i : Vector dimension */ + int maxN, /* i : Codebook dimension */ + int Idx[] /* o : Indices */ +); + +void msvq_dec +( + const float *const *cb, /* i : Codebook (indexed cb[*stages][levels][p]) */ + const int dims[], /* i : Dimension of each codebook stage (NULL: full dim.) */ + const int offs[], /* i : Starting dimension of each codebook stage (NULL: 0) */ + int stages, /* i : Number of stages */ + int N, /* i : Vector dimension */ + int maxN, /* i : Codebook dimension */ + const int Idx[], /* i : Indices */ + float *uq, /* o : quantized vector */ + Word16 *uq_ind /* o : quantized vector (fixed point) */ +); + + +void PulseResynchronization( + float const * src_exc, + float * dst_exc, + int nFrameLength, + int nSubframes, + float pitchStart, + float pitchEnd +); + + +void con_acelp( + float A[], /* i : coefficients NxAz[M+1] */ + int coder_type, /* i : ACELP coder type */ + float synth[], /* i/o: synthesis */ + int *pT, /* o : pitch for all subframe */ + float *pgainT, /* o : pitch gain for all subfr */ + float stab_fac, /* i : stability of isf */ + Decoder_State *st, /* i/o: coder memory state */ + float pitch_buffer[], /* i/o: floating pitch values for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *bwe_exc /* o : excitation for SWB TBE */ +); + +void con_tcx( + Decoder_State* st, /* i/o: coder memory state */ + float synth[] /* i/o: synth[] */ +); + +int tcxlpc_get_cdk( /* o : codebook index */ + int coder_type /* (I) GC/VC indicator */ +); + +int lsf_msvq_ma_encprm( + Encoder_State *st, + int *param_lpc, + int core, + int acelp_mode, + int acelp_midLpc, + short * bits_param_lpc, + short no_indices +); + +int lsf_msvq_ma_decprm( + Decoder_State *st, + int *param_lpc, + int core, + int acelp_mode, + int acelp_midLpc, + int narrowBand, + int sr_core +); + +int dec_lsf_tcxlpc( + Decoder_State *st, /* (I/O) Decoder state */ + int **indices, /* (O) Ptr to VQ indices */ + int narrowband, /* (I) narrowband flag */ + int cdk /* (I) codebook selector */ +); + +int D_lsf_tcxlpc( + const int indices[], /* (I) VQ indices */ + float lsf_q[], /* (O) quantized lsf */ + Word16 lsp_q_ind[], /* (O) quantized lsp (w/o MA prediction) */ + int narrowband, /* (I) narrowband flag */ + int cdk, /* (I) codebook selector */ + float mem_MA[] /* (I) MA memory */ +); + +void lsf_update_memory( + int narrowband, /* i : narrowband flag */ + const float qlsf[], /* i : quantized lsf coefficients */ + float old_mem_MA[], /* i : MA memory */ + float mem_MA[] /* o : updated MA memory */ +); + +int Q_lsf_tcxlpc( + /* const */ float lsf[], /* (I) original lsf */ + float lsf_q[], /* (O) quantized lsf */ + Word16 lsp_q_ind[], /* (O) quantized lsp (w/o MA prediction) */ + int indices[], /* (O) VQ indices */ + int narrowband, /* (I) narrowband flag */ + int cdk, /* (I) codebook selector */ + float mem_MA[], /* (I) MA memory */ + int coder_type, /* (I) acelp extended mode*/ + float *Bin_Ener /* (I) Spectrum energy*/ +); + +int E_LPC_lsp_unweight( + /* const */ float lsp_w[], /* (I): weighted lsp */ + float lsp_uw[], /* (O): unweighted lsp */ + float lsf_uw[], /* (O): unweighted lsf */ + float inv_gamma /* (I): inverse weighting factor */ +); + +int lsf_ind_is_active( + const Word16 lsf_q_ind[], + const float means[], + int bandwidth, + int cdk +); + +void midlsf_enc( + float qlsf0[], + float qlsf1[], + const float lsf[], + short *idx, + int N, + float *Bin_Ener, + int narrowBand, + int sr_core, + int coder_type +); + +void midlsf_dec( + float qlsf0[], + float qlsf1[], + short idx, + float qlsf[], + int N, + int coder_type, + short *mid_lsf_int, + short prev_bfi, + short safety_net +); + +void lsf_end_enc( + Encoder_State *st, + const float *lsf, + float *qlsf, + float *mem_AR, + float *mem_MA, + const short nBits, + const short coder_type_org, + const short bwidth, + float *Bin_Ener, + const float int_fs, + long core_brate, + float *streaklimit, + short *pstreaklen, + short force_sf, + short rf_flag, + short mode2_flag, + int * lpc_param, + short * no_stages, + short * bits_param_lpc, + short coder_type_raw +); + +void lsf_end_dec( + Decoder_State *st, + const short coder_type_org, + const short bwidth, + const short nBits, + float *qlsf, + float *mem_AR, + float *mem_MA, + const float int_fs, + long core_brate, + unsigned int *p_offset_scale1, + unsigned int *p_offset_scale2, + unsigned int *p_offset_scale1_p, + unsigned int *p_offset_scale2_p, + short *p_no_scales, + short *p_no_scales_p, + short *safety_net, + int *lpc_param, + short *LSF_Q_prediction, /* o : LSF prediction mode */ + int * nb_indices +); + +short find_pred_mode( + const short coder_type, + const short bwidth, + const float int_fs, + short * p_mode_lvq, + short * p_mode_lvq_p, + short core_brate +); + +void lpc_quantization( + Encoder_State * st, + int core, + int lpcQuantization, + float lsf_old[], + const float lsp[], + const float lspmid[], + float lsp_q[], + float lsf_q[], + float lspmid_q[], + float mem_MA[], + float mem_AR[], + int narrowBand, + short coder_type, + int acelp_midLpc, + int param_lpc[], + int nbits_lpc[], + short *seed_acelp, + int sr_core, + float *Bin_Ener, + float *Bin_Ener_old, + short * bits_param_lpc, + short * no_param_lpc +); + +void lpc_unquantize( + Decoder_State * st, + float *lsfold, + float *lspold, + float *lsf, + float *lsp, + int lpcQuantization, + int *param_lpc, + int numlpc, + int core, + float *mem_MA, + float *lspmid, + float *lsfmid, + short coder_type, + int acelp_midLpc, + int narrow_band, + short *seed_acelp, + int sr_core, + short *mid_lsf_int, + short prev_bfi, + short *LSF_Q_prediction, /* o : LSF prediction mode */ + short *safety_net +); + +void dlpc_bfi( + int L_frame, + float *lsf_q, /* o : quantized lsfs */ + const float *lsfold, /* i : past quantized lsf */ + const short last_good, /* i : last good received frame */ + const short nbLostCmpt, /* i : counter of consecutive bad frames */ + float mem_MA[], /* i/o: quantizer memory for MA model */ + float mem_AR[], /* i/o: quantizer memory for MA model */ + float *stab_fac, /* i : lsf stability factor */ + float *lsf_adaptive_mean,/* i : lsf adaptive mean, updated when BFI==0 */ + int numlpc, /* i : Number of division per superframe */ + float lsf_cng[], + int plcBackgroundNoiseUpdated, + float *lsf_q_cng, /* o : quantized lsfs of background noise */ + float *old_lsf_q_cng, /* o : old quantized lsfs for background noise */ + const float lsfBase[] /* i : base for differential lsf coding */ +); + +int decode_lpc_stoch(short *ptr, + int numlpc, + int *param_lpc, + int mode, + int lpc_quant_type, + short *isf_model, + int *isf_end_nbits, + int *isf_mid_nbits + ); + +void lsfi_enc( + float qisf0[], + float qisf1[], + float isf[], + short *idx +); + +void lsfi_dec( + float qisf0[], + float qisf1[], + short idx, + float qisf[] +); + +void lsf_dec_bfi( + short codec_mode, /* i: : codec_mode: MODE1 | MODE2 */ + float *lsf, /* o : estimated LSF vector */ + const float *lsfold, /* i : past quantized lsf */ + float *lsf_adaptive_mean, /* i : lsf adaptive mean, updated when BFI==0 */ + const float lsfBase[], /* i : base for differential lsf coding */ + float *mem_MA, /* i/o: quantizer memory for MA model */ + float *mem_AR, /* o : quantizer memory for AR model */ + float stab_fac, /* i : lsf stability factor */ + short last_coder_type, /* i : last coder type */ + short L_frame, /* i : frame length */ + const short last_good, /* i : last good received frame */ + const short nbLostCmpt, /* i : counter of consecutive bad frames */ + int plcBackgroundNoiseUpdated, /* i : background noise already updated? */ + float *lsf_q_cng, /* o : quantized lsfs of background noise */ + float *lsf_cng, /* i : long term target for fading to bg noise*/ + float *old_lsf_q_cng, /* o : old quantized lsfs for background noise*/ + short Last_GSC_pit_band_idx, /* i : AC mode (GSC) - Last pitch band index */ + short Opt_AMR_WB, /* i : IO flag */ + const short MODE1_bwidth /* i : coded bandwidth */ +); + +float const * PlcGetlsfBase( + int const lpcQuantization, + int const narrowBand, + int const sr_core +); + +void Unified_weighting( + float Bin_Ener_128[], /* i : FFT Bin energy 128 bins in two sets */ + const float lsf[], /* i : LSF vector */ + float w[], /* o : LP weighting filter (numerator) */ + const short narrowBand, /* i : flag for Narrowband */ + const short unvoiced, /* i : flag for Unvoiced frame */ + const short sr_core, /* i : sampling rate of core-coder */ + const int order /* i : LP order */ +); + +short vad_init( + T_CldfbVadState *st +); + +short vad_proc( + float realValues[16][60], /* CLDFB real values */ + float imagValues[16][60], /* CLDFB imag values */ + float *sb_power, /* Energy of CLDFB data */ + int numBands, /* number of input bands */ + T_CldfbVadState *vad_st, /* VAD state */ + short *cldfb_addition, + short vada_flag +); + +void subband_FFT( + float Sr[16][60], /*(i) real part */ + float Si[16][60], /*(i) imag part */ + float *spec_amp /*(o) spectral amplitude*/ +); + +int update_decision( + T_CldfbVadState *st, + float snr, /*(i) frequency domain SNR */ + float tsnr, /*(i) time domain SNR */ + float frame_energy, /*(i) current frame energy */ + float high_eng, /*(i) current frame high frequency energy*/ + int vad_flag, + int music_backgound_f /*(i) background music flag */ +); + +void frame_spec_dif_cor_rate( + float spec_amp[], /*(i) spectral amplitude */ + float pre_spec_low_dif[], /*(io) low spectrum different*/ + float f_tonality_rate[] /*(o) tonality rate*/ +); + +void ltd_stable( + float frames_power[], /*(io) energy of several frames*/ + float ltd_stable_rate[], /*(o) time-domain stable rate*/ + float frame_energy, /*(i) current frame energy*/ + int frameloop /*(i) number of frames*/ +); + +void SNR_calc( + float frame_sb_energy[], /*(i) energy of sub-band divided non-uniformly*/ + float sb_bg_energy[], /*(i) sub-band background energy*/ + float t_bg_energy, /*(i) time background energy of several frames*/ + float *snr, /*(o) frequency domain SNR */ + float *tsnr, /*(o) time domain SNR */ + float frame_energy, /*(i) current frame energy */ + int bandwidth /*(i) band width*/ +); + + + + +void background_update( + T_CldfbVadState *st, + float frame_energy, /*(i) current frame energy 2*/ + int update_flag, /*(i) current frame update flag*/ + int music_backgound_f /*(i) background music flag*/ + , float snr +); + +void bg_music_decision( + T_CldfbVadState *st, + int *music_backgound_f, /*(i) background music flag*/ + float frame_energy /*(i) current frame energy 1*/ +); + +void est_energy( + float sb_power[], /*(o) energy of sub-band divided uniformly*/ + float frame_sb_energy[], /*(o) energy of sub-band divided non-uniformly*/ + float *p_frame_energy, /*(o) frame energy 1*/ + float *p_frame_energy2, /*(o) frame energy 2*/ + float *p_high_energy, /*(o) high frequency energy*/ + int bw /*(i) band width*/ +); + +void spec_center( + float spec_power[], /*(i) energy of sub-band divided uniformly*/ + float sp_center[], /*(o) spectral center*/ + int bandwidth /*(i) band width*/ +); + +void spec_flatness( + float spec_amp[], /*(i) spectral amplitude*/ + float smooth_spec_amp[], /*(i) smoothed spectral amplitude*/ + float sSFM[] /*(o) spectral flatness rate*/ +); + +int vad_decision( + T_CldfbVadState *st, + float snr , /*(i) frequency domain SNR */ + float tsnr, /*(i) time domain SNR */ + float snr_flux, /*(i) average tsnr of several frames*/ + float lt_snr, /*(i)long time SNR calculated by fg_energy and bg_energy*/ + float lt_snr_org, /*(i)original long time SNR*/ + float lf_snr, /*(i) long time frequency domain SNR calculated by l_speech_snr and l_silence_snr*/ + float frame_energy, /*(i) current frame energy */ + int music_backgound_f /*(i) background music flag*/ +); + +int comvad_decision( + T_CldfbVadState *st, + float snr, /*(i) frequency domain SNR */ + float tsnr, /*(i) time domain SNR */ + float snr_flux, /*(i) average tsnr of several frames*/ + float lt_snr, /*(i) long time SNR calculated by fg_energy and bg_energy*/ + float lt_snr_org, /*(i) original long time SNR*/ + float lf_snr, /*(i) long time frequency domain + SNR calculated by l_speech_snr and l_silence_snr*/ + float frame_energy, /*(i) current frame energy */ + int music_backgound_f, /*(i) background music flag*/ + short *cldfb_addition, + short vada_flag +); + +void calc_snr_flux( + float tsnr, /*(i) time-domain SNR*/ + float pre_snr[], /*(io) time-domain SNR storage*/ + float *snr_flux /*(o) average tsnr*/ +); + +void calc_lt_snr( + float *lt_snr_org, /*(o)original long time SNR*/ + float *lt_snr, /*(o)long time SNR calculated by fg_energy and bg_energy*/ + float fg_energy, /*(i)foreground energy sum */ + int fg_energy_count, /*(i) number of the foreground energy frame */ + float bg_energy, /*(i)background energy sum */ + int bg_energy_count, /*(i) number of the background energy frame */ + int bw_index, /*(i) band width index*/ + float lt_noise_sp_center0 /*(i)long time noise spectral center by 0*/ +); + +void calc_lf_snr( + float *lf_snr_smooth, /*(o) smoothed lf_snr*/ + float *lf_snr, /*(o) long time frequency domain SNR calculated by l_speech_snr and l_silence_snr*/ + float l_speech_snr, /*(i) sum of active frames snr */ + int l_speech_snr_count, /*(i) number of the active frame */ + float l_silence_snr, /*(i) sum of the nonactive frames snr*/ + int l_silence_snr_count, /*(i) number of the nonactive frame */ + int fg_energy_count, /*(i) number of the foreground energy frame */ + int bg_energy_count, /*(i) number of the background energy frame */ + int bw_index /*(i) band width index*/ +); + +float construct_snr_thresh( + float sp_center[], /*(i) spectral center*/ + float snr_flux, /*(i) snr flux*/ + float lt_snr, /*(i) long time time domain snr*/ + float lf_snr, /*(i) long time frequency domain snr*/ + int continuous_speech_num, /*(i) continuous speech number*/ + int continuous_noise_num, /*(i) continuous noise number*/ + int fg_energy_est_start, /*(i) whether if estimated energy*/ + int bw_index /*(i) band width index*/ +); + +void createFdCngCom( + HANDLE_FD_CNG_COM* hFdCngCom +); + +void deleteFdCngCom( + HANDLE_FD_CNG_COM * hFdCngCom +); + +void initFdCngCom( + HANDLE_FD_CNG_COM hs, /* i/o: Contains the variables related to the FD-based CNG process */ + float scale +); + +void initPartitions( + const int * part_in, + int npart_in, + int startBand, + int stopBand, + int * part_out, + int * npart_out, + int * midband, + float * psize, + float * psize_inv, + int stopBandFR +); + +void minimum_statistics( + int len, /* i : Vector length */ + int lenFFT, /* i : Length of the FFT part of the vectors */ + float * psize, + float * msPeriodog, /* i : Periodograms */ + float * msNoiseFloor, + float * msNoiseEst, /* o : Noise estimates */ + float * msAlpha, + float * msPsd, + float * msPsdFirstMoment, + float * msPsdSecondMoment, + float * msMinBuf, + float * msBminWin, + float * msBminSubWin, + float * msCurrentMin, + float * msCurrentMinOut, + float * msCurrentMinSubWindow, + int * msLocalMinFlag, + int * msNewMinFlag, + float * msPeriodogBuf, + int * msPeriodogBufPtr, + HANDLE_FD_CNG_COM st /* i/o: FD_CNG structure containing all buffers and variables */ +); + +void generate_comfort_noise_enc( + Encoder_State *stcod +); + +void generate_comfort_noise_dec( + float ** bufferReal, /* o : Real part of input bands */ + float ** bufferImag, /* o : Imaginary part of input bands */ + Decoder_State *stdec +); + +void generate_comfort_noise_dec_hf( + float ** bufferReal, /* o : Real part of input bands */ + float ** bufferImag, /* o : Imaginary part of input bands */ + Decoder_State *stdec +); + +void generate_masking_noise( + float * timeDomainBuffer, /* i/o: time-domain signal */ + HANDLE_FD_CNG_COM st, /* i/o: FD_CNG structure containing all buffers and variables */ + short length, + short core +); + +void generate_masking_noise_update_seed( + HANDLE_FD_CNG_COM st /* i/o: FD_CNG structure containing all buffers and variables */ +); + +void generate_masking_noise_mdct( + float * mdctBuffer, /* i/o: time-domain signal */ + HANDLE_FD_CNG_COM st /* i/o: FD_CNG structure containing all buffers and variables */ +); + +void apply_scale( + float *scale, + int bandwidth, + int bitrate +); + +void compress_range( + float* in, + float* out, + int len +); + +/* Apply some dynamic range expansion to undo the compression */ +void expand_range( + float* in, + float* out, + int len +); + +void bandcombinepow( + float* bandpow, /* i : Power for each band */ + int nband, /* i : Number of bands */ + int* part, /* i : Partition upper boundaries (band indices starting from 0) */ + int npart, /* i : Number of partitions */ + float* psize_inv, /* i : Inverse partition sizes */ + float* partpow /* o : Power for each partition */ +); + +void scalebands( + float* partpow, /* i : Power for each partition */ + int* part, /* i : Partition upper boundaries (band indices starting from 0) */ + int npart, /* i : Number of partitions */ + int* midband, /* i : Central band of each partition */ + int nFFTpart, /* i : Number of FFT partitions */ + int nband, /* i : Number of bands */ + float* bandpow, /* o : Power for each band */ + short flag_fft_en +); + +void getmidbands( + int* part, /* i : Partition upper boundaries (band indices starting from 0) */ + int npart, /* i : Number of partitions */ + int* midband, /* o : Central band of each partition */ + float* psize, /* o : Partition sizes */ + float* psize_inv /* o : Inverse of partition sizes */ +); + +void AnalysisSTFT( + const float * timeDomainInput, + float * fftBuffer, /* o : FFT bins */ + HANDLE_FD_CNG_COM st /* i/o: FD_CNG structure containing all buffers and variables */ +); + +void SynthesisSTFT( + float * fftBuffer, + float * timeDomainOutput, + float * olapBuffer, + const float * olapWin, + int tcx_transition, HANDLE_FD_CNG_COM st +); + +void rand_gauss( + float *x, + short *seed +); + +void lpc_from_spectrum( + float* powspec, + int start, + int stop, + int fftlen, + const float *fftSineTab, + float *A, + float preemph_fac +); + +void createFdCngDec( + HANDLE_FD_CNG_DEC* hFdCngDec +); + +void deleteFdCngDec( + HANDLE_FD_CNG_DEC * hFdCngDec +); + +void initFdCngDec( + HANDLE_FD_CNG_DEC hs, /* i/o: Contains the variables related to the FD-based CNG process */ + float scale /* i: scaling factor */ +); +void configureFdCngDec( + HANDLE_FD_CNG_DEC hs, /* i/o: Contains the variables related to the FD-based CNG process */ + short bandwidth, + int bitrate, + short L_frame +); + +void configure_noise_estimation_dec( + HANDLE_FD_CNG_DEC st /* i/o: FD_CNG structure containing all buffers and variables */ +); + +void ApplyFdCng( + float * timeDomainInput, + float ** realBuffer, /* i/o: Real part of the buffer */ + float ** imagBuffer, /* i/o: Imaginary part of the buffer */ + HANDLE_FD_CNG_DEC st, /* i/o: FD_CNG structure containing all buffers and variables */ + unsigned char m_frame_type, /* i : Type of frame at the decoder side */ + Decoder_State *stdec, + const int concealWholeFrame, /* i : binary flag indicating frame loss */ + short is_music +); + +void perform_noise_estimation_dec( + const float * timeDomainInput, + HANDLE_FD_CNG_DEC st /* i/o: FD_CNG structure containing all buffers and variables */ +); + +void FdCng_decodeSID( + Decoder_State *st /* i/o: decoder state structure */ +); + +void FdCng_exc( + HANDLE_FD_CNG_COM hs, + short *CNG_mode, + short L_frame, + float *lsp_old, + short first_CNG, + float *lsp_CNG, + float *Aq, /* o: LPC coeffs */ + float *lsp_new, /* o: lsp */ + float *lsf_new, /* o: lsf */ + float *exc, /* o: LP excitation */ + float *exc2, /* o: LP excitation */ + float *bwe_exc /* o: LP excitation for BWE */ +); + +void noisy_speech_detection( + const short vad, + const float * ftimeInPtr, /* i : input time-domain frame */ + const int frameSize, /* i : frame size */ + const float * msNoiseEst, /* i : noise estimate over all critical bands */ + const float * psize, /* i : partition sizes */ + const int nFFTpart, /* i : Number of partitions taken into account */ + float *lp_noise, /* i/o: long term total Noise energy average */ + float *lp_speech, /* i/o: long term active speech energy average */ + short *flag_noisy_speech +); + + +void createFdCngEnc( + HANDLE_FD_CNG_ENC* hFdCngEnc +); + +void deleteFdCngEnc( + HANDLE_FD_CNG_ENC * hFdCngEnc +); + +void configureFdCngEnc( + HANDLE_FD_CNG_ENC hs, /* i/o: Contains the variables related to the FD-based CNG process */ + short bandwidth, + int bitrate +); + +void initFdCngEnc( + HANDLE_FD_CNG_ENC hs, /* i/o: Contains the variables related to the FD-based CNG process */ + int input_Fs, /* i: input signal sampling frequency in Hz */ + float scale /* i: scaling factor */ +); + +void resetFdCngEnc( + Encoder_State * st +); + +void perform_noise_estimation_enc( + float *band_energies, /* i: energy in critical bands without minimum noise floor E_MIN */ + float *enerBuffer, + HANDLE_FD_CNG_ENC st +); + +void AdjustFirstSID( + int npart, + float * msPeriodog, + float * energy_ho, + float * msNoiseEst, + float * msNoiseEst_old, + short * active_frame_counter, + Encoder_State *stcod +); + +void FdCng_encodeSID( + HANDLE_FD_CNG_ENC st, /* i/o: FD_CNG structure containing all buffers and variables */ + Encoder_State *corest, + float preemph_fac +); + +void GetParameters( + ParamsBitMap const * paramsBitMap, + int nParams, + void const * pParameter, + int ** pStream, + int * pnSize, + int * pnBits +); + +void SetParameters( + ParamsBitMap const * paramsBitMap, + int nParams, + void * pParameter, + int const ** pStream, + int * pnSize +); + +void WriteToBitstream( + ParamsBitMap const * paramsBitMap, + int nParams, + int const ** pStream, + int * pnSize, Encoder_State *st, + int * pnBits +); + +void ReadFromBitstream( + ParamsBitMap const * paramsBitMap, + int nArrayLength, + Decoder_State *st, + int ** pStream, + int * pnSize +); + +void const * GetTnsFilterOrder(void const * p, int index, int * pValue); +void * SetTnsFilterOrder(void * p, int index, int value); +void const * GetNumOfTnsFilters(void const * p, int index, int * pValue); +void * SetNumOfTnsFilters(void * p, int index, int value); +void const * GetTnsEnabled(void const * p, int index, int * pValue); +void * SetTnsEnabled(void * p, int index, int value); +void const * GetTnsEnabledSingleFilter(void const * p, int index, int * pValue); +void * SetTnsEnabledSingleFilter(void * p, int index, int value); +void const * GetTnsFilterCoeff(void const * p, int index, int * pValue); +void * SetTnsFilterCoeff(void * p, int index, int value); + +int GetSWBTCX10TnsFilterCoeffBits(int value, int index); +int EncodeSWBTCX10TnsFilterCoeff(int value, int index); +int DecodeSWBTCX10TnsFilterCoeff(Decoder_State *st, int index, int * pValue); +int GetSWBTCX20TnsFilterCoeffBits(int value, int index); +int EncodeSWBTCX20TnsFilterCoeff(int value, int index); +int DecodeSWBTCX20TnsFilterCoeff(Decoder_State *st, int index, int * pValue); + +int GetWBTCX20TnsFilterCoeffBits(int value, int index); +int EncodeWBTCX20TnsFilterCoeff(int value, int index); +int DecodeWBTCX20TnsFilterCoeff(Decoder_State *st, int index, int * pValue); + +int GetTnsFilterOrderBitsSWBTCX10(int value, int index); +int EncodeTnsFilterOrderSWBTCX10(int value, int index); +int DecodeTnsFilterOrderSWBTCX10(Decoder_State *st, int index, int * pValue); +int GetTnsFilterOrderBitsSWBTCX20(int value, int index); +int EncodeTnsFilterOrderSWBTCX20(int value, int index); +int DecodeTnsFilterOrderSWBTCX20(Decoder_State *st, int index, int * pValue); +int GetTnsFilterOrderBits(int value, int index); +int EncodeTnsFilterOrder(int value, int index); +int DecodeTnsFilterOrder(Decoder_State *st, int index, int * pValue); + +void ResetTnsData( + STnsData * pTnsData +); + +void ClearTnsFilterCoefficients( + STnsFilter * pTnsFilter +); + +TNS_ERROR InitTnsConfiguration( + int nSampleRate, + int frameLength, + STnsConfig * pTnsConfig, + int igfStopFreq, + int bitrate +); + +int DetectTnsFilt( + STnsConfig const * pTnsConfig, + float const pSpectrum[], + STnsData * pTnsData, + float* predictionGain +); + +TNS_ERROR ApplyTnsFilter( + STnsConfig const * pTnsConfig, + STnsData const * pTnsData, + float spectrum[], + int fIsAnalysis +); + +int ITF_Detect( + float const pSpectrum[], + short int startLine, + short int stopLine, + int maxOrder, + float* A, + float* predictionGain, + int* curr_order +); + +TNS_ERROR ITF_Apply( + float spectrum[], + short int startLine, + short int stopLine, + const float* A, + int curr_order +); + +TNS_ERROR EncodeTnsData( + STnsConfig const * pTnsConfig, + STnsData const * pTnsData, + int * stream, + int * pnSize, + int * pnBits +); + +int DecodeTnsData( + STnsConfig const * pTnsConfig, + int const * stream, + int * pnSize, + STnsData * pTnsData +); + +TNS_ERROR WriteTnsData( + STnsConfig const * pTnsConfig, + int const * stream, + int * pnSize, + Encoder_State *st, + int * pnBits +); + +TNS_ERROR ReadTnsData( + STnsConfig const * pTnsConfig, + Decoder_State * st, + int * pnBits, + int * stream, + int * pnSize +); + +void cldfbAnalysis ( + const float *timeIn, /* i : time buffer */ + float **realBuffer, /* o : real value buffer */ + float **imagBuffer, /* o : imag value buffer */ + int samplesToProcess, /* i : number of input samples */ + HANDLE_CLDFB_FILTER_BANK h_cldfb /* i : filterbank state */ +); + +void cldfbSynthesis ( + float **realBuffer, /* i : real values */ + float **imagBuffer, /* i : imag values */ + float *timeOut, /* o : synthesized output */ + int samplesToProcess, /* i : number of samples */ + HANDLE_CLDFB_FILTER_BANK h_cldfb /* i : filter bank state */ +); + +void analysisCldfbEncoder ( + Encoder_State *st, /* i/o: encoder state structure */ + const float *timeIn, + int samplesToProcess, + float realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + float imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + float *ppBuf_Ener +); + +int openCldfb ( + HANDLE_CLDFB_FILTER_BANK *h_cldfb, /* i/o : filter bank handle */ + CLDFB_TYPE type, /* i : analysis or synthesis */ + int samplerate /* i : max samplerate to oeprate */ +); + +void resampleCldfb ( + HANDLE_CLDFB_FILTER_BANK hs, /* i/o : filter bank handle */ + int newSamplerate /* i : new samplerate to operate */ +); + +int cldfb_save_memory( + HANDLE_CLDFB_FILTER_BANK hs /* i/o : filter bank handle */ +); + +int cldfb_restore_memory( + HANDLE_CLDFB_FILTER_BANK hs /* i/o : filter bank handle */ +); + +int cldfb_reset_memory ( + HANDLE_CLDFB_FILTER_BANK hs /* i/o : filter bank handle */ +); + +void deleteCldfb( + HANDLE_CLDFB_FILTER_BANK *h_cldfb /* i/o : filter bank handle */ +); + +void fft_cldfb ( + float *data, /* i/o: input/output vector */ + int size /* size of fft operation */ +); + +void BITS_ALLOC_init_config_acelp( + int bit_rate, + int narrowBand, + int nb_subfr, + ACELP_config *acelp_cfg /*o: configuration structure of ACELP*/ +); + +int BITS_ALLOC_config_acelp( + const int bits_frame, /* i : remaining bit budget for the frame */ + const short coder_type, /* i : acelp extended mode index */ + ACELP_config *acelp_cfg, /* i/o: configuration structure of ACELP */ + const short narrowband, /* i : narrowband flag */ + const short nb_subfr /* i : number of subframes */ +); + +void FEC_clas_estim( + const float *syn, + const float *pitch, /* i : pitch values for each subframe */ + const short L_frame, /* i : length of the frame */ + const short coder_type, /* i : coder type */ + const short codec_mode, /* i : codec mode */ + float *mem_syn_clas_estim, /* i/o: memory of the synthesis signal for frame class estimation */ + short *clas, /* i/o: frame classification */ + float *lp_speech, /* i/o: long term active speech energy average */ + long const bitrate, /* i : Decoded bitrate */ + short const Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + short *decision_hyst, /* i/o: hysteresis of the music/speech decision */ + short *locattack, /* i/o: detection of attack (mainly to localized speech burst) */ + short *UV_cnt, /* i/o: number of consecutives frames classified as UV */ + float *LT_UV_cnt, /* i/o: long term consecutives frames classified as UV */ + float *Last_ener, /* i/o: last_energy frame */ + short *amr_io_class, /* i/o: classification for AMR-WB IO mode */ + float *lt_diff_etot, /* i/o: long-term total energy variation */ + float *class_para, /* o : classification para. fmerit1 */ + const float LTP_Gain, /* i : */ + const int narrowBand, /* i : */ + const SIGNAL_CLASSIFIER_MODE mode,/* i : */ + const int bfi, /* i : */ + const float preemph_fac, /* i : */ + const int tcxonly, /* i : */ + const int last_core_brate /* i : last core bitrate */ +); + +void InitTransientDetection( + int nFrameLength, + int nTCXDelay, + struct TransientDetection * pTransientDetection +); + +void RunTransientDetection( + float const * input, + int nSamplesAvailable, + struct TransientDetection * pTransientDetection +); + +float GetTCXAvgTemporalFlatnessMeasure( + struct TransientDetection const * pTransientDetection, + int nCurrentSubblocks, + int nPrevSubblocks +); + +float GetTCXMaxenergyChange( + struct TransientDetection const * pTransientDetection, + const int isTCX10, + const int nCurrentSubblocks, + const int nPrevSubblocks +); + +void SetTCXModeInfo( + Encoder_State *st, /* i/o: encoder state structure */ + struct TransientDetection const * pTransientDetection, + short * tcxModeOverlap +); + +void TCX_MDCT( + float const *x, + float *y, + int l, + int m, + int r +); + +void TCX_MDST( + float const *x, + float *y, + int l, + int m, + int r +); + +void TCX_MDCT_Inverse( + float *x, + float *y, + int l, + int m, + int r +); + +void post_decoder( + Decoder_State *st, + const short coder_type, /* i : coder type */ + float synth_buf[], + const float pit_gain[], + const int pitch[], + float signal_out[], + float bpf_noise_buf[] +); + +float bass_pf_enc( + const float *orig, /* (i) : 12.8kHz original signal */ + const float *syn, /* (i) : 12.8kHz synthesis to postfilter */ + const float pitch_buf[],/* (i) : Pitch gain for all subframes (gainT_sf[16]) */ + const float gainT_sf[], /* (i) : Pitch gain for all subframes (gainT_sf[16]) */ + const short l_frame, /* (i) : frame length (should be multiple of l_subfr)*/ + const short l_subfr_in, /* (i) : sub-frame length (60/64) */ + float mem_bpf[], /* i/o : memory state [2*L_FILT] */ + float mem_error_bpf[], /* i/o : memory state [2*L_FILT] */ + int *gain_factor_param, /* (o) : quantized gain factor */ + const short mode, /* (i) : coding mode of adapt bpf */ + float *mem_deemph_err, /* i/o : Error deemphasis memory */ + float *lp_ener /* i/o : long_term error signal energy */ +); + +void cldfb_synth_set_bandsToZero( + Decoder_State *st, + float **rAnalysis, + float **iAnalysis, + const short nTimeSlots +); + +void longadd( + unsigned short a[], + unsigned short b[], + int lena, + int lenb +); + +void longshiftright( + unsigned short a[], + int b, + unsigned short d[], + int lena, + int lend +); + +void longshiftleft( + unsigned short a[], + int b, + unsigned short d[], + int len +); + +void open_decoder_LPD( + Decoder_State *st, + const int bit_rate, + const int bandwidth +); + +void update_decoder_LPD_cng( + Decoder_State *st, + const short coder_type, /* i : coder type */ + float *timeDomainBuffer, + float *A, + float *bpf_noise_buf +); + +void reconfig_decoder_LPD( + Decoder_State *st, + int bits_frame, + int bandwidth, + int bitrate, + int L_frame_old +); + +void mode_switch_decoder_LPD( + Decoder_State *st, + int bandwidth_in, + int bitrate, + int frame_size_index +); + +void dec_acelp_tcx_frame( + Decoder_State *st, /* i/o: encoder state structure */ + short *coder_type, /* o : coder type */ + short *concealWholeFrame, /* i/o: concealment flag */ + float *output, /* o : synthesis */ + float *bpf_noise_buf, /* i/o: BPF noise buffer */ + float * pcmbufFB, + float bwe_exc_extended[], /* i/o: bandwidth extended excitation */ + float *voice_factors, /* o : voicing factors */ + float pitch_buf[] /* o : floating pitch for each subframe */ +); + +void decoder_LPD( + float signal_out[], /* output: signal with LPD delay (7 subfrs) */ + float signal_outFB[], + short *total_nbbits, /* i/o: number of bits / decoded bits */ + Decoder_State *st, /* i/o: decoder memory state pointer */ + float *bpf_noise_buf, /* i/o: BPF noise buffer */ + short bfi, /* i : BFI flag */ + short *bitsRead, /* o : number of read bits */ + short *coder_type, /* o : coder type */ + int param[], /* o : buffer of parameters */ + float *pitch_buf, /* i/o: floating pitch values for each subfr*/ + float *voice_factors, /* o : voicing factors */ + float *ptr_bwe_exc /* o : excitation for SWB TBE */ +); + + +int tcxGetNoiseFillingTilt( + float A[], + int L_frame, + int mode, + float *noiseTiltFactor +); + +void tcxFormantEnhancement( + float xn_buf[], + float gainlpc[], + float spectrum[], + int L_frame +); + +void tcxInvertWindowGrouping( + TCX_config *tcx_cfg, + float xn_buf[], + float spectrum[], + int L_frame, + int fUseTns, + int last_core, + int index, + int frame_cnt, + int bfi +); + +void lerp( + float *f, + float *f_out, + int bufferNewSize, + int bufferOldSize +); + +void coderLookAheadInnovation( + const float A[], /* input: coefficients NxAz[M+1] */ + int *pT, /* out: pitch */ + HANDLE_PLC_ENC_EVS hPlc_Ext, + float *speechLookAhead, + float *old_exc, + int L_subfr, + int L_frame +); + +void encoderSideLossSimulation( + Encoder_State *st, + HANDLE_PLC_ENC_EVS hPlc_Ext, + float *isf_q, + float stab_fac, + int calcOnlyISF, + int L_frame +); + +void enc_prm_side_Info( + HANDLE_PLC_ENC_EVS hPlc_Ext, + Encoder_State *st +); + +void GplcTcxEncSetup( + Encoder_State *st, + HANDLE_PLC_ENC_EVS hPlc_Ext +); + +short encSideSpecPowDiffuseDetector( + float *isf_ref, + float *isf_con, + int sr_core, + float *prev_isf4_mean, + short sw + ,short coder_type +); + +void updateSpecPowDiffuseIdx( + Encoder_State *st, + const float gain_pitch_buf[], /* i : gain pitch values */ + const float gain_code_buf[] /* i : gain pitch values */ +); + +void getLookAheadResSig( + float *speechLookAhead, + const float *A, + float *res, + int L_frame, + int L_subfr, + int m, + int numSubFrame +); + +void updatelsfForConcealment( + HANDLE_PLC_ENC_EVS decState, + float *lsf +); + +void getConcealedLP( + HANDLE_PLC_ENC_EVS memDecState, + float *AqCon, + const float xsfBase[], + const float sr_core, + int last_good, + int L_frame +); + + +void getConcealedlsf( + HANDLE_PLC_ENC_EVS memDecState, + const float lsfBase[], + int L_frame, int last_good +); + +void RecLpcSpecPowDiffuseLc( + float *ispq, + float *isp_old, + float *isfq, + Decoder_State *st + , int reset_q +); + +void modify_lsf( + float *lsf, + const short n, + const int sr_core + , int reset_q +); + +void open_PLC_ENC_EVS( + HANDLE_PLC_ENC_EVS hPlcExt, + int sampleRate +); + +void gPLC_encInfo( + HANDLE_PLC_ENC_EVS self, + const int brate, + const int bwidth, + const short last_clas, + const int coder_type +); + +void resetTecDec( + HANDLE_TEC_DEC hTecDec +); + +void updateTecBuf( + float** pCldfbRealSrc, + float** pCldfbImagSrc, + float** pCldfbRealTgt, + float** pCldfbImagTgt, + int noCols, + int lowSubband +); + +void calcGainTemp_TBE( + float** pCldfbRealSrc, + float** pCldfbImagSrc, + float* loBuffer, + int startPos, /*!< Start position of the current envelope. */ + int stopPos, /*!< Stop position of the current envelope. */ + int lowSubband, /* lowSubband */ + float* pGainTemp, + short code +); + +void procTecTfa_TBE( + float *hb_synth, + float *gain, + short flat_flag, + short last_core, + int L_subfr, + short code +); + +void resetTecEnc( + HANDLE_TEC_ENC hTecEnc, + int flag +); + +void calcHiEnvLoBuff( + int noCols, + const int* pFreqBandTable, /*!< freqbandTable. */ + int nSfb, /*!< Number of scalefactors. */ + float** pYBuf, + float* loBuf, + float* hiTempEnv +); + +void calcLoEnvCheckCorrHiLo( + int noCols, + const int* pFreqBandTable, /*!< freqbandTable. */ + float* loBuf, + float* loTempEnv, + float* loTempEnv_ns, + float* hiTempEnv, + int* corr_flag /* 0 for original, 1 for TEC */ +); + +void tfaCalcEnv( + const float* shb_speech, + float* enr +); + +short tfaEnc_TBE( + float* enr, + short last_core, + float* voicing, + float* pitch_buf +); + +void tecEnc_TBE( + int* corrFlag, + const float* voicing, + short coder_type +); + +void set_TEC_TFA_code( + const short corrFlag, + short* tec_flag, + short* tfa_flag +); + +float Damping_fact( + const short coder_type,/* i : ACELP core coding mode */ + int nbLostCmpt, /* i : compt for number of consecutive lost frame */ + short last_good, /* i : class of last good received frame */ + float stab_fac, /* i : LSF stability factor */ + float *lp_gainp, /* i/o: low passed pitch gain used for concealment */ + int core /* i : current core: ACELP = 0, TCX20 = 1, TCX10 = 2 */ +); + +void fer_energy( + const int L_frame, /* i : frame length */ + const short clas, /* i : frame classification */ + const float synth[], /* i : synthesized speech at Fs = 12k8 Hz */ + const float pitch, /* i : pitch period */ + float *enr, /* o : pitch-synchronous or half_frame energy */ + const short useOffset /* i : speech pointer offset (0 or L_FRAME) */ +); + +float getLevelSynDeemph( + float const h1Init[], /* i: input value or vector to be processed */ + float const A[], /* i: LPC coefficients */ + int const lenLpcExc, /* i: length of the LPC excitation buffer */ + float const preemph_fac, /* i: preemphasis factor */ + int const numLoops /* i: number of loops */ +); + +void genPlcFiltBWAdap( + int const sr_core, /* i: core sampling rate */ + float* lpFiltAdapt, /* o: filter coefficients for filtering codebooks in case of flc */ + int const type, /* i: type of filter, either 0 : lowpass or 1 : highpass */ + float const alpha /* i: fade out factor [0 1) used decrease filter tilt */ +); + +void highPassFiltering( + const short last_good, /* i: last classification type */ + const int L_buffer, /* i: buffer length */ + float exc2[], /* i/o: unvoiced excitation before the high pass filtering */ + const float hp_filt[], /* i: high pass filter coefficients */ + const int l_fir_fer /* i: high pass filter length */ +); + +int GetPLCModeDecision( + Decoder_State *st /* i/o: decoder memory state pointer */ +); + +void addBassPostFilter ( + const float *harm_timeIn, + int samplesToProcess, + float **rAnalysis, + float **iAnalysis, + HANDLE_CLDFB_FILTER_BANK cldfb +); + +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_Init( + TonalMDCTConcealPtr self, + unsigned int samplesPerBlock, + unsigned int nSamplesCore, + unsigned int nScaleFactors, + TCX_config * tcx_cfg +); + +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_SaveFreqSignal( + TonalMDCTConcealPtr self, + float const * mdctSpectrum, + unsigned int numSamples, + unsigned int nNewSamplesCore, + float const *scaleFactors +); + +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_UpdateState( + TonalMDCTConcealPtr self, + int numSamples, + float pitchLag, + int badBlock, + int tonalConcealmentActive +); + +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_SaveTimeSignal( + TonalMDCTConcealPtr self, + float* timeSignal, + unsigned int numSamples +); + +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_Detect( + TonalMDCTConcealPtr const self, /*IN */ + float const pitchLag, /*IN */ + int * const umIndices /*OUT*/ +); + +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_Apply( + TonalMDCTConcealPtr self, /*IN */ + float* mdctSpectrum /*OUT*/ +); + +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_InsertNoise( + TonalMDCTConcealPtr self, /*IN */ + float* mdctSpectrum, /*OUT*/ + int tonalConcealmentActive, + short * pSeed, /*IN/OUT*/ + float tiltCompFactor, + float crossfadeGain, + int crossOverFreq +); + +void DetectTonalComponents( + unsigned short int indexOfTonalPeak[], + unsigned short int lowerIndex[], + unsigned short int upperIndex[], + unsigned int * pNumIndexes, + float lastPitchLag, + float currentPitchLag, + float const lastMDCTSpectrum[], + float const scaleFactors[], + float const secondLastPowerSpectrum[], + unsigned int nSamples, + unsigned int nSamplesCore, + float floorPowerSpectrum +); + +void RefineTonalComponents( + unsigned short int indexOfTonalPeak[], + unsigned short int lowerIndex[], + unsigned short int upperIndex[], + float phaseDiff[], + float phases[], + unsigned int * pNumIndexes, + float lastPitchLag, + float currentPitchLag, + float const lastMDCTSpectrum[], + float const scaleFactors[], + float const secondLastPowerSpectrum[], + unsigned int nSamples, + unsigned int nSamplesCore, + float floorPowerSpectrum +); + +void concealment_init( + int N, + void *_plcInfo +); + +void concealment_decode( + int pre_transient, + float *invkoef, + void *_plcInfo +); + +void concealment_update( + int bfi, + int core, + int harmonic, + float *invkoef, + void *_plcInfo +); + +void concealment_update2( + float *outx_new, + void *_plcInfo, + int FrameSize +); + +void concealment_signal_tuning( + int bfi, + int curr_mode, + float *outx_new, + void *_plcInfo, + int nbLostCmpt, + int pre_bfi, + float *OverlapBuf, + int past_core_mode, + float *outdata2, + Decoder_State *st +); + +void waveform_adj2( + float *overlapbuf, + float *outx_new, + float *data_noise, + float *outx_new_n1, + float *nsapp_gain, + float *nsapp_gain_n, + float *recovery_gain, + float step_concealgain, + int pitch, + int Framesize, + int delay, + int bfi_cnt, + int bfi +); + + +float SFM_Cal( + float const fcoef[], + int n +); + +void set_state( + int *state, + int num, + int N +); + +void Shellsort_float( + float *in, + int n +); + +int RFFTN( + float *afftData, + const float* trigPtr, + int len, + int isign +); + + +void DoFFT( + float * re2, + float * im2, + short length +); + + +short getTcxonly( + const int bitrate +); + +short getTnsAllowed( + const int bitrate, + const short igf +); + +short getCtxHm( + const int bitrate, + const short rf_flag +); + +short getResq( + const int bitrate +); + +short getRestrictedMode( + const int bitrate, + const short Opt_AMR_WB +); + +short getMdctWindowLength( + const float fscale +); + +short sr2fscale( + const int sr +); + +int getCoreSamplerateMode2( + const int bitrate, + const int bandwidth, + const short rf_mode +); + +float getTcxBandwidth( + const int bandwidth +); + +short getIgfPresent( + const int bitrate, + const int bandwidth, + const short rf_mode +); + +short getCnaPresent( + const int bitrate, + const int bandwidth +); + +short getTcxLtp( + const int sr_core +); + +short initPitchLagParameters( + const int sr_core, + int *pit_min, + int *pit_fr1, + int *pit_fr1b, + int *pit_fr2, + int *pit_max +); + +void attenuateNbSpectrum( + int L_frame, + float *spectrum +); + +void SetModeIndex( + Encoder_State *st, + const long total_brate, + const short bwidth +); + +short getNumTcxCodedLines( + const short bwidth +); + +short getTcxLpcShapedAri( + const int total_brate, + const short bwidth, + const short rf_mode +); + +void IGFEncApplyMono( + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + const int igfGridIdx, /**< in: | IGF grid index */ + Encoder_State *st, /**< in: | Encoder state */ + float *pMDCTSpectrum, /**< in: | MDCT spectrum */ + float *pPowerSpectrum, /**< in: | MDCT^2 + MDST^2 spectrum, or estimate */ + int isTCX20, /**< in: | flag indicating if the input is TCX20 or TCX10/2xTCX5 */ + int isTNSActive, /**< in: | flag indicating if the TNS is active */ + int last_core_acelp /**< in: | indictaor if last frame was acelp coded */ +); + +void IGFEncConcatenateBitstream( + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + short bsBits, /**< in: | number of IGF bits written to list of indices */ + short *next_ind, /**< in/out: | pointer to actual bit indice */ + short *nb_bits, /**< in/out: | total number of bits already written */ + Indice *ind_list /**< 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 int bitRate, /**< in: | encoder bitrate */ + const int mode /**< in: | encoder bandwidth mode */ + , const int f_mode /**< in: | flag to signal the RF mode */ +); + +int IGFEncWriteBitstream( /**< out: | number of bits written per frame */ + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + void *st, /**< in: | encoder state */ + int *pBitOffset, /**< in: | ptr to bitOffset counter */ + const int igfGridIdx, /**< in: | igf grid index see declaration of IGF_GRID_IDX for details */ + const int isIndepFlag /**< in: | if 1 frame is independent, 0 = frame is coded with data from previous frame */ +); + +int IGFEncWriteConcatenatedBitstream( /**< out: | total number of bits written */ + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + void *st /**< in: | encoder state */ +); + +void IGFDecApplyMono( + const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + float *spectrum, /**< in/out: | MDCT spectrum */ + const int igfGridIdx, /**< in: | in case of CELP->TCX switching, use 1.25 framelength */ + int bfi /**< in: | frame loss == 1, frame good == 0 */ +); + +void IGFDecCopyLPCFlatSpectrum( + const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + const float *pSpectrumFlat, /**< in: | LPC flattend spectrum from TCX dec */ + const int igfGridIdx /**< in: | IGF grid index */ +); + +void IGFDecReadData( + const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Deccoder */ + Decoder_State *st, /**< in: | decoder state */ + const int igfGridIdx, /**< in: | in case of CELP->TCX switching, use 1.25 framelength */ + const int isIndepFrame /**< in: | if 1: arith dec force reset, if 0: no reset */ +); + +int IGFDecReadLevel( /**< out: | return igfAllZero flag indicating if no envelope is transmitted */ + const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Deccoder */ + Decoder_State *st, /**< in: | decoder state */ + const int igfGridIdx, /**< in: | in case of CELP->TCX switching, use 1.25 framelength */ + const int isIndepFrame /**< in: | 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 int subFrameIdx /**< in: | index of subframe */ +); + +void IGFDecSetMode( + const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + const int bitRate, /**< in: | bitrate */ + const int mode, /**< in: | bandwidth mode */ + const int defaultStartLine, /**< in: | default start subband index */ + const int defaultStopLine, /**< in: | default stop subband index */ + const int rf_mode /**< in: | flag to signal the RF mode */ +); + +void IGFDecStoreTCX10SubFrameData( + const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + const int subFrameIdx /**< in: | index of subframe */ +); + +void IGFDecUpdateInfo( + const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + const int igfGridIdx /**< in: | IGF grid index */ +); + +int IGFCommonFuncsIGFConfiguration( /**< out: | error value: 0 -> error, 1 -> ok */ + int bitRate, /**< in: | bitrate in bs e.g. 9600 for 9.6kbs */ + int mode, /**< in: | bandwidth mode */ + H_IGF_INFO hIGFInfo, /**< out: | IGF info handle */ + int rf_mode /**< in: | flag to signal the RF mode */ +); + +int IGFCommonFuncsIGFGetCFTables( /**< out: | error value: 0 -> error, 1 -> ok */ + int bitRate, /**< in: | bitrate in bs e.g. 9600 for 9.6kbs */ + int mode, /**< in: | bandwidth mode */ + int rf_mode, /**< in: | flag to signal the RF mode */ + const unsigned short **cf_se00, /**< out: | CF table for t == 0 and f == 0 */ + const unsigned short **cf_se01, /**< out: | CF table for t == 0 and f == 1 */ + short *cf_off_se01, /**< out: | offset for CF table above */ + const unsigned short **cf_se02, /**< out: | CF tables for t == 0 and f >= 2 */ + const short **cf_off_se02, /**< out: | offsets for CF tables above */ + const unsigned short **cf_se10, /**< out: | CF table for t == 1 and f == 0 */ + short *cf_off_se10, /**< out: | offset for CF table above */ + const unsigned short **cf_se11, /**< out: | CF tables for t == 1 and f >= 1 */ + const short **cf_off_se11 /**< out: | offsets for CF tables above */ +); + +void IGFCommonFuncsWriteSerialBit( + void *st, /**< in: | encoder/decoder state structure */ + int *pBitOffset, /**< out: | bit offset */ + int bit /**< in: | value of bit */ +); + + +void IGFSCFEncoderOpen( + IGFSCFENC_INSTANCE_HANDLE hPublicData, /**< inout: handle to public data */ + int scfCountLongBlock, + int bitRate, + int mode + , int rf_mode +); + +int IGFSCFEncoderReset( + IGFSCFENC_INSTANCE_HANDLE hPublicData /**< inout: handle to public data or NULL in case there was no instance created */ +); + +int IGFSCFEncoderEncode( + IGFSCFENC_INSTANCE_HANDLE hPublicData, /**< inout: handle to public data or NULL in case there was no instance created */ + Encoder_State *st, + int bitCount, /**< in: offset to the first bit in bitbuffer which should be readed by iisArithDecoderDecode function */ + int *sfe, /**< in: ptr to an array which contain quantized scalefactor energies */ + int indepFlag, /**< in: if 1 on input the encoder will be forced to reset, + if 0 on input the encodder will be forced to encode without a reset */ + int doRealEncoding /**< in: whether the real encoding is needed, otherwise only the number of bits is used */ +); + +void IGFSCFEncoderSaveContextState( + IGFSCFENC_INSTANCE_HANDLE hPublicData /**< inout: handle to public data or NULL in case there was no instance created */ +); + +void IGFSCFEncoderRestoreContextState( + IGFSCFENC_INSTANCE_HANDLE hPublicData /**< inout: handle to public data or NULL in case there was no instance created */ +); + +void IGFSCFDecoderOpen( + IGFSCFDEC_INSTANCE_HANDLE hPublicData, /**< inout: handle to public data */ + int scfCountLongBlock, + int bitRate, + int mode, + int rf_mode +); + +void IGFSCFDecoderReset( + IGFSCFDEC_INSTANCE_HANDLE hPublicData /**< inout: handle to public data or NULL in case there was no instance created */ +); + +void IGFSCFDecoderDecode( + IGFSCFDEC_INSTANCE_HANDLE hPublicData, /**< inout: handle to public data or NULL in case there was no instance created */ + Decoder_State *st, /**< inout: pointer to decoder state */ + int *sfe, /**< out: ptr to an array which will contain the decoded quantized coefficients */ + int indepFlag /**< in: if 1 on input the encoder will be forced to reset, + if 0 on input the encodder will be forced to encode without a reset */ +); + +short tbe_celp_exc_offset( + const short T0, /* i : Integer pitch */ + const short T0_frac /* i : Fractional part of the pitch */ +); + +void blend_subfr2( + float *sigIn1, /* i : input signal for fade-out */ + float *sigIn2, /* i : input signal for fade-in */ + float *sigOut /* o : output signal */ +); + + + +#endif diff --git a/lib_com/pvq_com.c b/lib_com/pvq_com.c new file mode 100644 index 000000000..e1875195f --- /dev/null +++ b/lib_com/pvq_com.c @@ -0,0 +1,919 @@ + + /*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + + #include + #include "options.h" + #include "cnst.h" + #include "rom_com.h" + #include "prot.h" + #include "stl.h" + #include "wmc_auto.h" + + /*-------------------------------------------------------------------* + * Local definitions + *-------------------------------------------------------------------*/ + + + typedef unsigned long long ui64_t; + + + short shrtCDivSignedApprox( + const short num, + const short den + ) + { + Word16 pool_part; + #define WMC_TOOL_SKIP + 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) towards zero is used */ + if ( num < 0 ) + { + pool_part = negate(pool_part); /* make negative, one op */ + } + #undef WMC_TOOL_SKIP + return pool_part; + } + + int intLimCDivPos( int NUM, + short DEN + ) + { + int result; + + #define WMC_TOOL_SKIP + result = (int )(((ui64_t) (NUM << 1)* intLimCDivInvDQ31[DEN]) >> 32) ; + #undef WMC_TOOL_SKIP + + return result; + } + + int intLimCDivSigned( int NUM, + short DEN + ) + { + int result; + int tmp_num; + tmp_num = max(NUM,-NUM); + #define WMC_TOOL_SKIP + /* result = (int)sign(NUM)*intLimCDivPos(tmp_num, DEN); */ + result = (int)sign(NUM)*(int)(((ui64_t) (tmp_num << 1)* intLimCDivInvDQ31[DEN]) >> 32) ; + #undef WMC_TOOL_SKIP + return result; + } + + + + + static void nearProjQ15( + short x, + short *result + ) + { + int NearProjC[4] = {0x00003a77, 0xffff9c52, 0x00000d57, 0x00007e5f}; + int P12, P3; + + P12 = ((int)x * NearProjC[0] >> 16) + NearProjC[1]; + P3 = ((int)x * P12 >> 14) + NearProjC[2]; + *result =(short) (((int)x * P3 >> 15) + NearProjC[3]); + + return; + } + + + void obtainEnergyQuantizerDensity( + short L_in, + short R_in, + short *Density + ) + { + int Rnrg; + short den; + int L, R; + L=L_in; + R=R_in; + den = (2*L -1) ; + if( den<=67) + { + #define WMC_TOOL_SKIP + Rnrg = (int)(((ui64_t) (R << 1)* intLimCDivInvDQ31[den]) >> 32) ; + #undef WMC_TOOL_SKIP + } + else + { + Rnrg = (R / den); + } + Rnrg += 28; + + if ((R - 96 < 56) && (R - 96 < Rnrg)) + { + Rnrg = R - 96; + } + else if (56 < Rnrg) + { + Rnrg = 56; + } + + Rnrg = max(0, Rnrg); /* _f table set to 1 for low Rnrg */ + *Density = (short)obtainEnergyQuantizerDensity_f[Rnrg]; + return ; + } + + + void dsDirac2Dirac( + short dsDiracIndex, + short *diracs + ) + { + short dsHighIndex; + #define WMC_TOOL_SKIP + + dsHighIndex = dsDiracIndex - DS_INDEX_LINEAR_END - 1; + *diracs = dsDiracIndex; + if (dsDiracIndex > DS_INDEX_LINEAR_END) + { + *diracs = dsHighDiracsTab[dsHighIndex]; + } + #undef WMC_TOOL_SKIP + return ; + } + + + void dsDiracPerQuanta(short td, + short t_quanta, + short dsm, + const unsigned char* const *frQuanta, + short *DsIdx + ) + { + const unsigned char *sv; + short nsv; + short t_quanta_o; + short dsIndex; + short i; + + sv = frQuanta[td]; + nsv = sv[0]; + + t_quanta_o = t_quanta - QUANTAQ3OFFSET; + if ( t_quanta_o >= sv[nsv] ) + { + *DsIdx = nsv; + return; + } + if ( t_quanta_o <= sv[1] ) + { + *DsIdx = 1; + return ; + } + #define WMC_TOOL_SKIP + SHIFT(1); + dsIndex = 1 << frQuanta[0][td]; + SHIFT(1); TEST(1) ; + if (t_quanta_o > sv[nsv >> 1]) + { + dsIndex = nsv - dsIndex; /*single op*/ ADD(1); + } + #undef WMC_TOOL_SKIP + #define WMC_TOOL_SKIP + ADD(1); + for( i = frQuanta[0][td]-1; i >= 0; i--) + { + /* + tmp_diff = (t_quanta_o > sv[dsIndex] ); + dsIndex += ((tmp_diff<<1) - 1) << i; */ /* clang warns for (neg)< sv[dsIndex]); + #undef WMC_TOOL_SKIP + dsIndex -= (dsIndex > 1); + + if (dsm == CONS) + { + *DsIdx = dsIndex; + return ; + } + *DsIdx = dsIndex + ((sv[dsIndex + 1] + sv[dsIndex]) < (t_quanta_o << 1)) ; + return; + } + + void QuantaPerDsDirac( + short td, + short dsDiracIndex, + const unsigned char* const* dimFrQuanta, + short *Quanta + ) + { + if ( !dsDiracIndex ) + { + *Quanta = 0; + return; + } + *Quanta = ((short) dimFrQuanta[td][dsDiracIndex]) + QUANTAQ3OFFSET ; + return ; + } + + + + void conservativeL1Norm( + short L, + short Qvec, + short Fcons, + short Qavail, + short Qreserv, + short Dspec, + short *Dvec, /*o*/ + short *Qspare, /*o*/ + short *Qreservplus, /*o*/ + short *Dspecplus /*o*/ + ) + { + short Minit, Mprime; + short Qtestminus; + const unsigned char *frQuantaL; + + frQuantaL = hBitsN[L]; + + *Qreservplus = Qreserv + Qvec - QUANTAQ3OFFSET; + + dsDiracPerQuanta(L, Qvec, Fcons, hBitsN, &Minit); + Mprime = Minit; + do + { + Qtestminus = frQuantaL[Mprime]; + *Qspare = Qavail - Qtestminus; + Mprime = Mprime - 1; + {} {} } + while ( Mprime >= 0 && *Qspare < QUANTAQ3OFFSET); + + if (Mprime < 0) + { + *Qspare = Qavail + QUANTAQ3OFFSET; + } + + dsDirac2Dirac(Mprime + 1,Dvec); + + *Dspecplus = Dspec + *Dvec; + + *Qreservplus -= frQuantaL[Minit]; + + *Qspare -= QUANTAQ3OFFSET; + + return; + } + + + + + void bandBitsAdjustment( + short Brc, + unsigned int INTrc, + short Bavail, + short Nbands, + short D, + short L, + short Bband, + short Breserv, + short *Bband_adj, /* o */ + short *Brem, /* o */ + short *Breservplus /* o */ + ) + { + int Btemp; + short Bff ; + short Dtmp, tmp_short1 ,tmp_short2; + + rangeCoderFinalizationFBits(Brc, INTrc,&Bff); + + if (D < Nbands) + { + Dtmp = min(D, 3); /* avoid branch cost */ + Btemp = intLimCDivSigned( Breserv-Bff, Dtmp); + + *Breservplus = Bband + Breserv; + } + else + { + Btemp = 0; + *Breservplus = Bband + Bff; + } + + *Bband_adj = Bband; + tmp_short1 = L * 80; + if ( tmp_short1 < Bband ) + { + *Bband_adj = tmp_short1; + } + + tmp_short1 = Bavail - Bff; + tmp_short2 = *Bband_adj + Btemp ; + + *Bband_adj = tmp_short2; + if ( tmp_short1 < tmp_short2 ) + { + *Bband_adj = tmp_short1 ; + } + if (*Bband_adj < 0) + { + *Bband_adj = 0; + } + *Brem = Bavail - Bff; + } + + + + /*-------------------------------------------------------------------* + * local_norm_s() + * + * + *-------------------------------------------------------------------*/ + static + short local_norm_s ( /* o : n shifts needed to normalize */ + short short_var /* i : signed 16 bit variable */ + ) + { + short short_res; + + #define WMC_TOOL_SKIP + MAC(1); + if (short_var == -1 ) + { + return (16-1); + } + else + { + if (short_var == 0) + { + return 0; + } + + else + { + if (short_var < 0) + { + short_var = ~short_var; + } + + for (short_res = 0; short_var < 0x4000; short_res++) + { + short_var <<= 1; + } + } + } + #undef WMC_TOOL_SKIP + + return (short_res); + } + + + + + static short Ratio_base2Q11( /* o : , Q11 */ + short opp, /* i : Q15 */ + short near /* i : Q15 */ + ) + { + Word16 mc, nc, ms, ns, d, z; + Word16 result; + Word32 acc; + + ns = local_norm_s(opp ); /* exponent*/ + nc = local_norm_s(near ); /* exponent */ + + ms = opp << ns; /* mantissa */ + mc = near<< nc; /* mantissa */ + + #define WMC_TOOL_SKIP + 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)); + #undef WMC_TOOL_SKIP + return result; + } + + void Ratio_rQ3( + short opp, + short near, + short *result + ) + { + short tmp = 128; + tmp += Ratio_base2Q11(opp, near); + *result = (tmp >> 8); + return ; + } + + + + + + void densityAngle2RmsProjDec( + short D, /* i: density */ + short indexphi, /* i: decoded index from AR dec */ + + short *oppQ15, /* o: */ + short *nearQ15, /* o: */ + short *oppRatioQ3 /* o: */ + ) + { + short phiQ14q; + int L_2xPhiQ14q; + short oppTail, nearTail; + phiQ14q = intLimCDivPos( labs(indexphi)<<13,D>>1); + if ( (0xFFFe&D) == 0 ) /* even -> positive, odd -> 0 */ + { + phiQ14q = 1 << 13; /* one op */ + } + #define C_TOP ((1 << 14) - (1 << 6)) + #define C_BOT (1 << 6) + #define C_SHRT_MAXABS (1L << 15) + #define C_SHRT_MAX_POS ((1 << 15) - 1) + #define C_Q14_MAX (1<<14) + + oppTail = phiQ14q >= C_TOP; + nearTail = phiQ14q < C_BOT; + if (!(oppTail || nearTail)) + { + L_2xPhiQ14q = 2*(int)phiQ14q; + nearProjQ15( (short)(C_SHRT_MAXABS - L_2xPhiQ14q ) , oppQ15 ); + nearProjQ15(phiQ14q << 1, nearQ15 ); + Ratio_rQ3(*oppQ15, *nearQ15,oppRatioQ3 ); + } + else + { + *oppRatioQ3 = (1 - 2*nearTail)*C_Q14_MAX ; + *oppQ15 = oppTail * C_SHRT_MAX_POS; + *nearQ15 = nearTail * C_SHRT_MAX_POS; + } + #undef C_TOP + #undef C_BOT + #undef C_SHRT_MAXABS + #undef C_SHRT_MAX_POS + #undef C_Q14_MAX + return; + } + + void densityAngle2RmsProjEnc + ( + short D, + short phiQ14uq, + short *indexphi, + short *oppQ15, + short *nearQ15, + short *oppRatioQ3 + ) + { + + #define C_MAX13 (1L << 13) + *indexphi = ((int)D * phiQ14uq + C_MAX13 ) >> 14; + #undef C_MAX13 + + if( (0xFFFE&D) == 0 ) + { + *indexphi = -1; /* one op */ + } + densityAngle2RmsProjDec(D, *indexphi, oppQ15, nearQ15, oppRatioQ3); + return; + } + + void NearOppSplitAdjustment( + short qband, + short qzero, + const short Qac, + const unsigned int INTac, + short qglobal, + short FlagCons, + short Np, + short Nhead, + short Ntail, + short Nnear, + short Nopp, + short oppRQ3, + short *qnear, + short *qopp, + short *qglobalupd + ) + { + short qac, qskew, qboth, QIb; + int QIa, L_QIb, qnum; + short qmin, qavg, Midx; + + rangeCoderFinalizationFBits(Qac, INTac, &qac); + qboth = qband - (qac - qzero); + qskew = 0; /* skew calc code */ + if(Nhead > 1) + { + qavg = intLimCDivSigned(qboth, Np); + dsDiracPerQuanta(Ntail, qavg, FlagCons, hBitsN, &Midx ); + QuantaPerDsDirac( Nhead, Midx, hBitsN, &qmin); + + qskew = qavg - qmin; + qskew = max(0, qskew); + } /* end of skew calc code*/ + + QIa = intLimCDivPos(Nopp, Nnear) + 1; + qnum = qband + qzero - qac - qskew - Nopp * (int)oppRQ3; + L_QIb = 0; + if( qnum > 0 ) + { + L_QIb = intLimCDivPos(qnum, QIa); + } + QIb = (short) min(32767L,L_QIb); /* saturate, L_QIb >= 0 */ + *qnear = QIb; + if( QIb > qboth ) + { + *qnear = qboth; /*single op*/ + } + *qopp = qboth - *qnear; + *qglobalupd = qglobal - (qac - qzero); + return; + } + + /*--------------------------------------------------------------------------* + * apply_gain() + * + * Apply gain + *--------------------------------------------------------------------------*/ + + void apply_gain + ( + const short *ord, /* i : Indices for energy order */ + const short *band_start, /* i : Sub band start indices */ + const short *band_end, /* i : Sub band end indices */ + const short num_sfm, /* i : Number of bands */ + const float *gains, /* i : Band gain vector */ + float *xq /* i/o: Float synthesis / Gain adjusted synth */ + ) + { + short band,i; + float g; + + for ( band = 0; band < num_sfm; band++) + { + g = gains[ord[band]]; + + for( i = band_start[band]; i < band_end[band]; i++) + { + xq[i] *= g; + } + } + + return; + } + + + /*--------------------------------------------------------------------------* + * fine_gain_quant() + * + * Fine gain quantization + *--------------------------------------------------------------------------*/ + + void fine_gain_quant + ( + Encoder_State *st, + const short *ord, /* i : Indices for energy order */ + const short num_sfm, /* i : Number of bands */ + const short *gain_bits, /* i : Gain adjustment bits per sub band */ + float *fg_pred, /* i/o: Predicted gains / Corrected gains */ + const float *gopt /* i : Optimal gains */ + ) + { + short band; + short gbits; + short idx; + float gain_db,gain_dbq; + float err; + + for ( band = 0; band < num_sfm; band++) + { + gbits = gain_bits[ord[band]]; + if ( fg_pred[band] != 0 && gbits > 0 ) + { + err = gopt[band] / fg_pred[band]; + gain_db = 20.0f*(float)log10(err); + idx = (short) squant(gain_db, &gain_dbq, finegain[gbits-1], gain_cb_size[gbits-1]); + push_indice( st, IND_PVQ_FINE_GAIN, idx, gbits ); + + /* Update prediced gain with quantized correction */ + fg_pred[band] *= (float)pow(10, gain_dbq * 0.05f); + } + } + + return; + } + + /*-------------------------------------------------------------------* + * srt_vec_ind() + * + * sort vector and save sorting indices + *-------------------------------------------------------------------*/ + + void srt_vec_ind ( + const short *linear, /* i: linear input */ + short *srt, /* o: sorted output*/ + short *I, /* o: index for sorted output */ + short length /* i: length of vector */ + ) + { + float linear_f[MAX_SRT_LEN]; + float srt_f[MAX_SRT_LEN]; + + mvs2r(linear, linear_f, length); + srt_vec_ind_f(linear_f, srt_f, I, length); + mvr2s(srt_f, srt, length); + + return; + } + + /*-------------------------------------------------------------------* + * srt_vec_ind_f() + * + * sort vector and save sorting indices, using float input values + *-------------------------------------------------------------------*/ + + void srt_vec_ind_f( + const float *linear, /* i: linear input */ + float *srt, /* o: sorted output*/ + short *I, /* o: index for sorted output */ + short length /* i: length of vector */ + ) + { + short pos,npos; + short idxMem; + float valMem; + + /*initialize */ + for (pos = 0; pos < length; pos++) + { + I[pos] = pos; + } + + mvr2r(linear, srt,length); + + /* now iterate */ + for (pos = 0; pos < (length - 1); pos++) + { + for (npos = (pos + 1); npos < length; npos++) + { + if (srt[npos] < srt[pos]) + { + idxMem = I[pos]; + I[pos] = I[npos]; + I[npos] = idxMem; + + valMem = srt[pos]; + srt[pos] = srt[npos]; + srt[npos] = valMem; + } + } + } + + return; + } + + + unsigned int UMult_32_32(unsigned int UL_var1, unsigned int UL_var2) + { + ui64_t tmp; + + tmp = (ui64_t)UL_var1 * (ui64_t)UL_var2; + return (unsigned int)(tmp >> 32); + } + + /*-------------------------------------------------------------------* + * UL_div + * + * Calculate UL_num/UL_den. UL_num assumed to be Q31, UL_den assumed + * to be Q32, then result is in Q32. + *-------------------------------------------------------------------*/ + static unsigned int UL_div(const unsigned int UL_num, const unsigned int UL_den) + { + unsigned int UL_e, UL_Q; + unsigned int UL_msb; + short i; + + UL_e = 0xffffffff - UL_den; + UL_Q = UL_num; + + for (i = 0; i < 5; i++) + { + UL_msb = UMult_32_32(UL_Q, UL_e); + UL_Q = UL_Q + UL_msb; + UL_e = UMult_32_32(UL_e, UL_e); + } + + return UL_Q; + } + /*-------------------------------------------------------------------* + * UL_inverse + * + * Calculate inverse of UL_val. Output in Q_exp. + *-------------------------------------------------------------------*/ + unsigned int UL_inverse(const unsigned int UL_val, short *exp) + { + unsigned int UL_tmp; + + + #define WMC_TOOL_SKIP + MOVE(1); + *exp = norm_ul(UL_val); /* aligned to BASOP */ + #undef WMC_TOOL_SKIP + UL_tmp = UL_val << (*exp); /* Q32*/ + + *exp = 32 + 31 - *exp; + + return UL_div(0x80000000, UL_tmp); + } + + /*----------------------------------------------------------------------------- + * ratio() + * + * Divide the numerator by the denominator. + *----------------------------------------------------------------------------*/ + Word16 ratio(const Word32 numer, const Word32 denom, Word16 *expo) + { + Word16 expNumer, expDenom; + Word16 manNumer, manDenom; + Word16 quotient; + + #define WMC_TOOL_SKIP + expDenom = norm_l(denom); /* exponent */ + manDenom = extract_h(L_shl(denom, expDenom)); /* mantissa */ + expNumer = norm_l(numer); /* exponent */ + manNumer = extract_h(L_shl(numer, expNumer)); /* mantissa */ + manNumer = shr(manNumer, 1); /* Ensure the numerator < the denominator */ + quotient = div_s(manNumer, manDenom); /* in Q14 */ + + *expo = sub(expNumer, expDenom); + #undef WMC_TOOL_SKIP + + return quotient; /* Q14 */ + } + + /*----------------------------------------------------------------------------- + * 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 EVS_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; + + #define WMC_TOOL_SKIP + IF (L_sub(x, 0) == 0) + { + return 25736; /* EVS_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) = EVS_PI/2 - 1/x + 1/(3x^3) - 1/(5x^5) + ... + * ~ EVS_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 (EVS_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 (L_sub(L_shr(arg, 15), 10L) < 0) + { + 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 = 533625337L; /* Q31 c1 = a1*8^2 */ move32(); + z = mac_r(acc, w, -2161); /* Q15 c0 = a0*8^3 */ + acc = -797517542L; /* Q31 c2 = a2*8 */ move32(); + z = mac_r(acc, w, z); /* Q15 */ + acc = 592675551L; /* Q31 c3 = a3 */ move32(); + z = mac_r(acc, w, z); /* z (in:Q15, out:Q12) */ + acc = 201114012L; /* Q28 c4 = a4 */ move32(); + 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 = 702602883L; /* Q31 c1 = a1*8 */ move32(); + z = mac_r(acc, w, -2751); /* Q15 c0 = a0*32 */ + acc = -1100849465L; /* Q31 c2 = a2*2 */ move32(); + z = mac_r(acc, w, z); /* z (in:Q15, out:Q14) */ + acc = 877095185L; /* Q30 c3 = a3 */ move32(); + z = mac_r(acc, w, z); /* z (in:Q14, out:Q12) */ + acc = 57332634L; /* Q28 c4 = a4 */ move32(); + 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 = 655887249L; /* Q31 c1 = a1*2 */ move32(); + z = mac_r(acc, w, -2106); /* Q15 c0 = a0*4 */ + acc = -1314948992L; /* Q31 c2 = a2 */ move32(); + z = mac_r(acc, w, z); + acc = 1428924557L; /* Q31 c3 = a3/2 */ move32(); + z = mac_r(acc, w, z); /* z (in:Q15, out:Q13) */ + acc = -37424701L; /* Q29 c4 = a4 */ move32(); + 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 = 1188376431L; /* Q31 c1 = a1*2 */ move32(); + z = mac_r(acc, w, -3547); /* Q15 c0 = a0*2 */ + acc = -995054571L; /* Q31 c2 = a2 */ move32(); + z = extract_h(L_mac0(acc, w, z)); /* Q15 non-fractional mode multiply */ + acc = 61673254L; /* Q31 c3 = a3 */ move32(); + z = mac_r(acc, w, z); + acc = 2141982059L; /* Q31 c4 = a4 */ move32(); + z = mac_r(acc, w, z); + acc = 115139L; /* Q31 c5 = a5 */ move32(); + acc = L_mac(acc, w, z); /* Q31 */ + angle = extract_l(L_shr(acc, 31 - 14)); /* Q14 result of atan(x), where 0 <= x < 1 */ + } + #undef WMC_TOOL_SKIP + return angle; /* Q14 between 0 and EVS_PI/2 radian. */ + } diff --git a/lib_com/range_com.c b/lib_com/range_com.c new file mode 100644 index 000000000..04c66ada3 --- /dev/null +++ b/lib_com/range_com.c @@ -0,0 +1,77 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * rc_get_bits2() + * + * Get number of bits needed to finalize range coder + *-------------------------------------------------------------------*/ + +short rc_get_bits2( /* o: Number of bits needed */ + const short N, /* i: Number of bits currently used */ + const unsigned int range /* i: Range of range coder */ +) +{ + short tmp; +#define WMC_TOOL_SKIP + tmp = N + 2 + norm_ul(range); /* aligned to BASOP */ +#undef WMC_TOOL_SKIP + return tmp; +} + + +void rangeCoderFinalizationFBits( + short Brc, + unsigned int INTrc, + short *FBits +) +{ + unsigned int Bq15, UL_tmp; + unsigned short Bq15ui16, B, E; + short k; + +#define WMC_TOOL_SKIP + ADD(1); + B = 30 - norm_ul(INTrc); /* aligned to BASOP */ +#undef WMC_TOOL_SKIP + + +#define RCF_INIT_SHIFTp1 (RCF_INIT_SHIFT+1) +#define RCF_FINALIZE_LIMIT ((1L << 16) - 1) + *FBits = (Brc + 32) * 8; + + Bq15 = 0; + k = B - RCF_INIT_SHIFT; + if (k >= 0 ) + { + Bq15 = INTrc >> ( k ); /* single op */ + } + + E = 2; + for( k = 1; k < 4; k++) + { + Bq15ui16 = Bq15 >> (E & 1); + UL_tmp = (unsigned int)Bq15ui16; + Bq15 = (UL_tmp * Bq15ui16) >> RCF_INIT_SHIFTp1 ; + E = 2*B; + if( Bq15 > RCF_FINALIZE_LIMIT ) + { + E++; + } + B = E; + } + *FBits -= B; +#undef RCF_INIT_SHIFTp1 +#undef RCF_FINALIZE_LIMIT + + return; +} diff --git a/lib_com/re8_ppv.c b/lib_com/re8_ppv.c new file mode 100644 index 000000000..ac4d45684 --- /dev/null +++ b/lib_com/re8_ppv.c @@ -0,0 +1,179 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static void nearest_neighbor_2D8(float x[], int 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( + float x[], /* i : point in R^8 */ + int y[] /* o : point in RE8 (8-dimensional integer vector) */ +) +{ + int i,y0[8],y1[8]; + float e0,e1,x1[8],tmp; + + + /*--------------------------------------------------------------* + * find the nearest neighbor y0 of x in 2D8 + *--------------------------------------------------------------*/ + + nearest_neighbor_2D8(x, y0); + + /*--------------------------------------------------------------* + * find the nearest neighbor y1 of x in 2D8+(1,...,1) (by coset decoding) + *--------------------------------------------------------------*/ + + for (i=0; i<8; i++) + { + x1[i]=x[i]-1.0f; + } + + nearest_neighbor_2D8(x1, y1); + + for (i=0; i<8; i++) + { + y1[i]+=1; + } + + /*--------------------------------------------------------------* + * compute e0=||x-y0||^2 and e1=||x-y1||^2 + *--------------------------------------------------------------*/ + + e0=e1=0.0; + for (i=0; i<8; i++) + { + tmp = x[i]-y0[i]; + e0+=tmp*tmp; + tmp = x[i]-y1[i]; + e1+=tmp*tmp; + } + + /*--------------------------------------------------------------* + * select best candidate y0 or y1 to minimize distortion + *--------------------------------------------------------------*/ + + if (e0 0) */ + if (x[i] < 0) + { + y[i] = -2*(((int)(1.0-x[i]))>>1); + } + else + { + y[i] = 2*(((int)(1.0+x[i]))>>1); + } + 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 (sum%4) + { + /* find j = arg max_i | xi -yi| */ + em=0; + j=0; + for (i=0; i<8; i++) + { + /* compute ei = xi-yi */ + e[i]=x[i]-y[i]; + } + + for (i=0; i<8; i++) + { + /* compute |ei| = | xi-yi | */ + if (e[i]<0) + { + s=-e[i]; + } + else + { + s=e[i]; + } + /* check if |ei| is maximal, if so, set j=i */ + if (em4 */ + int c[], /* o : codevector in Q0, Q2, Q3, or Q4 if n<=4, y=c */ + int *ka /* o : identifier of absolute leader (needed to index c)*/ +) +{ + int i, r, m, v[8], c_tmp[8], k_mod[8], k_tmp[8], iter, ka_tmp, n_tmp, mask; + float sphere; + + + /*----------------------------------------------------------------* + * 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( y ); + + /*----------------------------------------------------------------* + * compute codebook number n of Qn (by table look-up) + * at this stage, n=0,2,3,4 or out=100 + *----------------------------------------------------------------*/ + + *n = Da_nq[*ka]; + + /*----------------------------------------------------------------* + * 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( *n <= 4 ) + { + for( i=0; i<8; i++ ) + { + c[i] = y[i]; + } + } + else + { + /*------------------------------------------------------------* + * initialize r and m=2^r based on || y ||^2/8 + *------------------------------------------------------------*/ + + sphere = 0.0; + for( i=0; i<8; i++ ) + { + sphere += (float)y[i]*(float)y[i]; + } + sphere *= 0.125; + r = 1; + sphere *= 0.25; /* not counted, merge 0.125*0.25 */ + while( sphere > 11.0 ) + { + r++; + sphere *= 0.25; + } + /*------------------------------------------------------------* + * compute the coordinates of y in the RE8 basis + *------------------------------------------------------------*/ + + re8_coord( y, k_mod ); + + /*------------------------------------------------------------* + * compute m and the mask needed for modulo m (for Voronoi coding) + *------------------------------------------------------------*/ + + m = 1< 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++; + m = m<<1; + mask = ((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) + *--------------------------------------------------------*/ + + if( n_tmp < 3 ) + { + n_tmp = 3; + } + + /*--------------------------------------------------------* + * save current values into ka, n, k and c + *--------------------------------------------------------*/ + + *ka = ka_tmp; + *n = n_tmp + 2*r; + for (i=0; i<8; i++) + { + k[i] = k_tmp[i]; + c[i] = c_tmp[i]; + } + + /*--------------------------------------------------------* + * try m = 2^(r-1) instead of 2^r to be sure that m is minimal + *--------------------------------------------------------*/ + + r--; + m = m>>1; + mask = mask>>1; + } + } + } + + 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 int re8_identify_absolute_leader( /* o : integer indicating if y if in Q0, Q2, Q3 or Q4 (or if y is an outlier) */ + int y[] /* i : point in RE8 (8-dimensional integer vector) */ +) +{ + int i,s,id,C[8],nb,pos,ka; + long tmp; + + + /*-----------------------------------------------------------------------* + * compute the RE8 shell number s = (y1^2+...+y8^2)/8 and C=(y1^2, ..., y8^2) + *-----------------------------------------------------------------------*/ + + s = 0; + for( i=0; i<8; i++ ) + { + C[i] = y[i]*y[i]; + s += C[i]; + } + s >>= 3; + + /*-----------------------------------------------------------------------* + * 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) + *-----------------------------------------------------------------------*/ + + ka = NB_LEADER+1; + if( s == 0 ) + { + /*-------------------------------------------------------------------* + * if s=0, y=0 i.e. y is in Q0 -> ka=index of element indicating Q0 + *-------------------------------------------------------------------*/ + + ka = NB_LEADER; + } + else + { + /*-------------------------------------------------------------------* + * 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( s <= NB_SPHERE ) + { + /*---------------------------------------------------------------* + * compute the unique identifier id of the absolute leader related to y: + * s = (y1^4 + ... + y8^4)/8 + *---------------------------------------------------------------*/ + + tmp = 0; + for( i=0; i<8; i++ ) + { + tmp += C[i]*C[i]; + } + id = (int)(tmp >> 3); + + /*---------------------------------------------------------------* + * 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[s-1]; /* get the number of absolute leaders used on the shell of number s */ + pos = Da_pos[s-1]; /* get the position of the first absolute leader of shell s in Da_id */ + for( i=0; i=1; i-- ) + { + /* apply factor 2/4 from M^-1 */ + k[i] = (y[i]-tmp)>>1; + sum -= y[i]; + } + + /* apply factor 1/4 from M^-1 */ + k[0] = (y[0]+sum)>>2; + + return; +} + + +/*------------------------------------------------------------------------- + * re8_k2y() + * + * Voronoi indexing (index decoding) k -> y + -----------------------------------------------------------------------*/ + +void re8_k2y( + const int *k, /* i : Voronoi index k[0..7] */ + const int m, /* i : Voronoi modulo (m = 2^r = 1<=2) */ + int *y /* o : 8-dimensional point y[0..7] in RE8 */ +) +{ + int i, v[8], tmp, sum, *ptr1, *ptr2; + float z[8]; + int lm=0; + + /*---------------------------------------------------------------* + * compute y = k M and z=(y-a)/m, where + * M = [4 ] + * [2 2 ] + * [| \ ] + * [2 2 ] + * [1 1 _ 1 1] + * a=(2,0,...,0) + *---------------------------------------------------------------*/ + + for (i=0; i<8; i++) + { + y[i] = k[7]; + } + + sum = 0; + for( i=6; i>=1; i-- ) + { + tmp = 2*k[i]; + sum += tmp; + y[i] += tmp; + } + y[0] += (4*k[0] + sum); + + /* find log2(m) */ + for (lm=0; lm<31; lm++) + { + if ((m>>lm)&0x0001) + { + break; + } + } + + z[0] = (float) ldexp(y[0] - 2, -lm); + for (i=1; i<8; i++) + { + z[i] = (float) ldexp(y[i], -lm); + } + + /*---------------------------------------------------------------* + * find nearest neighbor v of z in infinite RE8 + *---------------------------------------------------------------*/ + + re8_PPV( z, v ); + + /*---------------------------------------------------------------* + * compute y -= m v + *---------------------------------------------------------------*/ + + ptr1 = y; + ptr2 = v; + for( i=0; i<8; i++ ) + { + *ptr1++ -= m **ptr2++; + } + + return; +} diff --git a/lib_com/realft.c b/lib_com/realft.c new file mode 100644 index 000000000..89d799323 --- /dev/null +++ b/lib_com/realft.c @@ -0,0 +1,165 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "cnst.h" +#include "options.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * four1() + * + * From "numerical recipes in C". + * Replace data by its DFT, if isign is input as 1; or replace data + * by nn times its inverse-DFT, if isign is input as -1. + * data is a complex array of length nn, input as a real + * array data[1...2nn]. nn must be an integer power of 2 + *-------------------------------------------------------------------*/ + +static void four1( + float *data, /* i/o: data array .......... */ + short nn, /* i : length of data array */ + short isign /* i : sign +1 or -1 */ +) +{ + short n,mmax,m,j,istep,i; + float wtemp,wr,wpr,wpi,wi,theta; + float tempr,tempi; + + n=nn << 1; + j=1; + + /* this is the bit-reversal section of the routine */ + for (i=1; i i) + { + /* exchange the two complex numbers */ + SWAP(data[j],data[i]); + SWAP(data[j+1],data[i+1]); + } + m=n >> 1; + while (m >= 2 && j > m) + { + j -= m; + m >>= 1; + } + j += m; + } + mmax=2; + /* here begins the Danielson-Lanczos section of the routine */ + /* Outer loop executed log2(nn) times */ + while (n > mmax) + { + istep=2*mmax; + /* initialization for the trigonometric recurrence */ + theta=(float) (6.28318530717959/(isign*mmax)); + wtemp=(float) (sin(0.5f*theta)); + wpr = -2.0f*wtemp*wtemp; + wpi=(float) sin(theta); + wr=1.0f; + wi=0.0f; + /* here are the two nested loops */ + for (m=1; m "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, 2.0f, 1, 0, {8}, TRACKPOS_FREE_ONE }, /* 7 bits, 1 pulses, 4 tracks, 1000 free track */ + { 10, 4, 2.0f, 2, 0, {8}, TRACKPOS_FIXED_EVEN }, /* 10 bits, 2 pulses, 4 tracks 1010 (used only even tracks designed for NB) */ + { 12, 4, 2.0f, 2, 0, {8}, TRACKPOS_FIXED_TWO }, /* 12 bits, 2 pulses, 2 tracks 11 used all tracks ala AMR-WB 6.6 */ + { 15, 4, 2.0f, 3, 0, {8}, TRACKPOS_FIXED_FIRST }, /* 15 bits, 3 pulses, 4 tracks 1110 fixed track to first ? */ + { 17, 6, 2.0f, 3, 0, {8}, TRACKPOS_FREE_THREE }, /* 17 bits, 3 pulses, 4 tracks (used all tracks) - 1110, 1101, 1011, 0111 */ + { 20, 4, 2.0f, 4, 0, {4, 8}, TRACKPOS_FIXED_FIRST }, /* 20 bits, 4 pulses, 4 tracks 1111 */ + { 24, 4, 2.0f, 5, 0, {4, 8}, TRACKPOS_FIXED_FIRST }, /* 24 bits, 5 pulses, 4 tracks 2111 fixed track to first */ + { 26, 4, 2.0f, 5, 0, {4, 8}, TRACKPOS_FREE_ONE }, /* 26 bits, 5 pulses, 4 tracks 2111 one free track ? */ + { 28, 4, 1.5f, 6, 0, {4, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 28 bits, 6 pulses, 4 tracks 2211 */ + { 30, 4, 1.5f, 6, 0, {4, 8, 8}, TRACKPOS_FIXED_TWO }, /* 30 bits, 6 pulses, 4 tracks 2211 free consecutive track positions ? */ + { 32, 4, 1.5f, 7, 0, {4, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 32 bits, 6 pulses, 4 tracks 2221 fixed ?*/ + { 34, 4, 1.5f, 7, 0, {4, 8, 8}, TRACKPOS_FREE_THREE }, /* 34 bits, 6 pulses, 4 tracks 2221 free track positions ? */ + { 36, 4, 1.0f, 8, 2, {4, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 36 bits, 8 pulses, 4 tracks 2222 */ + { 40, 4, 1.0f, 9, 2, {4, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 40 bits, 9 pulses, 4 tracks 3222 fixed ?*/ + { 43, 4, 1.0f, 10, 2, {4, 6, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 44 bits, 10 pulses, 4 tracks 3322 */ + { 46, 4, 1.0f, 10, 2, {4, 6, 8, 8}, TRACKPOS_FIXED_TWO }, /* 46 bits, 10 pulses, 4 tracks 3322 free consecutive tracks ? */ + { 47, 4, 1.0f, 11, 2, {4, 6, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 47 bits, 10 pulses, 4 tracks 3332 fixed ? */ + { 49, 4, 1.0f, 11, 2, {4, 6, 8, 8}, TRACKPOS_FREE_THREE }, /* 49 bits, 10 pulses, 4 tracks 3332 free three track positions ? */ + { 50, 4, 1.0f, 12, 4, {4, 6, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 50 bits, 12 pulses, 4 tracks 3333 */ + { 53, 4, 1.0f, 13, 4, {4, 6, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 53 bits, 13 pulses, 4 tracks 4333 fixed ? */ + { 55, 4, 1.0f, 13, 4, {4, 6, 8, 8}, TRACKPOS_FREE_ONE }, /* 55 bits, 13 pulses, 4 tracks 4333 free one ? */ + { 56, 4, 1.0f, 14, 4, {4, 6, 6, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 56 bits, 14 pulses, 4 tracks 4433 fixed ?!?! */ + { 58, 4, 1.0f, 14, 4, {4, 6, 6, 8, 8}, TRACKPOS_FIXED_TWO }, /* 58 bits, 14 pulses, 4 tracks 4433 free consecutive ? */ + { 59, 4, 1.0f, 15, 4, {4, 6, 6, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 59 bits, 15 pulses, 4 tracks 4443 fixed ? */ + { 61, 4, 1.0f, 15, 4, {4, 6, 6, 8, 8}, TRACKPOS_FREE_THREE }, /* 61 bits, 15 pulses, 4 tracks 4443 free ? */ + { 62, 3, 0.8f, 16, 4, {4, 4, 6, 6, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 62 bits, 16 pulses, 4 tracks 4444 */ + { 65, 3, 0.8f, 17, 4, {4, 4, 6, 6, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 65 bits, 17 pulses, 4 tracks 5444 fixed ?*/ + { 68, 3, 0.75f, 18, 4, {2, 3, 4, 5, 6, 7, 8}, TRACKPOS_FIXED_FIRST }, /* 68 bits, 18 pulses, 4 tracks 5544 */ + { 70, 3, 0.75f, 19, 4, {2, 3, 4, 5, 6, 7, 8}, TRACKPOS_FIXED_FIRST }, /* 70 bits, 19 pulses, 4 tracks 5554 fixed ? */ + { 73, 3, 0.75f, 20, 4, {2, 3, 4, 5, 6, 7, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 73 bits, 20 pulses, 4 tracks 5555 fixed ? */ + { 75, 3, 0.75f, 21, 4, {2, 3, 4, 5, 6, 7, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 75 bits, 21 pulses, 4 tracks 6555 fixed ? */ + { 78, 3, 0.75f, 22, 4, {2, 3, 4, 5, 6, 7, 8, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 78 bits, 22 pulses, 4 tracks 6655 fixed ? */ + { 80, 3, 0.75f, 23, 4, {2, 3, 4, 5, 6, 7, 8, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 80 bits, 23 pulses, 4 tracks 6665 fixed ? */ + { 83, 2, 0.30f, 24, 4, {2, 3, 4, 5, 6, 7, 8, 8, 8, 8}, TRACKPOS_FIXED_FIRST}, /* 83 bits, 24 pulses, 4 tracks 6666 */ + { 85, 2, 0.30f, 25, 4, {2, 3, 4, 5, 6, 7, 8, 8, 8, 8}, TRACKPOS_FIXED_FIRST}, /* 85 bits, 25 pulses, 4 tracks 7666 */ + { 87, 2, 0.25f, 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, 0.25f, 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, 0.25f, 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, 0.25f, 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, 0.20f, 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, 0.20f, 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 */ +}; + + +/* Number of pulses & positions to the number of unique states that can be achieved with those pulses */ +const long unsigned 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}, +}; + +/*----------------------------------------------------------------------------------* + * Gain quantization table for memory-less gain quantizer + *----------------------------------------------------------------------------------*/ + +const float gain_qua_mless_7b[128*2] = +{ + 0.0256f, 0.0555f, + 0.0915f, 1.1847f, + 0.0968f, 0.6282f, + 0.0996f, 0.2821f, + 0.1029f, 0.4465f, + 0.1065f, 0.9677f, + 0.1332f, 0.7997f, + 0.1535f, 1.3985f, + 0.1692f, 1.6101f, + 0.1873f, 2.0886f, + 0.1960f, 1.8291f, + 0.1964f, 0.1732f, + 0.2122f, 2.4304f, + 0.2292f, 0.5306f, + 0.2359f, 1.0716f, + 0.2369f, 0.6796f, + 0.2546f, 0.3544f, + 0.2694f, 1.2247f, + 0.2697f, 0.9217f, + 0.2996f, 2.7903f, + 0.3197f, 0.7881f, + 0.3199f, 3.2249f, + 0.3492f, 0.1667f, + 0.3560f, 0.4883f, + 0.3568f, 1.3541f, + 0.3599f, 0.6346f, + 0.3684f, 1.0620f, + 0.3716f, 1.5223f, + 0.3942f, 3.6890f, + 0.4059f, 0.3064f, + 0.4076f, 0.9021f, + 0.4149f, 1.7170f, + 0.4225f, 1.9400f, + 0.4229f, 2.2074f, + 0.4487f, 1.2106f, + 0.4554f, 0.7548f, + 0.4800f, 0.4531f, + 0.4882f, 0.6140f, + 0.4966f, 1.0464f, + 0.5126f, 1.3905f, + 0.5298f, 0.8967f, + 0.5369f, 2.4926f, + 0.5521f, 1.5735f, + 0.5614f, 0.1682f, + 0.5758f, 0.7770f, + 0.5939f, 1.1468f, + 0.5942f, 0.5222f, + 0.5946f, 0.3409f, + 0.6053f, 1.7908f, + 0.6129f, 0.9937f, + 0.6136f, 1.2784f, + 0.6184f, 2.0111f, + 0.6249f, 0.6626f, + 0.6527f, 3.0463f, + 0.6602f, 0.8724f, + 0.6692f, 1.4121f, + 0.6961f, 2.2440f, + 0.7035f, 1.0724f, + 0.7069f, 0.7548f, + 0.7081f, 1.5445f, + 0.7091f, 0.5579f, + 0.7253f, 1.6832f, + 0.7296f, 1.1850f, + 0.7359f, 0.4175f, + 0.7388f, 0.9680f, + 0.7428f, 2.7283f, + 0.7591f, 1.3040f, + 0.7700f, 0.6550f, + 0.7732f, 1.8595f, + 0.7742f, 0.8500f, + 0.7924f, 0.2178f, + 0.8078f, 1.4486f, + 0.8178f, 1.0725f, + 0.8255f, 0.7421f, + 0.8256f, 0.5278f, + 0.8316f, 2.0390f, + 0.8382f, 0.9422f, + 0.8435f, 1.2053f, + 0.8567f, 1.5952f, + 0.8570f, 2.4549f, + 0.8725f, 0.8299f, + 0.8756f, 1.3365f, + 0.8769f, 0.6222f, + 0.8799f, 0.3881f, + 0.8938f, 1.7540f, + 0.9121f, 1.0122f, + 0.9210f, 0.7117f, + 0.9249f, 1.1285f, + 0.9344f, 0.9022f, + 0.9375f, 3.7762f, + 0.9376f, 1.4769f, + 0.9388f, 0.5124f, + 0.9501f, 2.2014f, + 0.9582f, 1.2478f, + 0.9646f, 0.8003f, + 0.9815f, 0.6165f, + 0.9864f, 1.9390f, + 0.9985f, 1.3694f, + 1.0041f, 1.6163f, + 1.0071f, 1.0599f, + 1.0095f, 0.9596f, + 1.0142f, 3.3774f, + 1.0150f, 0.3827f, + 1.0223f, 0.7201f, + 1.0351f, 2.9891f, + 1.0393f, 0.8629f, + 1.0461f, 1.1773f, + 1.0601f, 1.7548f, + 1.0616f, 0.5225f, + 1.0969f, 1.4899f, + 1.0977f, 2.6574f, + 1.0996f, 0.6500f, + 1.1006f, 1.3029f, + 1.1129f, 0.7923f, + 1.1151f, 0.2047f, + 1.1169f, 1.0829f, + 1.1195f, 0.9526f, + 1.1442f, 2.3570f, + 1.1613f, 2.0960f, + 1.1920f, 0.4212f, + 1.1942f, 1.8806f, + 1.2055f, 1.6309f, + 1.2081f, 1.2005f, + 1.2091f, 0.5825f, + 1.2200f, 1.3871f, + 1.2201f, 0.8762f, + 1.2210f, 0.7314f, + 1.2298f, 1.0376f +}; + +const float gain_qua_mless_6b[64*2] = +{ + 0.1023f, 0.1385f, + 0.1299f, 0.3865f, + 0.1415f, 0.9587f, + 0.1433f, 0.6630f, + 0.1708f, 1.2210f, + 0.1766f, 1.5334f, + 0.2387f, 2.1457f, + 0.2917f, 0.4762f, + 0.2918f, 0.8337f, + 0.3122f, 1.8254f, + 0.3231f, 2.9468f, + 0.3520f, 0.2219f, + 0.3673f, 1.0612f, + 0.3755f, 0.6540f, + 0.3787f, 1.3191f, + 0.3805f, 3.5578f, + 0.4114f, 2.4443f, + 0.4293f, 1.5662f, + 0.4750f, 0.8475f, + 0.4886f, 0.4489f, + 0.5635f, 1.2143f, + 0.5699f, 0.6556f, + 0.5730f, 1.0155f, + 0.5963f, 2.0279f, + 0.6021f, 1.4337f, + 0.6240f, 1.7159f, + 0.6480f, 0.2310f, + 0.6577f, 0.8326f, + 0.7030f, 0.4858f, + 0.7146f, 2.7331f, + 0.7351f, 1.1471f, + 0.7489f, 0.9787f, + 0.7493f, 0.6800f, + 0.7628f, 1.3365f, + 0.7947f, 1.5351f, + 0.7994f, 2.3357f, + 0.8258f, 0.8233f, + 0.8434f, 1.7918f, + 0.8620f, 0.5667f, + 0.8850f, 2.0286f, + 0.8873f, 1.2422f, + 0.8933f, 1.0855f, + 0.8952f, 0.9457f, + 0.9113f, 0.7066f, + 0.9189f, 0.4096f, + 0.9554f, 3.1133f, + 0.9662f, 3.6596f, + 0.9685f, 1.4001f, + 0.9703f, 1.6178f, + 0.9859f, 0.8469f, + 1.0095f, 0.5734f, + 1.0299f, 1.1866f, + 1.0337f, 1.0014f, + 1.0487f, 0.7284f, + 1.0769f, 2.6107f, + 1.0801f, 0.2455f, + 1.1195f, 2.1906f, + 1.1268f, 1.8445f, + 1.1591f, 0.4730f, + 1.1666f, 1.5523f, + 1.1711f, 1.3167f, + 1.1753f, 0.8763f, + 1.1893f, 1.0872f, + 1.1911f, 0.6722f +}; + +const float gain_qua_mless_5b[32*2] = +{ + 0.1645f, 0.2137f, + 0.2102f, 0.5295f, + 0.2154f, 0.8448f, + 0.2615f, 1.5636f, + 0.2664f, 1.1856f, + 0.3012f, 2.1266f, + 0.4209f, 2.7473f, + 0.4713f, 0.6328f, + 0.4830f, 0.2861f, + 0.4938f, 0.9146f, + 0.5523f, 1.7829f, + 0.5798f, 1.1716f, + 0.6039f, 1.4473f, + 0.6068f, 3.5936f, + 0.7267f, 0.7460f, + 0.7329f, 2.1548f, + 0.7537f, 0.4738f, + 0.7586f, 0.9788f, + 0.8354f, 1.2308f, + 0.8529f, 1.7499f, + 0.8856f, 1.4611f, + 0.9253f, 0.6280f, + 0.9414f, 0.8362f, + 0.9570f, 1.0559f, + 0.9663f, 3.0746f, + 0.9765f, 2.5027f, + 1.0512f, 0.4129f, + 1.0815f, 2.0090f, + 1.1099f, 1.2670f, + 1.1250f, 1.5985f, + 1.1376f, 0.6895f, + 1.1529f, 0.9632f +}; + +const short 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, +}; + +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 short 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, +}; + +/*----------------------------------------------------------------------------------* + * MA predicition coefficients for gain quantizer + *----------------------------------------------------------------------------------*/ + +const float pred_gain[GAIN_PRED_ORDER] = { 0.5f, 0.4f, 0.3f, 0.2f }; + +/*----------------------------------------------------------------------------------* + * 6-bit gain quantization table (only for AMR-WB IO mode) + *----------------------------------------------------------------------------------*/ + +const float t_qua_gain6b[64*2] = +{ + 0.095577f, 0.650507f, + 0.096232f, 1.737050f, + 0.187418f, 3.168846f, + 0.255896f, 4.962348f, + 0.274392f, 1.237365f, + 0.306340f, 2.191559f, + 0.340913f, 7.624112f, + 0.349443f, 0.694540f, + 0.393850f, 0.283414f, + 0.410411f, 3.335519f, + 0.467326f, 1.722400f, + 0.492699f, 1.024880f, + 0.502447f, 2.596945f, + 0.538748f, 4.284797f, + 0.594507f, 1.400231f, + 0.601562f, 0.715119f, + 0.615667f, 6.097708f, + 0.625075f, 2.174328f, + 0.662782f, 3.231284f, + 0.690967f, 1.751661f, + 0.696845f, 0.878992f, + 0.710639f, 1.185743f, + 0.715220f, 0.482280f, + 0.751490f, 2.486668f, + 0.764345f, 4.108078f, + 0.767472f, 12.8f, /*0.767472f, 13.875360f,*/ + 0.769099f, 1.658386f, + 0.803928f, 0.792686f, + 0.810832f, 1.183175f, + 0.818967f, 2.972155f, + 0.821480f, 6.255056f, + 0.833469f, 1.761157f, + 0.861276f, 2.207579f, + 0.863275f, 0.599961f, + 0.880429f, 0.913681f, + 0.880816f, 3.532393f, + 0.881643f, 1.383632f, + 0.892825f, 4.900598f, + 0.906974f, 8.542764f, + 0.925368f, 1.772085f, + 0.928281f, 2.841080f, + 0.933752f, 1.101603f, + 0.947124f, 2.305683f, + 0.956012f, 0.517399f, + 0.961870f, 3.892433f, + 0.972823f, 5.841643f, + 0.977796f, 1.463091f, + 0.981803f, 0.833284f, + 1.008362f, 2.077002f, + 1.011696f, 3.039251f, + 1.031157f, 1.162086f, + 1.031888f, 0.332692f, + 1.050599f, 4.104371f, + 1.074819f, 1.668828f, + 1.092217f, 2.572842f, + 1.108887f, 5.736302f, + 1.112667f, 0.769072f, + 1.135654f, 15.9999f, /*1.135654f, 28.065996f,*/ + 1.143096f, 10.587959f, + 1.168006f, 1.241697f, + 1.185414f, 3.211269f, + 1.186919f, 2.000422f, + 1.187154f, 4.421983f, + 1.243327f, 7.268204f +}; + +/*----------------------------------------------------------------------------------* + * 7-bit gain quantization table (only for AMR-WB IO mode) + *----------------------------------------------------------------------------------*/ + +const float t_qua_gain7b[128*2] = +{ + 0.012445f, 0.215546f, + 0.028326f, 0.965442f, + 0.053042f, 0.525819f, + 0.065409f, 1.495322f, + 0.078212f, 2.323725f, + 0.100504f, 0.751276f, + 0.112617f, 3.427530f, + 0.113124f, 0.309583f, + 0.121763f, 1.140685f, + 0.143515f, 7.519609f, + 0.162430f, 0.568752f, + 0.164940f, 1.904113f, + 0.165429f, 4.947562f, + 0.194985f, 0.855463f, + 0.213527f, 1.281019f, + 0.223544f, 0.414672f, + 0.243135f, 2.781766f, + 0.257180f, 1.659565f, + 0.269488f, 0.636749f, + 0.286539f, 1.003938f, + 0.328124f, 2.225436f, + 0.328761f, 0.330278f, + 0.336807f, 11.500983f, + 0.339794f, 3.805726f, + 0.344454f, 1.494626f, + 0.346165f, 0.738748f, + 0.363605f, 1.141454f, + 0.398729f, 0.517614f, + 0.415276f, 2.928666f, + 0.416282f, 0.862935f, + 0.423421f, 1.873310f, + 0.444151f, 0.202244f, + 0.445842f, 1.301113f, + 0.455671f, 5.519512f, + 0.484764f, 0.387607f, + 0.488696f, 0.967884f, + 0.488730f, 0.666771f, + 0.508189f, 1.516224f, + 0.508792f, 2.348662f, + 0.531504f, 3.883870f, + 0.548649f, 1.112861f, + 0.551182f, 0.514986f, + 0.564397f, 1.742030f, + 0.566598f, 0.796454f, + 0.589255f, 3.081743f, + 0.598816f, 1.271936f, + 0.617654f, 0.333501f, + 0.619073f, 2.040522f, + 0.625282f, 0.950244f, + 0.630798f, 0.594883f, + 0.638918f, 4.863197f, + 0.650102f, 1.464846f, + 0.668412f, 0.747138f, + 0.669490f, 2.583027f, + 0.683757f, 1.125479f, + 0.691216f, 1.739274f, + 0.718441f, 3.297789f, + 0.722608f, 0.902743f, + 0.728827f, 2.194941f, + 0.729586f, 0.633849f, + 0.730907f, 7.432957f, + 0.731017f, 0.431076f, + 0.731543f, 1.387847f, + 0.759183f, 1.045210f, + 0.768606f, 1.789648f, + 0.771245f, 4.085637f, + 0.772613f, 0.778145f, + 0.786483f, 1.283204f, + 0.792467f, 2.412891f, + 0.802393f, 0.544588f, + 0.807156f, 0.255978f, + 0.814280f, 1.544409f, + 0.817839f, 0.938798f, + 0.826959f, 2.910633f, + 0.830453f, 0.684066f, + 0.833431f, 1.171532f, + 0.841208f, 1.908628f, + 0.846440f, 5.333522f, + 0.868280f, 0.841519f, + 0.868662f, 1.435230f, + 0.871449f, 3.675784f, + 0.881317f, 2.245058f, + 0.882020f, 0.480249f, + 0.882476f, 1.105804f, + 0.902856f, 0.684850f, + 0.904419f, 1.682113f, + 0.909384f, 2.787801f, + 0.916558f, 7.500981f, + 0.918444f, 0.950341f, + 0.919721f, 1.296319f, + 0.940272f, 4.682978f, + 0.940273f, 1.991736f, + 0.950291f, 3.507281f, + 0.957455f, 1.116284f, + 0.957723f, 0.793034f, + 0.958217f, 1.497824f, + 0.962628f, 2.514156f, + 0.968507f, 0.588605f, + 0.974739f, 0.339933f, + 0.991738f, 1.750201f, + 0.997210f, 0.936131f, + 1.002422f, 1.250008f, + 1.006040f, 2.167232f, + 1.008848f, 3.129940f, + 1.014404f, 5.842819f, + 1.027798f, 4.287319f, + 1.039404f, 1.489295f, + 1.039628f, 8.947958f, + 1.043214f, 0.765733f, + 1.045089f, 2.537806f, + 1.058994f, 1.031496f, + 1.060415f, 0.478612f, + 1.072132f, 12.8f, /*1.072132f, 14.961459f,*/ + 1.074778f, 1.910049f, + 1.076570f, 15.9999f, /*1.076570f, 30.500374f,*/ + 1.107853f, 3.843067f, + 1.110673f, 1.228576f, + 1.110969f, 2.758471f, + 1.140058f, 1.603077f, + 1.155384f, 0.668935f, + 1.176229f, 6.717108f, + 1.179008f, 2.011940f, + 1.187735f, 0.963552f, + 1.199569f, 4.891432f, + 1.206311f, 3.316329f, + 1.215323f, 2.507536f, + 1.223150f, 1.387102f, + 1.296012f, 9.684225f +}; + +/*----------------------------------------------------------------------------------* + * Quantization table for scaled innovation energy prediciton + *----------------------------------------------------------------------------------*/ + +const float Es_pred_qua_5b[32] = +{ + -8.0000f, + -2.0519f, + 2.5095f, + 6.5923f, + 9.9507f, + 12.9923f, + 15.7251f, + 18.1521f, + 20.3552f, + 22.4218f, + 24.3014f, + 26.0214f, + 27.6040f, + 29.0898f, + 30.5291f, + 31.9154f, + 33.2749f, + 34.6277f, + 35.9525f, + 37.3081f, + 38.7173f, + 40.1734f, + 41.6751f, + 43.2697f, + 44.9559f, + 46.7826f, + 48.7749f, + 50.9729f, + 53.4967f, + 56.3814f, + 59.9748f, + 65.0000f +}; + + +const float Es_pred_qua_4b[16] = +{ + -8.0000f, + -0.1400f, + 7.1397f, + 12.8276f, + 17.9064f, + 22.4280f, + 26.6441f, + 30.6032f, + 34.2916f, + 37.8937f, + 41.4441f, + 45.0174f, + 48.7769f, + 52.9669f, + 58.0552f, + 65.0000f +}; + +const float Es_pred_qua_3b[8] = +{ + 5.9422f, + 15.2711f, + 23.3857f, + 30.5310f, + 37.0190f, + 43.4539f, + 50.2442f, + 58.7164f +}; + +const float Es_pred_qua_4b_no_ltp[16] = +{ + -5.f, + 0.f, + 5.f, + 10.f, + 15.f, + 20.f, + 25.f, + 30.f, + 35.f, + 40.f, + 45.f, + 50.f, + 55.f, + 60.f, + 65.f, + 70.f +}; + +/*----------------------------------------------------------------------------------* + * Gain estimation constants (for gain quantizer at 7.2 and 8.0 kbps) + *----------------------------------------------------------------------------------*/ + +const float b_1sfr[2] = +{ + 2.36736f, -0.22452f +}; + +const float b_2sfr[4] = +{ + -0.00027f, 0.01703f, 0.91879f, 0.13234f +}; + +const float b_3sfr[6] = +{ + -0.11658f, 0.02674f, 0.13513f, 0.79682f, 0.02241f, 0.17815f +}; + +const float b_4sfr[8] = +{ + -0.09296f, 0.01578f, -0.06606f, 0.20416f, 0.79254f, 0.00829f, 0.03499f, 0.15859f +}; + + +/*----------------------------------------------------------------------------------* + * Gain codebooks (for gain quantizer at 7.2 and 8.0 kbps) + *----------------------------------------------------------------------------------*/ + +const float gp_gamma_1sfr_8b[2*256] = +{ + 0.01864f, 0.29707f, + 0.02030f, 0.07182f, + 0.02151f, 1.08524f, + 0.03500f, 0.16009f, + 0.03977f, 0.02281f, + 0.04234f, 0.40424f, + 0.04933f, 0.76004f, + 0.05586f, 1.51515f, + 0.06020f, 2.12629f, + 0.06027f, 3.09183f, + 0.06439f, 0.11739f, + 0.07339f, 5.42703f, + 0.07352f, 0.03949f, + 0.08217f, 0.24883f, + 0.08739f, 0.64886f, + 0.10306f, 12.80025f, + 0.10466f, 0.50924f, + 0.11107f, 0.09482f, + 0.12457f, 1.36386f, + 0.13298f, 7.87494f, + 0.13422f, 0.19471f, + 0.13866f, 2.54472f, + 0.14144f, 0.90007f, + 0.14280f, 0.34101f, + 0.15640f, 0.05105f, + 0.15712f, 28.93375f, + 0.16220f, 4.10343f, + 0.16674f, 0.12822f, + 0.17199f, 0.01803f, + 0.17309f, 0.57791f, + 0.17880f, 1.83167f, + 0.21237f, 0.25432f, + 0.21425f, 0.42966f, + 0.22283f, 6.15919f, + 0.22382f, 1.40095f, + 0.22706f, 0.74928f, + 0.23090f, 1.03443f, + 0.23261f, 20.98373f, + 0.23699f, 10.51665f, + 0.24053f, 3.14177f, + 0.24195f, 0.09011f, + 0.25145f, 0.15676f, + 0.26865f, 0.02971f, + 0.27099f, 2.30569f, + 0.27377f, 0.33881f, + 0.28928f, 0.60729f, + 0.29592f, 0.06145f, + 0.31283f, 14.92646f, + 0.31414f, 0.21458f, + 0.31534f, 1.77427f, + 0.31962f, 0.49268f, + 0.32489f, 1.21756f, + 0.32814f, 4.91051f, + 0.34121f, 0.01364f, + 0.34148f, 8.74051f, + 0.34386f, 0.12541f, + 0.34508f, 0.89971f, + 0.35532f, 0.04229f, + 0.35970f, 0.27273f, + 0.36044f, 3.53446f, + 0.37703f, 0.71598f, + 0.38255f, 0.39178f, + 0.38772f, 2.13255f, + 0.40080f, 1.46796f, + 0.40443f, 0.09811f, + 0.41099f, 0.18558f, + 0.41248f, 0.57650f, + 0.42003f, 6.02510f, + 0.42491f, 2.66162f, + 0.44395f, 1.05504f, + 0.45244f, 0.32349f, + 0.46599f, 4.14121f, + 0.46643f, 0.07352f, + 0.46821f, 0.76710f, + 0.47180f, 0.44298f, + 0.47973f, 0.14694f, + 0.48709f, 0.22467f, + 0.48898f, 1.86483f, + 0.49391f, 7.20170f, + 0.49561f, 0.03365f, + 0.49719f, 11.52638f, + 0.51590f, 1.31314f, + 0.52029f, 3.12855f, + 0.52386f, 0.11286f, + 0.52972f, 0.53743f, + 0.54158f, 0.64936f, + 0.54442f, 0.88680f, + 0.54741f, 18.96873f, + 0.55717f, 5.01132f, + 0.55900f, 0.38267f, + 0.56108f, 2.20040f, + 0.56269f, 0.27811f, + 0.56764f, 0.01728f, + 0.56774f, 1.61683f, + 0.57428f, 0.17847f, + 0.59426f, 0.05172f, + 0.60253f, 1.12077f, + 0.61435f, 0.47966f, + 0.61837f, 2.64075f, + 0.61974f, 3.85052f, + 0.62233f, 0.77999f, + 0.62488f, 30.82914f, + 0.62591f, 8.30773f, + 0.63483f, 0.13040f, + 0.63717f, 0.08340f, + 0.64151f, 0.22596f, + 0.64277f, 14.45112f, + 0.65342f, 1.94833f, + 0.65906f, 1.41075f, + 0.66195f, 0.33327f, + 0.66208f, 0.59438f, + 0.66380f, 5.82288f, + 0.67561f, 55.08506f, + 0.67985f, 0.98953f, + 0.68848f, 0.02431f, + 0.69743f, 0.75692f, + 0.69940f, 0.41776f, + 0.71088f, 2.29372f, + 0.71473f, 9.88443f, + 0.71666f, 3.15179f, + 0.71976f, 1.57490f, + 0.72121f, 0.15977f, + 0.72569f, 0.25747f, + 0.73215f, 4.49475f, + 0.73242f, 1.17828f, + 0.73611f, 0.10706f, + 0.74660f, 0.50029f, + 0.75066f, 0.06441f, + 0.75918f, 0.66077f, + 0.76003f, 0.89356f, + 0.77072f, 6.95905f, + 0.77186f, 18.53232f, + 0.77303f, 1.82446f, + 0.78131f, 2.59582f, + 0.78137f, 0.37054f, + 0.78595f, 1.33439f, + 0.78988f, 0.20177f, + 0.79579f, 3.69204f, + 0.80621f, 12.12779f, + 0.80699f, 24.75305f, + 0.81287f, 0.04130f, + 0.81630f, 0.55362f, + 0.81694f, 0.29092f, + 0.81734f, 0.74874f, + 0.82110f, 1.06401f, + 0.82787f, 2.07876f, + 0.82981f, 5.00103f, + 0.84050f, 1.58158f, + 0.84438f, 2.89191f, + 0.84678f, 0.13416f, + 0.85616f, 0.44166f, + 0.86019f, 8.65103f, + 0.86346f, 0.01317f, + 0.86494f, 1.18927f, + 0.86577f, 0.09267f, + 0.86811f, 5.95882f, + 0.87117f, 0.84740f, + 0.87406f, 0.61269f, + 0.87981f, 0.23437f, + 0.88151f, 2.44548f, + 0.88504f, 0.33708f, + 0.88847f, 1.82180f, + 0.89206f, 3.31226f, + 0.89352f, 16.07224f, + 0.89868f, 0.17353f, + 0.90558f, 1.37396f, + 0.90956f, 4.04629f, + 0.91046f, 0.71437f, + 0.91555f, 0.95141f, + 0.91607f, 0.05802f, + 0.92133f, 0.50076f, + 0.92397f, 2.18529f, + 0.92943f, 6.99163f, + 0.93816f, 2.70762f, + 0.93915f, 10.79124f, + 0.93979f, 35.02379f, + 0.94373f, 0.29109f, + 0.94428f, 1.54440f, + 0.94915f, 1.11190f, + 0.94935f, 4.81827f, + 0.94963f, 0.39335f, + 0.95314f, 0.02810f, + 0.95605f, 0.62253f, + 0.96422f, 0.78364f, + 0.96502f, 1.90168f, + 0.96887f, 0.08041f, + 0.97223f, 3.22145f, + 0.97319f, 0.15476f, + 0.97937f, 0.21603f, + 0.99027f, 1.26402f, + 0.99060f, 2.42092f, + 0.99469f, 8.02656f, + 0.99661f, 20.50587f, + 0.99674f, 0.54301f, + 0.99823f, 5.86597f, + 0.99991f, 0.88884f, + 1.00124f, 0.33090f, + 1.00312f, 4.24275f, + 1.00328f, 1.65980f, + 1.02202f, 13.84765f, + 1.02395f, 0.69092f, + 1.02548f, 2.07584f, + 1.02556f, 0.12171f, + 1.02613f, 0.43643f, + 1.03316f, 1.03433f, + 1.03462f, 1.40902f, + 1.03999f, 2.82553f, + 1.05031f, 3.58878f, + 1.05184f, 0.26298f, + 1.06027f, 9.06668f, + 1.07241f, 0.79358f, + 1.07471f, 0.52241f, + 1.08008f, 1.76977f, + 1.08043f, 4.93935f, + 1.08062f, 45.38949f, + 1.08090f, 2.36074f, + 1.08304f, 1.15533f, + 1.08642f, 0.18015f, + 1.08996f, 0.06905f, + 1.09008f, 6.56321f, + 1.09044f, 0.01828f, + 1.09727f, 0.36021f, + 1.10075f, 0.62638f, + 1.11422f, 1.47205f, + 1.11535f, 0.93762f, + 1.11816f, 0.03576f, + 1.12340f, 0.10836f, + 1.13413f, 25.42389f, + 1.13994f, 2.96173f, + 1.14294f, 3.90159f, + 1.15382f, 0.04975f, + 1.15439f, 11.91982f, + 1.16090f, 16.73218f, + 1.16103f, 2.17967f, + 1.16117f, 0.68099f, + 1.16863f, 0.46714f, + 1.17332f, 1.18022f, + 1.17498f, 0.31199f, + 1.17616f, 9.51265f, + 1.18152f, 7.40048f, + 1.18372f, 0.24663f, + 1.18372f, 0.20126f, + 1.18610f, 0.14046f, + 1.18676f, 0.08978f, + 1.18699f, 5.55043f, + 1.18951f, 0.84044f, + 1.19478f, 1.59238f, + 1.19799f, 2.55164f, + 1.19820f, 1.89784f, + 1.19857f, 0.39387f, + 1.19888f, 0.56489f, + 1.19998f, 1.02889f, + 1.20345f, 3.31468f, + 1.20431f, 4.41910f, + 1.20567f, 1.32040f, + 1.21177f, 0.74548f +}; + +const float gp_gamma_1sfr_7b[2*128] = +{ + 0.02136f, 0.16576f, + 0.02610f, 0.04700f, + 0.02673f, 1.32916f, + 0.03917f, 0.38038f, + 0.06539f, 3.93015f, + 0.06590f, 0.78428f, + 0.07007f, 2.41347f, + 0.07073f, 0.12201f, + 0.08692f, 0.02273f, + 0.10144f, 0.26162f, + 0.12117f, 0.58428f, + 0.12817f, 0.06582f, + 0.13200f, 6.18738f, + 0.13542f, 1.05113f, + 0.14605f, 12.85127f, + 0.15252f, 1.88832f, + 0.17593f, 0.43086f, + 0.18150f, 24.88791f, + 0.19845f, 0.19059f, + 0.20102f, 0.09975f, + 0.21887f, 3.04712f, + 0.22650f, 0.80244f, + 0.22710f, 1.36678f, + 0.23569f, 0.04128f, + 0.24090f, 0.33017f, + 0.24423f, 4.39312f, + 0.25622f, 9.04696f, + 0.26686f, 0.01465f, + 0.30474f, 0.13696f, + 0.30653f, 0.51721f, + 0.33982f, 2.33214f, + 0.34572f, 0.96726f, + 0.34776f, 0.22391f, + 0.35921f, 1.66824f, + 0.37321f, 5.83958f, + 0.38246f, 0.29909f, + 0.38918f, 0.07567f, + 0.39258f, 0.03099f, + 0.40290f, 0.67440f, + 0.43384f, 3.82188f, + 0.44136f, 1.28810f, + 0.45720f, 0.39518f, + 0.46915f, 0.18114f, + 0.49155f, 7.58133f, + 0.49486f, 18.79692f, + 0.49964f, 2.78200f, + 0.50311f, 0.11426f, + 0.50988f, 1.82600f, + 0.51013f, 12.50225f, + 0.51163f, 0.85831f, + 0.53672f, 0.55661f, + 0.54568f, 0.24221f, + 0.58854f, 0.04842f, + 0.58856f, 1.13464f, + 0.59022f, 5.29180f, + 0.61432f, 0.31344f, + 0.62368f, 0.01799f, + 0.62503f, 3.37535f, + 0.62557f, 0.15698f, + 0.63586f, 2.17291f, + 0.64066f, 0.72903f, + 0.65002f, 0.46018f, + 0.67718f, 0.08632f, + 0.67719f, 1.47658f, + 0.68875f, 9.72347f, + 0.68911f, 32.65981f, + 0.72111f, 4.49107f, + 0.72523f, 0.94174f, + 0.73603f, 0.22351f, + 0.75271f, 16.69924f, + 0.75455f, 2.72292f, + 0.75633f, 0.36255f, + 0.76400f, 0.65651f, + 0.76595f, 6.66691f, + 0.77475f, 1.86222f, + 0.79933f, 1.19851f, + 0.80473f, 0.13963f, + 0.80852f, 0.51193f, + 0.82270f, 3.73825f, + 0.84176f, 0.02816f, + 0.84259f, 0.05841f, + 0.85838f, 0.27004f, + 0.86563f, 0.82004f, + 0.86743f, 2.29536f, + 0.88363f, 1.49460f, + 0.89140f, 5.36064f, + 0.89183f, 12.35149f, + 0.89905f, 8.20030f, + 0.90532f, 0.58773f, + 0.90588f, 0.39700f, + 0.91006f, 24.98023f, + 0.92596f, 0.19474f, + 0.92719f, 3.17426f, + 0.93316f, 1.03857f, + 0.94022f, 0.10069f, + 0.94912f, 1.92355f, + 0.98244f, 0.69665f, + 0.98723f, 4.12701f, + 0.99391f, 0.45338f, + 0.99688f, 1.30750f, + 0.99874f, 44.92089f, + 1.00074f, 0.30398f, + 1.00361f, 2.48072f, + 1.00432f, 6.80059f, + 1.00968f, 0.01556f, + 1.01623f, 10.59523f, + 1.03016f, 0.88271f, + 1.03693f, 0.16444f, + 1.03908f, 18.89908f, + 1.04942f, 1.71141f, + 1.08216f, 0.03947f, + 1.08519f, 2.81718f, + 1.09035f, 0.07394f, + 1.09092f, 0.49594f, + 1.09429f, 1.02772f, + 1.09931f, 4.69322f, + 1.14445f, 13.97163f, + 1.14663f, 0.22834f, + 1.14869f, 8.63215f, + 1.15982f, 0.12298f, + 1.16574f, 0.78265f, + 1.16644f, 0.35763f, + 1.17170f, 1.51544f, + 1.17199f, 5.76835f, + 1.17405f, 2.05383f, + 1.17523f, 0.58874f, + 1.18128f, 3.43730f, + 1.18605f, 1.15776f +}; + +const float gp_gamma_1sfr_6b[2*64] = +{ + 0.02662f, 0.35620f, + 0.02886f, 0.12384f, + 0.05872f, 0.03097f, + 0.06053f, 1.26461f, + 0.07678f, 3.09046f, + 0.08829f, 0.68582f, + 0.10444f, 0.24412f, + 0.11040f, 0.08899f, + 0.15678f, 8.15025f, + 0.15909f, 1.86873f, + 0.17247f, 0.48977f, + 0.17727f, 24.37615f, + 0.19825f, 0.05111f, + 0.21935f, 4.40219f, + 0.22361f, 0.15212f, + 0.22674f, 0.94328f, + 0.25832f, 0.01602f, + 0.28570f, 0.36784f, + 0.30922f, 12.93476f, + 0.31936f, 2.48635f, + 0.38038f, 1.35732f, + 0.38051f, 0.09521f, + 0.38075f, 0.21973f, + 0.38524f, 0.62092f, + 0.42799f, 0.03238f, + 0.44723f, 6.21713f, + 0.48877f, 3.39646f, + 0.53050f, 0.87060f, + 0.53522f, 0.31847f, + 0.54464f, 1.99023f, + 0.55504f, 0.15767f, + 0.63219f, 0.55908f, + 0.64035f, 0.05438f, + 0.64773f, 19.11642f, + 0.65402f, 1.48427f, + 0.67413f, 9.41877f, + 0.69087f, 4.69262f, + 0.71312f, 0.10928f, + 0.75159f, 0.21181f, + 0.76049f, 1.08676f, + 0.76781f, 0.01802f, + 0.77612f, 0.41533f, + 0.78253f, 2.60862f, + 0.86685f, 0.73032f, + 0.87435f, 33.14677f, + 0.89187f, 1.63714f, + 0.89264f, 6.41601f, + 0.89525f, 12.17085f, + 0.91060f, 0.07523f, + 0.92352f, 0.26853f, + 0.94457f, 3.60819f, + 0.97995f, 0.49732f, + 0.99345f, 0.96508f, + 0.99428f, 0.12950f, + 1.01209f, 2.04687f, + 1.02897f, 0.03326f, + 1.05102f, 17.03703f, + 1.06462f, 8.38911f, + 1.10284f, 4.88112f, + 1.11160f, 0.34356f, + 1.12908f, 0.17681f, + 1.13018f, 2.82130f, + 1.13048f, 0.64939f, + 1.13502f, 1.29540f +}; + + +const float gp_gamma_2sfr_7b[2*128] = +{ + 0.00607f, 2.39054f, + 0.00954f, 0.47393f, + 0.01025f, 1.13156f, + 0.01770f, 0.69243f, + 0.02670f, 0.86143f, + 0.02900f, 0.36511f, + 0.04481f, 1.44093f, + 0.05677f, 0.18129f, + 0.06916f, 0.29914f, + 0.06931f, 0.58281f, + 0.09094f, 0.99160f, + 0.11875f, 0.78403f, + 0.12072f, 32.79239f, + 0.12805f, 0.43746f, + 0.12919f, 1.87968f, + 0.14693f, 0.23271f, + 0.16393f, 0.66184f, + 0.17876f, 1.08413f, + 0.20774f, 0.52913f, + 0.21146f, 0.33304f, + 0.21176f, 0.82451f, + 0.22667f, 1.29470f, + 0.27074f, 0.96525f, + 0.27431f, 0.64919f, + 0.27900f, 0.42916f, + 0.27972f, 4.26235f, + 0.30501f, 1.65535f, + 0.32627f, 0.74124f, + 0.33076f, 0.21006f, + 0.33996f, 1.13073f, + 0.35145f, 0.51891f, + 0.35860f, 0.86393f, + 0.36177f, 0.33235f, + 0.37868f, 6.51886f, + 0.39024f, 12.56903f, + 0.39765f, 0.63998f, + 0.40513f, 1.42570f, + 0.40817f, 2.87488f, + 0.43002f, 2.06198f, + 0.43340f, 0.97173f, + 0.43475f, 0.40939f, + 0.43718f, 18.88363f, + 0.44833f, 0.75361f, + 0.46375f, 0.54756f, + 0.47932f, 1.22520f, + 0.51646f, 0.86275f, + 0.52785f, 0.64565f, + 0.53846f, 0.46049f, + 0.54240f, 1.07549f, + 0.54644f, 1.76965f, + 0.56866f, 0.26470f, + 0.58517f, 0.75438f, + 0.58905f, 1.35033f, + 0.59790f, 0.55874f, + 0.60132f, 0.95549f, + 0.61063f, 2.37370f, + 0.61285f, 0.37493f, + 0.64837f, 1.12469f, + 0.65662f, 0.64355f, + 0.66163f, 0.82985f, + 0.66799f, 1.54600f, + 0.67368f, 0.50148f, + 0.68300f, 3.65165f, + 0.70443f, 0.97799f, + 0.71587f, 1.25327f, + 0.72464f, 0.71612f, + 0.73632f, 0.31795f, + 0.75268f, 0.42125f, + 0.75309f, 2.14775f, + 0.75309f, 0.57562f, + 0.76160f, 0.86706f, + 0.76665f, 1.10985f, + 0.77299f, 1.64991f, + 0.80915f, 0.77262f, + 0.81281f, 1.32136f, + 0.81854f, 0.99876f, + 0.83675f, 0.63186f, + 0.83681f, 3.02209f, + 0.83687f, 0.48040f, + 0.85777f, 1.93471f, + 0.86131f, 0.87229f, + 0.86952f, 1.13226f, + 0.87613f, 1.46053f, + 0.87855f, 0.34269f, + 0.88214f, 0.19384f, + 0.89134f, 0.70978f, + 0.90866f, 0.95984f, + 0.92004f, 0.54981f, + 0.92222f, 1.24490f, + 0.93028f, 2.52260f, + 0.93695f, 0.80671f, + 0.94177f, 1.64620f, + 0.95825f, 1.05636f, + 0.96289f, 0.39904f, + 0.97439f, 0.65464f, + 0.97607f, 1.34420f, + 0.98128f, 0.88402f, + 0.99580f, 9.01834f, + 1.00135f, 2.01532f, + 1.01010f, 1.16279f, + 1.01723f, 0.74974f, + 1.02846f, 1.51554f, + 1.02849f, 0.94135f, + 1.03245f, 0.49354f, + 1.05191f, 0.60369f, + 1.05632f, 4.15579f, + 1.06623f, 1.06736f, + 1.07827f, 1.25591f, + 1.08027f, 0.82287f, + 1.08960f, 1.72193f, + 1.09072f, 0.28420f, + 1.10754f, 2.43024f, + 1.12653f, 0.95428f, + 1.12778f, 0.67641f, + 1.13450f, 1.41156f, + 1.14902f, 0.40686f, + 1.16032f, 3.38038f, + 1.16226f, 1.14385f, + 1.17713f, 0.54895f, + 1.18580f, 1.84337f, + 1.18686f, 0.74693f, + 1.19352f, 0.86699f, + 1.20171f, 1.54779f, + 1.20572f, 2.16971f, + 1.20617f, 1.02977f, + 1.20662f, 2.74485f, + 1.20688f, 1.28237f, + 1.20728f, 5.22483f +}; + + +const float gp_gamma_2sfr_6b[2*64] = +{ + 0.01130f, 0.59705f, + 0.02652f, 1.01430f, + 0.02794f, 0.28351f, + 0.06102f, 0.41178f, + 0.07430f, 0.77026f, + 0.07572f, 1.46777f, + 0.10914f, 0.18121f, + 0.12363f, 2.40953f, + 0.13197f, 0.51810f, + 0.14628f, 0.30909f, + 0.15972f, 0.92110f, + 0.20291f, 0.66321f, + 0.20694f, 1.21691f, + 0.23404f, 0.40495f, + 0.27484f, 33.61382f, + 0.28250f, 0.79452f, + 0.30145f, 1.75124f, + 0.31141f, 0.53656f, + 0.32351f, 0.23494f, + 0.33936f, 0.99733f, + 0.38508f, 3.72779f, + 0.40108f, 0.65367f, + 0.41319f, 0.40008f, + 0.42662f, 1.25364f, + 0.43246f, 9.93625f, + 0.45774f, 0.83578f, + 0.51009f, 1.61477f, + 0.51585f, 0.50984f, + 0.55413f, 1.04889f, + 0.56694f, 0.69123f, + 0.60142f, 2.29733f, + 0.60208f, 0.32174f, + 0.63695f, 16.75804f, + 0.64385f, 0.85349f, + 0.64786f, 1.32201f, + 0.67202f, 0.55054f, + 0.72879f, 1.03555f, + 0.74357f, 0.71744f, + 0.76140f, 1.79730f, + 0.78523f, 0.43896f, + 0.81538f, 1.20775f, + 0.81979f, 0.86215f, + 0.82523f, 3.16953f, + 0.86528f, 0.66633f, + 0.87274f, 0.25452f, + 0.88210f, 1.51311f, + 0.90326f, 0.99246f, + 0.93081f, 0.53871f, + 0.95916f, 2.20734f, + 0.96174f, 1.28996f, + 0.96917f, 0.82441f, + 0.99824f, 6.35842f, + 1.00335f, 0.36563f, + 1.02237f, 1.09680f, + 1.03188f, 0.64719f, + 1.04846f, 1.61469f, + 1.09185f, 0.91916f, + 1.11199f, 4.24727f, + 1.14659f, 0.48521f, + 1.15873f, 2.64461f, + 1.16374f, 1.37282f, + 1.17310f, 0.74954f, + 1.18098f, 1.86320f, + 1.18544f, 1.08087f +}; + +const float gp_gamma_3sfr_6b[2*64] = +{ + 0.01192f, 0.29245f, + 0.04985f, 0.56198f, + 0.07032f, 1.20261f, + 0.08337f, 0.36774f, + 0.08405f, 0.80061f, + 0.09313f, 1.76147f, + 0.09580f, 0.19048f, + 0.13781f, 0.46427f, + 0.15191f, 1.01263f, + 0.17911f, 0.66093f, + 0.19176f, 0.31423f, + 0.21095f, 3.33105f, + 0.24351f, 0.84426f, + 0.25383f, 1.38475f, + 0.25558f, 0.52730f, + 0.26697f, 2.41458f, + 0.32244f, 1.02709f, + 0.33147f, 0.25578f, + 0.33614f, 0.69549f, + 0.35169f, 0.41222f, + 0.41458f, 1.21107f, + 0.41759f, 0.87121f, + 0.42537f, 0.59296f, + 0.46820f, 1.57552f, + 0.51038f, 0.47823f, + 0.51562f, 1.03574f, + 0.52553f, 0.74288f, + 0.56848f, 2.12515f, + 0.59985f, 0.33289f, + 0.60551f, 13.69166f, + 0.61194f, 0.89674f, + 0.62213f, 0.60927f, + 0.62628f, 1.28489f, + 0.70519f, 0.76916f, + 0.71649f, 1.72293f, + 0.71964f, 1.05889f, + 0.73148f, 8.45570f, + 0.73217f, 0.48093f, + 0.77896f, 26.25153f, + 0.78396f, 2.95227f, + 0.80147f, 0.90896f, + 0.80167f, 0.66149f, + 0.80656f, 1.44516f, + 0.86294f, 1.18805f, + 0.88649f, 0.81413f, + 0.90213f, 2.01099f, + 0.90474f, 0.55259f, + 0.91649f, 0.33485f, + 0.93167f, 1.03017f, + 0.96578f, 5.28431f, + 0.97308f, 1.36442f, + 0.97409f, 0.70362f, + 0.99790f, 0.92401f, + 1.05048f, 1.12005f, + 1.05996f, 1.76024f, + 1.06915f, 0.46437f, + 1.08636f, 0.80929f, + 1.10286f, 2.76431f, + 1.13708f, 3.74909f, + 1.15280f, 1.23892f, + 1.16077f, 0.62175f, + 1.17824f, 0.96656f, + 1.18408f, 2.17545f, + 1.18487f, 1.49786f +}; + +const float gp_gamma_4sfr_6b[2*64] = +{ + 0.00934f, 0.27565f, + 0.01721f, 0.97811f, + 0.02433f, 0.46654f, + 0.04781f, 0.72086f, + 0.06776f, 1.45241f, + 0.08727f, 0.35723f, + 0.08791f, 3.41441f, + 0.09299f, 2.13125f, + 0.09778f, 0.57872f, + 0.11158f, 0.19319f, + 0.12208f, 0.85691f, + 0.16346f, 0.44503f, + 0.17183f, 1.17256f, + 0.18821f, 0.67810f, + 0.23565f, 0.93068f, + 0.25353f, 0.31870f, + 0.25723f, 0.55721f, + 0.27028f, 1.43169f, + 0.30369f, 0.74972f, + 0.33457f, 1.10643f, + 0.33886f, 0.45699f, + 0.37588f, 1.81394f, + 0.39890f, 0.91791f, + 0.40041f, 0.63732f, + 0.44484f, 0.33746f, + 0.45345f, 1.29581f, + 0.45454f, 20.73460f, + 0.48041f, 0.79572f, + 0.51620f, 0.51876f, + 0.52239f, 1.07372f, + 0.52970f, 2.77458f, + 0.57723f, 0.69551f, + 0.58187f, 1.53270f, + 0.60145f, 0.92017f, + 0.64601f, 11.29119f, + 0.65868f, 7.45030f, + 0.66000f, 0.40154f, + 0.66097f, 0.58966f, + 0.67054f, 1.18310f, + 0.69460f, 0.84554f, + 0.69993f, 2.09527f, + 0.76202f, 0.69518f, + 0.77672f, 1.01521f, + 0.78020f, 1.40843f, + 0.82725f, 0.50517f, + 0.84005f, 0.27186f, + 0.84739f, 0.84066f, + 0.85816f, 5.06160f, + 0.87075f, 1.17031f, + 0.87474f, 1.80610f, + 0.91532f, 0.65903f, + 0.93722f, 0.94775f, + 0.94762f, 1.39061f, + 1.00344f, 1.14608f, + 1.00732f, 0.77084f, + 1.01480f, 0.39878f, + 1.05149f, 2.51385f, + 1.07194f, 1.57173f, + 1.07599f, 1.01017f, + 1.10831f, 3.54277f, + 1.11815f, 0.59230f, + 1.17359f, 0.85449f, + 1.17572f, 1.24171f, + 1.18513f, 1.93190f +}; + + +/*----------------------------------------------------------------------------------* + * Transition coding - gain quantization table + *----------------------------------------------------------------------------------*/ + +const float tbl_gain_code_tc[N_GAIN_CODE_TC] = +{ + 0.36201f, + 0.72382f, + 0.96727f, + 1.1856f, + 1.4119f, + 1.679f, + 2.0743f, + 3.3301f +}; + +/*-----------------------------------------------------------------* + * Transition coding - gain quantization table for g_trans + *-----------------------------------------------------------------*/ + +const float tbl_gain_trans_tc[N_GAIN_TC] = +{ + 35.8449f, + 86.7884f, + 150.0926f, + 233.3001f, + 346.0286f, + 511.5196f, + 819.6746f, + 1500.0f +}; + +/*-----------------------------------------------------------------* + * Transition coding - table of prototype glottal impulses + *-----------------------------------------------------------------*/ + +const float glottal_cdbk[L_IMPULSE*NUM_IMPULSE] = +{ + /* impulse 0 */ + -0.0873f, -0.2063f, -0.3544f, -0.2126f, -0.1581f, -0.5208f, + -0.5973f, 0.2106f, 1.0000f, 0.7095f, -0.0767f, -0.2388f, + 0.0709f, 0.1143f, -0.0099f, 0.1015f, 0.1852f, + /* impulse 1 */ + -0.2646f, -0.1655f, -0.0493f, -0.3314f, -0.5455f, -0.2641f, + -0.2661f, -0.9837f, -1.1157f, 0.1420f, 1.2626f, 0.8151f, + -0.2146f, -0.3466f, 0.0460f, 0.0398f, -0.0598f, + /* impulse 2 */ + 0.0440f, 0.0685f, 0.5108f, 0.3092f, -0.4060f, -0.3111f, + 0.2513f, -0.2578f, -1.1648f, -0.7488f, 0.1596f, 0.0151f, + -0.4176f, -0.1788f, 0.0580f, -0.1082f, -0.1541f, + /* impulse 3 */ + -0.1579f, -0.0873f, -0.0224f, -0.1885f, -0.2000f, -0.0267f, + -0.4276f, -1.1485f, -0.9711f, -0.1718f, -0.0348f, -0.3044f, + 0.0372f, 0.5686f, 0.4015f, 0.0141f, 0.1816f, + /* impulse 4 */ + 0.1022f, 0.3080f, 0.2984f, 0.3270f, 0.7278f, 0.8466f, + -0.1128f, -1.2094f, -0.9235f, 0.0785f, 0.1648f, -0.3146f, + -0.2563f, -0.0338f, -0.1887f, -0.2782f, -0.1077f, + /* impulse 5 */ + -0.0510f, -0.1082f, -0.0058f, -0.0603f, -0.2891f, -0.2515f, + -0.1505f, -0.6434f, -1.2732f, -0.8490f, 0.4029f, 0.9251f, + 0.3172f, -0.2032f, -0.0563f, 0.0897f, -0.0221f, + /* impulse 6 */ + -0.0570f, -0.2277f, -0.1776f, -0.0155f, -0.2296f, -0.4609f, + 0.1004f, 1.0174f, 1.0000f, 0.1053f, -0.3371f, -0.0458f, + 0.0924f, -0.0681f, -0.0348f, 0.0797f, 0.0183f, + /* impulse 7 */ + 0.1327f, 0.0575f, -0.0754f, 0.0862f, 0.1887f, -0.1959f, + -0.3975f, 0.2925f, 0.9839f, 0.6334f, -0.0121f, -0.0045f, + 0.1349f, -0.0815f, -0.1751f, -0.0072f, -0.0099f +}; + +/*----------------------------------------------------------------------------------* + * AMR-WB IO WB BWE - deemphasis + *----------------------------------------------------------------------------------*/ + +const float deem_tab[56] = +{ + 0.630730419421360f, 0.629416164964296f, 0.628129905227103f, 0.626871385453679f, 0.625640357452226f, 0.624436579475560f, 0.623259816105156f, + 0.622109838138814f, 0.620986422481867f, 0.619889352041818f, 0.618818415626335f, 0.617773407844493f, 0.616754129011203f, 0.615760385054730f, + 0.614791987427225f, 0.613848753018209f, 0.612930504070914f, 0.612037068101433f, 0.611168277820597f, 0.610323971058526f, 0.609503990691786f, + 0.608708184573088f, 0.607936405463484f, 0.607188510967000f, 0.606464363467645f, 0.605763830068759f, 0.605086782534647f, 0.604433097234441f, + 0.603802655088168f, 0.603195341514964f, 0.602611046383395f, 0.602049663963857f, 0.601511092883003f, 0.600995236080178f, 0.600502000765808f, + 0.600031298381734f, 0.599583044563439f, 0.599157159104159f, 0.598753565920828f, 0.598372193021851f, 0.598012972476677f, 0.597675840387130f, + 0.597360736860508f, 0.597067605984399f, 0.596796395803217f, 0.596547058296428f, 0.596319549358454f, 0.596113828780239f, 0.595929860232466f, + 0.595767611250409f, 0.595627053220407f, 0.595508161367956f, 0.595410914747406f, 0.595335296233253f, 0.595281292513031f, 0.595248894081778f +}; + +const float filt_hp[56] = +{ + 0.001610570549503f, 0.004682981184545f, 0.008349027644995f, 0.012654118680910f, 0.017642537255539f, 0.023357023549788f, + 0.029838357405517f, 0.037124944278684f, 0.045252408764306f, 0.054253199698241f, 0.064156210737117f, 0.074986420169406f, + 0.086764553520305f, 0.099506772283889f, 0.113224391851657f, 0.127923631411203f, 0.143605398266754f, 0.160265108689438f, + 0.177892547044310f, 0.196471764568281f, 0.215981018793259f, 0.236392754226835f, 0.257673624523579f, 0.279784556007892f, + 0.302680852048711f, 0.326312337440982f, 0.350623541622164f, 0.375553919247241f, 0.401038106365070f, 0.427006210184762f, + 0.453384130194306f, 0.480093908196193f, 0.507054104656542f, 0.534180198625471f, 0.561385008376586f, 0.588579129831778f, + 0.615671389782721f, 0.642569310891142f, 0.669179585444241f, 0.695408554857669f, 0.721162691954086f, 0.746349083098340f, + 0.770875907338563f, 0.794652909783784f, 0.817591866540936f, 0.839607038635485f, 0.860615612448599f, 0.880538124318166f, + 0.899298867069991f, 0.916826276367851f, 0.933053294896263f, 0.947917712517199f, 0.961362480671352f, 0.973335999426038f, + 0.983792375705577f, 0.992691651376520f +}; + +/* table of values exp(-j*w*i) */ +const float exp_tab_q[34] = +{ + 1.000000000000000f, -0.980785280403230f, 0.923879532511287f, -0.831469612302544f, + 0.707106781186547f, -0.555570233019602f, 0.382683432365086f, -0.195090322016125f, + -0.000000000000003f, 0.195090322016130f, -0.382683432365091f, 0.555570233019606f, + -0.707106781186553f, 0.831469612302547f, -0.923879532511289f, 0.980785280403231f, + -1.000000000000000f, 0.000000000000000f, -0.195090322016129f, 0.382683432365090f, + -0.555570233019604f, 0.707106781186549f, -0.831469612302546f, 0.923879532511288f, + -0.980785280403231f, 1.000000000000000f, -0.980785280403230f, 0.923879532511286f, + -0.831469612302543f, 0.707106781186542f, -0.555570233019599f, 0.382683432365084f, + -0.195090322016126f, -0.000000000000005f +}; + +const float exp_tab_p[34] = +{ + 1.000000000000000f, -0.707106781186548f, -0.000000000000000f, 0.707106781186548f, + -1.000000000000000f, 0.707106781186547f, 0.000000000000000f, -0.707106781186547f, + 1.000000000000000f, -0.707106781186546f, -0.000000000000003f, 0.707106781186548f, + -1.000000000000000f, 0.707106781186546f, -0.000000000000000f, -0.707106781186548f, + 1.000000000000000f, 0.000000000000000f, -0.707106781186548f, 1.000000000000000f, + -0.707106781186547f, -0.000000000000000f, 0.707106781186549f, -1.000000000000000f, + 0.707106781186548f, 0.000000000000000f, -0.707106781186549f, 1.000000000000000f, + -0.707106781186548f, 0.000000000000000f, 0.707106781186549f, -1.000000000000000f, + 0.707106781186547f, 0.000000000000000f +}; + +/* gains for 23k85 mode */ +const float HP_gain[16] = +{ + /* values in Q15: 3624, 4673, 5597, 6479, 7425, 8378, 9324, 10264, 11210, 12206, 13391, 14844, 16770, 19655, 24289, 32728 */ + 0.110595703125000f, 0.142608642578125f, 0.170806884765625f, 0.197723388671875f, + 0.226593017578125f, 0.255676269531250f, 0.284545898437500f, 0.313232421875000f, + 0.342102050781250f, 0.372497558593750f, 0.408660888671875f, 0.453002929687500f, + 0.511779785156250f, 0.599822998046875f, 0.741241455078125f, 0.998779296875000f +}; + +/* band-pass 6-8kHz filter */ +const float fir_6k_8k[31]= +{ + 0.001331237773450f, -0.004734562657574f, 0.009865692979275f, -0.014704482109862f, + 0.017170883692091f, -0.018004559024736f, 0.022168155759205f, -0.036012990296002f, + 0.060614595353634f, -0.086000479894051f, 0.092413785317631f, -0.060769441864153f, + -0.012918738234409f, 0.109335430548556f, -0.191677822804549f, 0.224071909378974f, + -0.191677822804549f, 0.109335430548556f, -0.012918738234409f, -0.060769441864153f, + 0.092413785317631f, -0.086000479894051f, 0.060614595353634f, -0.036012990296002f, + 0.022168155759205f, -0.018004559024736f, 0.017170883692091f, -0.014704482109862f, + 0.009865692979275f, -0.004734562657574f, 0.001331237773450f +}; + + +/*----------------------------------------------------------------------------------* + * 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 float b_hp400[3] = { 0.893554687f, -1.787109375f, 0.893554687f }; +const float a_hp400[3] = { 1.000000000f, 1.787109375f, -0.864257812f }; + +/*----------------------------------------------------------------------------------* + * 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 float fir_6k_7k[31] = +{ + -0.001005f, 0.001428f, 0.000965f, -0.000863f, -0.011296f, + 0.034231f, -0.043397f, -0.000000f, 0.115906f, -0.271028f, + 0.376868f, -0.335243f, 0.108276f, 0.237003f, -0.549363f, + 0.675000f, -0.549363f, 0.237003f, 0.108276f, -0.335243f, + 0.376868f, -0.271028f, 0.115906f, -0.000000f, -0.043397f, + 0.034231f, -0.011296f, -0.000863f, 0.000965f, 0.001428f, + -0.001005f +}; + +/*----------------------------------------------------------------------------------* + * Enhacer - 2.0 - 6.4 kHz impulse response with phase dispersion in freq. domain + *----------------------------------------------------------------------------------*/ + +const float low_H[L_SUBFR] = +{ + 1.000300f, 0.999812f, 1.000125f, 0.999868f, 0.999879f, 0.999935f, 0.999838f, 0.999992f, 1.000076f, 0.626554f, 0.619763f, 0.603882f, 0.857647f, 0.997470f, -0.032403f, + 0.806652f, 0.999300f, 0.946634f, 0.574139f, 0.973425f, 0.288464f, 0.890704f, 0.635021f, 0.597882f, -0.997076f, -0.110774f, -0.648392f, 0.771888f, 0.888411f, -0.774123f, + 0.695109f, 0.498998f, 0.999900f, -0.866525f, 0.719081f, 0.633481f, 0.458722f, 0.636210f, -0.761251f, 0.993932f, -0.073228f, -0.801816f, 0.772627f, -0.454461f, 0.957250f, + -0.229682f, -0.818972f, -0.322274f, 0.031800f, -0.591141f, -0.999439f, -0.074385f, 0.514882f, -0.797032f, -0.784999f, -0.779712f, -0.000028f, 0.000164f, 0.000029f, -0.000135f, + -0.000047f, -0.000033f, -0.000080f, 0.000099f +}; + +/*----------------------------------------------------------------------------------* + * Enhancer - 3.2 - 6.4 kHz impulse response with phase dispersion in freq. domain + *----------------------------------------------------------------------------------*/ + +const float mid_H[L_SUBFR] = +{ + 0.999900f, 0.999848f, 1.000003f, 1.000048f, 1.000107f, 1.000242f, 1.000165f, 0.999909f, 1.000212f, 0.999933f, 1.000099f, 1.000100f, 1.000113f, 1.000018f, 0.999901f, 1.000267f, + 0.906200f, 0.587715f, 0.808629f, 0.884216f, 0.671089f, 0.039238f, 0.843369f, 0.841006f, 0.394788f, 0.528863f, 0.710110f, 0.596973f, -0.893309f, -0.059908f, 0.716925f, -0.044067f, + 1.000100f, -0.998848f, -0.697170f, 0.998190f, 0.449397f, 0.802480f, -0.704198f, -0.848591f, -0.918649f, -0.540881f, 0.537822f, -0.999200f, -0.741318f, 0.467580f, -0.588204f, + -0.808928f, -0.422500f, 0.000219f, -0.000261f, -0.000086f, -0.000313f, 0.000080f, 0.000406f, 0.000351f, -0.000449f, -0.000065f, 0.000214f, -0.000254f, 0.000002f, -0.000090f, + -0.000198f, 0.000193f +}; + +/*-------------------------------------------------------------------* + * Low-pass FIR filter for low-freq post-filtering + * response : 0dB @ 50Hz, -6dB @ 500Hz, -45dB @ 1kHz) + * filter parameters: fs/2=8000, fc=500, gain=1.0, n=16 + *-------------------------------------------------------------------*/ + +const float tab_hup_l[SIZ_TAB_HUP_L] = +{ + -0.001246f, 0.002200f, -0.004791f, 0.009621f, -0.017685f, 0.031212f, -0.057225f, 0.135470f, 0.973955f, -0.103495f, 0.048663f, -0.027090f, 0.015280f, -0.008160f, + 0.003961f, -0.001827f, -0.002388f, 0.004479f, -0.009715f, 0.019261f, -0.035118f, 0.061945f, -0.115187f, 0.294161f, 0.898322f, -0.170283f, 0.083211f, -0.046645f, + 0.026210f, -0.013854f, 0.006641f, -0.003099f, -0.003277f, 0.006456f, -0.013906f, 0.027229f, -0.049283f, 0.086990f, -0.164590f, 0.464041f, 0.780309f, -0.199879f, + 0.100795f, -0.056792f, 0.031761f, -0.016606f, 0.007866f, -0.003740f, -0.003770f, 0.007714f, -0.016462f, 0.031849f, -0.057272f, 0.101294f, -0.195755f, 0.630993f, + 0.630993f, -0.195755f, 0.101294f, -0.057272f, 0.031849f, -0.016462f, 0.007714f, -0.003770f, -0.003740f, 0.007866f, -0.016606f, 0.031761f, -0.056792f, 0.100795f, + -0.199879f, 0.780309f, 0.464041f, -0.164590f, 0.086990f, -0.049283f, 0.027229f, -0.013906f, 0.006456f, -0.003277f, -0.003099f, 0.006641f, -0.013854f, 0.026210f, + -0.046645f, 0.083211f, -0.170283f, 0.898322f, 0.294161f, -0.115187f, 0.061945f, -0.035118f, 0.019261f, -0.009715f, 0.004479f, -0.002388f, -0.001827f, 0.003961f, + -0.008160f, 0.015280f, -0.027090f, 0.048663f, -0.103495f, 0.973955f, 0.135470f, -0.057225f, 0.031212f, -0.017685f, 0.009621f, -0.004791f, 0.002200f, -0.001246f +}; + +const float tab_hup_s[SIZ_TAB_HUP_S] = +{ + -0.005772f, 0.087669f, 0.965882f, -0.048753f, -0.014793f, 0.214886f, 0.868791f, -0.065537f, -0.028507f, 0.374334f, 0.723418f, -0.060834f, -0.045567f, 0.550847f, + 0.550847f, -0.045567f, -0.060834f, 0.723418f, 0.374334f, -0.028507f, -0.065537f, 0.868791f, 0.214886f, -0.014793f, -0.048753f, 0.965882f, 0.087669f, -0.005772f +}; + +/*-------------------------------------------------------------------* + * Bass post-filter + *-------------------------------------------------------------------*/ + +const float filt_lp[1+L_FILT] = +{ + 0.088250f, 0.086410f, 0.081074f, 0.072768f, 0.062294f, 0.050623f, 0.038774f, 0.027692f, + 0.018130f, 0.010578f, 0.005221f, 0.001946f, 0.000385f +}; + +const float filt_lp_16kHz[1+L_FILT16k] = +{ + 0.071410f, 0.070433f, 0.067568f, 0.062999f, 0.057020f, 0.050005f, + 0.042378f, 0.034577f, 0.027022f, 0.020078f, 0.014031f, 0.009070f, + 0.005276f, 0.002625f, 0.000999f, 0.000205f +}; + +/*-------------------------------------------------------------------* + * Pulse indexing tables for ACELP innovation coding + *-------------------------------------------------------------------*/ + +const int PI_select_table[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 int PI_offset[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 short PI_factor[7] = {0,0,120,560,1820,4368,8008}; + +/*------------------------------------------------------------------------------* + * EDCT tables + *------------------------------------------------------------------------------*/ + +const float edct_table_80[80] = +{ + 0.33433591f, 0.33420702f, 0.33394929f, 0.33356281f, 0.33304773f, 0.33240426f, 0.33163264f, 0.33073317f, + 0.32970620f, 0.32855212f, 0.32727137f, 0.32586446f, 0.32433192f, 0.32267434f, 0.32089236f, 0.31898668f, + 0.31695802f, 0.31480717f, 0.31253495f, 0.31014224f, 0.30762997f, 0.30499910f, 0.30225065f, 0.29938568f, + 0.29640528f, 0.29331062f, 0.29010288f, 0.28678330f, 0.28335316f, 0.27981378f, 0.27616653f, 0.27241281f, + 0.26855407f, 0.26459179f, 0.26052751f, 0.25636280f, 0.25209925f, 0.24773851f, 0.24328226f, 0.23873223f, + 0.23409016f, 0.22935784f, 0.22453710f, 0.21962979f, 0.21463782f, 0.20956310f, 0.20440759f, 0.19917327f, + 0.19386217f, 0.18847633f, 0.18301783f, 0.17748878f, 0.17189129f, 0.16622755f, 0.16049971f, 0.15471000f, + 0.14886065f, 0.14295391f, 0.13699206f, 0.13097739f, 0.12491224f, 0.11879892f, 0.11263981f, 0.10643727f, + 0.10019369f, 0.09391149f, 0.08759309f, 0.08124092f, 0.07485742f, 0.06844507f, 0.06200633f, 0.05554369f, + 0.04905963f, 0.04255666f, 0.03603728f, 0.02950402f, 0.02295937f, 0.01640588f, 0.00984606f, 0.00328244f +}; + +const float edct_table_120[120] = +{ + 0.30212379f, 0.30207202f, 0.30196850f, 0.30181323f, 0.30160625f, 0.30134759f, 0.30103730f, 0.30067542f, + 0.30026203f, 0.29979718f, 0.29928097f, 0.29871348f, 0.29809481f, 0.29742505f, 0.29670434f, 0.29593279f, + 0.29511053f, 0.29423770f, 0.29331446f, 0.29234097f, 0.29131738f, 0.29024387f, 0.28912063f, 0.28794786f, + 0.28672574f, 0.28545450f, 0.28413434f, 0.28276550f, 0.28134821f, 0.27988271f, 0.27836926f, 0.27680811f, + 0.27519952f, 0.27354379f, 0.27184118f, 0.27009200f, 0.26829654f, 0.26645510f, 0.26456801f, 0.26263559f, + 0.26065816f, 0.25863608f, 0.25656968f, 0.25445931f, 0.25230535f, 0.25010815f, 0.24786810f, 0.24558558f, + 0.24326098f, 0.24089470f, 0.23848714f, 0.23603872f, 0.23354985f, 0.23102097f, 0.22845250f, 0.22584489f, + 0.22319858f, 0.22051402f, 0.21779168f, 0.21503203f, 0.21223553f, 0.20940267f, 0.20653392f, 0.20362979f, + 0.20069076f, 0.19771735f, 0.19471006f, 0.19166941f, 0.18859591f, 0.18549011f, 0.18235251f, 0.17918368f, + 0.17598414f, 0.17275445f, 0.16949515f, 0.16620682f, 0.16289000f, 0.15954528f, 0.15617322f, 0.15277439f, + 0.14934940f, 0.14589881f, 0.14242322f, 0.13892323f, 0.13539943f, 0.13185244f, 0.12828285f, 0.12469128f, + 0.12107835f, 0.11744467f, 0.11379087f, 0.11011757f, 0.10642540f, 0.10271499f, 0.09898699f, 0.09524203f, + 0.09148074f, 0.08770378f, 0.08391180f, 0.08010544f, 0.07628535f, 0.07245219f, 0.06860661f, 0.06474928f, + 0.06088086f, 0.05700200f, 0.05311338f, 0.04921565f, 0.04530949f, 0.04139557f, 0.03747456f, 0.03354713f, + 0.02961394f, 0.02567569f, 0.02173303f, 0.01778665f, 0.01383722f, 0.00988542f, 0.00593193f, 0.00197742f +}; + +const float edct_table_320[320] = +{ + 0.23643389f, 0.23642819f, 0.23641680f, 0.23639971f, 0.23637692f, 0.23634844f, 0.23631426f, 0.23627439f, + 0.23622882f, 0.23617757f, 0.23612062f, 0.23605798f, 0.23598966f, 0.23591565f, 0.23583595f, 0.23575057f, + 0.23565951f, 0.23556278f, 0.23546036f, 0.23535227f, 0.23523852f, 0.23511909f, 0.23499400f, 0.23486324f, + 0.23472683f, 0.23458476f, 0.23443704f, 0.23428367f, 0.23412465f, 0.23396000f, 0.23378970f, 0.23361377f, + 0.23343222f, 0.23324504f, 0.23305223f, 0.23285382f, 0.23264979f, 0.23244015f, 0.23222492f, 0.23200409f, + 0.23177767f, 0.23154566f, 0.23130808f, 0.23106492f, 0.23081619f, 0.23056191f, 0.23030206f, 0.23003667f, + 0.22976573f, 0.22948926f, 0.22920726f, 0.22891974f, 0.22862670f, 0.22832815f, 0.22802410f, 0.22771455f, + 0.22739952f, 0.22707901f, 0.22675302f, 0.22642158f, 0.22608467f, 0.22574232f, 0.22539453f, 0.22504131f, + 0.22468267f, 0.22431861f, 0.22394915f, 0.22357429f, 0.22319405f, 0.22280842f, 0.22241743f, 0.22202108f, + 0.22161938f, 0.22121233f, 0.22079996f, 0.22038227f, 0.21995927f, 0.21953096f, 0.21909737f, 0.21865850f, + 0.21821436f, 0.21776496f, 0.21731032f, 0.21685044f, 0.21638533f, 0.21591501f, 0.21543948f, 0.21495877f, + 0.21447288f, 0.21398181f, 0.21348560f, 0.21298423f, 0.21247774f, 0.21196612f, 0.21144940f, 0.21092759f, + 0.21040069f, 0.20986872f, 0.20933169f, 0.20878962f, 0.20824252f, 0.20769041f, 0.20713328f, 0.20657117f, + 0.20600408f, 0.20543202f, 0.20485502f, 0.20427308f, 0.20368621f, 0.20309444f, 0.20249778f, 0.20189623f, + 0.20128983f, 0.20067857f, 0.20006247f, 0.19944156f, 0.19881584f, 0.19818532f, 0.19755004f, 0.19690999f, + 0.19626520f, 0.19561568f, 0.19496144f, 0.19430251f, 0.19363890f, 0.19297062f, 0.19229769f, 0.19162012f, + 0.19093794f, 0.19025116f, 0.18955980f, 0.18886386f, 0.18816338f, 0.18745836f, 0.18674883f, 0.18603479f, + 0.18531628f, 0.18459330f, 0.18386586f, 0.18313400f, 0.18239773f, 0.18165706f, 0.18091202f, 0.18016261f, + 0.17940887f, 0.17865080f, 0.17788842f, 0.17712176f, 0.17635084f, 0.17557566f, 0.17479625f, 0.17401263f, + 0.17322482f, 0.17243283f, 0.17163669f, 0.17083642f, 0.17003202f, 0.16922353f, 0.16841096f, 0.16759434f, + 0.16677367f, 0.16594899f, 0.16512031f, 0.16428765f, 0.16345103f, 0.16261047f, 0.16176600f, 0.16091763f, + 0.16006537f, 0.15920927f, 0.15834932f, 0.15748556f, 0.15661801f, 0.15574668f, 0.15487160f, 0.15399279f, + 0.15311027f, 0.15222405f, 0.15133417f, 0.15044065f, 0.14954350f, 0.14864274f, 0.14773840f, 0.14683051f, + 0.14591907f, 0.14500412f, 0.14408568f, 0.14316376f, 0.14223840f, 0.14130960f, 0.14037740f, 0.13944182f, + 0.13850288f, 0.13756060f, 0.13661501f, 0.13566613f, 0.13471397f, 0.13375858f, 0.13279995f, 0.13183813f, + 0.13087313f, 0.12990498f, 0.12893370f, 0.12795931f, 0.12698183f, 0.12600130f, 0.12501773f, 0.12403115f, + 0.12304158f, 0.12204905f, 0.12105357f, 0.12005518f, 0.11905390f, 0.11804974f, 0.11704275f, 0.11603293f, + 0.11502031f, 0.11400493f, 0.11298680f, 0.11196594f, 0.11094239f, 0.10991616f, 0.10888729f, 0.10785579f, + 0.10682169f, 0.10578502f, 0.10474580f, 0.10370406f, 0.10265981f, 0.10161310f, 0.10056393f, 0.09951234f, + 0.09845836f, 0.09740200f, 0.09634329f, 0.09528227f, 0.09421894f, 0.09315335f, 0.09208551f, 0.09101546f, + 0.08994321f, 0.08886879f, 0.08779223f, 0.08671356f, 0.08563280f, 0.08454997f, 0.08346511f, 0.08237823f, + 0.08128937f, 0.08019855f, 0.07910580f, 0.07801115f, 0.07691461f, 0.07581622f, 0.07471600f, 0.07361399f, + 0.07251019f, 0.07140466f, 0.07029740f, 0.06918844f, 0.06807783f, 0.06696557f, 0.06585169f, 0.06473623f, + 0.06361921f, 0.06250066f, 0.06138060f, 0.06025906f, 0.05913607f, 0.05801166f, 0.05688584f, 0.05575866f, + 0.05463013f, 0.05350029f, 0.05236916f, 0.05123676f, 0.05010313f, 0.04896830f, 0.04783228f, 0.04669511f, + 0.04555682f, 0.04441742f, 0.04327696f, 0.04213546f, 0.04099294f, 0.03984943f, 0.03870496f, 0.03755956f, + 0.03641326f, 0.03526607f, 0.03411804f, 0.03296919f, 0.03181954f, 0.03066912f, 0.02951797f, 0.02836610f, + 0.02721355f, 0.02606034f, 0.02490651f, 0.02375208f, 0.02259707f, 0.02144152f, 0.02028545f, 0.01912890f, + 0.01797188f, 0.01681443f, 0.01565658f, 0.01449834f, 0.01333976f, 0.01218086f, 0.01102166f, 0.00986220f, + 0.00870250f, 0.00754259f, 0.00638250f, 0.00522226f, 0.00406188f, 0.00290142f, 0.00174088f, 0.00058030f +}; + +const float edct_table_480[480] = +{ + 0.21364290f, 0.21364061f, 0.21363603f, 0.21362917f, 0.21362002f, 0.21360858f, 0.21359485f, 0.21357884f, + 0.21356053f, 0.21353995f, 0.21351707f, 0.21349191f, 0.21346446f, 0.21343473f, 0.21340271f, 0.21336840f, + 0.21333181f, 0.21329294f, 0.21325178f, 0.21320833f, 0.21316261f, 0.21311460f, 0.21306431f, 0.21301173f, + 0.21295688f, 0.21289974f, 0.21284033f, 0.21277863f, 0.21271466f, 0.21264841f, 0.21257988f, 0.21250908f, + 0.21243600f, 0.21236064f, 0.21228301f, 0.21220311f, 0.21212093f, 0.21203649f, 0.21194977f, 0.21186078f, + 0.21176952f, 0.21167600f, 0.21158021f, 0.21148215f, 0.21138183f, 0.21127924f, 0.21117439f, 0.21106728f, + 0.21095791f, 0.21084628f, 0.21073239f, 0.21061625f, 0.21049785f, 0.21037720f, 0.21025429f, 0.21012913f, + 0.21000172f, 0.20987206f, 0.20974016f, 0.20960601f, 0.20946961f, 0.20933097f, 0.20919009f, 0.20904697f, + 0.20890161f, 0.20875401f, 0.20860417f, 0.20845211f, 0.20829781f, 0.20814128f, 0.20798252f, 0.20782153f, + 0.20765832f, 0.20749288f, 0.20732522f, 0.20715535f, 0.20698325f, 0.20680894f, 0.20663241f, 0.20645367f, + 0.20627271f, 0.20608955f, 0.20590418f, 0.20571661f, 0.20552684f, 0.20533486f, 0.20514068f, 0.20494431f, + 0.20474574f, 0.20454498f, 0.20434203f, 0.20413689f, 0.20392956f, 0.20372005f, 0.20350836f, 0.20329449f, + 0.20307844f, 0.20286022f, 0.20263983f, 0.20241726f, 0.20219253f, 0.20196563f, 0.20173657f, 0.20150535f, + 0.20127197f, 0.20103643f, 0.20079874f, 0.20055891f, 0.20031692f, 0.20007279f, 0.19982652f, 0.19957810f, + 0.19932755f, 0.19907486f, 0.19882005f, 0.19856310f, 0.19830403f, 0.19804283f, 0.19777951f, 0.19751407f, + 0.19724652f, 0.19697686f, 0.19670509f, 0.19643121f, 0.19615522f, 0.19587714f, 0.19559696f, 0.19531468f, + 0.19503031f, 0.19474386f, 0.19445531f, 0.19416469f, 0.19387199f, 0.19357720f, 0.19328035f, 0.19298143f, + 0.19268044f, 0.19237739f, 0.19207227f, 0.19176510f, 0.19145588f, 0.19114460f, 0.19083128f, 0.19051592f, + 0.19019851f, 0.18987907f, 0.18955759f, 0.18923409f, 0.18890856f, 0.18858100f, 0.18825143f, 0.18791983f, + 0.18758623f, 0.18725062f, 0.18691300f, 0.18657338f, 0.18623176f, 0.18588815f, 0.18554255f, 0.18519496f, + 0.18484539f, 0.18449384f, 0.18414031f, 0.18378481f, 0.18342734f, 0.18306791f, 0.18270651f, 0.18234316f, + 0.18197786f, 0.18161061f, 0.18124141f, 0.18087028f, 0.18049720f, 0.18012220f, 0.17974526f, 0.17936640f, + 0.17898562f, 0.17860292f, 0.17821831f, 0.17783179f, 0.17744336f, 0.17705304f, 0.17666082f, 0.17626671f, + 0.17587071f, 0.17547282f, 0.17507306f, 0.17467142f, 0.17426791f, 0.17386254f, 0.17345530f, 0.17304621f, + 0.17263526f, 0.17222246f, 0.17180782f, 0.17139134f, 0.17097303f, 0.17055288f, 0.17013091f, 0.16970711f, + 0.16928150f, 0.16885407f, 0.16842484f, 0.16799380f, 0.16756096f, 0.16712633f, 0.16668991f, 0.16625171f, + 0.16581172f, 0.16536996f, 0.16492642f, 0.16448113f, 0.16403406f, 0.16358525f, 0.16313468f, 0.16268236f, + 0.16222830f, 0.16177251f, 0.16131498f, 0.16085572f, 0.16039474f, 0.15993205f, 0.15946764f, 0.15900152f, + 0.15853370f, 0.15806419f, 0.15759298f, 0.15712008f, 0.15664550f, 0.15616924f, 0.15569131f, 0.15521171f, + 0.15473045f, 0.15424753f, 0.15376297f, 0.15327675f, 0.15278889f, 0.15229940f, 0.15180828f, 0.15131553f, + 0.15082115f, 0.15032517f, 0.14982757f, 0.14932837f, 0.14882757f, 0.14832518f, 0.14782120f, 0.14731564f, + 0.14680849f, 0.14629978f, 0.14578950f, 0.14527766f, 0.14476426f, 0.14424931f, 0.14373282f, 0.14321478f, + 0.14269522f, 0.14217412f, 0.14165151f, 0.14112737f, 0.14060173f, 0.14007458f, 0.13954592f, 0.13901578f, + 0.13848414f, 0.13795103f, 0.13741643f, 0.13688037f, 0.13634283f, 0.13580384f, 0.13526339f, 0.13472150f, + 0.13417816f, 0.13363339f, 0.13308718f, 0.13253955f, 0.13199050f, 0.13144003f, 0.13088816f, 0.13033489f, + 0.12978022f, 0.12922416f, 0.12866672f, 0.12810790f, 0.12754770f, 0.12698614f, 0.12642323f, 0.12585895f, + 0.12529333f, 0.12472637f, 0.12415807f, 0.12358845f, 0.12301749f, 0.12244523f, 0.12187165f, 0.12129676f, + 0.12072058f, 0.12014310f, 0.11956434f, 0.11898429f, 0.11840297f, 0.11782039f, 0.11723654f, 0.11665144f, + 0.11606508f, 0.11547749f, 0.11488866f, 0.11429859f, 0.11370731f, 0.11311480f, 0.11252109f, 0.11192617f, + 0.11133005f, 0.11073273f, 0.11013424f, 0.10953456f, 0.10893371f, 0.10833169f, 0.10772852f, 0.10712419f, + 0.10651871f, 0.10591209f, 0.10530434f, 0.10469546f, 0.10408546f, 0.10347434f, 0.10286212f, 0.10224879f, + 0.10163437f, 0.10101886f, 0.10040227f, 0.09978460f, 0.09916587f, 0.09854607f, 0.09792522f, 0.09730332f, + 0.09668037f, 0.09605639f, 0.09543139f, 0.09480536f, 0.09417831f, 0.09355026f, 0.09292121f, 0.09229116f, + 0.09166012f, 0.09102810f, 0.09039510f, 0.08976114f, 0.08912622f, 0.08849034f, 0.08785351f, 0.08721574f, + 0.08657704f, 0.08593742f, 0.08529687f, 0.08465540f, 0.08401304f, 0.08336977f, 0.08272561f, 0.08208056f, + 0.08143463f, 0.08078784f, 0.08014017f, 0.07949165f, 0.07884228f, 0.07819206f, 0.07754101f, 0.07688912f, + 0.07623641f, 0.07558289f, 0.07492855f, 0.07427342f, 0.07361748f, 0.07296076f, 0.07230326f, 0.07164499f, + 0.07098594f, 0.07032614f, 0.06966558f, 0.06900428f, 0.06834224f, 0.06767946f, 0.06701596f, 0.06635175f, + 0.06568682f, 0.06502119f, 0.06435487f, 0.06368785f, 0.06302015f, 0.06235178f, 0.06168274f, 0.06101304f, + 0.06034268f, 0.05967168f, 0.05900004f, 0.05832777f, 0.05765488f, 0.05698136f, 0.05630724f, 0.05563251f, + 0.05495719f, 0.05428128f, 0.05360479f, 0.05292772f, 0.05225009f, 0.05157189f, 0.05089315f, 0.05021386f, + 0.04953403f, 0.04885367f, 0.04817279f, 0.04749139f, 0.04680949f, 0.04612708f, 0.04544418f, 0.04476079f, + 0.04407692f, 0.04339258f, 0.04270778f, 0.04202252f, 0.04133681f, 0.04065065f, 0.03996406f, 0.03927704f, + 0.03858961f, 0.03790175f, 0.03721350f, 0.03652484f, 0.03583579f, 0.03514636f, 0.03445656f, 0.03376638f, + 0.03307584f, 0.03238495f, 0.03169371f, 0.03100213f, 0.03031022f, 0.02961799f, 0.02892544f, 0.02823258f, + 0.02753941f, 0.02684595f, 0.02615221f, 0.02545818f, 0.02476388f, 0.02406932f, 0.02337449f, 0.02267942f, + 0.02198411f, 0.02128856f, 0.02059278f, 0.01989678f, 0.01920056f, 0.01850415f, 0.01780753f, 0.01711072f, + 0.01641373f, 0.01571657f, 0.01501923f, 0.01432174f, 0.01362409f, 0.01292630f, 0.01222836f, 0.01153030f, + 0.01083211f, 0.01013381f, 0.00943540f, 0.00873688f, 0.00803828f, 0.00733959f, 0.00664081f, 0.00594197f, + 0.00524307f, 0.00454410f, 0.00384509f, 0.00314604f, 0.00244696f, 0.00174784f, 0.00104871f, 0.00034957f +}; + +const float edct_table_128[128] = +{ + 0.29728989f, 0.29724512f, 0.29715558f, 0.29702130f, 0.29684228f, 0.29661856f, 0.29635017f, 0.29603715f, + 0.29567955f, 0.29527743f, 0.29483083f, 0.29433983f, 0.29380451f, 0.29322494f, 0.29260121f, 0.29193342f, + 0.29122167f, 0.29046605f, 0.28966670f, 0.28882372f, 0.28793724f, 0.28700741f, 0.28603435f, 0.28501821f, + 0.28395915f, 0.28285733f, 0.28171292f, 0.28052607f, 0.27929698f, 0.27802583f, 0.27671281f, 0.27535812f, + 0.27396196f, 0.27252454f, 0.27104609f, 0.26952681f, 0.26796694f, 0.26636672f, 0.26472638f, 0.26304618f, + 0.26132636f, 0.25956719f, 0.25776893f, 0.25593185f, 0.25405623f, 0.25214235f, 0.25019049f, 0.24820096f, + 0.24617405f, 0.24411007f, 0.24200932f, 0.23987213f, 0.23769882f, 0.23548971f, 0.23324513f, 0.23096543f, + 0.22865095f, 0.22630203f, 0.22391903f, 0.22150231f, 0.21905224f, 0.21656917f, 0.21405349f, 0.21150558f, + 0.20892581f, 0.20631458f, 0.20367228f, 0.20099931f, 0.19829606f, 0.19556296f, 0.19280040f, 0.19000881f, + 0.18718860f, 0.18434021f, 0.18146405f, 0.17856057f, 0.17563019f, 0.17267337f, 0.16969054f, 0.16668215f, + 0.16364867f, 0.16059054f, 0.15750822f, 0.15440219f, 0.15127290f, 0.14812083f, 0.14494646f, 0.14175026f, + 0.13853271f, 0.13529429f, 0.13203551f, 0.12875684f, 0.12545877f, 0.12214182f, 0.11880647f, 0.11545323f, + 0.11208260f, 0.10869509f, 0.10529122f, 0.10187148f, 0.09843641f, 0.09498651f, 0.09152231f, 0.08804432f, + 0.08455308f, 0.08104910f, 0.07753291f, 0.07400505f, 0.07046605f, 0.06691643f, 0.06335674f, 0.05978750f, + 0.05620926f, 0.05262256f, 0.04902793f, 0.04542591f, 0.04181706f, 0.03820191f, 0.03458100f, 0.03095489f, + 0.02732412f, 0.02368923f, 0.02005077f, 0.01640930f, 0.01276535f, 0.00911948f, 0.00547224f, 0.00182417f +}; + +const float edct_table_160[160] = +{ + 0.28116346f, 0.28113637f, 0.28108217f, 0.28100088f, 0.28089251f, 0.28075707f, 0.28059457f, 0.28040502f, + 0.28018844f, 0.27994487f, 0.27967431f, 0.27937679f, 0.27905235f, 0.27870101f, 0.27832281f, 0.27791778f, + 0.27748597f, 0.27702741f, 0.27654216f, 0.27603024f, 0.27549173f, 0.27492666f, 0.27433510f, 0.27371709f, + 0.27307270f, 0.27240199f, 0.27170503f, 0.27098188f, 0.27023261f, 0.26945730f, 0.26865602f, 0.26782884f, + 0.26697585f, 0.26609713f, 0.26519276f, 0.26426283f, 0.26330743f, 0.26232665f, 0.26132059f, 0.26028934f, + 0.25923300f, 0.25815168f, 0.25704548f, 0.25591450f, 0.25475886f, 0.25357866f, 0.25237403f, 0.25114506f, + 0.24989190f, 0.24861465f, 0.24731343f, 0.24598838f, 0.24463962f, 0.24326728f, 0.24187150f, 0.24045240f, + 0.23901013f, 0.23754482f, 0.23605661f, 0.23454566f, 0.23301210f, 0.23145608f, 0.22987775f, 0.22827726f, + 0.22665478f, 0.22501045f, 0.22334443f, 0.22165688f, 0.21994797f, 0.21821787f, 0.21646673f, 0.21469472f, + 0.21290203f, 0.21108881f, 0.20925525f, 0.20740152f, 0.20552780f, 0.20363427f, 0.20172112f, 0.19978852f, + 0.19783667f, 0.19586574f, 0.19387594f, 0.19186746f, 0.18984048f, 0.18779520f, 0.18573183f, 0.18365055f, + 0.18155157f, 0.17943510f, 0.17730133f, 0.17515047f, 0.17298273f, 0.17079832f, 0.16859744f, 0.16638032f, + 0.16414716f, 0.16189818f, 0.15963359f, 0.15735362f, 0.15505848f, 0.15274840f, 0.15042360f, 0.14808429f, + 0.14573072f, 0.14336310f, 0.14098166f, 0.13858663f, 0.13617825f, 0.13375674f, 0.13132234f, 0.12887528f, + 0.12641580f, 0.12394414f, 0.12146053f, 0.11896521f, 0.11645843f, 0.11394042f, 0.11141144f, 0.10887171f, + 0.10632149f, 0.10376102f, 0.10119055f, 0.09861033f, 0.09602061f, 0.09342163f, 0.09081364f, 0.08819691f, + 0.08557167f, 0.08293818f, 0.08029671f, 0.07764749f, 0.07499079f, 0.07232686f, 0.06965596f, 0.06697834f, + 0.06429427f, 0.06160401f, 0.05890780f, 0.05620592f, 0.05349862f, 0.05078617f, 0.04806882f, 0.04534683f, + 0.04262048f, 0.03989002f, 0.03715571f, 0.03441782f, 0.03167662f, 0.02893236f, 0.02618532f, 0.02343575f, + 0.02068392f, 0.01793009f, 0.01517454f, 0.01241753f, 0.00965932f, 0.00690018f, 0.00414037f, 0.00138017f +}; + +const float edct_table_40[40] = +{ + 0.39747255f, 0.39685967f, 0.39563487f, 0.39380003f, 0.39135797f, 0.38831247f, 0.38466823f, 0.38043085f, + 0.37560687f, 0.37020373f, 0.36422977f, 0.35769419f, 0.35060707f, 0.34297935f, 0.33482277f, 0.32614992f, + 0.31697417f, 0.30730967f, 0.29717132f, 0.28657476f, 0.27553631f, 0.26407301f, 0.25220253f, 0.23994317f, + 0.22731383f, 0.21433400f, 0.20102367f, 0.18740339f, 0.17349414f, 0.15931737f, 0.14489495f, 0.13024911f, + 0.11540244f, 0.10037782f, 0.08519843f, 0.06988767f, 0.05446914f, 0.03896663f, 0.02340404f, 0.00780536f +}; + +const float edct_table_20[20] = +{ + 0.47209725f, 0.46918661f, 0.46338329f, 0.45472305f, 0.44325929f, 0.42906269f, 0.41222077f, 0.39283738f, + 0.37103202f, 0.34693912f, 0.32070722f, 0.29249806f, 0.26248555f, 0.23085473f, 0.19780061f, 0.16352698f, + 0.12824516f, 0.09217267f, 0.05553190f, 0.01854875f +}; + + +const float edct_table_64[64] = +{ + 0.35349683f, 0.35328389f, 0.35285816f, 0.35221987f, 0.35136942f, 0.35030732f, 0.34903420f, 0.34755084f, + 0.34585813f, 0.34395709f, 0.34184886f, 0.33953471f, 0.33701604f, 0.33429436f, 0.33137132f, 0.32824867f, + 0.32492830f, 0.32141220f, 0.31770249f, 0.31380142f, 0.30971132f, 0.30543466f, 0.30097402f, 0.29633209f, + 0.29151165f, 0.28651562f, 0.28134701f, 0.27600892f, 0.27050457f, 0.26483728f, 0.25901046f, 0.25302763f, + 0.24689238f, 0.24060841f, 0.23417951f, 0.22760955f, 0.22090248f, 0.21406235f, 0.20709328f, 0.19999946f, + 0.19278517f, 0.18545475f, 0.17801263f, 0.17046327f, 0.16281123f, 0.15506112f, 0.14721761f, 0.13928542f, + 0.13126933f, 0.12317417f, 0.11500482f, 0.10676618f, 0.09846324f, 0.09010099f, 0.08168446f, 0.07321873f, + 0.06470889f, 0.05616008f, 0.04757744f, 0.03896613f, 0.03033136f, 0.02167832f, 0.01301222f, 0.00433828f +}; + +const float edct_table_100[100] = +{ + 0.31620704f, 0.31612902f, 0.31597300f, 0.31573902f, 0.31542714f, 0.31503742f, 0.31456998f, 0.31402492f, + 0.31340238f, 0.31270252f, 0.31192550f, 0.31107151f, 0.31014078f, 0.30913352f, 0.30804998f, 0.30689044f, + 0.30565518f, 0.30434451f, 0.30295874f, 0.30149822f, 0.29996331f, 0.29835439f, 0.29667186f, 0.29491612f, + 0.29308762f, 0.29118680f, 0.28921414f, 0.28717012f, 0.28505525f, 0.28287004f, 0.28061503f, 0.27829079f, + 0.27589789f, 0.27343691f, 0.27090847f, 0.26831318f, 0.26565169f, 0.26292465f, 0.26013275f, 0.25727665f, + 0.25435708f, 0.25137475f, 0.24833040f, 0.24522478f, 0.24205865f, 0.23883279f, 0.23554801f, 0.23220511f, + 0.22880491f, 0.22534827f, 0.22183602f, 0.21826903f, 0.21464819f, 0.21097439f, 0.20724854f, 0.20347155f, + 0.19964436f, 0.19576790f, 0.19184315f, 0.18787106f, 0.18385261f, 0.17978880f, 0.17568064f, 0.17152912f, + 0.16733529f, 0.16310016f, 0.15882480f, 0.15451024f, 0.15015756f, 0.14576784f, 0.14134215f, 0.13688158f, + 0.13238724f, 0.12786023f, 0.12330168f, 0.11871271f, 0.11409444f, 0.10944803f, 0.10477460f, 0.10007533f, + 0.09535137f, 0.09060388f, 0.08583403f, 0.08104300f, 0.07623198f, 0.07140215f, 0.06655470f, 0.06169084f, + 0.05681175f, 0.05191864f, 0.04701272f, 0.04209520f, 0.03716730f, 0.03223022f, 0.02728520f, 0.02233344f, + 0.01737617f, 0.01241461f, 0.00744999f, 0.00248354f +}; + + +const float edct_table_200[200] = +{ + 0.26591044f, 0.26589403f, 0.26586123f, 0.26581203f, 0.26574643f, 0.26566443f, 0.26556605f, 0.26545129f, + 0.26532015f, 0.26517265f, 0.26500879f, 0.26482859f, 0.26463205f, 0.26441918f, 0.26419000f, 0.26394453f, + 0.26368278f, 0.26340476f, 0.26311049f, 0.26279999f, 0.26247328f, 0.26213038f, 0.26177132f, 0.26139610f, + 0.26100476f, 0.26059732f, 0.26017381f, 0.25973424f, 0.25927866f, 0.25880708f, 0.25831954f, 0.25781606f, + 0.25729668f, 0.25676143f, 0.25621034f, 0.25564344f, 0.25506078f, 0.25446238f, 0.25384829f, 0.25321854f, + 0.25257317f, 0.25191222f, 0.25123573f, 0.25054374f, 0.24983629f, 0.24911344f, 0.24837522f, 0.24762168f, + 0.24685286f, 0.24606882f, 0.24526960f, 0.24445525f, 0.24362582f, 0.24278136f, 0.24192193f, 0.24104757f, + 0.24015834f, 0.23925430f, 0.23833551f, 0.23740201f, 0.23645386f, 0.23549113f, 0.23451388f, 0.23352215f, + 0.23251603f, 0.23149556f, 0.23046081f, 0.22941185f, 0.22834873f, 0.22727153f, 0.22618031f, 0.22507514f, + 0.22395608f, 0.22282321f, 0.22167659f, 0.22051630f, 0.21934241f, 0.21815499f, 0.21695411f, 0.21573985f, + 0.21451228f, 0.21327148f, 0.21201752f, 0.21075048f, 0.20947045f, 0.20817749f, 0.20687169f, 0.20555313f, + 0.20422189f, 0.20287806f, 0.20152171f, 0.20015293f, 0.19877180f, 0.19737841f, 0.19597285f, 0.19455519f, + 0.19312554f, 0.19168397f, 0.19023058f, 0.18876546f, 0.18728869f, 0.18580037f, 0.18430058f, 0.18278943f, + 0.18126701f, 0.17973340f, 0.17818870f, 0.17663302f, 0.17506644f, 0.17348906f, 0.17190097f, 0.17030229f, + 0.16869310f, 0.16707350f, 0.16544360f, 0.16380349f, 0.16215328f, 0.16049306f, 0.15882295f, 0.15714304f, + 0.15545343f, 0.15375424f, 0.15204556f, 0.15032750f, 0.14860017f, 0.14686367f, 0.14511812f, 0.14336361f, + 0.14160026f, 0.13982818f, 0.13804747f, 0.13625824f, 0.13446061f, 0.13265468f, 0.13084058f, 0.12901840f, + 0.12718826f, 0.12535028f, 0.12350456f, 0.12165123f, 0.11979039f, 0.11792217f, 0.11604667f, 0.11416401f, + 0.11227431f, 0.11037768f, 0.10847425f, 0.10656412f, 0.10464742f, 0.10272426f, 0.10079477f, 0.09885906f, + 0.09691726f, 0.09496947f, 0.09301583f, 0.09105645f, 0.08909145f, 0.08712096f, 0.08514509f, 0.08316397f, + 0.08117772f, 0.07918646f, 0.07719032f, 0.07518942f, 0.07318388f, 0.07117382f, 0.06915937f, 0.06714066f, + 0.06511781f, 0.06309094f, 0.06106018f, 0.05902565f, 0.05698748f, 0.05494580f, 0.05290072f, 0.05085238f, + 0.04880091f, 0.04674643f, 0.04468906f, 0.04262893f, 0.04056618f, 0.03850092f, 0.03643329f, 0.03436341f, + 0.03229142f, 0.03021743f, 0.02814157f, 0.02606398f, 0.02398478f, 0.02190411f, 0.01982208f, 0.01773883f, + 0.01565448f, 0.01356917f, 0.01148302f, 0.00939617f, 0.00730873f, 0.00522084f, 0.00313264f, 0.00104423f +}; + +const float edct_table_240[240] = +{ + 0.25406349f, 0.25405260f, 0.25403084f, 0.25399819f, 0.25395466f, 0.25390025f, 0.25383497f, 0.25375881f, + 0.25367179f, 0.25357389f, 0.25346514f, 0.25334553f, 0.25321506f, 0.25307375f, 0.25292160f, 0.25275861f, + 0.25258479f, 0.25240016f, 0.25220471f, 0.25199846f, 0.25178142f, 0.25155358f, 0.25131498f, 0.25106561f, + 0.25080548f, 0.25053461f, 0.25025301f, 0.24996068f, 0.24965766f, 0.24934393f, 0.24901953f, 0.24868445f, + 0.24833873f, 0.24798236f, 0.24761538f, 0.24723778f, 0.24684960f, 0.24645084f, 0.24604153f, 0.24562167f, + 0.24519129f, 0.24475042f, 0.24429905f, 0.24383722f, 0.24336495f, 0.24288225f, 0.24238915f, 0.24188566f, + 0.24137181f, 0.24084762f, 0.24031312f, 0.23976832f, 0.23921325f, 0.23864793f, 0.23807239f, 0.23748665f, + 0.23689074f, 0.23628468f, 0.23566850f, 0.23504223f, 0.23440588f, 0.23375950f, 0.23310310f, 0.23243671f, + 0.23176037f, 0.23107410f, 0.23037794f, 0.22967190f, 0.22895603f, 0.22823035f, 0.22749489f, 0.22674968f, + 0.22599477f, 0.22523017f, 0.22445592f, 0.22367206f, 0.22287862f, 0.22207563f, 0.22126313f, 0.22044115f, + 0.21960972f, 0.21876889f, 0.21791869f, 0.21705915f, 0.21619032f, 0.21531222f, 0.21442490f, 0.21352839f, + 0.21262274f, 0.21170798f, 0.21078415f, 0.20985130f, 0.20890945f, 0.20795865f, 0.20699895f, 0.20603038f, + 0.20505298f, 0.20406680f, 0.20307188f, 0.20206825f, 0.20105598f, 0.20003509f, 0.19900563f, 0.19796764f, + 0.19692118f, 0.19586628f, 0.19480299f, 0.19373136f, 0.19265142f, 0.19156324f, 0.19046685f, 0.18936230f, + 0.18824963f, 0.18712891f, 0.18600017f, 0.18486346f, 0.18371883f, 0.18256633f, 0.18140601f, 0.18023792f, + 0.17906211f, 0.17787863f, 0.17668753f, 0.17548886f, 0.17428267f, 0.17306902f, 0.17184795f, 0.17061952f, + 0.16938379f, 0.16814079f, 0.16689060f, 0.16563326f, 0.16436882f, 0.16309734f, 0.16181887f, 0.16053347f, + 0.15924120f, 0.15794210f, 0.15663624f, 0.15532366f, 0.15400444f, 0.15267862f, 0.15134625f, 0.15000741f, + 0.14866213f, 0.14731049f, 0.14595254f, 0.14458834f, 0.14321795f, 0.14184141f, 0.14045881f, 0.13907018f, + 0.13767560f, 0.13627512f, 0.13486881f, 0.13345671f, 0.13203890f, 0.13061544f, 0.12918637f, 0.12775178f, + 0.12631171f, 0.12486623f, 0.12341540f, 0.12195929f, 0.12049795f, 0.11903145f, 0.11755985f, 0.11608321f, + 0.11460161f, 0.11311509f, 0.11162373f, 0.11012758f, 0.10862672f, 0.10712120f, 0.10561110f, 0.10409647f, + 0.10257739f, 0.10105391f, 0.09952610f, 0.09799402f, 0.09645775f, 0.09491735f, 0.09337288f, 0.09182441f, + 0.09027201f, 0.08871574f, 0.08715567f, 0.08559187f, 0.08402440f, 0.08245333f, 0.08087873f, 0.07930067f, + 0.07771920f, 0.07613441f, 0.07454636f, 0.07295511f, 0.07136074f, 0.06976332f, 0.06816290f, 0.06655956f, + 0.06495338f, 0.06334441f, 0.06173272f, 0.06011839f, 0.05850149f, 0.05688208f, 0.05526024f, 0.05363602f, + 0.05200951f, 0.05038078f, 0.04874988f, 0.04711689f, 0.04548189f, 0.04384494f, 0.04220611f, 0.04056547f, + 0.03892310f, 0.03727906f, 0.03563342f, 0.03398625f, 0.03233763f, 0.03068762f, 0.02903630f, 0.02738373f, + 0.02573000f, 0.02407516f, 0.02241928f, 0.02076245f, 0.01910473f, 0.01744619f, 0.01578690f, 0.01412694f, + 0.01246637f, 0.01080527f, 0.00914370f, 0.00748175f, 0.00581947f, 0.00415694f, 0.00249424f, 0.00083142f +}; + +const float edct_table_256[256] = +{ + 0.24999750f, 0.24998809f, 0.24996926f, 0.24994103f, 0.24990338f, 0.24985633f, 0.24979987f, 0.24973400f, + 0.24965873f, 0.24957406f, 0.24948000f, 0.24937654f, 0.24926370f, 0.24914147f, 0.24900986f, 0.24886887f, + 0.24871852f, 0.24855880f, 0.24838972f, 0.24821129f, 0.24802352f, 0.24782640f, 0.24761996f, 0.24740419f, + 0.24717911f, 0.24694473f, 0.24670104f, 0.24644807f, 0.24618582f, 0.24591430f, 0.24563353f, 0.24534350f, + 0.24504424f, 0.24473575f, 0.24441805f, 0.24409114f, 0.24375505f, 0.24340977f, 0.24305534f, 0.24269175f, + 0.24231903f, 0.24193718f, 0.24154622f, 0.24114617f, 0.24073704f, 0.24031885f, 0.23989161f, 0.23945534f, + 0.23901005f, 0.23855576f, 0.23809249f, 0.23762026f, 0.23713908f, 0.23664898f, 0.23614996f, 0.23564205f, + 0.23512527f, 0.23459964f, 0.23406518f, 0.23352190f, 0.23296983f, 0.23240899f, 0.23183940f, 0.23126109f, + 0.23067406f, 0.23007835f, 0.22947398f, 0.22886097f, 0.22823934f, 0.22760912f, 0.22697033f, 0.22632299f, + 0.22566713f, 0.22500278f, 0.22432996f, 0.22364869f, 0.22295900f, 0.22226091f, 0.22155446f, 0.22083967f, + 0.22011656f, 0.21938516f, 0.21864551f, 0.21789762f, 0.21714153f, 0.21637726f, 0.21560485f, 0.21482432f, + 0.21403570f, 0.21323902f, 0.21243432f, 0.21162161f, 0.21080094f, 0.20997234f, 0.20913582f, 0.20829144f, + 0.20743921f, 0.20657917f, 0.20571136f, 0.20483580f, 0.20395252f, 0.20306157f, 0.20216298f, 0.20125677f, + 0.20034298f, 0.19942165f, 0.19849282f, 0.19755651f, 0.19661276f, 0.19566161f, 0.19470310f, 0.19373725f, + 0.19276411f, 0.19178371f, 0.19079609f, 0.18980129f, 0.18879934f, 0.18779029f, 0.18677416f, 0.18575100f, + 0.18472085f, 0.18368375f, 0.18263973f, 0.18158883f, 0.18053109f, 0.17946656f, 0.17839527f, 0.17731727f, + 0.17623259f, 0.17514127f, 0.17404336f, 0.17293890f, 0.17182793f, 0.17071048f, 0.16958661f, 0.16845636f, + 0.16731976f, 0.16617686f, 0.16502771f, 0.16387235f, 0.16271081f, 0.16154315f, 0.16036940f, 0.15918962f, + 0.15800385f, 0.15681212f, 0.15561450f, 0.15441101f, 0.15320171f, 0.15198664f, 0.15076585f, 0.14953939f, + 0.14830729f, 0.14706961f, 0.14582639f, 0.14457768f, 0.14332353f, 0.14206399f, 0.14079909f, 0.13952889f, + 0.13825344f, 0.13697279f, 0.13568698f, 0.13439606f, 0.13310008f, 0.13179909f, 0.13049313f, 0.12918227f, + 0.12786654f, 0.12654599f, 0.12522068f, 0.12389066f, 0.12255597f, 0.12121667f, 0.11987280f, 0.11852443f, + 0.11717159f, 0.11581433f, 0.11445272f, 0.11308680f, 0.11171662f, 0.11034223f, 0.10896369f, 0.10758105f, + 0.10619436f, 0.10480367f, 0.10340903f, 0.10201050f, 0.10060813f, 0.09920197f, 0.09779208f, 0.09637850f, + 0.09496130f, 0.09354052f, 0.09211622f, 0.09068845f, 0.08925727f, 0.08782272f, 0.08638487f, 0.08494377f, + 0.08349947f, 0.08205203f, 0.08060149f, 0.07914792f, 0.07769138f, 0.07623190f, 0.07476956f, 0.07330440f, + 0.07183648f, 0.07036586f, 0.06889259f, 0.06741672f, 0.06593832f, 0.06445743f, 0.06297412f, 0.06148844f, + 0.06000044f, 0.05851018f, 0.05701772f, 0.05552311f, 0.05402641f, 0.05252768f, 0.05102697f, 0.04952434f, + 0.04801985f, 0.04651354f, 0.04500549f, 0.04349574f, 0.04198435f, 0.04047138f, 0.03895689f, 0.03744094f, + 0.03592357f, 0.03440485f, 0.03288483f, 0.03136358f, 0.02984115f, 0.02831759f, 0.02679296f, 0.02526733f, + 0.02374075f, 0.02221327f, 0.02068496f, 0.01915586f, 0.01762605f, 0.01609557f, 0.01456449f, 0.01303286f, + 0.01150073f, 0.00996818f, 0.00843525f, 0.00690200f, 0.00536849f, 0.00383478f, 0.00230093f, 0.00076699f +}; + +const float edct_table_400[400] = +{ + 0.22360588f, 0.22360243f, 0.22359554f, 0.22358519f, 0.22357140f, 0.22355416f, 0.22353347f, 0.22350934f, + 0.22348175f, 0.22345073f, 0.22341625f, 0.22337833f, 0.22333697f, 0.22329216f, 0.22324391f, 0.22319221f, + 0.22313708f, 0.22307850f, 0.22301648f, 0.22295103f, 0.22288213f, 0.22280980f, 0.22273403f, 0.22265483f, + 0.22257219f, 0.22248612f, 0.22239662f, 0.22230369f, 0.22220734f, 0.22210755f, 0.22200434f, 0.22189771f, + 0.22178765f, 0.22167418f, 0.22155728f, 0.22143697f, 0.22131325f, 0.22118611f, 0.22105556f, 0.22092160f, + 0.22078424f, 0.22064347f, 0.22049930f, 0.22035172f, 0.22020075f, 0.22004639f, 0.21988863f, 0.21972748f, + 0.21956294f, 0.21939501f, 0.21922370f, 0.21904901f, 0.21887095f, 0.21868950f, 0.21850469f, 0.21831650f, + 0.21812495f, 0.21793004f, 0.21773176f, 0.21753013f, 0.21732514f, 0.21711680f, 0.21690511f, 0.21669008f, + 0.21647170f, 0.21624999f, 0.21602494f, 0.21579656f, 0.21556486f, 0.21532983f, 0.21509147f, 0.21484981f, + 0.21460482f, 0.21435653f, 0.21410494f, 0.21385004f, 0.21359184f, 0.21333035f, 0.21306557f, 0.21279750f, + 0.21252616f, 0.21225153f, 0.21197363f, 0.21169247f, 0.21140803f, 0.21112034f, 0.21082939f, 0.21053520f, + 0.21023775f, 0.20993706f, 0.20963314f, 0.20932598f, 0.20901559f, 0.20870198f, 0.20838516f, 0.20806511f, + 0.20774186f, 0.20741541f, 0.20708576f, 0.20675291f, 0.20641688f, 0.20607766f, 0.20573527f, 0.20538970f, + 0.20504096f, 0.20468907f, 0.20433401f, 0.20397581f, 0.20361446f, 0.20324997f, 0.20288234f, 0.20251159f, + 0.20213771f, 0.20176072f, 0.20138061f, 0.20099740f, 0.20061109f, 0.20022169f, 0.19982920f, 0.19943362f, + 0.19903497f, 0.19863326f, 0.19822847f, 0.19782064f, 0.19740975f, 0.19699581f, 0.19657884f, 0.19615884f, + 0.19573581f, 0.19530977f, 0.19488071f, 0.19444865f, 0.19401358f, 0.19357553f, 0.19313449f, 0.19269047f, + 0.19224348f, 0.19179353f, 0.19134062f, 0.19088476f, 0.19042595f, 0.18996421f, 0.18949954f, 0.18903194f, + 0.18856143f, 0.18808802f, 0.18761170f, 0.18713249f, 0.18665039f, 0.18616542f, 0.18567757f, 0.18518686f, + 0.18469330f, 0.18419688f, 0.18369763f, 0.18319554f, 0.18269063f, 0.18218290f, 0.18167236f, 0.18115902f, + 0.18064289f, 0.18012397f, 0.17960227f, 0.17907781f, 0.17855058f, 0.17802060f, 0.17748787f, 0.17695240f, + 0.17641421f, 0.17587330f, 0.17532967f, 0.17478334f, 0.17423432f, 0.17368260f, 0.17312821f, 0.17257115f, + 0.17201143f, 0.17144906f, 0.17088404f, 0.17031639f, 0.16974611f, 0.16917321f, 0.16859770f, 0.16801960f, + 0.16743890f, 0.16685562f, 0.16626977f, 0.16568135f, 0.16509038f, 0.16449686f, 0.16390080f, 0.16330222f, + 0.16270112f, 0.16209751f, 0.16149140f, 0.16088280f, 0.16027172f, 0.15965817f, 0.15904216f, 0.15842369f, + 0.15780278f, 0.15717944f, 0.15655367f, 0.15592549f, 0.15529490f, 0.15466192f, 0.15402655f, 0.15338881f, + 0.15274870f, 0.15210624f, 0.15146143f, 0.15081429f, 0.15016482f, 0.14951304f, 0.14885894f, 0.14820256f, + 0.14754389f, 0.14688294f, 0.14621973f, 0.14555426f, 0.14488655f, 0.14421660f, 0.14354443f, 0.14287005f, + 0.14219346f, 0.14151468f, 0.14083372f, 0.14015058f, 0.13946529f, 0.13877784f, 0.13808825f, 0.13739654f, + 0.13670270f, 0.13600676f, 0.13530872f, 0.13460859f, 0.13390639f, 0.13320212f, 0.13249580f, 0.13178744f, + 0.13107704f, 0.13036462f, 0.12965019f, 0.12893376f, 0.12821535f, 0.12749495f, 0.12677259f, 0.12604828f, + 0.12532202f, 0.12459383f, 0.12386371f, 0.12313169f, 0.12239777f, 0.12166196f, 0.12092427f, 0.12018472f, + 0.11944332f, 0.11870007f, 0.11795500f, 0.11720810f, 0.11645940f, 0.11570890f, 0.11495662f, 0.11420256f, + 0.11344675f, 0.11268918f, 0.11192987f, 0.11116884f, 0.11040610f, 0.10964165f, 0.10887551f, 0.10810770f, + 0.10733821f, 0.10656707f, 0.10579429f, 0.10501988f, 0.10424384f, 0.10346620f, 0.10268696f, 0.10190614f, + 0.10112375f, 0.10033980f, 0.09955430f, 0.09876726f, 0.09797871f, 0.09718864f, 0.09639707f, 0.09560402f, + 0.09480949f, 0.09401350f, 0.09321606f, 0.09241718f, 0.09161688f, 0.09081516f, 0.09001205f, 0.08920754f, + 0.08840166f, 0.08759442f, 0.08678583f, 0.08597589f, 0.08516464f, 0.08435207f, 0.08353819f, 0.08272303f, + 0.08190660f, 0.08108890f, 0.08026995f, 0.07944976f, 0.07862835f, 0.07780572f, 0.07698190f, 0.07615688f, + 0.07533070f, 0.07450335f, 0.07367485f, 0.07284522f, 0.07201446f, 0.07118259f, 0.07034963f, 0.06951558f, + 0.06868046f, 0.06784427f, 0.06700705f, 0.06616879f, 0.06532951f, 0.06448922f, 0.06364793f, 0.06280567f, + 0.06196244f, 0.06111825f, 0.06027312f, 0.05942705f, 0.05858008f, 0.05773220f, 0.05688343f, 0.05603378f, + 0.05518327f, 0.05433190f, 0.05347970f, 0.05262667f, 0.05177284f, 0.05091820f, 0.05006278f, 0.04920659f, + 0.04834964f, 0.04749194f, 0.04663351f, 0.04577436f, 0.04491450f, 0.04405396f, 0.04319273f, 0.04233084f, + 0.04146829f, 0.04060511f, 0.03974129f, 0.03887687f, 0.03801185f, 0.03714624f, 0.03628005f, 0.03541331f, + 0.03454602f, 0.03367820f, 0.03280986f, 0.03194101f, 0.03107167f, 0.03020186f, 0.02933157f, 0.02846084f, + 0.02758966f, 0.02671806f, 0.02584605f, 0.02497364f, 0.02410084f, 0.02322767f, 0.02235414f, 0.02148027f, + 0.02060607f, 0.01973155f, 0.01885673f, 0.01798161f, 0.01710622f, 0.01623056f, 0.01535466f, 0.01447851f, + 0.01360215f, 0.01272557f, 0.01184880f, 0.01097184f, 0.01009472f, 0.00921744f, 0.00834001f, 0.00746246f, + 0.00658480f, 0.00570703f, 0.00482917f, 0.00395124f, 0.00307325f, 0.00219521f, 0.00131714f, 0.00043905f +}; + +const float edct_table_600[600] = +{ + 0.20205118f, 0.20204980f, 0.20204703f, 0.20204287f, 0.20203734f, 0.20203041f, 0.20202210f, 0.20201241f, + 0.20200133f, 0.20198887f, 0.20197502f, 0.20195979f, 0.20194318f, 0.20192518f, 0.20190579f, 0.20188503f, + 0.20186288f, 0.20183934f, 0.20181442f, 0.20178812f, 0.20176044f, 0.20173137f, 0.20170092f, 0.20166909f, + 0.20163587f, 0.20160128f, 0.20156530f, 0.20152794f, 0.20148920f, 0.20144908f, 0.20140758f, 0.20136469f, + 0.20132043f, 0.20127479f, 0.20122777f, 0.20117936f, 0.20112958f, 0.20107842f, 0.20102589f, 0.20097197f, + 0.20091668f, 0.20086001f, 0.20080196f, 0.20074254f, 0.20068174f, 0.20061957f, 0.20055602f, 0.20049110f, + 0.20042480f, 0.20035713f, 0.20028809f, 0.20021767f, 0.20014588f, 0.20007272f, 0.19999819f, 0.19992228f, + 0.19984501f, 0.19976637f, 0.19968635f, 0.19960497f, 0.19952222f, 0.19943811f, 0.19935262f, 0.19926577f, + 0.19917756f, 0.19908798f, 0.19899703f, 0.19890472f, 0.19881105f, 0.19871602f, 0.19861962f, 0.19852186f, + 0.19842274f, 0.19832226f, 0.19822043f, 0.19811723f, 0.19801267f, 0.19790676f, 0.19779949f, 0.19769087f, + 0.19758089f, 0.19746956f, 0.19735687f, 0.19724283f, 0.19712744f, 0.19701070f, 0.19689261f, 0.19677317f, + 0.19665237f, 0.19653024f, 0.19640675f, 0.19628192f, 0.19615574f, 0.19602822f, 0.19589936f, 0.19576915f, + 0.19563760f, 0.19550471f, 0.19537048f, 0.19523491f, 0.19509800f, 0.19495976f, 0.19482018f, 0.19467926f, + 0.19453701f, 0.19439343f, 0.19424851f, 0.19410226f, 0.19395469f, 0.19380578f, 0.19365554f, 0.19350398f, + 0.19335109f, 0.19319688f, 0.19304134f, 0.19288448f, 0.19272630f, 0.19256679f, 0.19240597f, 0.19224383f, + 0.19208036f, 0.19191559f, 0.19174950f, 0.19158209f, 0.19141337f, 0.19124334f, 0.19107200f, 0.19089934f, + 0.19072538f, 0.19055012f, 0.19037354f, 0.19019566f, 0.19001648f, 0.18983600f, 0.18965421f, 0.18947113f, + 0.18928674f, 0.18910106f, 0.18891409f, 0.18872581f, 0.18853625f, 0.18834539f, 0.18815324f, 0.18795980f, + 0.18776508f, 0.18756906f, 0.18737176f, 0.18717318f, 0.18697331f, 0.18677217f, 0.18656974f, 0.18636603f, + 0.18616105f, 0.18595479f, 0.18574726f, 0.18553845f, 0.18532837f, 0.18511702f, 0.18490440f, 0.18469052f, + 0.18447537f, 0.18425895f, 0.18404127f, 0.18382233f, 0.18360213f, 0.18338067f, 0.18315796f, 0.18293399f, + 0.18270877f, 0.18248229f, 0.18225456f, 0.18202559f, 0.18179536f, 0.18156389f, 0.18133118f, 0.18109722f, + 0.18086202f, 0.18062558f, 0.18038791f, 0.18014900f, 0.17990885f, 0.17966747f, 0.17942486f, 0.17918102f, + 0.17893595f, 0.17868965f, 0.17844213f, 0.17819339f, 0.17794342f, 0.17769224f, 0.17743984f, 0.17718622f, + 0.17693139f, 0.17667534f, 0.17641808f, 0.17615962f, 0.17589995f, 0.17563907f, 0.17537698f, 0.17511370f, + 0.17484922f, 0.17458353f, 0.17431665f, 0.17404858f, 0.17377931f, 0.17350885f, 0.17323721f, 0.17296437f, + 0.17269035f, 0.17241515f, 0.17213876f, 0.17186120f, 0.17158245f, 0.17130253f, 0.17102144f, 0.17073917f, + 0.17045574f, 0.17017113f, 0.16988536f, 0.16959843f, 0.16931033f, 0.16902107f, 0.16873066f, 0.16843909f, + 0.16814636f, 0.16785248f, 0.16755745f, 0.16726127f, 0.16696395f, 0.16666548f, 0.16636587f, 0.16606511f, + 0.16576322f, 0.16546020f, 0.16515604f, 0.16485075f, 0.16454433f, 0.16423678f, 0.16392810f, 0.16361830f, + 0.16330738f, 0.16299534f, 0.16268219f, 0.16236791f, 0.16205253f, 0.16173603f, 0.16141843f, 0.16109972f, + 0.16077991f, 0.16045899f, 0.16013697f, 0.15981386f, 0.15948965f, 0.15916435f, 0.15883796f, 0.15851047f, + 0.15818191f, 0.15785225f, 0.15752152f, 0.15718971f, 0.15685682f, 0.15652285f, 0.15618781f, 0.15585170f, + 0.15551452f, 0.15517628f, 0.15483697f, 0.15449661f, 0.15415518f, 0.15381269f, 0.15346916f, 0.15312457f, + 0.15277893f, 0.15243224f, 0.15208451f, 0.15173574f, 0.15138592f, 0.15103507f, 0.15068319f, 0.15033027f, + 0.14997632f, 0.14962134f, 0.14926534f, 0.14890831f, 0.14855026f, 0.14819120f, 0.14783112f, 0.14747003f, + 0.14710792f, 0.14674481f, 0.14638069f, 0.14601557f, 0.14564945f, 0.14528233f, 0.14491421f, 0.14454510f, + 0.14417500f, 0.14380391f, 0.14343184f, 0.14305878f, 0.14268474f, 0.14230973f, 0.14193374f, 0.14155677f, + 0.14117884f, 0.14079994f, 0.14042007f, 0.14003924f, 0.13965745f, 0.13927471f, 0.13889101f, 0.13850635f, + 0.13812075f, 0.13773420f, 0.13734671f, 0.13695828f, 0.13656890f, 0.13617860f, 0.13578735f, 0.13539518f, + 0.13500208f, 0.13460805f, 0.13421311f, 0.13381724f, 0.13342045f, 0.13302275f, 0.13262414f, 0.13222462f, + 0.13182419f, 0.13142286f, 0.13102063f, 0.13061750f, 0.13021348f, 0.12980856f, 0.12940275f, 0.12899606f, + 0.12858848f, 0.12818002f, 0.12777069f, 0.12736047f, 0.12694939f, 0.12653743f, 0.12612461f, 0.12571092f, + 0.12529637f, 0.12488096f, 0.12446470f, 0.12404758f, 0.12362961f, 0.12321080f, 0.12279114f, 0.12237064f, + 0.12194930f, 0.12152712f, 0.12110411f, 0.12068027f, 0.12025561f, 0.11983012f, 0.11940381f, 0.11897668f, + 0.11854873f, 0.11811998f, 0.11769041f, 0.11726004f, 0.11682886f, 0.11639688f, 0.11596410f, 0.11553053f, + 0.11509617f, 0.11466102f, 0.11422508f, 0.11378836f, 0.11335086f, 0.11291258f, 0.11247353f, 0.11203371f, + 0.11159312f, 0.11115177f, 0.11070965f, 0.11026678f, 0.10982315f, 0.10937876f, 0.10893363f, 0.10848775f, + 0.10804113f, 0.10759376f, 0.10714566f, 0.10669683f, 0.10624726f, 0.10579696f, 0.10534594f, 0.10489420f, + 0.10444174f, 0.10398856f, 0.10353467f, 0.10308007f, 0.10262477f, 0.10216876f, 0.10171205f, 0.10125464f, + 0.10079654f, 0.10033775f, 0.09987827f, 0.09941811f, 0.09895726f, 0.09849574f, 0.09803354f, 0.09757067f, + 0.09710713f, 0.09664293f, 0.09617806f, 0.09571253f, 0.09524635f, 0.09477952f, 0.09431203f, 0.09384390f, + 0.09337513f, 0.09290571f, 0.09243566f, 0.09196498f, 0.09149366f, 0.09102172f, 0.09054915f, 0.09007597f, + 0.08960216f, 0.08912774f, 0.08865272f, 0.08817708f, 0.08770084f, 0.08722400f, 0.08674656f, 0.08626852f, + 0.08578990f, 0.08531068f, 0.08483089f, 0.08435051f, 0.08386955f, 0.08338802f, 0.08290591f, 0.08242324f, + 0.08194000f, 0.08145620f, 0.08097185f, 0.08048693f, 0.08000147f, 0.07951546f, 0.07902890f, 0.07854180f, + 0.07805416f, 0.07756599f, 0.07707729f, 0.07658806f, 0.07609830f, 0.07560802f, 0.07511722f, 0.07462591f, + 0.07413409f, 0.07364176f, 0.07314892f, 0.07265559f, 0.07216175f, 0.07166742f, 0.07117260f, 0.07067729f, + 0.07018150f, 0.06968522f, 0.06918847f, 0.06869125f, 0.06819355f, 0.06769539f, 0.06719676f, 0.06669767f, + 0.06619812f, 0.06569812f, 0.06519767f, 0.06469678f, 0.06419544f, 0.06369366f, 0.06319144f, 0.06268879f, + 0.06218571f, 0.06168220f, 0.06117828f, 0.06067393f, 0.06016916f, 0.05966399f, 0.05915840f, 0.05865241f, + 0.05814602f, 0.05763923f, 0.05713204f, 0.05662447f, 0.05611650f, 0.05560815f, 0.05509942f, 0.05459031f, + 0.05408083f, 0.05357097f, 0.05306075f, 0.05255017f, 0.05203922f, 0.05152792f, 0.05101627f, 0.05050426f, + 0.04999191f, 0.04947922f, 0.04896619f, 0.04845282f, 0.04793912f, 0.04742509f, 0.04691074f, 0.04639606f, + 0.04588107f, 0.04536576f, 0.04485014f, 0.04433422f, 0.04381799f, 0.04330146f, 0.04278463f, 0.04226751f, + 0.04175010f, 0.04123240f, 0.04071442f, 0.04019617f, 0.03967763f, 0.03915883f, 0.03863975f, 0.03812042f, + 0.03760082f, 0.03708096f, 0.03656085f, 0.03604049f, 0.03551988f, 0.03499902f, 0.03447793f, 0.03395660f, + 0.03343504f, 0.03291325f, 0.03239124f, 0.03186900f, 0.03134654f, 0.03082387f, 0.03030099f, 0.02977790f, + 0.02925460f, 0.02873111f, 0.02820741f, 0.02768353f, 0.02715945f, 0.02663519f, 0.02611075f, 0.02558613f, + 0.02506133f, 0.02453636f, 0.02401122f, 0.02348592f, 0.02296046f, 0.02243483f, 0.02190906f, 0.02138314f, + 0.02085706f, 0.02033085f, 0.01980450f, 0.01927801f, 0.01875139f, 0.01822464f, 0.01769776f, 0.01717076f, + 0.01664365f, 0.01611642f, 0.01558908f, 0.01506164f, 0.01453409f, 0.01400644f, 0.01347870f, 0.01295086f, + 0.01242294f, 0.01189493f, 0.01136683f, 0.01083866f, 0.01031042f, 0.00978211f, 0.00925372f, 0.00872528f, + 0.00819677f, 0.00766821f, 0.00713960f, 0.00661094f, 0.00608223f, 0.00555348f, 0.00502469f, 0.00449587f, + 0.00396701f, 0.00343813f, 0.00290923f, 0.00238031f, 0.00185137f, 0.00132241f, 0.00079345f, 0.00026448f +}; + +/*----------------------------------------------------------------------------------* + * Mean ISF vector for active signal (only for AMR-WB IO mode) + *----------------------------------------------------------------------------------*/ + +const float mean_isf_amr_wb[M] = +{ + 288.411774f, + 518.149414f, + 912.352051f, + 1397.743652f, + 1795.418823f, + 2211.536133f, + 2621.461182f, + 3019.680176f, + 3417.989746f, + 3809.700928f, + 4181.547363f, + 4581.064941f, + 5012.819824f, + 5457.521484f, + 5876.145020f, + 1576.906494f +}; + +/*----------------------------------------------------------------------------------* + * Mean ISF vector for SID frames (only in AMR-WB IO mode) + *----------------------------------------------------------------------------------*/ + +const float mean_isf_noise_amr_wb[M] = +{ + 186.625259f, + 429.613403f, + 864.525085f, + 1276.010254f, + 1648.228394f, + 2039.998535f, + 2420.943115f, + 2828.022461f, + 3214.584961f, + 3575.200195f, + 3944.685303f, + 4338.971191f, + 4743.657227f, + 5149.993164f, + 5533.081055f, + 1485.457031f +}; + +/*----------------------------------------------------------------------------------* + * Initial LSF memory + *----------------------------------------------------------------------------------*/ + +const float lsf_init[16] = +{ + 375.0, 750.0, 1125.0, 1500.0, 1875.0, 2250.0, 2625.0, 3000.0, + 3375.0, 3750.0, 4125.0, 4500.0, 4875.0, 5250.0, 5625.0, 6000.0 +}; + + +/*----------------------------------------------------------------------------------* + * Gaussian codebook + *----------------------------------------------------------------------------------*/ + +const float gaus_dico[190] = +{ + -0.0973f, -0.0306f, 0.1278f, -0.1138f, 0.0744f, -0.1606f, + -0.1976f, 0.0115f, -0.0344f, -0.0417f, -0.1424f, -0.0633f, + 0.0723f, 0.3257f, -0.0697f, -0.0978f, -0.1168f, -0.1021f, + 0.0342f, -0.1319f, 0.0431f, -0.2658f, 0.0317f, -0.0712f, + 0.0348f, 0.1200f, -0.0758f, -0.2104f, -0.0781f, 0.0947f, + 0.1333f, 0.0204f, -0.2934f, 0.0262f, 0.0264f, 0.0830f, + 0.0584f, -0.0318f, 0.2271f, 0.0835f, 0.0374f, -0.0645f, + -0.1864f, -0.0277f, 0.0945f, -0.1306f, 0.0202f, -0.2090f, + -0.0881f, -0.1029f, 0.0292f, 0.0966f, -0.0896f, 0.1563f, + 0.1994f, 0.0543f, -0.2482f, -0.0201f, -0.0294f, 0.2172f, + 0.0830f, -0.0938f, 0.0115f, 0.0827f, -0.1233f, -0.1051f, + 0.0394f, 0.2390f, 0.2172f, -0.0653f, 0.0253f, 0.1241f, + -0.0366f, -0.0473f, 0.1080f, 0.0470f, 0.1009f, -0.0059f, + 0.0964f, -0.0105f, -0.0531f, 0.0169f, -0.0972f, 0.0408f, + 0.0283f, -0.2285f, -0.0232f, 0.3580f, -0.1063f, 0.1125f, + 0.2105f, -0.0331f, -0.0230f, 0.3200f, -0.0905f, 0.0166f, + 0.0328f, -0.0722f, -0.0380f, -0.1377f, -0.0118f, -0.1189f, + 0.1580f, 0.0769f, 0.1252f, -0.0247f, -0.1672f, -0.0777f, + -0.0841f, -0.1573f, -0.0160f, 0.2078f, 0.1011f, -0.0070f, + 0.1242f, 0.1011f, 0.1225f, 0.0973f, 0.1361f, 0.1584f, + -0.0729f, 0.1831f, 0.1332f, -0.1846f, -0.0029f, -0.0890f, + 0.1447f, -0.1727f, 0.0963f, -0.0321f, -0.0916f, -0.0151f, + -0.2232f, -0.0624f, -0.1036f, 0.0157f, 0.1134f, -0.2782f, + 0.0684f, 0.0222f, -0.0202f, -0.0704f, -0.1342f, 0.0950f, + 0.0128f, -0.2999f, 0.0015f, -0.1051f, 0.0180f, 0.0500f, + -0.1166f, -0.0361f, -0.1446f, 0.0688f, -0.0179f, 0.2959f, + 0.0102f, 0.1416f, -0.0815f, 0.1181f, -0.1867f, 0.1082f, + 0.1585f, 0.0661f, -0.1805f, 0.0915f, 0.1497f, -0.1124f, + -0.0508f, 0.0573f, -0.0294f, -0.0119f, -0.0759f, 0.1477f, + 0.2136f, 0.1271f, 0.0492f, -0.1235f, -0.1337f, -0.2657f, + -0.0106f, -0.0540f, 0.1642f, -0.0598f, -0.0065f, 0.1146f, + 0.0863f, 0.0129f, 0.1816f, 0.0672f +}; + +const float gaus_dico_swb[256] = +{ + 0.02164473f, 0.35885197f, -0.16274954f, -0.08241354f, 0.07313631f, -0.00054929f, -0.13080014f, 0.07226136f, + -0.13965981f, -0.04834007f, -0.02745908f, -0.02867859f, 0.11216793f, 0.16604294f, -0.00134274f, 0.06818508f, + -0.17387933f, 0.09406016f, -0.08150196f, 0.05083200f, -0.01952806f, -0.10203217f, -0.03067050f, -0.05153965f, + 0.06250680f, 0.00859049f, -0.12008808f, -0.11361376f, 0.17176038f, 0.01174004f, -0.02275130f, -0.09895785f, + -0.10167463f, -0.22059087f, -0.05334539f, -0.00629700f, -0.16706355f, 0.07795000f, 0.08731710f, 0.09669208f, + 0.15378080f, 0.01794813f, -0.01549965f, -0.24923822f, 0.19985947f, -0.10477958f, 0.06674605f, -0.11186616f, + -0.17927034f, 0.08443811f, 0.25542912f, 0.03167623f, 0.19633667f, 0.19163096f, 0.01907267f, 0.12298489f, + -0.03147158f, 0.05562247f, 0.30200079f, -0.04257871f, 0.08275045f, -0.03386311f, -0.02265750f, 0.18742503f, + -0.13598505f, -0.32004824f, -0.00438390f, -0.15576170f, 0.06006401f, -0.00952147f, 0.18848655f, 0.06630960f, + 0.07121546f, -0.00733249f, 0.08277771f, 0.22764891f, 0.06772452f, -0.09509693f, -0.00172236f, 0.08452052f, + 0.17020901f, -0.03737585f, 0.02349647f, 0.10855560f, 0.06854416f, 0.07084806f, 0.09390105f, 0.00124924f, + 0.03026483f, -0.15169589f, 0.01347072f, -0.15377805f, 0.14992996f, 0.11630810f, 0.03483583f, -0.03914850f, + -0.20075595f, 0.12728901f, -0.04495851f, -0.11576717f, -0.15281813f, 0.06055827f, -0.03471978f, -0.03617816f, + 0.17230885f, 0.03094525f, -0.15618153f, 0.21792564f, 0.08106838f, -0.22098514f, -0.10796417f, 0.07131225f, + 0.22092983f, -0.01539366f, -0.02876964f, -0.30910203f, 0.02143815f, -0.11630868f, -0.00922897f, 0.07431208f, + 0.15533504f, 0.11425125f, 0.07125455f, -0.11914105f, -0.04275274f, -0.05072749f, -0.22143129f, 0.19787727f, + -0.20946717f, -0.16564523f, 0.05962536f, -0.22325630f, -0.04333350f, -0.04707248f, 0.16608582f, 0.00948954f, + 0.11283893f, -0.04097161f, -0.09076904f, 0.26722300f, 0.00987607f, -0.05807892f, 0.07872546f, 0.08040629f, + 0.12927419f, -0.05647410f, 0.09603068f, -0.02356448f, -0.02160797f, -0.11687102f, 0.07936122f, -0.05764586f, + -0.10510305f, -0.02326054f, 0.12021790f, 0.09782617f, -0.22600858f, -0.02555378f, -0.03561033f, -0.01337216f, + 0.11311363f, -0.03096960f, -0.22801498f, 0.05643769f, 0.13053033f, 0.04452197f, -0.09299882f, -0.11475921f, + 0.02257649f, -0.21770498f, -0.11454470f, -0.09435777f, 0.00638951f, -0.36990553f, 0.04266735f, 0.06915011f, + 0.07644624f, -0.24336053f, -0.03421960f, -0.10622191f, -0.17223521f, 0.04054553f, 0.13831380f, 0.02925055f, + 0.16207848f, -0.12994884f, -0.09751288f, -0.05397306f, -0.09323815f, 0.13425350f, -0.00046960f, 0.31072289f, + 0.13740718f, 0.05835414f, -0.04803475f, 0.15423043f, -0.09652353f, 0.14896898f, -0.16368309f, 0.05875925f, + -0.03678078f, -0.19627908f, 0.07034992f, -0.27213186f, -0.04338680f, 0.01567988f, -0.09158870f, 0.11987700f, + 0.07083926f, 0.01099900f, -0.01084446f, 0.04508050f, -0.10655984f, -0.13945042f, 0.05837287f, 0.08458713f, + -0.04212087f, -0.15749574f, 0.11632511f, 0.07976698f, 0.06725866f, -0.09567240f, 0.03796997f, -0.09355708f, + -0.13569611f, -0.19498724f, 0.14951572f, -0.16023041f, 0.04185898f, 0.06099325f, 0.03425207f, 0.16211477f, + 0.03998571f, -0.03629408f, -0.10099959f, 0.19540504f, 0.11653102f, 0.23601755f, 0.04943547f, -0.26040605f, + 0.02153429f, 0.22880882f, -0.13646534f, 0.03881640f, -0.02896636f, 0.09774253f, -0.13509314f, -0.08713179f, + 0.13485038f, 0.06968338f, 0.19561967f, 0.07884958f, -0.10365590f, -0.10321335f, -0.09081125f, -0.00147976f +}; + +/*----------------------------------------------------------------------------------* + * CLDFB tables + *----------------------------------------------------------------------------------*/ + +const int freqTable[2] = {20, 40}; + +/* SNR: 109.44, PHASE: 3.500000000000000 */ +const float CLDFB80_10[100] = +{ + 0.0000033382f, -0.0000023292f, -0.0000006582f, 0.0000001464f, -0.0000010899f, -0.0000009664f, + -0.0000000104f, -0.0000018105f, -0.0000012856f, 0.0000017112f, 0.0000137155f, -0.0000084710f, + -0.0000015748f, -0.0000002482f, 0.0000036294f, -0.0000043816f, 0.0000003906f, 0.0000043318f, + 0.0000049126f, -0.0000061826f, -0.0002270069f, -0.0000675402f, -0.0000158982f, 0.0000138120f, + -0.0000220086f, -0.0000356560f, 0.0000171849f, -0.0000194504f, -0.0000058158f, -0.0002621811f, + -0.0009969691f, -0.0001427984f, -0.0000188085f, -0.0000040399f, -0.0001954359f, 0.0001806872f, + 0.0000232574f, -0.0000047551f, -0.0000321009f, 0.0010723262f, -0.0020160153f, -0.0007751652f, + 0.0003508478f, 0.0015707671f, 0.0017180828f, 0.0015807568f, 0.0021944824f, 0.0028288425f, + 0.0030257006f, 0.0016570983f, -0.0014279413f, -0.0015962377f, 0.0007765516f, 0.0025625922f, + 0.0022554877f, 0.0002647332f, -0.0032977409f, -0.0065113932f, -0.0095444393f, -0.0136373114f, + 0.0186561662f, 0.0242546518f, 0.0320538418f, 0.0427742450f, 0.0565841171f, 0.0732940277f, + 0.0914110197f, 0.1082620545f, 0.1209072165f, 0.1269811579f, 0.1253574855f, 0.1136768387f, + 0.0887587689f, 0.0497640968f, -0.0031398279f, -0.0698373206f, -0.1494875982f, -0.2406007759f, + -0.3411996303f, -0.4484628681f, 0.5579472269f, 0.6655527761f, 0.7669493517f, 0.8575328375f, + 0.9329386030f, 0.9892971917f, 1.0250167399f, 1.0397966587f, 1.0375221638f, 1.0163053398f, + 0.9610874400f, 0.8748972145f, 0.7783924293f, 0.6777346686f, 0.5724389618f, 0.4648620471f, + 0.3560337451f, 0.2485564060f, 0.1386438276f, 0.0416433203f, +}; + +/* SNR: 292.49, PHASE: 2.000000000000000 */ +const float CLDFB80_16[160] = +{ + 0.0000005510f, -0.0000007674f, -0.0000002340f, 0.0000000964f, 0.0000000593f, -0.0000000017f, + -0.0000000178f, 0.0000021953f, 0.0000030004f, -0.0000000167f, -0.0000000019f, 0.0000000702f, + 0.0000000344f, -0.0000000765f, -0.0000005553f, 0.0000007526f, 0.0000020881f, -0.0000028263f, + -0.0000007033f, 0.0000002370f, 0.0000001175f, -0.0000004048f, 0.0000000996f, -0.0000180207f, + 0.0000246292f, -0.0000000934f, 0.0000004489f, -0.0000001390f, -0.0000000845f, 0.0000002300f, + 0.0000020452f, -0.0000028520f, -0.0003204839f, -0.0001476489f, -0.0000626217f, -0.0000446346f, + -0.0000202236f, 0.0000151160f, 0.0000057995f, 0.0000450017f, 0.0000433006f, 0.0000050745f, + 0.0000167005f, -0.0000314631f, -0.0000244547f, -0.0000125422f, -0.0000911863f, -0.0004371781f, + -0.0012267106f, -0.0005247118f, -0.0001857576f, -0.0001103593f, -0.0000402931f, 0.0000108771f, + -0.0000576360f, 0.0000602621f, -0.0002317927f, 0.0000520316f, 0.0000035090f, 0.0000625950f, + 0.0000603417f, 0.0000368907f, 0.0003220307f, 0.0016733998f, -0.0021551784f, -0.0015444660f, + -0.0007592329f, -0.0001077355f, 0.0007091208f, 0.0015054295f, 0.0017984668f, 0.0011461500f, + 0.0015946160f, 0.0018157551f, 0.0022526599f, 0.0027665136f, 0.0029611644f, 0.0030474884f, + 0.0025509350f, 0.0012885692f, -0.0011048694f, -0.0019476595f, -0.0014849578f, -0.0000191307f, + 0.0014542427f, 0.0025014060f, 0.0026282341f, 0.0020896060f, 0.0009380930f, -0.0012303806f, + -0.0035150110f, -0.0055687066f, -0.0074233361f, -0.0093371234f, -0.0117127490f, -0.0145175090f, + 0.0177813213f, 0.0209221310f, 0.0246700384f, 0.0293186424f, 0.0350939424f, 0.0420166741f, + 0.0501689083f, 0.0594973479f, 0.0699793095f, 0.0811978302f, 0.0925316969f, 0.1033039355f, + 0.1127998301f, 0.1202885467f, 0.1252446307f, 0.1272143872f, 0.1262547749f, 0.1217276780f, + 0.1125292370f, 0.0980647299f, 0.0780704213f, 0.0526074650f, 0.0217182187f, -0.0146037409f, + -0.0563029259f, -0.1031675028f, -0.1548654211f, -0.2110103318f, -0.2711216615f, -0.3346791161f, + -0.4009613796f, -0.4689983890f, 0.5374920358f, 0.6054498150f, 0.6721266919f, 0.7362374318f, + 0.7966023599f, 0.8522654625f, 0.9021245679f, 0.9450253190f, 0.9802630812f, 1.0075496836f, + 1.0265340754f, 1.0372359728f, 1.0407524022f, 1.0381397893f, 1.0284102813f, 1.0099196627f, + 0.9753688495f, 0.9254582964f, 0.8690385973f, 0.8090082031f, 0.7474414548f, 0.6841760105f, + 0.6189218236f, 0.5524001591f, 0.4851748506f, 0.4172433895f, 0.3492691242f, 0.2821066655f, + 0.2146356085f, 0.1455327617f, 0.0796914490f, 0.0278251946f, +}; + +/* SNR: 89.77, PHASE: 1.500000000000000 */ +const float CLDFB80_20[200] = +{ + 0.0000016461f, -0.0000046862f, -0.0000000815f, -0.0000001822f, 0.0000000240f, 0.0000001892f, + -0.0000002365f, -0.0000007031f, -0.0000000079f, 0.0000048656f, 0.0000070490f, 0.0000000032f, + 0.0000001499f, -0.0000000944f, 0.0000004307f, -0.0000000787f, -0.0000001070f, 0.0000015376f, + -0.0000025088f, 0.0000044280f, 0.0000046060f, -0.0000207092f, -0.0000004877f, -0.0000006126f, + 0.0000000605f, 0.0000004365f, -0.0000003741f, -0.0000009508f, 0.0000006700f, -0.0000087189f, + 0.0000114297f, -0.0000007710f, -0.0000002908f, 0.0000001583f, -0.0000010138f, 0.0000001875f, + 0.0000003789f, -0.0000065731f, 0.0000112115f, -0.0000036253f, -0.0003045828f, -0.0002068946f, + -0.0000330428f, -0.0000658559f, -0.0000416668f, -0.0000207558f, -0.0000046097f, 0.0000096778f, + -0.0000064960f, 0.0000515938f, 0.0000257367f, -0.0000068671f, 0.0000029284f, -0.0000209369f, + -0.0000191720f, -0.0000235869f, -0.0000286778f, 0.0000594843f, -0.0001104448f, -0.0004947290f, + -0.0011759540f, -0.0006581582f, -0.0001310136f, -0.0001782524f, -0.0001002354f, -0.0000465158f, + -0.0000188237f, 0.0000285072f, -0.0001359344f, 0.0002814194f, -0.0004814411f, 0.0001302339f, + -0.0000257394f, 0.0000578339f, 0.0000485628f, 0.0000543116f, 0.0000763443f, -0.0001495108f, + 0.0003492618f, 0.0018283780f, -0.0019931487f, -0.0018716309f, -0.0008617653f, -0.0006080124f, + -0.0000337803f, 0.0006187704f, 0.0012478726f, 0.0016757046f, 0.0018115391f, 0.0007745483f, + 0.0016550121f, 0.0017032298f, 0.0019356593f, 0.0024080283f, 0.0027878510f, 0.0029379588f, + 0.0030637651f, 0.0028257202f, 0.0021943273f, 0.0010679683f, -0.0009250455f, -0.0017798333f, + -0.0018826540f, -0.0011010583f, 0.0001463485f, 0.0013293069f, 0.0022974838f, 0.0027746423f, + 0.0025078917f, 0.0020425098f, 0.0011954954f, -0.0005741594f, -0.0024120809f, -0.0041653667f, + -0.0057623702f, -0.0072425386f, -0.0087363677f, -0.0104237699f, -0.0125156239f, -0.0148077168f, + 0.0174398402f, 0.0199230411f, 0.0226649147f, 0.0259599813f, 0.0298434758f, 0.0344649815f, + 0.0398139569f, 0.0459314689f, 0.0528498740f, 0.0604788669f, 0.0688814001f, 0.0777923399f, + 0.0868947517f, 0.0958553537f, 0.1043243835f, 0.1119302041f, 0.1182880738f, 0.1231125873f, + 0.1261745561f, 0.1272284850f, 0.1264656300f, 0.1235525506f, 0.1177556666f, 0.1087635447f, + 0.0963144136f, 0.0803171444f, 0.0608146076f, 0.0378425383f, 0.0113896330f, -0.0185270856f, + -0.0518892622f, -0.0885871716f, -0.1284318249f, -0.1712634880f, -0.2168508609f, -0.2649463144f, + -0.3152867427f, -0.3675395959f, -0.4212350657f, -0.4758650706f, 0.5306725282f, 0.5851445237f, + 0.6390281696f, 0.6916889535f, 0.7424591009f, 0.7907617163f, 0.8361206884f, 0.8779983070f, + 0.9157691951f, 0.9489012228f, 0.9770929872f, 1.0002174168f, 1.0180999340f, 1.0305853696f, + 1.0378851378f, 1.0406826783f, 1.0395784114f, 1.0343061945f, 1.0237762412f, 1.0076524569f, + 0.9800034826f, 0.9411740407f, 0.8979145998f, 0.8512639848f, 0.8029102780f, 0.7536620391f, + 0.7033730373f, 0.6517679660f, 0.5990562278f, 0.5457078369f, 0.4919297136f, 0.4376796414f, + 0.3831842053f, 0.3290362900f, 0.2754121565f, 0.2214602867f, 0.1663238479f, 0.1115465981f, + 0.0622889538f, 0.0233593568f, +}; + +/* SNR: 89.29, PHASE: 0.833333333333333 */ +const float CLDFB80_30[300] = +{ + -0.0000002772f, 0.0000033382f, 0.0000018078f, -0.0000007965f, -0.0000023292f, -0.0000000163f, + 0.0000001004f, -0.0000006582f, 0.0000000287f, 0.0000000140f, 0.0000001464f, 0.0000002826f, + 0.0000000427f, -0.0000010899f, 0.0000048488f, 0.0000070973f, -0.0000009664f, 0.0000000360f, + 0.0000004432f, -0.0000000104f, -0.0000000269f, -0.0000000107f, -0.0000018105f, 0.0000000543f, + -0.0000000029f, -0.0000012856f, -0.0000006144f, 0.0000009806f, 0.0000017112f, -0.0000026992f, + -0.0000120997f, 0.0000137155f, 0.0000075545f, -0.0000032372f, -0.0000084710f, -0.0000000206f, + 0.0000002472f, -0.0000015748f, 0.0000000428f, -0.0000000299f, -0.0000002482f, 0.0000005522f, + 0.0000001959f, 0.0000036294f, 0.0000084418f, -0.0000120850f, -0.0000043816f, -0.0000001651f, + -0.0000010266f, 0.0000003906f, 0.0000001476f, 0.0000000560f, 0.0000043318f, -0.0000001327f, + -0.0000000099f, 0.0000049126f, 0.0000025641f, -0.0000041212f, -0.0000061826f, 0.0000182899f, + -0.0003177625f, -0.0002270069f, -0.0001470513f, -0.0000710867f, -0.0000675402f, -0.0000612052f, + -0.0000458905f, -0.0000158982f, -0.0000198609f, -0.0000044865f, 0.0000138120f, 0.0000259521f, + -0.0000014174f, -0.0000220086f, 0.0000046746f, -0.0000478217f, -0.0000356560f, -0.0000008176f, + 0.0000554471f, 0.0000171849f, -0.0000104782f, -0.0000342931f, -0.0000194504f, -0.0000247231f, + -0.0000266321f, -0.0000058158f, -0.0000154718f, -0.0000860619f, -0.0002621811f, -0.0006329730f, + -0.0010151313f, -0.0009969691f, -0.0006401095f, -0.0002347208f, -0.0001427984f, -0.0001657818f, + -0.0001142242f, -0.0000188085f, -0.0000385187f, -0.0000275046f, -0.0000040399f, 0.0000495378f, + -0.0001045437f, -0.0001954359f, 0.0005754000f, -0.0007487377f, 0.0001806872f, 0.0000995589f, + -0.0000996504f, 0.0000232574f, 0.0000603268f, 0.0000660807f, -0.0000047551f, 0.0000619265f, + 0.0000723872f, -0.0000321009f, 0.0000223561f, 0.0003720504f, 0.0010723262f, 0.0019477029f, + -0.0018122293f, -0.0020160153f, -0.0017426363f, -0.0010556444f, -0.0007751652f, -0.0005221317f, + -0.0001347624f, 0.0003508478f, 0.0007386346f, 0.0011721899f, 0.0015707671f, 0.0017166805f, + 0.0018089705f, 0.0017180828f, 0.0002671723f, 0.0016677326f, 0.0015807568f, 0.0017534327f, + 0.0019075685f, 0.0021944824f, 0.0024875266f, 0.0027574445f, 0.0028288425f, 0.0029688585f, + 0.0030573770f, 0.0030257006f, 0.0027683197f, 0.0023855538f, 0.0016570983f, 0.0007261425f, + -0.0006240877f, -0.0014279413f, -0.0018848796f, -0.0019263976f, -0.0015962377f, -0.0009120500f, + -0.0000736785f, 0.0007765516f, 0.0014961634f, 0.0021524541f, 0.0025625922f, 0.0027460441f, + 0.0025688449f, 0.0022554877f, 0.0019970512f, 0.0015552223f, 0.0002647332f, -0.0008620885f, + -0.0020865380f, -0.0032977409f, -0.0044403210f, -0.0055039505f, -0.0065113932f, -0.0074839181f, + -0.0084786965f, -0.0095444393f, -0.0107566368f, -0.0121559845f, -0.0136373114f, -0.0152125941f, + 0.0169692165f, 0.0186561662f, 0.0203704498f, 0.0221787331f, 0.0242546518f, 0.0265582983f, + 0.0291465321f, 0.0320538418f, 0.0353059968f, 0.0388699993f, 0.0427742450f, 0.0470319574f, + 0.0516455579f, 0.0565841171f, 0.0617960053f, 0.0674208876f, 0.0732940277f, 0.0793036968f, + 0.0853757711f, 0.0914110197f, 0.0973085175f, 0.1029609938f, 0.1082620545f, 0.1130850459f, + 0.1173295323f, 0.1209072165f, 0.1237469292f, 0.1257934619f, 0.1269811579f, 0.1271703366f, + 0.1266559114f, 0.1253574855f, 0.1227915199f, 0.1189360593f, 0.1136768387f, 0.1069333476f, + 0.0986359173f, 0.0887587689f, 0.0773092890f, 0.0643073307f, 0.0497640968f, 0.0336765771f, + 0.0160401582f, -0.0031398279f, -0.0238366387f, -0.0460799881f, -0.0698373206f, -0.0950128018f, + -0.1215783841f, -0.1494875982f, -0.1786760784f, -0.2090721736f, -0.2406007759f, -0.2731879051f, + -0.3067537961f, -0.3411996303f, -0.3764015708f, -0.4122065782f, -0.4484628681f, -0.4850451997f, + 0.5215924710f, 0.5579472269f, 0.5941804962f, 0.6301135607f, 0.6655527761f, 0.7002994797f, + 0.7341550905f, 0.7669493517f, 0.7985389090f, 0.8287866009f, 0.8575328375f, 0.8845952462f, + 0.9097846281f, 0.9329386030f, 0.9539491421f, 0.9727435862f, 0.9892971917f, 1.0035676672f, + 1.0154927835f, 1.0250167399f, 1.0321480823f, 1.0370035227f, 1.0397966587f, 1.0407627030f, + 1.0400314908f, 1.0375221638f, 1.0329480648f, 1.0259438203f, 1.0163053398f, 1.0048344063f, + 0.9863956401f, 0.9610874400f, 0.9342743262f, 0.9054084925f, 0.8748972145f, 0.8432873810f, + 0.8110381808f, 0.7783924293f, 0.7453640666f, 0.7118431392f, 0.6777346686f, 0.6430470493f, + 0.6078972260f, 0.5724389618f, 0.5367746506f, 0.5009238704f, 0.4648620471f, 0.4286003322f, + 0.3922588980f, 0.3560337451f, 0.3200733025f, 0.2843378434f, 0.2485564060f, 0.2123552623f, + 0.1755742394f, 0.1386438276f, 0.1027751331f, 0.0698223020f, 0.0416433203f, 0.0171881989f, +}; + +/* SNR: 85.69, PHASE: 0.750000000000000 */ +const float CLDFB80_32[320] = +{ + -0.0000010182f, 0.0000018812f, -0.0000013969f, 0.0000000702f, -0.0000030351f, -0.0000001862f, + 0.0000000017f, 0.0000000804f, -0.0000002859f, -0.0000000058f, -0.0000003463f, -0.0000003782f, + 0.0000006385f, 0.0000000365f, -0.0000015696f, 0.0000043896f, 0.0000063462f, -0.0000013860f, + 0.0000000439f, 0.0000007243f, -0.0000000373f, -0.0000001214f, 0.0000000228f, -0.0000008123f, + 0.0000002096f, -0.0000000043f, -0.0000001079f, -0.0000005174f, -0.0000001146f, -0.0000006991f, + 0.0000012420f, -0.0000054157f, -0.0000164806f, 0.0000076445f, -0.0000065087f, 0.0000002224f, + -0.0000110942f, -0.0000006228f, 0.0000000012f, 0.0000001914f, -0.0000006876f, 0.0000000004f, + -0.0000005395f, -0.0000007555f, 0.0000015057f, 0.0000005303f, 0.0000035648f, 0.0000094151f, + -0.0000133505f, -0.0000042847f, -0.0000005848f, -0.0000018021f, 0.0000001676f, 0.0000001730f, + -0.0000000645f, 0.0000019429f, -0.0000005012f, 0.0000000132f, 0.0000003799f, 0.0000014190f, + 0.0000005446f, 0.0000033533f, -0.0000041925f, 0.0000243728f, -0.0003249116f, -0.0002555667f, + -0.0001781466f, -0.0000946691f, -0.0000512440f, -0.0000668181f, -0.0000538663f, -0.0000367589f, + -0.0000153566f, -0.0000159763f, -0.0000043008f, 0.0000014360f, 0.0000256407f, -0.0000045056f, + -0.0000224244f, -0.0000056258f, -0.0000573469f, -0.0000427838f, -0.0000040513f, 0.0000493530f, + -0.0000199927f, -0.0000284530f, -0.0000443529f, -0.0000157197f, -0.0000152059f, -0.0000265666f, + -0.0000286606f, 0.0000426372f, -0.0000445737f, -0.0000968212f, -0.0002992176f, -0.0006564777f, + -0.0009923400f, -0.0010465131f, -0.0006586000f, -0.0003460162f, -0.0000803812f, -0.0001828317f, + -0.0001374910f, -0.0000892170f, -0.0000247429f, -0.0000281266f, -0.0000112548f, -0.0000220216f, + 0.0000281030f, -0.0001241423f, -0.0001739019f, 0.0006003709f, -0.0007665771f, 0.0001545192f, + 0.0001183979f, -0.0000725009f, 0.0000709099f, 0.0000556600f, 0.0000787870f, 0.0000127551f, + 0.0000418355f, 0.0000676110f, 0.0000771386f, -0.0001678521f, 0.0001526165f, 0.0003591734f, + 0.0011851563f, 0.0019531880f, -0.0018073091f, -0.0020646655f, -0.0018286838f, -0.0012220764f, + -0.0007555665f, -0.0006377868f, -0.0003093176f, 0.0000756312f, 0.0005274300f, 0.0009274213f, + 0.0012803192f, 0.0016235299f, 0.0017557598f, 0.0018111856f, 0.0016683303f, 0.0002150325f, + 0.0016540635f, 0.0015774318f, 0.0017217761f, 0.0018831036f, 0.0020842542f, 0.0023790930f, + 0.0026699692f, 0.0028034973f, 0.0028981065f, 0.0030135931f, 0.0030635897f, 0.0029615904f, + 0.0027120429f, 0.0022714745f, 0.0016059652f, 0.0006835412f, -0.0005828829f, -0.0013844400f, + -0.0018243580f, -0.0019502151f, -0.0017356111f, -0.0011689841f, -0.0004229350f, 0.0003965073f, + 0.0011294169f, 0.0017707072f, 0.0023448371f, 0.0026728102f, 0.0027087051f, 0.0025324105f, + 0.0022209939f, 0.0019939538f, 0.0015995394f, 0.0003709522f, -0.0006814813f, -0.0018062812f, + -0.0029774326f, -0.0040602444f, -0.0050788762f, -0.0060470476f, -0.0069716019f, -0.0078811278f, + -0.0088339160f, -0.0098593061f, -0.0110571431f, -0.0123801308f, -0.0137829951f, -0.0152658987f, + 0.0169119551f, 0.0185130319f, 0.0200914127f, 0.0217670701f, 0.0236411334f, 0.0257401339f, + 0.0280588687f, 0.0306516429f, 0.0335396415f, 0.0367140220f, 0.0401734073f, 0.0439328404f, + 0.0480118471f, 0.0523958086f, 0.0570643279f, 0.0619617615f, 0.0672386055f, 0.0727386082f, + 0.0783586322f, 0.0840454562f, 0.0897239254f, 0.0953063133f, 0.1006989894f, 0.1058297221f, + 0.1105886458f, 0.1148828316f, 0.1186363019f, 0.1217873693f, 0.1242652074f, 0.1260376844f, + 0.1270428159f, 0.1271553981f, 0.1266717254f, 0.1255342565f, 0.1232765470f, 0.1198938969f, + 0.1153006197f, 0.1094250684f, 0.1021978763f, 0.0935850985f, 0.0835853025f, 0.0722146942f, + 0.0594803881f, 0.0453959671f, 0.0299515180f, 0.0131448092f, -0.0050174243f, -0.0245067664f, + -0.0453599939f, -0.0675506175f, -0.0909864895f, -0.1156500318f, -0.1415054519f, -0.1685034579f, + -0.1965824123f, -0.2256851924f, -0.2557490596f, -0.2867109877f, -0.3185003509f, -0.3510308710f, + -0.3841878257f, -0.4178462189f, -0.4518783777f, -0.4861948985f, 0.5204589154f, 0.5545392477f, + 0.5885349528f, 0.6222881265f, 0.6556472882f, 0.6884462258f, 0.7205203255f, 0.7517187214f, + 0.7819150729f, 0.8109973423f, 0.8388462493f, 0.8653227793f, 0.8902717587f, 0.9135401037f, + 0.9350004724f, 0.9545704608f, 0.9721900670f, 0.9878415249f, 1.0014908046f, 1.0130877123f, + 1.0225821802f, 1.0299620942f, 1.0352930981f, 1.0387279035f, 1.0404656862f, 1.0406699226f, + 1.0393792732f, 1.0364602207f, 1.0316371259f, 1.0246094465f, 1.0152749279f, 1.0045111461f, + 0.9872243762f, 0.9634951727f, 0.9386029698f, 0.9118835665f, 0.8836131513f, 0.8542438147f, + 0.8241955864f, 0.7937396816f, 0.7629631733f, 0.7318123869f, 0.7001870615f, 0.6680338585f, + 0.6353919868f, 0.6023736401f, 0.5691034053f, 0.5356571527f, 0.5020472026f, 0.4682522004f, + 0.4342757821f, 0.4002060880f, 0.3661991567f, 0.3324016480f, 0.2988415427f, 0.2653598332f, + 0.2316572400f, 0.1974745970f, 0.1628547074f, 0.1283770554f, 0.0952404323f, 0.0650740936f, + 0.0392771501f, 0.0163785856f, +}; + +/* SNR: 81.55, PHASE: 0.500000000000000 */ +const float CLDFB80_40[400] = +{ + -0.0000041528f, -0.0000003900f, -0.0000033779f, 0.0000013260f, -0.0000003143f, -0.0000019348f, + 0.0000002820f, 0.0000000171f, 0.0000000756f, 0.0000001478f, -0.0000006625f, 0.0000000082f, + 0.0000000114f, -0.0000002690f, -0.0000007281f, 0.0000005577f, -0.0000000239f, 0.0000002429f, + -0.0000004091f, 0.0000026069f, 0.0000034995f, -0.0000001726f, 0.0000002145f, -0.0000000401f, + 0.0000006351f, -0.0000000199f, -0.0000000701f, -0.0000000269f, -0.0000000511f, -0.0000018158f, + 0.0000003875f, 0.0000000519f, 0.0000000148f, 0.0000002168f, 0.0000008257f, -0.0000004464f, + 0.0000006336f, -0.0000025316f, -0.0000005295f, -0.0000153180f, -0.0000308298f, -0.0000015398f, + -0.0000152958f, 0.0000058438f, -0.0000013050f, -0.0000070187f, 0.0000011695f, 0.0000000763f, + 0.0000001881f, 0.0000003524f, -0.0000015865f, -0.0000000049f, -0.0000000249f, -0.0000006192f, + -0.0000011121f, 0.0000012060f, -0.0000000166f, 0.0000001099f, -0.0000106587f, 0.0000106129f, + -0.0000148286f, 0.0000149412f, 0.0000001626f, 0.0000000725f, -0.0000015409f, 0.0000000950f, + 0.0000003484f, 0.0000001231f, 0.0000001497f, 0.0000043429f, -0.0000009269f, -0.0000001280f, + -0.0000000626f, -0.0000009033f, -0.0000040910f, 0.0000019169f, -0.0000028704f, 0.0000109325f, + -0.0000009252f, 0.0000489011f, -0.0003468893f, -0.0003166165f, -0.0002216732f, -0.0001440458f, + -0.0000849613f, -0.0000369773f, -0.0000635098f, -0.0000591070f, -0.0000486803f, -0.0000341989f, + -0.0000120811f, -0.0000190275f, -0.0000064494f, 0.0000069162f, -0.0000021987f, 0.0000272330f, + 0.0000008567f, -0.0000105879f, 0.0000129785f, -0.0000391934f, -0.0000840231f, 0.0000041534f, + -0.0000069437f, 0.0000002747f, 0.0000564106f, -0.0000335888f, -0.0000091603f, -0.0000220067f, + -0.0000377648f, -0.0000212702f, -0.0000107779f, -0.0000254405f, -0.0000262093f, -0.0000203017f, + 0.0000691479f, -0.0000348713f, -0.0000882526f, -0.0001632241f, -0.0003897623f, -0.0007277920f, + -0.0009273781f, -0.0011866370f, -0.0007657374f, -0.0005999553f, -0.0002985749f, -0.0000739204f, + -0.0001965512f, -0.0001587267f, -0.0001222374f, -0.0000844484f, -0.0000080229f, -0.0000361957f, + -0.0000240334f, 0.0000097698f, -0.0000196647f, 0.0000408240f, -0.0000873313f, -0.0001974888f, + -0.0000745679f, 0.0006405856f, -0.0007833142f, -0.0000263740f, 0.0001825899f, 0.0000836328f, + -0.0000919747f, 0.0000758216f, 0.0000210116f, 0.0000664122f, 0.0000716628f, -0.0000011497f, + 0.0000361513f, 0.0000644816f, 0.0000707314f, 0.0000692091f, -0.0002055217f, 0.0001007125f, + 0.0003613597f, 0.0005722141f, 0.0014928248f, 0.0019595151f, -0.0018123181f, -0.0021841686f, + -0.0019313868f, -0.0016661118f, -0.0011520847f, -0.0007460794f, -0.0007200000f, -0.0004759622f, + -0.0001911740f, 0.0001177745f, 0.0005112609f, 0.0007956582f, 0.0011317990f, 0.0014125904f, + 0.0016338868f, 0.0017396047f, 0.0018056445f, 0.0018052119f, 0.0014209425f, 0.0000970427f, + 0.0015804238f, 0.0015713347f, 0.0016260006f, 0.0017792934f, 0.0018939546f, 0.0020439435f, + 0.0023023017f, 0.0025264800f, 0.0027361034f, 0.0028056985f, 0.0028830887f, 0.0029840440f, + 0.0030499023f, 0.0030582362f, 0.0029323543f, 0.0027372045f, 0.0024602608f, 0.0018918251f, + 0.0014430869f, 0.0005567848f, -0.0004563602f, -0.0012376069f, -0.0015957612f, -0.0019181670f, + -0.0019416943f, -0.0017732047f, -0.0013639015f, -0.0008131398f, -0.0001818974f, 0.0004785653f, + 0.0010577894f, 0.0015807496f, 0.0020750864f, 0.0024484891f, 0.0027097859f, 0.0027252487f, + 0.0025942388f, 0.0023933812f, 0.0021363139f, 0.0019878937f, 0.0017252901f, 0.0007007239f, + -0.0001528669f, -0.0010081819f, -0.0019255759f, -0.0028704299f, -0.0037352063f, -0.0045760650f, + -0.0053741521f, -0.0061399643f, -0.0068807053f, -0.0076055948f, -0.0083505693f, -0.0091327970f, + -0.0099660466f, -0.0109276265f, -0.0119779770f, -0.0130668832f, -0.0142243967f, -0.0154284789f, + 0.0167425678f, 0.0180870259f, 0.0192629868f, 0.0205914974f, 0.0219419942f, 0.0234393525f, + 0.0250925019f, 0.0268648248f, 0.0288064481f, 0.0309261411f, 0.0332359672f, 0.0357337882f, + 0.0384058373f, 0.0412703873f, 0.0443254146f, 0.0475898752f, 0.0510512395f, 0.0546934731f, + 0.0585192825f, 0.0624617968f, 0.0666925081f, 0.0710800609f, 0.0755330962f, 0.0800607977f, + 0.0846155968f, 0.0891603964f, 0.0936468776f, 0.0980290565f, 0.1022710303f, 0.1063242147f, + 0.1101321383f, 0.1136484689f, 0.1168337639f, 0.1196454804f, 0.1220672782f, 0.1240474957f, + 0.1255837620f, 0.1266445580f, 0.1271706795f, 0.1271032514f, 0.1267122859f, 0.1259990302f, + 0.1245431141f, 0.1223810246f, 0.1194917271f, 0.1158164730f, 0.1113281486f, 0.1059821849f, + 0.0997598463f, 0.0926475473f, 0.0846476380f, 0.0757687538f, 0.0660180747f, 0.0553969977f, + 0.0439122033f, 0.0315571111f, 0.0183294511f, 0.0042339687f, -0.0107303776f, -0.0265261206f, + -0.0432087461f, -0.0607651851f, -0.0791119955f, -0.0982585186f, -0.1181828257f, -0.1388675094f, + -0.1602878821f, -0.1824109255f, -0.2052090118f, -0.2286494873f, -0.2527009969f, -0.2773319455f, + -0.3025075323f, -0.3281859857f, -0.3543210024f, -0.3808473827f, -0.4077028160f, -0.4348259057f, + -0.4621422068f, -0.4896449982f, 0.5170583948f, 0.5443118380f, 0.5715622296f, 0.5986919021f, + 0.6256446209f, 0.6523342207f, 0.6786749944f, 0.7045840109f, 0.7299779641f, 0.7547853740f, + 0.7789437691f, 0.8023962911f, 0.8250842263f, 0.8469401272f, 0.8678891784f, 0.8878500705f, + 0.9067442457f, 0.9245026353f, 0.9410725379f, 0.9564213901f, 0.9705164338f, 0.9833542233f, + 0.9949193206f, 1.0051881116f, 1.0141325299f, 1.0217280805f, 1.0279678321f, 1.0328759990f, + 1.0365142018f, 1.0389749476f, 1.0403626832f, 1.0407638661f, 1.0402158247f, 1.0386859218f, + 1.0360693875f, 1.0322135556f, 1.0269616972f, 1.0202228069f, 1.0121135675f, 1.0035354422f, + 0.9897053659f, 0.9706651118f, 0.9512828704f, 0.9307719520f, 0.9091186544f, 0.8864979484f, + 0.8631436896f, 0.8392834698f, 0.8150938957f, 0.7906763160f, 0.7660562253f, 0.7412033356f, + 0.7160643565f, 0.6905965223f, 0.6647900873f, 0.6386753533f, 0.6123109042f, 0.5857635917f, + 0.5590863635f, 0.5323035448f, 0.5054159767f, 0.4784116395f, 0.4512831657f, 0.4240582163f, + 0.3967995814f, 0.3695924504f, 0.3425141525f, 0.3155972383f, 0.2888001961f, 0.2620044852f, + 0.2350467488f, 0.2077866806f, 0.1801971236f, 0.1524510915f, 0.1249766396f, 0.0984509433f, + 0.0737154373f, 0.0515800648f, 0.0323408448f, 0.0138765961f, +}; + + +/* SNR: 85.15, PHASE: 0.166666666666667 */ +const float CLDFB80_60[600] = +{ + -0.0000108386f, 0.0000016461f, -0.0000001140f, 0.0000015161f, -0.0000046862f, -0.0000001825f, + 0.0000001498f, -0.0000000815f, -0.0000033014f, 0.0000001274f, -0.0000001822f, 0.0000000191f, + 0.0000000335f, 0.0000000240f, 0.0000001226f, -0.0000010507f, 0.0000001892f, 0.0000000108f, + -0.0000000274f, -0.0000002365f, -0.0000000901f, -0.0000002666f, -0.0000007031f, 0.0000006413f, + -0.0000000514f, -0.0000000079f, 0.0000002000f, -0.0000014744f, 0.0000048656f, -0.0000001578f, + -0.0000005544f, 0.0000070490f, -0.0000012678f, 0.0000001774f, 0.0000000032f, -0.0000000624f, + 0.0000007343f, 0.0000001499f, -0.0000000401f, -0.0000000182f, -0.0000000944f, -0.0000000302f, + -0.0000000091f, 0.0000004307f, -0.0000028538f, 0.0000002990f, -0.0000000787f, 0.0000000221f, + 0.0000000116f, -0.0000001070f, 0.0000001406f, -0.0000009019f, 0.0000015376f, -0.0000000209f, + -0.0000002404f, -0.0000025088f, -0.0000000262f, 0.0000000630f, 0.0000044280f, -0.0000305498f, + -0.0000482857f, 0.0000046060f, -0.0000005548f, 0.0000056679f, -0.0000207092f, -0.0000003611f, + 0.0000005381f, -0.0000004877f, -0.0000120827f, 0.0000006267f, -0.0000006126f, 0.0000000608f, + 0.0000000850f, 0.0000000605f, 0.0000002921f, -0.0000025140f, 0.0000004365f, 0.0000000116f, + -0.0000000639f, -0.0000003741f, -0.0000004826f, -0.0000006420f, -0.0000009508f, 0.0000015544f, + -0.0000000218f, 0.0000006700f, 0.0000004181f, -0.0000021629f, -0.0000087189f, 0.0000088821f, + -0.0000126345f, 0.0000114297f, 0.0000034734f, -0.0000001464f, -0.0000007710f, 0.0000000568f, + -0.0000018420f, -0.0000002908f, 0.0000001921f, 0.0000004300f, 0.0000001583f, 0.0000000782f, + 0.0000000378f, -0.0000010138f, 0.0000068268f, -0.0000007152f, 0.0000001875f, -0.0000000557f, + -0.0000000384f, 0.0000003789f, -0.0000006147f, 0.0000030092f, -0.0000065731f, 0.0000001500f, + 0.0000007177f, 0.0000112115f, 0.0000001848f, -0.0000012026f, -0.0000036253f, 0.0000992289f, + -0.0003607599f, -0.0003045828f, -0.0002977550f, -0.0001992588f, -0.0002068946f, -0.0001476180f, + -0.0000980857f, -0.0000330428f, -0.0000555832f, -0.0000621497f, -0.0000658559f, -0.0000573785f, + -0.0000513819f, -0.0000416668f, -0.0000295334f, -0.0000092197f, -0.0000207558f, -0.0000179295f, + -0.0000092361f, -0.0000046097f, 0.0000131986f, 0.0000028970f, 0.0000096778f, 0.0000247417f, + 0.0000038052f, -0.0000064960f, -0.0000124163f, -0.0000092122f, 0.0000515938f, -0.0000831154f, + -0.0001125238f, 0.0000257367f, -0.0000286390f, -0.0000087198f, -0.0000068671f, 0.0000026174f, + 0.0000461536f, 0.0000029284f, -0.0000148640f, 0.0000099199f, -0.0000209369f, -0.0000366334f, + -0.0000401223f, -0.0000191720f, -0.0000276997f, -0.0000075415f, -0.0000235869f, -0.0000261427f, + -0.0000261960f, -0.0000286778f, -0.0000147880f, 0.0000339128f, 0.0000594843f, -0.0000475296f, + -0.0000916631f, -0.0001104448f, -0.0001832659f, -0.0003546036f, -0.0004947290f, -0.0008075304f, + -0.0008607843f, -0.0011759540f, -0.0011280060f, -0.0008472242f, -0.0006581582f, -0.0005496107f, + -0.0003610854f, -0.0001310136f, -0.0000843705f, -0.0001929211f, -0.0001782524f, -0.0001519136f, + -0.0001298443f, -0.0001002354f, -0.0000721302f, 0.0000080280f, -0.0000465158f, -0.0000338343f, + -0.0000199728f, -0.0000188237f, 0.0000123819f, -0.0000217824f, 0.0000285072f, 0.0000230642f, + -0.0000681343f, -0.0001359344f, -0.0002126650f, -0.0001268185f, 0.0002814194f, 0.0005796200f, + -0.0006917457f, -0.0004814411f, 0.0000740708f, 0.0001943933f, 0.0001302339f, 0.0000640566f, + -0.0000644259f, -0.0000257394f, 0.0000673956f, 0.0000057778f, 0.0000578339f, 0.0000733133f, + 0.0000756517f, 0.0000485628f, -0.0000143756f, 0.0000258732f, 0.0000543116f, 0.0000662824f, + 0.0000694890f, 0.0000763443f, 0.0000515654f, -0.0001531987f, -0.0001495108f, 0.0001684928f, + 0.0003371435f, 0.0003492618f, 0.0007408282f, 0.0013614773f, 0.0018283780f, 0.0019512654f, + -0.0018468584f, -0.0019931487f, -0.0021435886f, -0.0019354719f, -0.0018716309f, -0.0015855347f, + -0.0012449413f, -0.0008617653f, -0.0007595430f, -0.0007484226f, -0.0006080124f, -0.0004298524f, + -0.0002469285f, -0.0000337803f, 0.0001833366f, 0.0004827171f, 0.0006187704f, 0.0008525160f, + 0.0010861242f, 0.0012478726f, 0.0014766763f, 0.0016195479f, 0.0016757046f, 0.0017606977f, + 0.0018011194f, 0.0018115391f, 0.0017918594f, 0.0015514538f, 0.0007745483f, 0.0000722375f, + 0.0013858425f, 0.0016550121f, 0.0015724609f, 0.0016037139f, 0.0017032298f, 0.0018041572f, + 0.0018793499f, 0.0019356593f, 0.0020977586f, 0.0022698159f, 0.0024080283f, 0.0025652021f, + 0.0027100014f, 0.0027878510f, 0.0028094267f, 0.0028631331f, 0.0029379588f, 0.0029982766f, + 0.0030408094f, 0.0030637651f, 0.0030520617f, 0.0029707674f, 0.0028257202f, 0.0027032586f, + 0.0025230449f, 0.0021943273f, 0.0018058213f, 0.0015201289f, 0.0010679683f, 0.0003894925f, + -0.0002840705f, -0.0009250455f, -0.0013074121f, -0.0015395618f, -0.0017798333f, -0.0019401547f, + -0.0019524700f, -0.0018826540f, -0.0017220928f, -0.0014455464f, -0.0011010583f, -0.0007116751f, + -0.0002892919f, 0.0001463485f, 0.0005842019f, 0.0009616845f, 0.0013293069f, 0.0016655901f, + 0.0019957600f, 0.0022974838f, 0.0024834913f, 0.0026599403f, 0.0027746423f, 0.0027031419f, + 0.0026172855f, 0.0025078917f, 0.0023497345f, 0.0021702568f, 0.0020425098f, 0.0019860915f, + 0.0018636567f, 0.0011954954f, 0.0005514571f, -0.0000141897f, -0.0005741594f, -0.0011558780f, + -0.0017668142f, -0.0024120809f, -0.0030128714f, -0.0035882532f, -0.0041653667f, -0.0047110318f, + -0.0052436287f, -0.0057623702f, -0.0062633358f, -0.0067586961f, -0.0072425386f, -0.0077278117f, + -0.0082234072f, -0.0087363677f, -0.0092686369f, -0.0098240661f, -0.0104237699f, -0.0111004947f, + -0.0118009488f, -0.0125156239f, -0.0132546394f, -0.0140277665f, -0.0148077168f, -0.0156486149f, + 0.0165211147f, 0.0174398402f, 0.0182775949f, 0.0190534138f, 0.0199230411f, 0.0208118290f, + 0.0217092634f, 0.0226649147f, 0.0237088141f, 0.0248100351f, 0.0259599813f, 0.0271764016f, + 0.0284714021f, 0.0298434758f, 0.0312965027f, 0.0328356927f, 0.0344649815f, 0.0361664394f, + 0.0379470806f, 0.0398139569f, 0.0417666458f, 0.0438027210f, 0.0459314689f, 0.0481532079f, + 0.0504618496f, 0.0528498740f, 0.0553180491f, 0.0578703090f, 0.0604788669f, 0.0631374695f, + 0.0659669298f, 0.0688814001f, 0.0718159332f, 0.0747835495f, 0.0777923399f, 0.0808186627f, + 0.0838554308f, 0.0868947517f, 0.0899116089f, 0.0929041126f, 0.0958553537f, 0.0987459119f, + 0.1015756668f, 0.1043243835f, 0.1069774737f, 0.1095164928f, 0.1119302041f, 0.1142027056f, + 0.1163273532f, 0.1182880738f, 0.1200768686f, 0.1216925159f, 0.1231125873f, 0.1243362384f, + 0.1253610086f, 0.1261745561f, 0.1267721689f, 0.1271241769f, 0.1272284850f, 0.1270239254f, + 0.1267589302f, 0.1264656300f, 0.1258046109f, 0.1248336057f, 0.1235525506f, 0.1219504858f, + 0.1200252469f, 0.1177556666f, 0.1151258716f, 0.1121348547f, 0.1087635447f, 0.1050067776f, + 0.1008590143f, 0.0963144136f, 0.0913759079f, 0.0860427416f, 0.0803171444f, 0.0742040884f, + 0.0677045255f, 0.0608146076f, 0.0535432746f, 0.0458874964f, 0.0378425383f, 0.0294132744f, + 0.0205946670f, 0.0113896330f, 0.0018004463f, -0.0081766098f, -0.0185270856f, -0.0292402963f, + -0.0403618604f, -0.0518892622f, -0.0637672152f, -0.0759976007f, -0.0885871716f, -0.1015258403f, + -0.1148084399f, -0.1284318249f, -0.1423873123f, -0.1566679827f, -0.1712634880f, -0.1861645588f, + -0.2013636452f, -0.2168508609f, -0.2326166940f, -0.2486510515f, -0.2649463144f, -0.2814911369f, + -0.2982752192f, -0.3152867427f, -0.3325116487f, -0.3499355632f, -0.3675395959f, -0.3853024154f, + -0.4032065616f, -0.4212350657f, -0.4393672268f, -0.4575772736f, -0.4758650706f, -0.4942431738f, + 0.5125205124f, 0.5306725282f, 0.5488577283f, 0.5670276108f, 0.5851445237f, 0.6031984616f, + 0.6211684103f, 0.6390281696f, 0.6567504157f, 0.6743123793f, 0.6916889535f, 0.7088542063f, + 0.7257845309f, 0.7424591009f, 0.7588584440f, 0.7749648928f, 0.7907617163f, 0.8062324551f, + 0.8213587554f, 0.8361206884f, 0.8504967301f, 0.8644639148f, 0.8779983070f, 0.8910752510f, + 0.9036722755f, 0.9157691951f, 0.9273480313f, 0.9383949141f, 0.9489012228f, 0.9588586337f, + 0.9682545154f, 0.9770929872f, 0.9853708240f, 0.9930809758f, 1.0002174168f, 1.0067717565f, + 1.0127347711f, 1.0180999340f, 1.0228621525f, 1.0270212624f, 1.0305853696f, 1.0335685634f, + 1.0359921286f, 1.0378851378f, 1.0392782898f, 1.0402014380f, 1.0406826783f, 1.0407387739f, + 1.0403729933f, 1.0395784114f, 1.0383296408f, 1.0365863031f, 1.0343061945f, 1.0314399587f, + 1.0279374991f, 1.0237762412f, 1.0189593836f, 1.0135316260f, 1.0076524569f, 1.0021150619f, + 0.9928949328f, 0.9800034826f, 0.9674886109f, 0.9545877700f, 0.9411740407f, 0.9272370892f, + 0.9128016387f, 0.8979145998f, 0.8826491402f, 0.8670774704f, 0.8512639848f, 0.8352705212f, + 0.8191434022f, 0.8029102780f, 0.7865870046f, 0.7701746598f, 0.7536620391f, 0.7370346195f, + 0.7202763550f, 0.7033730373f, 0.6863185156f, 0.6691140098f, 0.6517679660f, 0.6342966925f, + 0.6167195326f, 0.5990562278f, 0.5813252524f, 0.5635402746f, 0.5457078369f, 0.5278295335f, + 0.5099048467f, 0.4919297136f, 0.4738984035f, 0.4558126317f, 0.4376796414f, 0.4195151253f, + 0.4013417258f, 0.3831842053f, 0.3650685616f, 0.3470163688f, 0.3290362900f, 0.3111247009f, + 0.2932627295f, 0.2754121565f, 0.2575267491f, 0.2395585877f, 0.2214602867f, 0.2032086383f, + 0.1848152793f, 0.1663238479f, 0.1478361334f, 0.1295133662f, 0.1115465981f, 0.0941771468f, + 0.0776828916f, 0.0622889538f, 0.0481725935f, 0.0353986404f, 0.0233593568f, 0.0103354077f, +}; + +const float rot_vec_ana_re_L10[5] = +{ + 2.8262465099f,2.6536058227f,2.2212117088f,1.5713899168f,0.7677495312f, +}; + +const float rot_vec_ana_im_L10[5] = +{ + -0.1110435278f,-0.9789668726f,-1.7510621190f,-2.3517512048f,-2.7222344971f, +}; + +const float rot_vec_ana_re_L16[8] = +{ + 2.2353945156f,2.1817362886f,2.0442351594f,1.8281752196f,1.5418595313f,1.1962910459f, + 0.8047497665f,0.3822824048f, +}; + +const float rot_vec_ana_im_L16[8] = +{ + -0.0548758552f,-0.4899252669f,-0.9061471254f,-1.2875462580f,-1.6194657100f,-1.8891500029f, + -2.0862353207f,-2.2031477851f, +}; + +const float rot_vec_ana_re_L20[10] = +{ + 1.9996144810f,1.9688531362f,1.8896120929f,1.7638425287f,1.5946413075f,1.3861747251f, + 1.1435759205f,0.8728184813f,0.5805693545f,0.2740246834f, +}; + +const float rot_vec_ana_im_L20[10] = +{ + -0.0392673849f,-0.3515925599f,-0.6552603591f,-0.9427934737f,-1.2071118839f,-1.4417071934f, + -1.6408028871f,-1.7994965681f,-1.9138806715f,-1.9811386809f, +}; + +const float rot_vec_ana_re_L30[15] = +{ + 1.6328532594f,1.6216739995f,1.5927273399f,1.5463304262f,1.4829915928f,1.4034047932f, + 1.3084419970f,1.1991436365f,1.0767072074f,0.9424741487f,0.7979151461f,0.6446140182f, + 0.4842503641f,0.3185811618f,0.1494215176f, +}; + +const float rot_vec_ana_im_L30[15] = +{ + -0.0213752201f,-0.1919377663f,-0.3603974022f,-0.5249084488f,-0.6836684885f,-0.8349381133f, + -0.9770599813f,-1.1084769757f,-1.2277492644f,-1.3335700753f,-1.4247800133f,-1.5003797633f, + -1.5595410387f,-1.6016156561f,-1.6261426373f, +}; + +const float rot_vec_ana_re_L32[16] = +{ + 1.5810197732f,1.5715049038f,1.5468555830f,1.5073091974f,1.4532466002f,1.3851884438f, + 1.3037901655f,1.2098356752f,1.1042298059f,0.9879896000f,0.8622345142f,0.7281756387f, + 0.5871040336f,0.4403782958f,0.2894114743f,0.1356574621f, +}; + +const float rot_vec_ana_im_L32[16] = +{ + -0.0194030057f,-0.1742766119f,-0.3274718390f,-0.4775133334f,-0.6229561133f,-0.7623994853f, + -0.8945005334f,-1.0179870525f,-1.1316697997f,-1.2344539482f,-1.3253496303f,-1.4034814709f, + -1.4680970178f,-1.5185739878f,-1.5544262602f,-1.5753085580f, +}; + +const float rot_vec_ana_re_L40[20] = +{ + 1.4141454099f,1.4086967623f,1.3945630307f,1.3718313542f,1.3406418813f,1.3011869053f, + 1.2537096794f,1.1985029164f,1.1359069844f,1.0663078081f,0.9901344896f,0.9078566627f, + 0.8199815976f,0.7270510733f,0.6296380373f,0.5283430735f,0.4237906989f,0.3166255137f, + 0.2075082270f,0.0971115830f, +}; + +const float rot_vec_ana_im_L40[20] = +{ + -0.0138837862f,-0.1247935572f,-0.2349339344f,-0.3436258658f,-0.4501992295f,-0.5539969652f, + -0.6543791254f,-0.7507268207f,-0.8424460355f,-0.9289712904f,-1.0097691283f,-1.0843414038f, + -1.1522283539f,-1.2130114331f,-1.2663158934f,-1.3118130952f,-1.3492225330f,-1.3783135652f, + -1.3989068360f,-1.4108753809f, +}; + +const float rot_vec_ana_re_L60[30] = +{ + 1.1546758066f,1.1526978375f,1.1475604038f,1.1392775867f,1.1278720890f,1.1133751723f, + 1.0958265716f,1.0752743865f,1.0517749490f,1.0253926695f,0.9961998600f,0.9642765358f, + 0.9297101968f,0.8925955867f,0.8530344341f,0.8111351735f,0.7670126477f,0.7207877935f, + 0.6725873102f,0.6225433117f,0.5707929653f,0.5174781151f,0.4627448933f,0.4067433200f, + 0.3496268915f,0.2915521599f,0.2326783042f,0.1731666934f,0.1131804447f,0.0528839763f, +}; + +const float rot_vec_ana_im_L60[30] = +{ + -0.0075574434f,-0.0679781487f,-0.1282125306f,-0.1880954908f,-0.2474628944f,-0.3061520194f, + -0.3640020030f,-0.4208542824f,-0.4765530295f,-0.5309455779f,-0.5838828413f,-0.6352197224f, + -0.6848155104f,-0.7325342668f,-0.7782451976f,-0.8218230124f,-0.8631482675f,-0.9021076931f, + -0.9385945043f,-0.9725086932f,-1.0037573034f,-1.0322546845f,-1.0579227273f,-1.0806910775f, + -1.1004973285f,-1.1172871929f,-1.1310146507f,-1.1416420760f,-1.1491403397f,-1.1534888896f, +}; + + + +const float rot_vec_syn_re_L10[5] = +{ + 0.1117172025f,0.1048929802f,0.0878011021f,0.0621146404f,0.0303479649f, +}; + +const float rot_vec_syn_im_L10[5] = +{ + -0.0043893808f,-0.0386970634f,-0.0692168078f,-0.0929611287f,-0.1076057667f, +}; + +const float rot_vec_syn_re_L16[8] = +{ + 0.1117697258f,0.1090868144f,0.1022117580f,0.0914087610f,0.0770929766f,0.0598145523f, + 0.0402374883f,0.0191141202f, +}; + +const float rot_vec_syn_im_L16[8] = +{ + -0.0027437928f,-0.0244962633f,-0.0453073563f,-0.0643773129f,-0.0809732855f,-0.0944575001f, + -0.1043117660f,-0.1101573893f, +}; + +const float rot_vec_syn_re_L20[10] = +{ + 0.1117818477f,0.1100622363f,0.1056325273f,0.0986017949f,0.0891431591f,0.0774895228f, + 0.0639278374f,0.0487920364f,0.0324548136f,0.0153184455f, +}; + +const float rot_vec_syn_im_L20[10] = +{ + -0.0021951135f,-0.0196546216f,-0.0366301676f,-0.0527037574f,-0.0674796057f,-0.0805938822f, + -0.0917236698f,-0.1005949163f,-0.1069891821f,-0.1107490191f, +}; + +const float rot_vec_syn_re_L30[15] = +{ + 0.1117938204f,0.1110284288f,0.1090465865f,0.1058700070f,0.1015334935f,0.0960845578f, + 0.0895828996f,0.0820997524f,0.0737171032f,0.0645267939f,0.0546295156f,0.0441337048f, + 0.0331543560f,0.0218117611f,0.0102301920f, +}; + +const float rot_vec_syn_im_L30[15] = +{ + -0.0014634613f,-0.0131410805f,-0.0246747234f,-0.0359380248f,-0.0468075816f,-0.0571643048f, + -0.0668947240f,-0.0758922305f,-0.0840582459f,-0.0913033015f,-0.0975480191f,-0.1027239802f, + -0.1067744758f,-0.1096551279f,-0.1113343755f, +}; + +const float rot_vec_syn_re_L32[16] = +{ + 0.1117949803f,0.1111221774f,0.1093792072f,0.1065828555f,0.1027600526f,0.0979476142f, + 0.0921918867f,0.0855483010f,0.0780808384f,0.0698614146f,0.0609691872f,0.0514897932f, + 0.0415145243f,0.0311394479f,0.0204644816f,0.0095924311f, +}; + +const float rot_vec_syn_im_L32[16] = +{ + -0.0013719997f,-0.0123232174f,-0.0231557558f,-0.0337652916f,-0.0440496492f,-0.0539097846f, + -0.0632507393f,-0.0719825548f,-0.0800211389f,-0.0872890758f,-0.0937163711f,-0.0992411265f, + -0.1038101357f,-0.1073793965f,-0.1099145349f,-0.1113911364f, +}; + +const float rot_vec_syn_re_L40[20] = +{ + 0.1117980110f,0.1113672575f,0.1102498879f,0.1084527911f,0.1059870468f,0.1028678571f, + 0.0991144528f,0.0947499750f,0.0898013320f,0.0842990340f,0.0782770044f,0.0717723711f, + 0.0648252372f,0.0574784342f,0.0497772575f,0.0417691875f,0.0335035965f,0.0250314447f, + 0.0164049658f,0.0076773447f, +}; + +const float rot_vec_syn_im_L40[20] = +{ + -0.0010976097f,-0.0098657969f,-0.0185731583f,-0.0271660100f,-0.0355913742f,-0.0437973057f, + -0.0517332122f,-0.0593501664f,-0.0666012069f,-0.0734416290f,-0.0798292589f,-0.0857247149f, + -0.0910916496f,-0.0958969739f,-0.1001110615f,-0.1037079311f,-0.1066654069f,-0.1089652549f, + -0.1105932959f,-0.1115394925f, +}; + +const float rot_vec_syn_re_L60[30] = +{ + 0.1118010042f,0.1116094882f,0.1111120583f,0.1103100780f,0.1092057454f,0.1078020875f, + 0.1061029516f,0.1041129948f,0.1018376715f,0.0992832183f,0.0964566367f,0.0933656741f, + 0.0900188027f,0.0864251961f,0.0825947039f,0.0785378255f,0.0742656803f,0.0697899780f, + 0.0651229863f,0.0602774970f,0.0552667912f,0.0501046030f,0.0448050816f,0.0393827526f, + 0.0338524782f,0.0282294165f,0.0225289799f,0.0167667930f,0.0109586494f,0.0051204690f, +}; + +const float rot_vec_syn_im_L60[30] = +{ + -0.0007317463f,-0.0065819559f,-0.0124141249f,-0.0182122676f,-0.0239604917f,-0.0296430418f, + -0.0352443424f,-0.0407490407f,-0.0461420487f,-0.0514085845f,-0.0565342130f,-0.0615048852f, + -0.0663069767f,-0.0709273254f,-0.0753532672f,-0.0795726710f,-0.0835739716f,-0.0873462018f, + -0.0908790221f,-0.0941627493f,-0.0971883830f,-0.0999476301f,-0.1024329276f,-0.1046374636f, + -0.1065551956f,-0.1081808673f,-0.1095100227f,-0.1105390187f,-0.1112650350f,-0.1116860815f, +}; + + +const float bpf_weights_16[CLDFB_NO_COL_MAX] = +{ + 1.000040f, 0.702561f, 0.208838f, 0.001553f, 0.001777f, 0.001370f, 0.000926f, 0.000554f, + 0.000270f, 0.000080f, 0.000030f, 0.000082f, 0.000081f, 0.000052f, 0.000017f, 0.000016f +}; + +/*-------------------------------------------------------------------* + * LP CNG excitation details code book + *-------------------------------------------------------------------*/ +const float CNG_details_codebook[64][NUM_ENV_CNG]= +{ + { + 6.924306f,8.544082f,9.583108f,8.550549f,7.972679f,7.363361f,8.439027f,7.487016f, + 9.149983f,8.352748f,8.823824f,9.544188f,8.314853f,7.809112f,7.218567f,8.612295f, + 7.780142f,7.232745f,6.965988f,7.568601f + }, + { + 9.374340f,7.795641f,7.379285f,8.396346f,9.895033f,10.221931f,10.015446f,10.087706f, + 10.536375f,10.581183f,10.733459f,10.821303f,10.822197f,10.777159f,10.746262f,10.936824f, + 10.820635f,10.881506f,9.992537f,8.925898f + }, + { + 8.260058f,8.387338f,7.832300f,9.092162f,8.387571f,7.401807f,7.888559f,7.678440f, + 8.136854f,8.515383f,8.772667f,9.228788f,8.836490f,9.518608f,8.908790f,9.499302f, + 9.932305f,10.237994f,10.133189f,8.193151f + }, + { + 10.124639f,10.788106f,10.767182f,10.692019f,10.830482f,9.359397f,10.431694f,11.161179f, + 10.356518f,10.541230f,8.185465f,8.116880f,11.338371f,10.284152f,10.511218f,10.880645f, + 10.220743f,11.179196f,11.066867f,10.445066f + }, + { + 9.726912f,9.842380f,10.314793f,10.252558f,10.717097f,10.746290f,9.953682f,10.412869f, + 9.836176f,8.674436f,7.351096f,7.309156f,7.246638f,6.955070f,7.846981f,9.111964f, + 9.612611f,8.519944f,9.454450f,9.249232f + }, + { + 10.298511f,10.439103f,10.451839f,9.763371f,10.337607f,10.939195f,10.938910f,10.824776f, + 10.976114f,10.974276f,10.754051f,10.581675f,10.222703f,9.126027f,8.198234f,7.695039f, + 6.968823f,7.457246f,9.904172f,9.612813f + }, + { + 9.908430f,10.124971f,10.253873f,8.625096f,8.128853f,8.701863f,10.346726f,10.291558f, + 8.935132f,9.638033f,10.793781f,10.670537f,10.681151f,10.410478f,10.512748f,10.861156f, + 10.653567f,10.911621f,10.629312f,9.736268f + }, + { + 11.810060f,11.612185f,11.468822f,11.083865f,11.406177f,11.832067f,11.661546f,11.277926f, + 7.555347f,8.622866f,12.176802f,10.751250f,10.721958f,9.523929f,9.626828f,11.701570f, + 11.848139f,10.849975f,11.640839f,11.392167f + }, + { + 8.572747f,8.869074f,8.680323f,9.760900f,10.671435f,9.673125f,9.516179f,10.428748f, + 10.353197f,10.692994f,11.081258f,10.146167f,10.790188f,10.432859f,9.273769f,7.979839f, + 8.209611f,9.644866f,8.476103f,10.683167f + }, + { + 8.595222f,7.301031f,8.322734f,11.874195f,11.543133f,10.814659f,12.073861f,11.818481f, + 11.602201f,12.035087f,11.952577f,12.363761f,12.167592f,12.254158f,12.108662f,12.373547f, + 11.860260f,9.014181f,10.036099f,8.638621f + }, + { + 10.275646f,10.526311f,10.252750f,10.178793f,10.466885f,9.088381f,9.273152f,8.119694f, + 7.295121f,7.350810f,8.158489f,9.209213f,9.370357f,9.310070f,9.168746f,9.856857f, + 10.187559f,10.613888f,10.080095f,10.451872f + }, + { + 12.318529f,11.945473f,12.303066f,12.451133f,12.272326f,12.478561f,12.303981f,12.279855f, + 12.189694f,10.818603f,10.013278f,8.600300f,7.832378f,8.014066f,11.346451f,11.673646f, + 10.466306f,10.728513f,11.475281f,12.085626f + }, + { + 10.014422f,10.218554f,10.442979f,10.508470f,10.393559f,10.661362f,10.757983f,10.689740f, + 10.897243f,10.382886f,10.379339f,9.271018f,8.495484f,7.720114f,7.161139f,8.396199f, + 9.721141f,10.159747f,9.918998f,9.919149f + }, + { + 11.034192f,11.766760f,11.903868f,11.195253f,11.683506f,11.900399f,12.318353f,12.368064f, + 12.271189f,12.306809f,12.485785f,12.136335f,12.220796f,11.960956f,11.879458f,11.099092f, + 11.004694f,7.854421f,8.103326f,11.485018f + }, + { + 11.692872f,12.115354f,12.250820f,9.919422f,11.204221f,7.870928f,8.415102f,9.997985f, + 11.942008f,12.149603f,10.633919f,11.269428f,12.354749f,12.288899f,12.291698f,12.195188f, + 12.179792f,12.030136f,12.092098f,12.207270f + }, + { + 11.755179f,8.064263f,9.749080f,12.185180f,11.136729f,11.763196f,8.889953f,8.555951f, + 12.034410f,12.245128f,11.697193f,11.559429f,10.780444f,11.789196f,12.130393f,11.689948f, + 11.623942f,11.399507f,11.981954f,10.904933f + }, + { + 7.074471f,7.358261f,8.067513f,8.080610f,8.765159f,10.199254f,10.289200f,9.618623f, + 9.822992f,9.500810f,10.655619f,10.906424f,10.611357f,10.641397f,10.077725f,9.173571f, + 9.274541f,8.160206f,7.797956f,7.321218f + }, + { + 9.641497f,8.341463f,7.913689f,9.615902f,12.212582f,12.373892f,11.788377f,12.044415f, + 11.569188f,12.302634f,12.361569f,12.119579f,12.223657f,12.303328f,12.384604f,12.306796f, + 12.109153f,12.154896f,10.165297f,11.492375f + }, + { + 10.334753f,9.264669f,7.656600f,7.729103f,7.665664f,7.728192f,8.657525f,10.255910f, + 10.287778f,9.540968f,9.808374f,10.307826f,10.623036f,10.579712f,10.909159f,10.597071f, + 10.508566f,10.917792f,10.740663f,10.609496f + }, + { + 12.464439f,12.387059f,12.281745f,12.415715f,12.481938f,12.064619f,12.051270f,10.871007f, + 9.753584f,8.710700f,7.918756f,8.510613f,11.316961f,11.829647f,11.667075f,12.037048f, + 12.184728f,12.269155f,12.388278f,12.256269f + }, + { + 10.985455f,10.863164f,10.984641f,11.150430f,10.892216f,10.949295f,10.885633f,9.861358f, + 9.347205f,7.782274f,7.420996f,7.042737f,7.859407f,9.545682f,10.120652f,10.378402f, + 10.381286f,10.677829f,10.603589f,10.744861f + }, + { + 11.619549f,10.501878f,10.291579f,11.911536f,12.263100f,11.638079f,11.827111f,11.886570f, + 11.885740f,11.982909f,11.279054f,11.820845f,11.897547f,11.508306f,10.922131f,7.355962f, + 9.090330f,12.035433f,11.309077f,11.814055f + }, + { + 12.109969f,11.648486f,8.360036f,10.628968f,8.450899f,8.016151f,10.885192f,11.289871f, + 11.616718f,11.618735f,12.016033f,11.572757f,11.580486f,11.526383f,12.019007f,12.063487f, + 12.178980f,11.612581f,11.149741f,11.315678f + }, + { + 11.982289f,12.039945f,10.895576f,11.808078f,11.972691f,11.752888f,11.100145f,7.459962f, + 9.401170f,12.240148f,11.661579f,11.968470f,10.817088f,11.060538f,12.236608f,12.217974f, + 11.888335f,12.158744f,12.290771f,12.263520f + }, + { + 7.551557f,9.193432f,10.939713f,10.390559f,10.388751f,10.007786f,10.151727f,11.200849f, + 10.927567f,11.044189f,10.805322f,10.912845f,10.931647f,10.806228f,10.434938f,10.151430f, + 9.517872f,9.532900f,8.436217f,7.561033f + }, + { + 7.914798f,9.662442f,12.315506f,11.969525f,11.779161f,10.819254f,11.074059f,12.259423f, + 12.310757f,12.028122f,12.393316f,12.259255f,12.478424f,12.251179f,11.982938f,12.119265f, + 12.321500f,11.854281f,11.885189f,7.733390f + }, + { + 11.074573f,11.119295f,11.026623f,10.587306f,10.326489f,9.440902f,7.861374f,7.502906f, + 10.206084f,10.379787f,10.375632f,9.986627f,9.698876f,10.544230f,10.857472f,10.772952f, + 11.004036f,10.641294f,11.111090f,11.084974f + }, + { + 12.312282f,11.569094f,12.027453f,11.997540f,12.050622f,12.124397f,11.441438f,11.697535f, + 11.553439f,11.941341f,11.153276f,7.695126f,8.494260f,12.226931f,11.163250f,11.056936f, + 11.197067f,8.736544f,11.552220f,11.995921f + }, + { + 11.841222f,12.040383f,12.323356f,12.164479f,12.146215f,12.485503f,12.354469f,12.261094f, + 12.176959f,12.164176f,11.750998f,10.552405f,11.221596f,7.971972f,7.827245f,9.382548f, + 11.354092f,11.724841f,11.744237f,11.836000f + }, + { + 11.863342f,11.946292f,10.565049f,10.276701f,12.088562f,11.987997f,11.516201f,11.701505f, + 12.013391f,12.254663f,12.160517f,11.530292f,11.789889f,12.011831f,12.307916f,11.817711f, + 7.388736f,8.277118f,12.146955f,11.330376f + }, + { + 10.445749f,10.383992f,11.260086f,10.207924f,7.801878f,12.093586f,12.186577f,12.208809f, + 11.981275f,8.760727f,10.776209f,11.675901f,11.273578f,12.169944f,11.829489f,11.361869f, + 11.931891f,11.640718f,12.033961f,11.504183f + }, + { + 11.418176f,11.996329f,11.634505f,12.108740f,12.232028f,12.223016f,11.168437f,11.585357f, + 12.287769f,10.519855f,11.961341f,12.135221f,11.941004f,11.400546f,12.083041f,12.021441f, + 12.087834f,12.196712f,12.153121f,11.933741f + }, + { + 8.696248f,7.886807f,8.518339f,9.431623f,10.314435f,10.492967f,9.433606f,9.312992f, + 9.056099f,9.558634f,9.174564f,8.692657f,8.529263f,9.327991f,8.283659f,7.715106f, + 6.828506f,7.494133f,8.531253f,8.664100f + }, + { + 8.749990f,9.185427f,7.974370f,7.730459f,9.471635f,11.246136f,11.225875f,11.585999f, + 11.810496f,11.799830f,11.983171f,12.095557f,12.123705f,12.150494f,12.057273f,12.058468f, + 12.128398f,12.119547f,11.788305f,9.252466f + }, + { + 10.620537f,10.064924f,9.681692f,9.556549f,8.067345f,7.460412f,7.355683f,7.793144f, + 7.842898f,9.346528f,10.380497f,9.183150f,10.255505f,10.654870f,10.772358f,10.480097f, + 10.444176f,10.506150f,10.650716f,10.807790f + }, + { + 11.832230f,12.163531f,12.210456f,12.488221f,12.106194f,11.716965f,12.486103f,11.839725f, + 12.333147f,12.101274f,7.643279f,9.040410f,12.480962f,11.550027f,12.089822f,11.299880f, + 10.714154f,12.309387f,12.290308f,12.153176f + }, + { + 11.011459f,10.708299f,10.217109f,10.618895f,10.503453f,10.618390f,10.261137f,9.054105f, + 8.967848f,9.665904f,9.986521f,8.089101f,7.524849f,8.521540f,10.395278f,9.179631f, + 8.431019f,9.362102f,9.471244f,10.168259f + }, + { + 11.385670f,11.988930f,11.979943f,12.082343f,12.240467f,12.163774f,12.389517f,12.076717f, + 12.254186f,12.165658f,11.824725f,11.992508f,10.716744f,10.217215f,10.610125f,8.819359f, + 7.553169f,8.576138f,7.663194f,8.161689f + }, + { + 11.335433f,10.824145f,11.164507f,9.187079f,8.159495f,9.823243f,11.259155f,10.102992f, + 10.894949f,10.692467f,9.597807f,11.322961f,11.068228f,10.523948f,11.179681f,11.389847f, + 11.204894f,11.328845f,10.761085f,11.533332f + }, + { + 12.452473f,12.226961f,12.414132f,12.453005f,12.224496f,11.829764f,9.932276f,9.747059f, + 7.944996f,8.074952f,10.982581f,11.711254f,11.656355f,11.826878f,12.063810f,12.048336f, + 12.100821f,12.339723f,12.171370f,12.491159f + }, + { + 8.693851f,9.237082f,10.193584f,10.816728f,11.382530f,11.124274f,10.905251f,10.747824f, + 11.006325f,11.224193f,11.377479f,11.195903f,11.132830f,10.824033f,11.188758f,8.716391f, + 7.654446f,8.441257f,9.691014f,10.598401f + }, + { + 8.319717f,9.639095f,12.133827f,12.102556f,11.919735f,12.334815f,11.993119f,12.259864f, + 12.158967f,12.356464f,12.374672f,12.379640f,12.396713f,12.146963f,12.203291f,11.311678f, + 8.605060f,10.391322f,8.431939f,7.948593f + }, + { + 11.088415f,10.884553f,11.032227f,11.202397f,10.523194f,10.606202f,9.688022f,9.082882f, + 8.526981f,7.401042f,8.779226f,10.680804f,10.619134f,10.539470f,10.309608f,10.253415f, + 10.965061f,10.624226f,10.946682f,11.063556f + }, + { + 12.049884f,12.395158f,12.315166f,12.298508f,12.409452f,12.353070f,12.369121f,12.232027f, + 12.363715f,12.371237f,11.460312f,12.028971f,8.312684f,8.200596f,10.810326f,11.885057f, + 12.140730f,11.769361f,11.470847f,11.374696f + }, + { + 11.318600f,10.855831f,10.592196f,10.190356f,10.852498f,11.480312f,10.896217f,11.130247f, + 11.148643f,11.272378f,10.871895f,11.095495f,8.893303f,9.083083f,8.899607f,8.150163f, + 10.035096f,11.004933f,11.685496f,11.349737f + }, + { + 12.437282f,11.779876f,12.273005f,12.224300f,11.436580f,12.714269f,12.546281f,12.410135f, + 12.488817f,12.347595f,12.661417f,12.587544f,12.405058f,12.452996f,11.808998f,11.644467f, + 11.697278f,7.908151f,11.580981f,12.178329f + }, + { + 12.383582f,11.978909f,12.263449f,12.181010f,11.308676f,10.129762f,7.630591f,11.672964f, + 12.255041f,12.043112f,12.393015f,11.554902f,11.858689f,12.585340f,12.405621f,12.438987f, + 12.422440f,12.429326f,12.518377f,12.596020f + }, + { + 12.294228f,7.930717f,10.000073f,12.115003f,11.276157f,12.374399f,12.087711f,11.020492f, + 12.205840f,12.519583f,12.094537f,12.497026f,12.274739f,12.595242f,12.627252f,12.238583f, + 12.414072f,12.458577f,12.250254f,12.212063f + }, + { + 10.220644f,10.133038f,9.384470f,9.330061f,9.287414f,10.419335f,10.086744f,10.347366f, + 9.606766f,9.729086f,10.175982f,10.490002f,10.450778f,10.530566f,10.662402f,10.198713f, + 9.756838f,7.568992f,7.395587f,10.386068f + }, + { + 12.338935f,11.958341f,7.484207f,8.228665f,11.650372f,11.382147f,12.027068f,11.762714f, + 11.266207f,12.095256f,12.402075f,12.538692f,12.335326f,12.212730f,12.551470f,12.419568f, + 11.941353f,12.565509f,12.164819f,12.121121f + }, + { + 11.530771f,10.926392f,10.037753f,7.947472f,8.046108f,7.827244f,7.274969f,9.599776f, + 10.971369f,9.563985f,10.664629f,11.255960f,10.737041f,11.198854f,11.004945f,11.547729f, + 11.150601f,11.446258f,11.272099f,11.224279f + }, + { + 12.154252f,12.426224f,12.362570f,12.276526f,11.848105f,12.233492f,12.238678f,11.606319f, + 11.630966f,8.226843f,8.663989f,12.324718f,11.910058f,11.977910f,11.282999f,11.276901f, + 12.135061f,12.316558f,12.126414f,12.222776f + }, + { + 10.840468f,10.882261f,10.935246f,10.880699f,11.083740f,11.099067f,10.870871f,10.768135f, + 10.532293f,10.338410f,9.085450f,8.402101f,7.755022f,9.959888f,10.061506f,10.644034f, + 10.614702f,10.481884f,10.760615f,11.004514f + }, + { + 12.122748f,12.306721f,11.587852f,12.430750f,12.175253f,11.815797f,12.308073f,12.320755f, + 12.218995f,12.463879f,12.424328f,12.559034f,12.042230f,11.765315f,8.922847f,9.539627f, + 7.874360f,8.521064f,9.272277f,12.165272f + }, + { + 12.485865f,11.205798f,11.664264f,10.653128f,7.610178f,8.947474f,11.966330f,12.100983f, + 12.107791f,11.909583f,11.112039f,12.535769f,12.489249f,12.444782f,12.346417f,12.296227f, + 12.534035f,12.334972f,12.077379f,12.275601f + }, + { + 12.425206f,12.450086f,12.341137f,12.568719f,12.320243f,12.361140f,12.099853f,11.035367f, + 8.319082f,12.032015f,12.280725f,11.606254f,12.321961f,11.066000f,11.799191f,12.266534f, + 12.556672f,12.545979f,12.602019f,12.030170f + }, + { + 8.871724f,11.287228f,11.532060f,10.621922f,11.143099f,10.988887f,10.820709f,11.695601f, + 10.989671f,11.008445f,11.567303f,11.250048f,11.122625f,9.865336f,9.707122f,11.365924f, + 11.399251f,11.287416f,8.975295f,9.569743f + }, + { + 9.780970f,11.908114f,11.473997f,12.024678f,11.860840f,11.723680f,12.367899f,12.108915f, + 12.340000f,12.381660f,12.315555f,12.282724f,12.359691f,11.991398f,12.220946f,12.155458f, + 12.413619f,11.642963f,7.867479f,8.503173f + }, + { + 12.100057f,12.246774f,12.168076f,11.771790f,10.224229f,8.752139f,8.276130f,8.317601f, + 8.677964f,10.925248f,11.599258f,10.861567f,11.187905f,11.979478f,12.035626f,12.058556f, + 12.150581f,12.192816f,12.171208f,12.225122f + }, + { + 12.205771f,12.205347f,12.351176f,12.237871f,12.382323f,12.461397f,12.301606f,12.369697f, + 11.959662f,11.558475f,10.953750f,8.388442f,8.819866f,12.077829f,11.983337f,11.818386f, + 12.286803f,12.458479f,12.329653f,12.507854f + }, + { + 11.530513f,11.199886f,12.487312f,12.406390f,12.054689f,12.255518f,12.097314f,12.346512f, + 12.310920f,11.682766f,12.332119f,12.015944f,11.992967f,11.917038f,7.877818f,9.167294f, + 12.226696f,11.735081f,12.256387f,11.444395f + }, + { + 12.132508f,12.328980f,11.918468f,12.068428f,12.493188f,12.275755f,12.524507f,12.294735f, + 12.582710f,12.488275f,12.132201f,12.076183f,12.373331f,11.888222f,11.716764f,10.961454f, + 8.318602f,11.632863f,12.609443f,11.484080f + }, + { + 11.948422f,12.164044f,11.930634f,7.560744f,9.486037f,12.354504f,11.826571f,11.874330f, + 10.939306f,10.727631f,12.333044f,12.133337f,12.172671f,12.228312f,12.004416f,12.354714f, + 12.154241f,11.830939f,12.245022f,12.033812f + }, + { + 12.494522f,12.883386f,12.105121f,12.216132f,12.821167f,10.613010f,12.572326f,12.881424f, + 11.754890f,12.876678f,12.439420f,12.258423f,12.945374f,12.765532f,12.874741f,12.539070f, + 12.711823f,12.611643f,11.904738f,12.176199f + } +}; +/*-------------------------------------------------------------------* + * FD CNG + *-------------------------------------------------------------------*/ + +const int d_array[18] = { 1, 2, 5, 8, 10, 15, 20, 30, 40, 60, 80, 120, 140, 160, 180, 220, 260, 300 }; +const float m_array[18] = { 0.000f, 0.260f, 0.480f, 0.580f, 0.610f, 0.668f, 0.705f, 0.762f, 0.800f, 0.841f, 0.865f, 0.890f, 0.900f, 0.910f, 0.920f, 0.930f, 0.935f, 0.940f }; + +const float msQeqInvAv_thresh[3] = { 0.01f, 0.03f, 0.05f }; +const float msNoiseSlopeMax[4] = { 2.f, 1.6f, 1.3f, 1.1f }; + +const SCALE_SETUP scaleTable[20] = +{ + { 0, 0, 8000, -5.5f }, + { 0, 8000, 9600, -5.0f }, + { 0, 9600, 13200, -4.0f }, + { 0, 13200, 16400, -3.0f }, + { 0, 16400, 24400, -1.5f }, + { 0, 24400,128001, -0.5f }, + + { 1, 0, 8000, -5.5f }, + { 1, 8000, 9600, -5.0f }, + { 1, 9600, 13200, -1.55f}, + { 1, 13200, 16400, -3.0f }, + { 1, 16400, 24400, -0.6f }, + { 1, 24400, 32000, -0.2f }, + { 1, 32000,128001, 0.0f }, + + { 2, 0, 8000, -0.9f }, + { 2, 8000, 9600, -0.65f}, + { 2, 9600, 13200, -2.0f }, + { 2, 13200, 16400, -3.0f }, + { 2, 16400, 24400, -0.8f }, + { 2, 24400, 32000, -0.25f}, + { 2, 32000,128001, 0.0f }, +}; + +const SCALE_SETUP scaleTable_cn_only[18] = +{ + { 0, 0, 8000, -3.5f }, + { 0, 8000, 9600, -3.0f }, + { 0, 9600, 13200, -2.5f }, + { 0, 13200,16400, -2.0f }, + { 0, 16400,128001, 0.0f }, + + { 1, 0, 8000, -3.0f }, + { 1, 8000, 9600, -2.5f }, + { 1, 9600, 13200, -1.5f }, + { 1, 13200, 16400, -2.5f }, + { 1, 16400, 24400, -0.5f }, + { 1, 24400, 128001, 0.0f }, + + { 2, 0, 8000, -2.5f }, + { 2, 8000, 9600, -2.5f }, + { 2, 9600, 13200, -2.0f }, + { 2, 13200, 16400, -1.0f }, + + { 2, 16400, 24400, -0.5f }, + { 2, 24400, 32000, 0.0f }, + { 2, 32000,128001, 0.0f }, +}; +const float scaleTable_cn_only_amrwbio[3][2] = +{ + { ACELP_6k60, -4.0f }, + { ACELP_8k85, -3.0f }, + { ACELP_12k65, -2.0f }, +}; + + +const int 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 int sidPartitions_nb[] = { 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 58, 68, 80, 92, 108, 126, 159 }; +const int sidPartitions_wb1[] = { 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 58, 68, 80, 92, 108, 126, 148, 176, 212, 255 }; +const int sidPartitions_wb2[] = { 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 58, 68, 80, 92, 108, 126, 148, 176, 212, 255, 259 }; +const int sidPartitions_wb3[] = { 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 58, 68, 80, 92, 108, 126, 148, 176, 212, 255, 319 }; +const int 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 int 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 int 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 int 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 int 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 int 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 int 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 int 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(int), sidPartitions_nb, sizeof(shapingPartitions_nb)/sizeof(int), shapingPartitions_nb }; +const FD_CNG_SETUP FdCngSetup_wb1 = { 512, 256, sizeof(sidPartitions_wb1)/sizeof(int), sidPartitions_wb1, sizeof(shapingPartitions_wb1)/sizeof(int), shapingPartitions_wb1 }; +const FD_CNG_SETUP FdCngSetup_wb2 = { 512, 256, sizeof(sidPartitions_wb2)/sizeof(int), sidPartitions_wb2, sizeof(shapingPartitions_wb2)/sizeof(int), shapingPartitions_wb2 }; +const FD_CNG_SETUP FdCngSetup_wb3 = { 640, 320, sizeof(sidPartitions_wb3)/sizeof(int), sidPartitions_wb3, sizeof(shapingPartitions_wb3)/sizeof(int), shapingPartitions_wb3 }; +const FD_CNG_SETUP FdCngSetup_swb1 = { 512, 256, sizeof(sidPartitions_swb1)/sizeof(int), sidPartitions_swb1, sizeof(shapingPartitions_swb1)/sizeof(int), shapingPartitions_swb1 }; +const FD_CNG_SETUP FdCngSetup_swb2 = { 640, 320, sizeof(sidPartitions_swb2)/sizeof(int), sidPartitions_swb2, sizeof(shapingPartitions_swb2)/sizeof(int), shapingPartitions_swb2 }; + + +const short maxN_37bits = 24; +const short maxC_37bits = 8; +const short stages_37bits = 6; +const int levels_37bits[6] = { 128, 64, 64, 64, 64, 64 }; +const short bits_37bits[6] = { 7, 6, 6, 6, 6, 6 }; + +const float cdk_37bits_1[3072] = +{ + 2.95778982f , 10.56049102f , 13.09386355f , 11.08385962f , 10.88871781f , 10.92789554f , 9.47024852f , 7.50377851f , 7.19700973f , 4.42757028f , 1.25511814f , -2.60106001f , -6.04950165f , -7.63603604f , -10.41446639f , -11.12590625f , -13.84344441f , -18.68891181f , -23.55780389f , -29.45805147f , -31.65253302f , -32.27424892f , -35.22751137f , -36.90949842f , + 17.21398978f , 22.50723507f , 17.78339684f , 15.22053850f , 11.61821405f , 7.94613723f , 7.75072026f , 6.23305331f , 5.76430087f , 4.13707869f , 0.16499081f , -2.39493762f , -1.55086212f , -3.50433708f , -8.18443711f , -11.97061123f , -16.00947999f , -20.53183145f , -25.24387497f , -29.42436369f , -32.38843392f , -36.11523183f , -39.31249120f , -40.92553153f , + 16.16413908f , 12.51338319f , 10.81668845f , 7.51107282f , 8.58783122f , 9.70942586f , 8.90484747f , 7.74361213f , 8.38927229f , 6.09180806f , 2.25606211f , -1.80804139f , -5.77866789f , -6.64266134f , -10.11888694f , -12.07031815f , -15.26437992f , -20.26969656f , -25.12160881f , -31.11024903f , -33.35847205f , -33.13640725f , -35.95124987f , -37.90657962f , + 33.31978298f , 27.26394617f , 24.25514764f , 20.23232332f , 16.65548737f , 15.67786748f , 13.12878045f , 12.68415364f , 8.46975797f , 6.86052690f , 1.44223072f , -3.05984201f , -6.92484285f , -10.16404365f , -13.70298321f , -18.48343165f , -22.58372752f , -26.62074680f , -30.39592772f , -34.37439216f , -36.06769058f , -38.82086191f , -40.35157222f , -41.14327920f , + -10.92203045f , 3.01052036f , 7.74241345f , 9.28295437f , 6.38021756f , 11.19483089f , 9.71179193f , 7.58317778f , 0.03720981f , 2.75397106f , -1.50772774f , -2.01443682f , -2.44887133f , -6.15187538f , -8.81821668f , -8.69151269f , -8.02852922f , -11.09910056f , -13.17097763f , -13.93076356f , -13.66079044f , -16.47777711f , -18.46333278f , -20.06869553f , + 33.16037159f , 28.50574364f , 18.84668394f , 16.14503275f , 12.64238398f , 8.82733160f , 8.27164568f , 6.62567905f , 6.59003037f , 4.47312530f , 0.90824775f , -2.49975515f , -1.08141480f , -3.20431000f , -9.25248952f , -13.89338354f , -18.40719472f , -22.60361057f , -27.04357211f , -31.31499557f , -33.93185338f , -37.43894780f , -40.22405388f , -41.64367850f , + 27.31804653f , 14.89045549f , 10.86226202f , 8.23925819f , 7.20277478f , 6.05860544f , 5.52091762f , 4.91558992f , 4.25466169f , 3.41244595f , 1.84809938f , 0.56793582f , -2.09446303f , -5.61345827f , -7.92063692f , -8.33385890f , -9.81872455f , -14.00821261f , -17.95712781f , -19.97458899f , -22.84515408f , -26.34052831f , -31.61432841f , -36.58172847f , + 41.62594036f , 30.53353379f , 27.89510180f , 24.11265594f , 18.43485443f , 15.64729005f , 13.50845997f , 10.26280433f , 8.91720676f , 5.83154831f , 0.58848737f , -2.93497066f , -7.66347118f , -10.65504548f , -14.43162023f , -17.54532056f , -19.96025099f , -21.34714524f , -24.14933678f , -25.76118364f , -25.95869147f , -27.17577493f , -27.71455668f , -28.20012422f , + -2.78784194f , 8.02032552f , 10.68963597f , 6.42169471f , 8.39643500f , 5.92698403f , 3.72431779f , 2.34240994f , 2.84441568f , 2.28173308f , 0.51005528f , -0.63277332f , -1.88760888f , -3.64699895f , -6.19490118f , -6.91564436f , -6.74837856f , -9.01957311f , -13.08326862f , -15.61846381f , -17.51686622f , -20.98788704f , -24.84189318f , -27.88764499f , + 15.22736138f , 21.67028596f , 22.69998521f , 19.32303652f , 16.57824995f , 14.43971050f , 12.86116984f , 12.06004138f , 8.96691160f , 5.75441483f , 0.69857059f , -2.99592995f , -6.37751956f , -10.52101418f , -13.54087476f , -17.17818777f , -20.74546985f , -23.38284886f , -27.16166346f , -32.39741856f , -34.96265685f , -38.29574314f , -40.21463793f , -40.97396233f , + 9.26133859f , 10.07373727f , 10.66915549f , 8.57462295f , 7.07983445f , 6.08004124f , 5.43616008f , 4.66385278f , 4.13923283f , 3.46291473f , 2.00919193f , 0.41431808f , -2.15659988f , -5.73419766f , -7.77729962f , -8.10963302f , -9.50797759f , -13.76609560f , -17.88454433f , -20.18355620f , -22.78079775f , -26.25300986f , -31.65196065f , -36.72266405f , + 26.92737845f , 27.50669000f , 26.91247977f , 21.31279552f , 16.15678270f , 12.72639800f , 8.67528477f , 8.63540827f , 6.12171634f , 5.39466263f , 2.40935018f , -2.03514541f , -5.98268282f , -9.33268447f , -11.64966136f , -14.87079782f , -16.24856435f , -18.12429449f , -20.78266693f , -23.71237445f , -24.73440188f , -27.34821266f , -28.25918906f , -28.93790683f , + 4.90379335f , 9.93686137f , 10.91780723f , 9.09752074f , 8.60650951f , 8.80459898f , 8.14900070f , 8.09228751f , 4.14934489f , 1.56227390f , 0.22948186f , -2.11175133f , -3.74247153f , -6.07379086f , -7.30507236f , -9.28287821f , -11.07748811f , -12.71211521f , -13.84649241f , -14.34403824f , -15.35123200f , -17.12232100f , -20.33875194f , -23.90062854f , + 34.56400510f , 28.64513545f , 19.89686686f , 16.71498339f , 14.13374646f , 9.59301176f , 8.64527668f , 7.89097544f , 7.45460471f , 4.94035649f , 1.12449009f , -1.91803209f , -2.36876539f , -4.85907115f , -10.96920929f , -15.11783181f , -18.54964139f , -22.92691742f , -27.54026485f , -32.37334407f , -34.34801279f , -37.11646404f , -38.85197445f , -40.08034397f , + 21.85246210f , 14.72764339f , 11.27302628f , 9.14638512f , 8.54804115f , 8.77093797f , 8.12903725f , 8.26861602f , 4.19886932f , 1.54799726f , 0.20257140f , -1.95701999f , -3.69888430f , -6.13502639f , -7.32329151f , -9.38507779f , -11.16665977f , -12.74666897f , -13.89635990f , -14.42352149f , -15.69403582f , -17.31656047f , -20.46657786f , -24.00174177f , + 42.72694479f , 31.23947048f , 24.43494280f , 19.72208465f , 15.30350682f , 10.47491489f , 7.32088994f , 10.21936673f , 9.85497717f , 5.26501746f , 1.65994049f , -1.03290160f , -4.60874619f , -8.54769573f , -14.17151340f , -15.71521704f , -16.02262568f , -18.90844987f , -24.28632557f , -26.72718508f , -27.02265332f , -28.78362362f , -30.43253072f , -32.28558858f , + -0.39765072f , 7.11128294f , 8.77607625f , 6.97094061f , 6.49768999f , 5.29876062f , 5.33292418f , 5.12420845f , 5.06120539f , 3.76514540f , 1.86852875f , 0.36828311f , -2.70182085f , -4.67846439f , -6.65927858f , -8.64219681f , -10.63500087f , -13.14101813f , -15.41381490f , -18.10176174f , -22.39767659f , -26.30065166f , -30.06922086f , -34.02575582f , + 24.65122317f , 23.93886440f , 24.33639262f , 20.20634124f , 14.95533543f , 10.67440066f , 7.90685648f , 7.77227130f , 4.69229603f , 3.94984243f , 1.03135714f , -2.78561381f , -5.59708858f , -8.11252879f , -10.03836955f , -12.17557001f , -12.27299654f , -12.23090635f , -14.81077879f , -18.41474220f , -21.95921345f , -26.31237335f , -28.83347746f , -30.57799152f , + 15.48674375f , 10.58586035f , 8.41258222f , 6.11115928f , 7.26712645f , 7.70076576f , 6.51745234f , 4.83537618f , 3.78315908f , 2.87162280f , 1.60923393f , 0.07194700f , -4.00474978f , -3.57899280f , -6.50550572f , -8.00337288f , -12.56429875f , -16.64572160f , -21.77660604f , -29.00324770f , -29.28924218f , -28.45842093f , -31.46000362f , -33.72961920f , + 31.66756941f , 26.50681469f , 23.07696706f , 19.47940753f , 16.43776948f , 14.65422928f , 13.13762571f , 12.13565647f , 9.05541090f , 5.85409354f , 0.53053075f , -3.03585502f , -6.54517878f , -10.70179318f , -13.64861349f , -17.10229453f , -20.77152138f , -23.04102596f , -26.76284884f , -32.09288570f , -34.95454717f , -38.37953105f , -40.31456890f , -41.06305403f , + -4.57998646f , 6.78815016f , 11.60677893f , 12.12189632f , 10.03649399f , 6.73163226f , 5.60997256f , 3.61382681f , 1.07119505f , 1.44124760f , -0.36649688f , -1.93594310f , -2.67098539f , -3.97236341f , -4.49309238f , -7.67841048f , -7.38721745f , -9.04687595f , -10.64729812f , -12.35782845f , -15.80889240f , -18.10394377f , -20.75255913f , -23.16714596f , + 32.06565538f , 26.34062469f , 17.62317465f , 14.54318257f , 11.33965592f , 7.22380894f , 6.69999570f , 5.16548324f , 5.32078994f , 3.68894995f , 0.21139809f , -1.89643313f , -1.43729232f , -3.38299704f , -8.16315990f , -10.90725548f , -13.86285241f , -19.27930679f , -24.24221687f , -29.37957484f , -32.97371289f , -37.01956565f , -40.64301363f , -42.42283871f , + 27.34861464f , 17.35254831f , 14.71216625f , 11.21480476f , 9.71751794f , 8.92216110f , 7.88950008f , 4.72051984f , 2.08541644f , 1.24484417f , -0.29448212f , -3.22367745f , -4.12078688f , -4.51431029f , -5.02457729f , -7.46382757f , -9.93828200f , -11.94075167f , -14.42548881f , -16.83893529f , -20.57517980f , -23.86145012f , -26.35488436f , -28.09220448f , + 43.77568289f , 30.35391726f , 27.63839793f , 23.39292280f , 18.14120263f , 16.09279111f , 13.38540751f , 10.06671431f , 7.94669649f , 4.12623028f , -0.90332148f , -3.32951717f , -7.24035516f , -10.01970377f , -13.39421641f , -16.33052649f , -18.54117920f , -19.77745925f , -22.77363614f , -24.12093907f , -24.21920369f , -25.28960607f , -25.77614399f , -26.25683024f , + 5.79368652f , 12.51991626f , 14.00370768f , 11.32137999f , 9.77109082f , 8.98151357f , 7.49776119f , 4.79998026f , 2.33448317f , 1.18610607f , -0.35969383f , -2.93257557f , -4.07562790f , -4.76160858f , -5.42531466f , -7.40360649f , -9.61250822f , -11.03547938f , -13.14054419f , -15.06085658f , -17.47288279f , -20.42082642f , -22.95063518f , -25.16468847f , + 16.09302292f , 22.55335432f , 23.75600812f , 20.07565839f , 16.86390794f , 15.22041485f , 13.34925505f , 12.47627523f , 8.78929960f , 6.22941075f , 0.65362548f , -3.19021243f , -6.62717988f , -10.64596960f , -13.82088718f , -17.58372103f , -21.71419292f , -24.30895894f , -26.77314588f , -28.87032013f , -30.13179973f , -31.71459259f , -32.84856396f , -33.50577477f , + 16.44441330f , 12.31360615f , 9.71047235f , 7.21837937f , 6.79215980f , 5.58913206f , 5.23450348f , 5.31837117f , 5.47119664f , 3.91860558f , 2.00713858f , 0.29754081f , -2.62407946f , -4.75220497f , -6.96490868f , -9.09693835f , -11.19050998f , -13.60732328f , -15.96794842f , -18.87093112f , -23.15019536f , -27.14449468f , -31.05584505f , -35.00208930f , + 21.56078764f , 25.60904841f , 27.31524375f , 24.74664217f , 19.15754045f , 16.48262030f , 13.62284337f , 10.32185769f , 7.82788054f , 4.56867787f , -0.55500429f , -3.54399244f , -7.74464129f , -10.04653026f , -13.91638701f , -16.89276027f , -19.28210045f , -21.11725885f , -23.80905063f , -25.61468851f , -25.54369860f , -26.75644280f , -27.40565527f , -27.80349551f , + 11.75649526f , 11.59267300f , 11.85607639f , 12.09984636f , 10.17904946f , 6.68242306f , 5.49769393f , 3.62565532f , 1.04153359f , 1.37348105f , -0.36614776f , -1.85988088f , -2.65180489f , -3.95188781f , -4.54582064f , -7.65185164f , -7.37260518f , -8.94498668f , -10.57379044f , -12.29831281f , -15.91573373f , -18.15620068f , -20.77255846f , -23.17991063f , + 35.63174061f , 30.87426279f , 20.05864161f , 16.98958650f , 13.11156738f , 9.37587068f , 8.39373792f , 6.91457513f , 7.06726843f , 4.45504564f , 0.31410924f , -2.55476072f , -1.55052341f , -3.58183174f , -10.02850753f , -13.83773408f , -18.07893844f , -21.87127412f , -26.40618053f , -30.05923316f , -32.16211735f , -34.97392895f , -36.96538585f , -38.31916152f , + 22.45827967f , 18.85001245f , 13.60039332f , 10.10815816f , 9.34790218f , 6.59206524f , 5.06185868f , 4.27885917f , 3.12432252f , 2.43301895f , 0.16458112f , -0.87956151f , -3.52884867f , -4.30776590f , -5.96584396f , -7.24696688f , -9.07355786f , -10.64880142f , -12.04156041f , -13.57831230f , -16.13223545f , -19.28691238f , -20.73379126f , -22.35985284f , + 45.50285910f , 30.56079275f , 25.12585245f , 19.34243209f , 14.67812492f , 11.09479624f , 7.62809337f , 7.36329508f , 5.02791068f , 4.57220923f , 1.95015079f , -1.57507512f , -5.20307171f , -7.99911947f , -9.95812261f , -13.13787688f , -14.44121237f , -16.19333355f , -19.15028237f , -22.75607672f , -25.37417688f , -27.76304019f , -28.42538941f , -29.09271083f , + -0.20862409f , 7.40922209f , 9.52611206f , 7.19556599f , 8.56285670f , 9.23113851f , 8.29119614f , 6.74033461f , 7.39436505f , 4.76996743f , 1.52467647f , -2.37784656f , -6.09813737f , -6.29918182f , -8.30626415f , -10.26550962f , -13.16761101f , -17.25290821f , -21.82832704f , -28.08208094f , -29.69995762f , -30.02997066f , -32.54067640f , -34.86791052f , + 20.15336204f , 23.69787743f , 20.03743258f , 17.32388877f , 13.85816349f , 9.75929930f , 8.81062377f , 7.33399060f , 7.03590133f , 4.83049697f , 0.70944621f , -2.33770508f , -2.40423376f , -4.83395025f , -10.23084612f , -14.36365636f , -18.16750414f , -21.75786888f , -26.07319165f , -30.47064791f , -32.03827614f , -34.62324863f , -36.38403786f , -37.62380175f , + 21.02807550f , 15.43123168f , 13.19159292f , 11.05909310f , 9.93532083f , 10.14330557f , 8.44788836f , 7.05092375f , 6.65547179f , 3.80156734f , 1.01028469f , -2.51036572f , -5.52907299f , -7.16917980f , -9.69618129f , -9.79583611f , -12.34407663f , -16.35321338f , -21.00738251f , -27.34102498f , -30.48319293f , -30.90104975f , -33.93924526f , -35.92883268f , + 33.46103317f , 28.05909534f , 25.27576527f , 21.45366856f , 18.39016725f , 16.16268691f , 14.43168731f , 12.88073327f , 9.27668693f , 6.28692861f , 0.27771848f , -3.24264663f , -7.02703161f , -11.49310707f , -14.63223263f , -18.01065380f , -23.30098657f , -26.04536683f , -29.97889152f , -33.31061266f , -34.90527704f , -37.51005914f , -38.89607504f , -39.43668242f , + -6.19448103f , 7.00670386f , 6.42929262f , 11.44842292f , 10.59782711f , 3.51908910f , 5.03700693f , 11.99440282f , 2.46784279f , 2.52636549f , 0.19509676f , -0.66292825f , -3.57724994f , -4.27935354f , -7.71003982f , -9.31027578f , -10.79777387f , -12.03284160f , -14.50955075f , -15.24259860f , -15.04293408f , -17.84913152f , -19.24800026f , -20.43127990f , + 34.36219386f , 29.15654122f , 17.89907772f , 15.96853719f , 12.24737290f , 8.58997407f , 8.02028124f , 6.73852407f , 6.68229615f , 4.41515543f , 0.31647818f , -2.71422396f , -1.11008623f , -3.15418403f , -8.78373906f , -13.46164937f , -17.78623382f , -22.03141049f , -26.52011865f , -30.42263732f , -32.88924845f , -36.52063092f , -39.44879402f , -41.00582791f , + 28.59389870f , 16.57976885f , 11.69506951f , 9.00946677f , 6.59434708f , 5.58892350f , 5.15576244f , 4.26874238f , 3.83962965f , 3.10490992f , 1.74950191f , 0.21359494f , -2.34614415f , -5.90830965f , -7.32978245f , -6.79210755f , -8.13921426f , -12.39307835f , -16.42105838f , -17.81533132f , -20.43309456f , -23.50336304f , -28.11010949f , -32.19800165f , + 42.18709382f , 31.66042119f , 28.18576191f , 24.02454209f , 17.80243401f , 14.32604318f , 12.38219020f , 9.68299766f , 9.84153789f , 7.22418488f , 1.90320264f , -0.79109427f , -7.30502888f , -10.99217358f , -15.03902326f , -18.25651222f , -20.77870269f , -22.27969332f , -25.21134893f , -26.73864852f , -26.81597564f , -28.06561283f , -28.74871236f , -29.19027505f , + 3.14453423f , 9.82704694f , 10.42102234f , 7.53076819f , 6.65445918f , 5.42078795f , 4.35248487f , 3.38200688f , 3.34653224f , 2.23758939f , 0.98007038f , -0.82512415f , -3.06552968f , -3.74092446f , -5.19946109f , -6.26762478f , -7.27519640f , -9.56355666f , -11.49652218f , -12.93977382f , -15.16570550f , -17.89500321f , -20.88144101f , -24.27090982f , + 16.89397941f , 22.41751392f , 23.75354684f , 20.15652247f , 16.71460178f , 15.68435339f , 13.05195327f , 12.59734003f , 8.36320984f , 6.61926140f , 1.34089883f , -3.04095047f , -6.87072914f , -10.11874127f , -13.60230073f , -18.32905014f , -22.40986754f , -26.40241648f , -30.22653356f , -34.35524827f , -35.82875887f , -38.56697745f , -40.04466299f , -40.77890542f , + 14.06040489f , 12.38456984f , 11.38443857f , 6.43429982f , 8.36024783f , 5.74773204f , 3.64617779f , 2.27891511f , 2.88575114f , 2.28853033f , 0.47176709f , -0.58104559f , -1.80751192f , -3.57542575f , -6.25556579f , -6.84838146f , -6.61115232f , -8.86429480f , -13.12243997f , -15.53130507f , -17.39294606f , -20.82817234f , -24.80352676f , -27.90102832f , + 29.08127657f , 30.25267470f , 28.50445786f , 22.88590940f , 16.95382919f , 12.99666306f , 9.24548766f , 10.17354633f , 7.44385880f , 5.98968070f , 1.98160871f , -1.99320988f , -6.45502374f , -10.08296200f , -12.58332338f , -15.94023376f , -17.72993147f , -19.46222023f , -22.64433239f , -25.73538061f , -25.10103202f , -27.34115443f , -28.00719352f , -28.71283003f , + 10.44191657f , 11.89739900f , 6.63050752f , 11.66862838f , 10.95389970f , 3.62853936f , 5.27338772f , 12.22397146f , 2.38303236f , 2.27598761f , 0.20057759f , -0.69953882f , -3.74592500f , -4.11363308f , -7.73279200f , -9.56396050f , -11.08358715f , -12.21155490f , -14.86254610f , -15.45527754f , -15.28325702f , -17.98672312f , -19.17774681f , -20.23644212f , + 35.53276331f , 29.79176377f , 19.61709874f , 16.86634001f , 13.09981576f , 9.35098387f , 8.47743299f , 7.04997634f , 7.03070014f , 4.96729480f , 0.92976195f , -2.31151272f , -1.83127970f , -4.34635324f , -9.67542557f , -14.26377116f , -18.47764765f , -22.80532113f , -27.40873215f , -31.63558241f , -33.75926234f , -36.57926085f , -38.64751733f , -39.92187198f , + 19.57623370f , 14.52227951f , 10.90006748f , 7.46479458f , 6.57710504f , 5.35248052f , 4.32022732f , 3.44261943f , 3.11088406f , 2.14252838f , 0.91565155f , -0.88167185f , -3.01132437f , -3.66994851f , -5.19376018f , -6.09616750f , -7.00842420f , -9.47621384f , -11.55078876f , -12.93214130f , -15.11703243f , -17.74349778f , -20.81631949f , -24.26610975f , + 45.46539087f , 33.65225910f , 27.04759024f , 20.37287228f , 15.20605258f , 10.95754596f , 8.25353280f , 10.41134779f , 9.16332898f , 5.00593619f , 1.56893245f , -0.96934543f , -4.76115225f , -9.35265480f , -13.96830603f , -15.58493281f , -15.93026458f , -18.72056170f , -22.62999991f , -24.01724401f , -24.13966976f , -25.75662986f , -27.30657872f , -29.31976842f , + 3.35383892f , 10.46089277f , 12.67572651f , 10.67316057f , 8.86420657f , 7.41699857f , 6.40472576f , 5.55584594f , 4.78140149f , 3.39101090f , 1.64891901f , -0.88431535f , -3.41794053f , -5.52966105f , -7.12950981f , -9.73843277f , -11.36318390f , -12.90076410f , -15.02653519f , -17.80793193f , -20.85950171f , -24.60915288f , -28.33117068f , -31.97961671f , + 24.16381226f , 26.61189391f , 24.86498593f , 19.87730202f , 15.18991454f , 10.98879994f , 7.42531150f , 10.49136744f , 9.62334804f , 4.97806393f , 1.38953872f , -1.07543238f , -4.87438861f , -8.84994346f , -14.12865608f , -15.38136709f , -15.77648418f , -18.65254160f , -24.07064465f , -26.65375941f , -26.62799211f , -28.37449714f , -30.00703668f , -31.95561063f , + 16.73297197f , 13.40079340f , 11.36295685f , 8.12888004f , 8.67057438f , 9.98791316f , 7.17503401f , 3.41805962f , 3.84708100f , 3.38229324f , 1.69308513f , -2.44779633f , -7.15056120f , -5.22964233f , -5.71002448f , -7.24979808f , -10.38621901f , -12.40506839f , -16.88434384f , -24.40525376f , -27.96468183f , -28.87188624f , -31.73758135f , -34.45997553f , + 36.82320664f , 30.14889839f , 24.36495733f , 19.95821910f , 17.28215670f , 15.34405446f , 12.71014649f , 11.84061146f , 8.74552404f , 5.19431776f , 0.62656711f , -3.30567052f , -7.09245555f , -11.63075940f , -14.43930927f , -16.55893715f , -18.71623060f , -21.39863923f , -24.41215684f , -27.71989721f , -29.44073312f , -31.13601153f , -33.00550113f , -35.01755294f , + -0.75323250f , -0.49333543f , -0.03686038f , 0.00580498f , -0.02595636f , -0.42521553f , -0.11620129f , 0.04925008f , -0.22349130f , -0.41036697f , -0.08797780f , -0.31029326f , -0.33370732f , -0.04414976f , -0.18188899f , -0.39067975f , -0.19015430f , -0.13924769f , -0.07489774f , -0.24338076f , 0.02616867f , -0.90654191f , -0.36674078f , -0.92659945f , + 32.82257425f , 26.93225108f , 17.97275820f , 15.52062575f , 12.24580971f , 7.87298134f , 7.92790101f , 6.69153001f , 6.20377725f , 4.87524910f , 0.20987746f , -2.32068931f , -1.19022086f , -3.62043573f , -8.66527100f , -13.17653707f , -17.05395098f , -21.30672374f , -26.02442938f , -29.84148775f , -32.77866358f , -36.44067731f , -39.64793075f , -41.28669431f , + 23.66104031f , 18.77341211f , 15.43023272f , 11.20366406f , 8.42366176f , 6.11675293f , 5.33405011f , 5.20406381f , 4.67626106f , 3.65065286f , 1.53469689f , -1.60771292f , -3.81129242f , -4.57130038f , -6.33850722f , -8.60971199f , -10.00167377f , -11.97538710f , -14.16507562f , -16.60464075f , -19.14351164f , -22.49496272f , -25.49215425f , -28.47836779f , + 48.83791360f , 34.21172740f , 28.24854170f , 23.78581370f , 19.15275096f , 16.36583739f , 13.52652252f , 12.00825971f , 7.58820783f , 4.57182675f , -0.44096755f , -5.59444127f , -9.20335237f , -11.60423121f , -13.38376584f , -15.82699559f , -17.15943218f , -18.22349154f , -21.00159236f , -23.41802307f , -24.09185136f , -26.12025700f , -26.38389340f , -26.90015217f , + 5.65030538f , 13.78536254f , 12.93384260f , 10.10554338f , 9.25200312f , 6.70079894f , 4.97946459f , 4.14010675f , 3.20266413f , 2.24703740f , 0.17096077f , -0.76854332f , -3.49746682f , -4.40509828f , -5.92984501f , -7.16813639f , -8.92390949f , -10.44235555f , -11.73970476f , -13.07525739f , -15.58860787f , -18.82754905f , -20.11226045f , -21.89670528f , + 20.00764046f , 25.05163905f , 23.67903478f , 19.61532654f , 16.85580272f , 14.84943508f , 12.32422151f , 11.72685290f , 8.55557474f , 4.89724925f , 0.62350153f , -3.12200178f , -6.95129787f , -11.32051330f , -13.87728564f , -16.20738435f , -18.35417789f , -21.22501359f , -24.26412556f , -27.53754401f , -29.04562197f , -30.52655890f , -32.50623950f , -34.76405591f , + 20.12464864f , 15.20430829f , 13.25055947f , 10.65904743f , 8.91134621f , 7.46363884f , 6.44402323f , 5.71195079f , 4.79807746f , 3.49335087f , 1.75260934f , -0.74115357f , -3.42285816f , -5.45747278f , -7.23479115f , -10.08709890f , -11.63154322f , -13.05708157f , -15.18339592f , -18.14822179f , -21.33849269f , -25.01926113f , -28.92560049f , -32.56657725f , + 26.54656966f , 26.13227118f , 27.82488903f , 24.22335030f , 18.87683777f , 16.59425031f , 13.64047520f , 9.75915298f , 7.28698308f , 4.09515905f , -0.71835272f , -3.26926527f , -7.31384281f , -9.98624418f , -13.59589213f , -16.50790941f , -18.86147233f , -20.11404881f , -22.88197092f , -24.35845023f , -23.98592903f , -25.19061201f , -25.66357488f , -26.11120895f , + 16.92428437f , 15.63926123f , 14.68264077f , 9.17511817f , 11.72199221f , 8.73358423f , 5.74525565f , 3.31019020f , 3.82744364f , 2.82061126f , 0.00479914f , -1.62974092f , -3.21227479f , -5.78430830f , -8.71508730f , -8.80926274f , -8.01316743f , -9.54120965f , -13.35104985f , -15.74348284f , -16.40121304f , -19.46521021f , -22.26957651f , -24.80475300f , + 33.27372786f , 28.98123208f , 18.52554956f , 16.22324845f , 11.82428088f , 8.06497636f , 6.95248523f , 6.23909474f , 5.55428912f , 3.52189864f , 0.54297482f , -2.65061141f , -0.24235908f , -2.49418732f , -8.10730403f , -12.50952978f , -16.69612524f , -20.49938193f , -23.81401973f , -26.29697125f , -27.78204736f , -29.60465452f , -31.26624714f , -32.52437926f , + 27.66207964f , 21.38029622f , 15.28817924f , 11.29865816f , 7.24050384f , 4.07114269f , 2.23434724f , 2.00312407f , 2.12063407f , 2.37092879f , 1.11181974f , -0.06676605f , -1.62128339f , -3.18849566f , -4.50247820f , -5.27330824f , -6.50012921f , -8.95962773f , -11.25753877f , -13.15591465f , -15.55510117f , -17.77008388f , -21.51057093f , -23.68928360f , + 46.17063826f , 35.44350933f , 27.63882719f , 20.58749084f , 15.09358456f , 11.34450671f , 8.36303546f , 10.32329718f , 9.40828446f , 4.81846192f , 1.44590103f , -1.30265822f , -4.80681268f , -9.60995360f , -14.00088486f , -15.02315852f , -16.05368713f , -18.40913671f , -21.04455075f , -21.77101439f , -21.86714844f , -23.34699503f , -24.81999799f , -26.75598881f , + 5.55447222f , 11.08900430f , 12.67418749f , 11.37730706f , 10.35233661f , 9.77194599f , 7.54804411f , 5.59512280f , 5.26611322f , 3.61130922f , 1.29867980f , -1.53794101f , -4.94548169f , -6.44099913f , -9.14750567f , -9.26394627f , -12.10780921f , -16.54821135f , -21.09601890f , -27.26975914f , -29.20341664f , -29.16031453f , -32.31338409f , -33.81412751f , + 18.12507160f , 24.70366354f , 18.80553588f , 16.44619360f , 12.73212014f , 8.73243452f , 8.13965750f , 6.85564846f , 6.54211122f , 4.41684143f , 0.86730242f , -2.56492428f , -1.51931938f , -3.44405406f , -9.13992613f , -13.62181635f , -17.99613747f , -22.23637312f , -26.67002377f , -30.83211183f , -32.97908996f , -36.30619371f , -38.88768859f , -40.31682212f , + 19.30313062f , 15.53926343f , 13.90808840f , 11.50585735f , 11.38433252f , 11.23569306f , 9.65078250f , 7.30888386f , 6.96318572f , 4.35594359f , 1.27768650f , -2.51618855f , -6.09345175f , -7.65932096f , -10.43421302f , -11.30754584f , -14.16597758f , -18.97180923f , -23.84334763f , -29.44331171f , -31.44436223f , -32.10318621f , -34.92490176f , -36.47617953f , + 32.84070800f , 26.98843227f , 23.97706735f , 20.09690811f , 17.17772395f , 15.21303519f , 13.42060419f , 12.43874328f , 9.15968596f , 6.16038922f , 0.71905975f , -2.92001972f , -6.40947412f , -10.83784032f , -13.95928861f , -17.62432172f , -22.53835937f , -25.41550617f , -29.42258267f , -33.41667068f , -35.41334436f , -38.22281954f , -39.80199786f , -40.32675160f , + -9.91625093f , 4.80418237f , 9.08604693f , 11.01664820f , 7.24939971f , 12.00629737f , 10.14522962f , 7.79868426f , 0.03388286f , 3.22894410f , -1.49188110f , -1.77551920f , -5.08350600f , -6.11630690f , -8.19142417f , -8.31829806f , -9.48559967f , -10.78591755f , -12.34898021f , -13.04347069f , -12.86564050f , -16.09519878f , -17.66110352f , -20.13284843f , + 33.93076696f , 29.73735327f , 19.23905822f , 17.23103235f , 12.77046694f , 8.83451844f , 8.23785020f , 7.11377423f , 6.72823159f , 4.05823561f , 1.17653434f , -2.62333502f , -1.84527480f , -3.46714831f , -9.29420158f , -13.72585514f , -17.96342825f , -22.04254130f , -26.29305138f , -30.25871596f , -32.43685342f , -36.04907640f , -39.16814132f , -40.73022661f , + 30.53206150f , 19.40488473f , 12.75598255f , 9.25954864f , 6.70414010f , 5.72747123f , 5.03381227f , 4.01075984f , 3.61146616f , 3.58899760f , 2.32432976f , 0.53033441f , -2.14938224f , -5.59608713f , -7.14094606f , -7.65425973f , -8.99080383f , -12.95963757f , -17.18036927f , -19.46195053f , -21.56000305f , -24.52225545f , -30.08064474f , -35.71887681f , + 43.21595883f , 30.91880384f , 28.28763915f , 25.00936743f , 19.09701763f , 16.45025980f , 13.97496410f , 11.13694940f , 8.55554358f , 4.99105536f , -0.75976252f , -4.26698912f , -8.42682321f , -9.48353121f , -14.21251069f , -17.24378853f , -19.81223810f , -21.34834559f , -23.80150703f , -25.40905846f , -25.28209830f , -26.22742436f , -26.66260243f , -27.01651200f , + -0.14361434f , 11.33097675f , 14.22933286f , 9.09701983f , 11.66148024f , 8.76183273f , 5.66551557f , 3.17860698f , 3.87061452f , 2.88805964f , 0.11657889f , -1.62298350f , -3.19956391f , -5.77861831f , -8.72933989f , -8.83773190f , -7.97439380f , -9.53621475f , -13.35824515f , -15.73862835f , -16.23732929f , -19.37222733f , -22.16495373f , -24.69705224f , + 14.97516906f , 20.24358485f , 21.71690634f , 18.67539860f , 16.12099511f , 13.68136380f , 12.06765212f , 10.76593030f , 7.44448363f , 4.69310947f , 0.32375113f , -2.82379840f , -6.24406445f , -9.85549248f , -12.35464306f , -15.66193154f , -18.15727457f , -19.51476533f , -21.69116638f , -26.65585670f , -30.96969557f , -34.93908838f , -37.17487414f , -38.69523980f , + 11.79211750f , 11.97065541f , 11.42461150f , 9.07103015f , 6.75482034f , 5.60897088f , 5.19878959f , 4.12715904f , 3.68541174f , 3.10916340f , 1.75493030f , 0.12722322f , -2.45721866f , -5.96134122f , -7.29240229f , -6.69634000f , -7.95934523f , -12.27446428f , -16.49521939f , -17.81789512f , -20.15378269f , -23.44933417f , -28.12142909f , -32.19480869f , + 31.52643526f , 28.52259080f , 26.69926841f , 20.98459124f , 15.75207892f , 11.93364546f , 8.26555040f , 7.77743568f , 5.47651258f , 4.83040775f , 1.65268569f , -2.13370539f , -5.16522881f , -8.08709801f , -10.71942352f , -14.02185419f , -15.56110704f , -16.98333790f , -19.99452598f , -22.68342788f , -23.41377838f , -25.94358058f , -26.53240068f , -27.12327850f , + 6.80087128f , 11.58644896f , 12.45313320f , 10.29597723f , 9.18481781f , 8.48775117f , 7.26614653f , 5.90419380f , 4.38057275f , 2.43656205f , 0.69276327f , -1.81218785f , -3.96339389f , -5.75303899f , -7.09187068f , -8.88618164f , -10.84611660f , -12.42796224f , -13.13959174f , -13.43223783f , -14.11628112f , -15.89113608f , -18.99839794f , -22.60584539f , + 36.38520889f , 28.78012839f , 21.05496218f , 17.53636167f , 13.96758507f , 11.67472760f , 10.42791533f , 9.67412184f , 7.27606489f , 5.56430120f , 0.35452150f , -3.04945909f , -3.73479650f , -6.39521181f , -11.23696830f , -15.42073952f , -19.10245341f , -22.52588883f , -26.73438324f , -31.13547298f , -32.74648378f , -35.08411011f , -36.64862406f , -37.83303410f , + 23.44391246f , 16.34449728f , 12.74386848f , 10.37728433f , 9.26531402f , 8.62835052f , 7.30803355f , 5.91607884f , 4.36863155f , 2.42037310f , 0.72270664f , -1.87419199f , -3.98816276f , -5.80775521f , -7.13994994f , -8.93853756f , -10.88091925f , -12.48019720f , -13.11652631f , -13.43063220f , -14.21381571f , -15.91218672f , -19.00174998f , -22.61508378f , + 42.41685465f , 32.92785864f , 26.73527519f , 20.02657328f , 15.25763921f , 11.51912083f , 7.75120808f , 10.47560309f , 9.43865509f , 4.72161580f , 1.23456822f , -1.24509427f , -5.12070011f , -8.97924223f , -14.13085652f , -15.32553884f , -15.59705390f , -18.30233488f , -23.33478017f , -25.58695872f , -25.86117061f , -27.64564989f , -29.28904725f , -31.28074013f , + 1.52342001f , 9.12417569f , 10.32715957f , 8.66545459f , 7.07445753f , 5.84320555f , 5.74305920f , 4.78929426f , 4.24381536f , 2.93093263f , 1.43577760f , -0.53860173f , -3.06985625f , -4.84378216f , -6.19218421f , -7.82485861f , -9.59127476f , -11.55775664f , -13.43280469f , -15.63550289f , -19.62772693f , -22.98849208f , -25.64470241f , -28.78809716f , + 25.56643800f , 24.60767519f , 24.69578809f , 19.70646081f , 15.16249776f , 11.52050408f , 7.81769903f , 7.63275125f , 5.49767989f , 4.82720507f , 1.97596070f , -1.66260544f , -5.25016669f , -8.43401653f , -10.50840106f , -13.66164463f , -14.91737550f , -16.34161902f , -19.45629644f , -23.46159848f , -25.62249781f , -27.82515036f , -28.34414019f , -28.79284328f , + 16.92655154f , 13.22739747f , 11.12354116f , 8.43784353f , 9.39924384f , 10.05896738f , 8.60043956f , 6.03413409f , 6.90507663f , 4.38541942f , 1.33274141f , -3.40564903f , -6.91513167f , -6.87459047f , -7.76883773f , -9.68917237f , -12.06267819f , -15.74184854f , -20.57971046f , -26.94266349f , -28.91713407f , -29.90809627f , -32.33980009f , -34.78712756f , + 31.86686358f , 25.05708453f , 21.93386932f , 18.59721235f , 16.14828273f , 13.65996344f , 12.23768162f , 10.88830652f , 7.52143926f , 4.65925062f , 0.21911333f , -2.95634076f , -6.28361110f , -9.89608579f , -12.31443795f , -15.63623136f , -18.24730809f , -19.62072228f , -21.80325803f , -26.65045940f , -31.07260802f , -34.93098644f , -37.15982288f , -38.71632279f , + -1.13403660f , 8.44528954f , 11.51295187f , 14.00328114f , 13.22245841f , 6.86239877f , 5.34172769f , 2.20794235f , 0.66973127f , 0.80995393f , 0.18013549f , -1.34499371f , -2.89430852f , -4.11662287f , -4.87021345f , -7.99460808f , -8.07372401f , -10.75957729f , -12.01649380f , -13.25826273f , -16.07989264f , -18.05984187f , -19.66161990f , -20.39890287f , + 34.47278093f , 29.24647924f , 19.01794852f , 15.12449850f , 12.02160432f , 7.97153847f , 7.45763494f , 5.89473413f , 5.37914684f , 4.00235938f , 0.64484508f , -2.70552406f , -1.74008061f , -3.83315860f , -8.38542072f , -11.12882737f , -15.57900872f , -20.44309400f , -25.22215650f , -30.01421316f , -32.58722714f , -35.83261388f , -38.09733270f , -39.57915419f , + 26.99752631f , 17.33775755f , 13.92510612f , 10.93298244f , 9.54482419f , 7.98334199f , 6.83019538f , 4.82308161f , 2.24070293f , 0.99075525f , -1.02697127f , -2.29004143f , -3.77731663f , -5.16939314f , -6.16294107f , -6.18510893f , -7.80109455f , -10.31816129f , -12.42321458f , -14.13119051f , -16.75176785f , -19.57160270f , -22.21041760f , -24.43862133f , + 42.61148531f , 31.03862448f , 28.85875173f , 25.19534132f , 19.51936632f , 17.22593169f , 13.88213981f , 9.45821554f , 6.10128356f , 3.64177773f , -0.92329563f , -2.97749460f , -7.09143508f , -9.90051943f , -13.44778189f , -16.62642688f , -18.86184149f , -20.09465179f , -22.86181406f , -24.16906530f , -24.29058326f , -25.46900644f , -25.99854039f , -26.44256368f , + 11.21919787f , 12.93487301f , 14.44441998f , 11.21144561f , 9.65171981f , 8.40946672f , 7.55500249f , 5.20337067f , 2.41664302f , 1.45692356f , -0.41811214f , -3.03866042f , -4.18715822f , -4.62852017f , -5.34679829f , -7.37187974f , -9.70194778f , -11.87551235f , -14.41976938f , -16.77473090f , -20.18921925f , -23.53459021f , -26.08250760f , -28.00378414f , + 20.34283034f , 23.93100647f , 23.37840521f , 19.69998040f , 16.97580649f , 15.22176840f , 12.49942414f , 11.65471077f , 8.40962769f , 5.04811003f , 0.69748903f , -3.16572674f , -7.04148304f , -11.24778876f , -13.98941379f , -16.42484438f , -18.63762955f , -20.97458282f , -23.23612236f , -25.18653947f , -26.21052089f , -27.41104425f , -28.62675281f , -29.47926632f , + 16.10744102f , 12.46174606f , 9.67751113f , 7.41625956f , 6.37054729f , 5.04682742f , 5.17633155f , 4.68688374f , 3.91606026f , 3.15494649f , 1.41414217f , -0.14124367f , -2.67444251f , -4.50662805f , -5.84468690f , -7.56186331f , -9.03680543f , -11.41274706f , -13.28658702f , -15.69552507f , -20.26071976f , -23.69377768f , -26.71593694f , -30.31014067f , + 23.92977739f , 27.36060494f , 28.84534340f , 25.31470096f , 19.06231769f , 15.59405931f , 13.34476843f , 10.49105930f , 10.02936877f , 7.13162822f , 1.31449322f , -2.20667410f , -8.24469533f , -11.78467489f , -15.48551597f , -18.43809063f , -20.80800912f , -22.21620783f , -24.85301893f , -26.38738069f , -25.80522754f , -27.00307256f , -27.56365136f , -28.00697638f , + 14.20627416f , 13.22102035f , 12.02604633f , 14.08327071f , 13.26998454f , 6.88224307f , 5.35679783f , 2.25352772f , 0.65358807f , 0.88975002f , 0.25204959f , -1.26498593f , -2.99170955f , -4.16405714f , -4.90721314f , -8.09596924f , -8.13409888f , -10.82708078f , -12.07413388f , -13.34328963f , -16.41337023f , -18.35676002f , -19.98799588f , -20.75791138f , + 35.53474913f , 29.48558719f , 19.65603645f , 16.46619256f , 12.12345599f , 8.85911530f , 8.44629251f , 7.05107660f , 6.71696658f , 4.07340114f , 1.41090109f , -2.86480122f , -1.47018231f , -3.19146903f , -9.63933408f , -13.43801687f , -18.07739816f , -21.62350791f , -25.40446924f , -28.56460703f , -30.18164019f , -32.53467864f , -34.28547688f , -35.28943834f , + 25.00794399f , 21.33869877f , 16.33988340f , 13.32545569f , 11.45579996f , 9.10207550f , 5.25001638f , 3.47011991f , 4.05816364f , 1.86646664f , -0.86488053f , -3.00452324f , -3.76486650f , -4.79552937f , -6.02719617f , -7.73977293f , -9.00587006f , -9.73374090f , -11.85870497f , -14.34560315f , -16.77881295f , -19.01848975f , -21.05935919f , -22.79963588f , + 43.77792792f , 31.32894231f , 26.45922262f , 21.35876446f , 15.14525981f , 10.71588831f , 8.36941090f , 8.13517319f , 4.60128461f , 4.27211986f , 0.48686102f , -2.99834845f , -5.70951224f , -8.40090526f , -10.59412598f , -12.10770405f , -11.91522373f , -11.91518882f , -14.41049054f , -17.78623890f , -21.49234475f , -25.81448584f , -28.36724870f , -30.21155944f , + 1.50464115f , 9.93376270f , 11.74048494f , 9.30038969f , 9.79598610f , 10.20363220f , 7.85569223f , 4.26334672f , 4.97315307f , 3.54446278f , 1.25546594f , -3.09504089f , -6.84943958f , -5.99780503f , -6.73288678f , -8.33022105f , -10.88645558f , -13.74251357f , -18.59070672f , -25.24686013f , -27.59378675f , -28.40807602f , -30.81519883f , -33.03504083f , + 19.29716892f , 22.72202601f , 17.97653030f , 16.27096251f , 12.41466110f , 8.84546373f , 8.15910118f , 6.66039787f , 6.35335478f , 4.08653893f , 0.72117759f , -2.80728034f , -1.28889621f , -3.09741558f , -8.84182975f , -13.43826617f , -17.76712819f , -21.05170423f , -24.61965449f , -27.56558965f , -28.70738278f , -30.61253475f , -32.09933492f , -32.92557847f , + 22.91112025f , 16.28797584f , 13.32980234f , 11.77954583f , 11.10520613f , 9.60502556f , 6.99639805f , 4.92750381f , 4.37578890f , 3.30304792f , 1.59780404f , -0.85650398f , -4.51942915f , -6.12826489f , -9.01178894f , -9.24740841f , -12.14748862f , -16.76564804f , -21.19272621f , -27.28665412f , -29.08952731f , -28.60120961f , -31.88653060f , -33.18962566f , + 33.45651993f , 27.28201548f , 24.14734641f , 20.06703472f , 17.00409549f , 15.37948573f , 13.16136491f , 12.54752730f , 8.51110832f , 6.15322442f , 1.01576259f , -3.20755791f , -6.86882472f , -10.60714935f , -13.86074399f , -17.81294984f , -21.41525794f , -23.90831312f , -26.23400053f , -28.17563657f , -29.78113366f , -31.33044221f , -32.48533160f , -33.17676836f , + -1.33562639f , 7.12695001f , 9.13702377f , 12.15068677f , 10.08162039f , 4.24738369f , 5.64945952f , 9.32178364f , 3.03127020f , 1.38560225f , -0.47615923f , -1.64981857f , -3.39596649f , -4.05192511f , -6.43198431f , -7.97537953f , -9.73574405f , -10.49517550f , -11.53586670f , -11.55974030f , -11.95164592f , -14.31159626f , -16.17106881f , -17.68912312f , + 35.41108122f , 29.91060467f , 19.58523453f , 16.06777717f , 12.57822747f , 8.35950205f , 8.09246540f , 6.67806922f , 5.88366701f , 4.60628742f , 0.66866287f , -2.63518420f , -1.20919288f , -3.25276235f , -8.81348472f , -13.41243642f , -17.54390333f , -21.59153299f , -26.13142590f , -30.39899536f , -32.82264487f , -35.85023060f , -38.02784458f , -39.40873711f , + 28.20606627f , 15.99154594f , 10.90529614f , 8.27787590f , 6.06401205f , 5.06158745f , 4.71175812f , 3.71857258f , 3.29421131f , 3.15470022f , 1.47961235f , -0.11358400f , -2.36135275f , -5.91849835f , -7.03135770f , -5.55512296f , -6.50513100f , -10.60214350f , -14.97482271f , -15.31088270f , -17.34686348f , -20.99732736f , -25.70312725f , -29.22139957f , + 42.93694373f , 32.74699191f , 30.21736822f , 26.00007059f , 19.54808802f , 16.15153602f , 13.70906743f , 10.84988327f , 10.20654657f , 7.38885117f , 1.18592616f , -2.68553419f , -8.73683094f , -12.15884936f , -15.82753433f , -18.59595794f , -21.03522899f , -22.52642663f , -25.16717079f , -26.41557750f , -26.29502925f , -27.33330821f , -27.87099339f , -28.30239553f , + 6.98493107f , 12.11140261f , 12.92505832f , 10.63602573f , 9.29436222f , 7.80676869f , 6.62557343f , 4.68392090f , 2.17174988f , 1.01311116f , -1.11858724f , -2.22498325f , -3.56605973f , -4.96869680f , -6.04787508f , -6.05424850f , -7.61493730f , -9.33729157f , -10.80071194f , -12.03282608f , -14.46539670f , -17.02917589f , -19.33639362f , -21.15590027f , + 16.58485816f , 23.25532800f , 24.92928523f , 21.35853037f , 18.27283576f , 16.09710359f , 14.23738656f , 12.78815582f , 9.26070976f , 6.16634740f , 0.30018833f , -3.21368036f , -6.95869200f , -11.45995031f , -14.49141925f , -17.86218539f , -23.13676669f , -25.83259792f , -29.74871192f , -33.41994284f , -34.94573093f , -37.66843375f , -39.07414904f , -39.56312642f , + 19.19373953f , 14.21085832f , 10.67306675f , 8.33934581f , 6.82717763f , 6.09582415f , 5.89997396f , 4.53145606f , 4.46589963f , 2.98486276f , 1.45382349f , -0.47196753f , -3.08165487f , -4.80601244f , -6.35558877f , -7.88794845f , -9.65590673f , -11.39978404f , -12.89635391f , -14.32655348f , -17.79398377f , -21.03259304f , -23.41750892f , -26.20513637f , + 29.53404537f , 30.67650669f , 27.35804255f , 20.58387049f , 15.13774878f , 11.44742263f , 8.37085526f , 10.32676908f , 9.44758339f , 4.78688526f , 1.42891547f , -1.32094691f , -4.89316199f , -9.59224642f , -14.04691133f , -15.02972510f , -16.06330505f , -18.39580808f , -21.09539458f , -21.98720102f , -21.73206018f , -23.31133245f , -24.77510819f , -26.73382495f , + 8.21213806f , 10.71817099f , 6.95322984f , 10.27747529f , 8.84487068f , 3.08387427f , 4.45029470f , 10.93157046f , 2.20726443f , 2.60772269f , 0.11878151f , -0.75484803f , -2.80874481f , -3.82230411f , -6.83748866f , -8.27100427f , -9.75013326f , -11.03913114f , -12.78391580f , -13.82412848f , -14.12344338f , -16.73927451f , -18.69924100f , -20.13526564f , + 36.59329684f , 30.98184338f , 20.31505022f , 15.92064718f , 13.03648432f , 8.83096086f , 8.56348539f , 7.43266836f , 6.82375344f , 4.40627973f , 1.13184165f , -3.01500873f , -1.77040231f , -3.69259653f , -9.49579170f , -13.95449102f , -18.29710034f , -22.56971615f , -26.64665710f , -30.91115675f , -33.15396332f , -36.23947175f , -38.66101864f , -40.00954322f , + 21.55198111f , 18.08013792f , 12.86298781f , 10.08865136f , 9.05061804f , 6.54215134f , 4.72951143f , 3.72642094f , 2.85320817f , 1.71125125f , -0.07271721f , -0.95539550f , -3.50605983f , -4.43298306f , -5.50932418f , -6.32571893f , -7.81088376f , -8.89702447f , -9.73519051f , -10.67801247f , -13.58487694f , -16.68643366f , -17.77012871f , -20.05291511f , + 46.89729788f , 35.56958745f , 28.59584038f , 22.30896946f , 16.77464328f , 13.26417085f , 9.50081776f , 9.90989766f , 7.34552811f , 5.94667087f , 1.99541819f , -1.96361481f , -6.27398279f , -10.07653618f , -12.56282109f , -16.11090729f , -17.74907160f , -19.50939014f , -22.57118303f , -25.05439958f , -25.40229780f , -27.63187647f , -28.24619732f , -28.92835915f , + 7.04882350f , 14.81563453f , 15.61978870f , 11.48753791f , 8.54260976f , 6.22345107f , 5.45372753f , 5.28049811f , 4.65171365f , 3.62223181f , 1.43071415f , -1.72597185f , -3.88591530f , -4.61140675f , -6.49788570f , -8.59851355f , -9.88533610f , -11.88847906f , -14.04273862f , -16.54736577f , -19.07821687f , -22.45007228f , -25.58564675f , -28.56726867f , + 26.62300533f , 28.26693809f , 26.50090754f , 20.40002747f , 15.09430263f , 11.11188625f , 8.11413871f , 10.45873727f , 9.34406319f , 4.93078412f , 1.46033398f , -1.08739740f , -4.89307642f , -9.31800578f , -13.94736720f , -15.44189741f , -15.82638440f , -18.64996439f , -23.01530348f , -24.89778906f , -24.73159812f , -26.54494768f , -28.17985037f , -30.12506435f , + 18.67019979f , 15.08336786f , 12.94476580f , 10.08150497f , 10.00925560f , 9.67310787f , 7.30307309f , 4.52404204f , 5.06127062f , 3.29409992f , 1.11564223f , -2.83692116f , -5.88020005f , -6.25987188f , -7.10071550f , -8.19345902f , -10.70954639f , -13.53857613f , -18.30301326f , -24.52520568f , -27.34703702f , -27.97535570f , -30.09726173f , -32.24832937f , + 36.04980859f , 29.26056864f , 23.78078855f , 19.63374982f , 16.81000279f , 14.81984984f , 12.41523810f , 11.85197437f , 8.58759306f , 5.22704793f , 0.47511965f , -3.18839218f , -7.11099580f , -11.31735229f , -13.99002045f , -16.24783283f , -18.33216567f , -20.74910417f , -23.21510782f , -25.78954590f , -27.11200149f , -28.25034071f , -29.54019390f , -30.46288370f , + 0.37670779f , 0.29687493f , -0.01730927f , 0.11726067f , 0.11179207f , 0.33596355f , 0.21138045f , -0.04339771f , -0.02563331f , 0.38427089f , 0.09512665f , -0.07913710f , -0.00292995f , 0.29039347f , 0.10659745f , 0.19430847f , 0.34841833f , 0.11527277f , -0.04865383f , 0.19615645f , 0.02847621f , 0.06718820f , -0.22446622f , 0.20364433f , + 33.05884904f , 28.21806545f , 18.28672366f , 14.90465855f , 11.81838140f , 8.53018928f , 7.36436457f , 6.22819968f , 5.84887442f , 3.66847974f , 0.20260152f , -2.66704796f , -1.47894289f , -2.86302773f , -7.85434089f , -12.24209362f , -16.55564265f , -20.61195764f , -25.12237933f , -29.08693654f , -31.94525806f , -35.55122030f , -38.95909687f , -40.60633258f , + 24.50578368f , 23.21164155f , 17.92457034f , 12.07933488f , 8.98364311f , 6.80371606f , 5.83939766f , 5.41161671f , 4.31883022f , 3.60077410f , 1.63582448f , -1.36979682f , -3.64312460f , -5.15824621f , -7.52882787f , -8.79219701f , -10.10176923f , -12.04124517f , -13.96520976f , -16.84553679f , -20.16579953f , -23.43856366f , -26.82374740f , -29.86100013f , + 48.50819832f , 34.15289137f , 28.24457133f , 23.53440589f , 18.31072957f , 15.88776926f , 12.53987092f , 11.18245335f , 6.24944164f , 4.11493883f , -0.52409240f , -5.30803325f , -9.07637769f , -11.17513219f , -12.30672893f , -14.59517059f , -15.29955284f , -16.17617119f , -18.50798560f , -20.76566614f , -22.52791437f , -25.09691027f , -26.04976551f , -26.89355524f , + 8.09511743f , 16.72934786f , 15.91762640f , 13.38776480f , 11.39996807f , 9.07169312f , 5.27363212f , 3.54887142f , 4.12516542f , 1.95190718f , -0.86304369f , -2.99361979f , -3.82488041f , -4.85774399f , -6.10028496f , -7.73781042f , -8.99385716f , -9.74269129f , -11.87311775f , -14.36412448f , -16.63984465f , -18.98401676f , -21.03949226f , -22.80551374f , + 20.87378295f , 25.56786054f , 24.37761370f , 20.59749879f , 17.50210689f , 15.81599869f , 13.08379347f , 12.05910670f , 8.96864073f , 5.68078325f , 0.54144388f , -3.56427128f , -7.29664065f , -11.97853799f , -15.04589649f , -16.84207789f , -18.92440518f , -21.49140235f , -24.44638942f , -27.80142626f , -29.24580339f , -31.40581424f , -33.20452192f , -34.96038674f , + 19.41104922f , 14.92637618f , 12.34176913f , 10.26196252f , 8.23856507f , 6.94579600f , 6.09672941f , 5.11937634f , 4.33940607f , 3.00270291f , 1.52448177f , -0.93710759f , -3.39576042f , -5.47615969f , -6.39919115f , -8.50931643f , -10.54951473f , -12.31607256f , -14.47860786f , -16.84616423f , -20.24052021f , -23.50168995f , -26.54506826f , -30.16170088f , + 28.94913403f , 28.15793287f , 27.35445852f , 23.88021364f , 19.04664597f , 16.62782585f , 13.23041024f , 11.80165357f , 6.78531707f , 3.80696933f , -0.83387114f , -5.70452993f , -9.22126990f , -11.40351884f , -12.85584125f , -15.17252463f , -16.10728336f , -17.34847712f , -19.92401313f , -22.57735630f , -23.06177883f , -25.40758146f , -25.92714954f , -26.49459925f , + 12.32069177f , 16.71685865f , 15.41594910f , 11.66621173f , 7.27561715f , 4.39258627f , 3.29820147f , 3.32758485f , 3.22734089f , 2.78470278f , 1.44650193f , -0.81598784f , -3.12521932f , -3.93668706f , -4.64477937f , -6.10317000f , -7.12681751f , -8.89530539f , -11.17332758f , -13.38366313f , -16.18909111f , -19.08724858f , -21.72257955f , -24.33222369f , + 35.39248501f , 28.61432228f , 17.95058353f , 16.39813320f , 12.26449602f , 9.14706821f , 8.63032788f , 5.85616320f , 5.28119540f , 2.63526927f , -0.28717841f , -3.14181019f , -2.72478672f , -3.16234838f , -8.13078551f , -11.42272872f , -14.94525653f , -18.82791922f , -23.24088065f , -27.02082853f , -28.42092038f , -30.16472575f , -31.40325103f , -31.84491940f , + 29.17417043f , 22.35669900f , 16.18973605f , 11.81596682f , 7.33020525f , 4.62573743f , 3.88471147f , 3.94864957f , 3.63555026f , 2.84599249f , 1.57602679f , -1.21735288f , -3.89478177f , -4.22974940f , -4.64250760f , -6.47171963f , -7.39065220f , -8.84922447f , -11.09964915f , -13.32068423f , -16.59227278f , -19.66683547f , -21.69504139f , -24.56742611f , + 47.82535148f , 33.38325580f , 27.02560388f , 20.91023436f , 15.90238857f , 12.04933297f , 8.33681708f , 7.94847051f , 5.44070980f , 4.97685841f , 1.92697687f , -2.14584476f , -5.24005039f , -8.46045386f , -10.93596293f , -14.12648623f , -15.67279334f , -17.08482629f , -19.99575822f , -22.16249633f , -23.35032624f , -25.73870364f , -26.42301184f , -27.09098779f +}; + +const float cdk_37bits_2[1536] = +{ + -0.60245706f , -0.36895614f , -0.28565548f , -0.61568604f , -0.21106471f , 0.01679180f , -0.21655981f , -0.14874146f , 0.18445090f , 0.68365367f , 0.72441464f , 0.85147601f , 0.66205855f , 0.18971396f , -0.61367179f , -0.98009038f , -1.14245763f , -1.87659153f , -2.50979179f , -2.95026349f , -3.02743274f , -2.99854930f , -2.88275498f , -2.56850176f , + -5.65082964f , -2.53862673f , 0.40160897f , 2.96821191f , -0.14824038f , -1.30349223f , 2.28641587f , 2.52644085f , -0.74130153f , -0.58139293f , -0.40073314f , -0.35906410f , -1.19626114f , 0.06293193f , 0.64564279f , -0.28942601f , -0.50149314f , 0.15944196f , -0.49731843f , -1.16475251f , -1.23551169f , -1.75642099f , -1.69671673f , -3.27291796f , + -3.65205633f , -1.67292739f , -1.06391729f , -1.37244548f , -1.12591558f , -0.69120125f , -0.80026251f , -0.27722939f , -0.15083351f , -0.13788690f , 0.03718469f , 0.68916477f , 0.75420341f , 0.54895929f , 0.40054739f , 0.43983204f , 0.31332249f , 0.46565374f , 0.40388762f , 0.35105496f , -0.40253674f , -0.51485592f , -0.89858941f , -1.05731152f , + -2.11612178f , -1.68149840f , -1.39421377f , -0.97488811f , -0.68836346f , -0.25122725f , 0.16979554f , 0.57375560f , 1.03704438f , 0.52788495f , 0.50037128f , 0.36855698f , 0.00455631f , -0.09861634f , -0.62955146f , -0.58507783f , -0.92884745f , -1.12052521f , -1.30254994f , -1.47192536f , -1.44028535f , -1.35850941f , -1.34195842f , -1.31721028f , + 0.25982061f , -1.32220193f , -0.47678762f , -0.12979514f , 0.86306107f , 0.97702394f , 0.51749416f , 0.16146949f , 0.02988918f , 0.04663050f , 0.16707804f , 0.08767141f , -0.04519466f , -0.62683764f , -0.72798866f , -0.62087439f , -0.82935248f , -1.03592460f , -1.01752567f , -0.84860483f , -0.97413949f , -0.96705657f , -0.88017027f , -0.73637371f , + -0.26891091f , -0.80936559f , -0.58294544f , -1.02346364f , -0.43822029f , 0.57696314f , 1.16119077f , 2.18526688f , 0.18783659f , -0.57134867f , -0.83284393f , -0.78823212f , -0.76995104f , -1.09940636f , -0.46951794f , 0.39805438f , 0.45964480f , -0.63039899f , -0.74118394f , -0.78835034f , 0.14868248f , 0.93250274f , 0.68897718f , 0.90075101f , + -1.66784004f , -0.50476115f , -0.02030205f , 0.46798248f , 0.49883263f , 1.17082801f , 0.80713467f , 1.16362509f , 0.81774163f , 0.49553337f , 0.11478912f , -0.22236563f , -0.67572086f , -1.30599465f , -1.03213159f , -0.97366307f , -0.85875427f , -0.98596121f , -0.74580950f , -0.40837319f , -0.08418331f , 0.86784028f , 1.43480309f , 1.64139207f , + 2.27287621f , -0.58474310f , -0.69019045f , -0.47070058f , -0.61574738f , -0.51533540f , -0.29508852f , 0.10165453f , 0.36287882f , 0.55457305f , 0.57810155f , 0.47931307f , 0.43968104f , 0.06171771f , -0.25362137f , -0.47864384f , -0.41913420f , -0.68219417f , -0.57749295f , -0.73286321f , -0.88652778f , -1.14118878f , -1.17860702f , -1.07742659f , + -0.26605958f , -1.09199471f , -1.65740224f , -2.14201695f , -2.06186690f , -1.68936539f , -1.00901439f , -0.37549041f , -0.06256679f , 0.35513419f , 0.98053497f , 0.91466430f , 0.86530432f , 0.83552545f , 0.81062242f , 0.38603024f , 0.05045884f , -0.59611788f , -0.82572806f , -1.24150282f , -1.51280469f , -1.59822307f , -1.71808914f , -1.60728998f , + -1.09129709f , 0.06734422f , 0.07681791f , -1.25010854f , 0.11998545f , 0.44876184f , 0.34324970f , 0.19227749f , -0.14778119f , -0.08340870f , -0.08182976f , -0.20398755f , 0.06772352f , -0.09075007f , -0.02123454f , -0.25839401f , -0.28488980f , -0.64962465f , -0.75312989f , -1.01319788f , -1.29428363f , -1.46281777f , -1.48497336f , -1.34472564f , + -0.64660266f , -0.88691293f , -0.84393960f , -0.34552440f , 0.32824730f , -0.29728699f , -1.56066720f , -1.75726505f , -1.37935080f , -0.41983170f , 0.07847383f , 1.10763083f , 1.38831040f , 0.68960638f , 0.33240448f , 0.76690865f , 0.72333401f , 0.09227846f , -0.25578331f , 0.21326173f , 0.72267697f , 1.03823367f , 0.53396722f , 0.85492859f , + -0.66178264f , -0.72781507f , -1.16616398f , -0.61180318f , -0.13929383f , -0.36461939f , -0.18208278f , -0.01288829f , 0.07717647f , -0.10024019f , 0.07436033f , 0.26910493f , 0.35220120f , 0.08875997f , 0.10426474f , -0.03109220f , -0.13636337f , -0.22965524f , -0.32874358f , -0.25961753f , -0.26897008f , -0.21251566f , -0.09802804f , 0.02321489f , + 0.68981472f , -1.15206563f , -2.29258605f , 2.55986100f , 0.37026158f , -2.06518041f , 0.29082193f , 1.93844641f , 0.99052150f , 0.20248720f , -0.02548929f , 0.16880347f , 0.07779328f , 0.02567656f , -0.88067113f , -0.62757477f , -0.46579846f , -0.15896606f , -0.60482751f , -0.61951099f , -0.93517849f , -1.57434405f , -2.41362494f , -3.62613249f , + 0.10916433f , 0.43521512f , 1.56203262f , 2.28014034f , 2.45964989f , 1.28206740f , 0.62678461f , 0.76120906f , 0.64803676f , 0.26869080f , -0.47306419f , -0.43773939f , -0.62382319f , -1.07053542f , -0.92812261f , -1.19576823f , -1.31738270f , -1.36433226f , -1.44943362f , -1.75263554f , -1.79107934f , -1.65086642f , -1.63564703f , -1.48679794f , + -1.03508578f , -1.33591451f , -0.93011319f , -0.44471674f , 0.37500761f , 0.92138871f , 0.47036706f , -0.45250578f , -0.67117578f , -1.17172575f , -0.80474849f , -0.45208178f , 0.34756513f , 0.94484979f , 0.66316845f , 0.02661059f , -0.19689367f , 0.28637288f , 0.19763960f , -0.18457662f , -0.24564459f , -0.27740232f , -0.16466847f , -0.07240464f , + 0.79283938f , 0.04072154f , -0.45284799f , 0.62520205f , 0.40461878f , 0.46378915f , 0.26074483f , -0.00916984f , 0.17535410f , 0.03167535f , -0.07586785f , 0.26470352f , -0.21568977f , -0.76557444f , -0.42590064f , -0.12909543f , 0.02061938f , 0.20821266f , 0.45608502f , 0.64917803f , 0.55163697f , 0.57240961f , 0.62231726f , 0.71731998f , + 0.22967499f , -0.05073000f , 0.51257014f , 0.53635363f , 0.90936842f , -0.47960537f , -0.60503509f , -0.38078624f , 0.72254161f , 0.43714553f , 0.48654362f , 0.43714660f , 0.18700370f , 0.03007471f , -0.39817882f , -0.59285823f , -0.75351375f , -0.75107912f , -0.77902788f , -0.82750373f , -0.72882091f , -0.75427284f , -0.57531634f , -0.37148640f , + -2.32676805f , -0.68486879f , -0.28456416f , -0.36791144f , -0.29071024f , -0.01135526f , 0.16172201f , 0.27899421f , 0.23877415f , 0.01902860f , -0.32670357f , -0.28942004f , -0.25341926f , -0.28159658f , 0.07050306f , 0.26414188f , 0.42045388f , 0.49934376f , 0.55163730f , 0.80964449f , 0.41444864f , 0.21371086f , 0.07501103f , 0.11308696f , + -0.27305539f , -1.16787053f , -1.40565538f , -0.99925137f , -1.11970497f , -0.87627497f , -0.63268066f , -0.40045797f , -0.40525654f , -0.06010181f , 0.13266298f , 0.44378479f , 0.45144645f , 0.18695876f , 0.55290900f , 0.78041480f , 0.94641486f , 1.00887739f , 1.70081287f , 2.26350129f , 2.47817098f , 2.59918260f , 2.79591047f , 2.78437201f , + -0.32246249f , -1.71452730f , -2.64055100f , -2.67577145f , -0.92654110f , 0.26408617f , -0.25926943f , 0.02139616f , 0.33878547f , 0.06917466f , 0.02594366f , 0.24868381f , 0.39107983f , -0.01529301f , -0.20036110f , 0.01057045f , 0.03136854f , 0.09346079f , 0.22821765f , 0.33206417f , 0.01105828f , 0.17529667f , 0.88221791f , 0.89873292f , + 0.93496823f , 0.51731100f , 0.04196463f , -0.75388451f , 0.47715970f , 0.54630853f , 0.18782570f , -0.38877496f , -0.07979449f , -0.12966809f , 0.12211422f , -0.22771599f , 0.03309780f , 0.02166307f , -0.05844436f , -0.17678384f , -0.32696150f , -0.45229639f , -0.40223728f , -0.45381663f , -0.55363514f , -0.44568304f , -0.41742550f , -0.27033009f , + 1.24789723f , -0.16270145f , -0.23526508f , -0.91495192f , 0.09192658f , 0.94791314f , 0.99514796f , 1.48011022f , 1.18575675f , 0.34462249f , 0.08649944f , -0.30288071f , -0.33154349f , -0.62323828f , -1.23683351f , -1.35258474f , -1.28447604f , -1.39540423f , -1.48493397f , -1.22352799f , -0.64023287f , -0.31408935f , 0.05098542f , 0.60709035f , + -1.28296443f , 0.30739631f , 0.06005469f , 0.20911344f , 0.24839533f , 0.32438667f , 0.52129460f , -0.19296009f , 0.56893959f , 0.27689822f , 0.19535841f , -0.28910358f , -0.03222614f , -0.11973675f , -0.43887472f , -0.57077656f , -0.49160952f , -0.12962890f , 0.67632833f , 1.51844798f , 1.92676111f , 2.40049046f , 3.14497224f , 4.02974673f , + 1.80516481f , -0.56393339f , -1.30448044f , -1.40495082f , -0.68191674f , -0.76180008f , -0.59977868f , -0.51019494f , -0.68339140f , -0.49281527f , -0.13376455f , 0.19985525f , 0.65099755f , 0.67547152f , 0.63174636f , 0.88059571f , 0.82474329f , 0.51834518f , 0.45799476f , 0.48269666f , 0.41156043f , 0.45527314f , 0.53753557f , 0.66268670f , + -1.55606025f , -0.20257947f , -0.14962756f , -0.99675497f , -1.37013665f , -1.22741192f , -0.99079753f , -0.49157059f , 1.03655475f , 1.41721212f , 0.93733685f , 0.23984335f , -0.04670573f , -0.46782519f , -0.11250628f , 0.37457349f , 0.70065238f , 0.30049206f , 0.12589128f , 0.00816302f , -0.30417620f , -0.55639550f , -0.97628459f , -1.33776955f , + -0.91978133f , 2.03647597f , 2.08783454f , -0.34357589f , -0.53113823f , -0.79082032f , -0.35484777f , -0.04415842f , -0.05569113f , 0.29670211f , 0.20802391f , 0.20847836f , 0.24786650f , 0.08187504f , 0.25883128f , 0.36261019f , 0.11231239f , 0.00938238f , 0.04224603f , -0.13883262f , -0.17357685f , 0.27783307f , 0.24645533f , 0.26199958f , + -0.61248405f , -0.07406218f , -0.61345974f , -1.32868141f , -1.08503963f , -0.61503512f , -0.40217073f , -0.50619739f , -0.34879559f , -0.33683180f , -0.13424100f , -0.05819325f , 0.01983650f , 0.38272624f , 0.44165965f , 1.08335723f , 1.55918521f , 0.91879734f , 0.66719572f , 0.40972477f , 0.11617552f , 0.02573831f , -0.13026683f , -0.32568351f , + 0.31463364f , -0.03452175f , -0.04820884f , -0.36356998f , -1.78279482f , 0.33915182f , 0.23383962f , 0.10388632f , 0.30795414f , 0.18689800f , 0.20754344f , -0.09819817f , 0.32111428f , 0.28504616f , 0.07722536f , -0.01904677f , -0.16255073f , -0.15042754f , -0.03877674f , 0.01867447f , -0.00999362f , 0.02968441f , 0.12366541f , 0.24417438f , + 1.09843253f , 0.09916156f , -0.26715787f , -0.21319307f , 0.17488666f , -0.03969684f , -0.42084276f , -0.26687268f , -0.54193150f , -0.73872758f , -0.38673483f , -0.31271029f , 0.04756063f , 0.03567565f , 0.10843090f , 1.00179157f , 1.33899024f , 0.51010916f , -0.26441522f , -0.71717032f , -1.14185896f , -1.44276220f , -1.62450955f , -1.61374667f , + -1.17644421f , -0.65722894f , -0.85514146f , -1.00555806f , 0.26053267f , 0.49309357f , -0.37877784f , -0.93210797f , -1.08883971f , -0.98901078f , -0.77758095f , -1.41471701f , -1.75752311f , 0.13457770f , 2.71551042f , 3.08606371f , 0.64870422f , 0.21086401f , -1.21315351f , -2.33440097f , 0.01456974f , 2.06478611f , 0.27046489f , 0.39813046f , + -0.48133789f , 0.05248478f , 0.15702810f , 1.09901110f , 1.05962736f , 1.17102152f , 1.55536593f , 0.44906344f , -0.41703175f , -1.12950682f , -0.93068802f , -1.09338708f , -0.91150200f , -0.48817666f , 0.10937607f , 0.37946930f , 0.24542719f , 0.26431763f , 0.67229593f , 0.65079198f , 0.00926221f , -0.87021868f , -1.26123155f , -1.41977363f , + 1.54426896f , 1.64264747f , 1.49559347f , 0.46249745f , 0.93411099f , 1.07714355f , 0.81133504f , 0.18134510f , 0.47877461f , 0.29451902f , -0.11266912f , -0.50269456f , -0.69526938f , -0.66772091f , -0.81400219f , -0.48607791f , -0.49953687f , -0.35945370f , -0.41495272f , -0.22003468f , 0.19724418f , 0.40213003f , 0.75369682f , 0.99864576f , + 0.09877598f , -0.24834930f , 0.70781761f , -0.02941638f , 0.04788121f , -0.17525416f , 0.24389545f , 1.27018837f , 1.54269729f , 1.25537489f , 1.40965823f , 0.83108228f , -0.00482938f , -0.57803168f , -1.40272349f , -2.04807395f , -2.39183907f , -2.28421278f , -1.59956397f , -1.84523910f , -1.49830221f , -1.32118632f , -1.41289179f , -1.07949145f , + -3.00057476f , -0.33414238f , 0.53147236f , 0.51026648f , 0.64656500f , 0.22188527f , 0.26159611f , -0.05358452f , 0.08996934f , -0.14007857f , -0.16740033f , 0.20548656f , 0.24617443f , -0.14274519f , -0.22696206f , -0.33493349f , -0.60597008f , -0.59551620f , -0.65068169f , -0.58018184f , -0.85498638f , -0.83283956f , -0.68903400f , -0.56704530f , + -1.80644488f , -2.09723761f , -2.47792833f , -2.51218612f , -1.89574511f , -1.52165564f , -1.43122992f , -1.31255781f , -1.17590463f , -0.75299628f , 0.13501040f , 1.04659662f , 0.78957362f , 1.33259798f , 1.48274046f , 1.92412844f , 1.37934388f , 1.51991312f , 1.53887225f , 1.07173430f , 0.52056336f , 0.89063725f , 0.75213286f , 0.48137117f , + -0.83123316f , -1.25502416f , -0.24000076f , -0.86042163f , -1.31788654f , -1.01630239f , -0.29559367f , 0.06110944f , 1.41025494f , 1.14012093f , 1.09233283f , 0.65906473f , 0.66635495f , 0.22542242f , -0.48939739f , -0.90887258f , -1.22778778f , -1.13528888f , -0.64749466f , -0.33117378f , -0.13886376f , 0.32663134f , 0.80397143f , 1.24264775f , + 0.02879094f , -0.40518021f , 1.01153472f , 0.24919166f , 0.21717242f , 0.73565158f , 0.11322127f , 0.18792292f , -0.13373281f , -0.08074408f , -0.11253388f , -0.16098838f , 0.11676604f , -0.16172666f , -0.26254412f , -0.20650902f , -0.25114318f , -0.21747560f , -0.22020914f , -0.32979603f , -0.32478632f , -0.30167186f , -0.14634515f , 0.05782533f , + -0.47454777f , -0.56928151f , -1.15476553f , -0.09623004f , 2.88751281f , -0.14714366f , -0.88522957f , 4.22040983f , 1.39699412f , -1.50292392f , -0.43572570f , -0.83179815f , -0.31636548f , -0.93272549f , -0.76482978f , -1.38859059f , -1.29829764f , -0.15529744f , 0.26864398f , 0.27166310f , 0.10090808f , 0.27140121f , 0.10246642f , -0.11585636f , + -0.83199745f , 1.25871280f , 2.32976268f , 1.04422262f , 0.72052750f , 0.58033767f , 1.01197514f , -0.00356009f , 0.64222581f , 0.17810713f , -0.27271599f , -0.30971603f , -0.36262209f , -0.59621272f , -0.71907027f , -0.37465802f , -0.49493312f , -0.23002788f , 0.22678857f , 0.61676427f , 1.15089995f , 1.45602224f , 1.73714565f , 1.76230856f , + 3.78596594f , 0.70843751f , 0.56143039f , 0.59983620f , 0.91117855f , 1.14938132f , 0.62640275f , 0.25328046f , 0.05444886f , -0.14074779f , -0.18351720f , -0.14467121f , -0.17323666f , -0.19046734f , -0.48709718f , -0.78123776f , -0.89375672f , -0.92818935f , -0.92156607f , -0.91479400f , -0.71603833f , -0.54172884f , -0.35025273f , -0.10097845f , + 1.88294702f , 1.24216466f , -0.99369851f , -0.70762866f , -0.80134642f , -1.57956697f , -1.53644146f , -0.73206309f , -0.05717919f , 0.79275997f , 0.73656524f , 0.59776925f , 0.89457859f , 0.27389259f , 0.55266497f , 0.42166521f , 0.43646218f , 0.18667357f , -0.37565357f , -0.34247443f , -0.46905572f , -0.54608498f , -0.46535569f , -0.51501131f , + -0.47999037f , 1.00431088f , 0.73194666f , 0.53070406f , -0.01938612f , 0.03027495f , 0.40371180f , 0.67811524f , 0.70405966f , 0.58218726f , 0.21637318f , 0.01593260f , -0.21413948f , -0.51479804f , -0.67811458f , -0.52916655f , -0.67532514f , -0.70141319f , -0.64914555f , -0.67794975f , -0.70067665f , -0.79806639f , -0.63846191f , -0.48442451f , + 1.27348348f , 0.96416420f , 0.39017217f , 0.71785608f , 1.03161791f , 0.22200744f , -0.65764394f , -1.59478709f , -0.95580133f , -0.45685571f , 0.24849072f , 0.90500271f , 0.94710102f , 0.11334884f , -0.15646077f , 0.15567420f , 0.19951531f , 0.06661949f , 0.16776497f , 0.92645175f , 1.51329143f , 1.99768327f , 2.23252155f , 2.82502657f , + -0.54469743f , 0.32018638f , 0.18026765f , -0.24717676f , 0.16334731f , 0.24119007f , -0.09150780f , -0.62258235f , -0.36174875f , -0.54007117f , -0.16902754f , 0.05782464f , 0.32844560f , 0.29531844f , 0.39903673f , 0.21807358f , 0.08243945f , 0.19009618f , 0.32130029f , 0.40374798f , 0.59707077f , 0.94425923f , 1.12228590f , 1.33995773f , + -0.11751559f , -0.41810808f , 0.01454897f , 0.64372292f , -0.51236310f , -1.28919088f , -0.27493502f , -0.15853449f , -0.26953216f , -0.08601421f , 0.47049578f , 0.62472064f , 0.47447185f , 0.17523033f , 0.30837586f , 0.34012918f , 0.19798450f , 0.18240973f , 0.24439643f , 0.37610178f , 0.25546586f , 0.34660852f , 0.25152738f , 0.33684884f , + 0.11066744f , 1.19858921f , 0.91132496f , 1.17666312f , 1.24521727f , 0.96210985f , 0.48787188f , -0.08729327f , -0.75696449f , -0.61950811f , -0.12399623f , -0.05243043f , 0.12080690f , 0.07846342f , -0.05639926f , -0.49681521f , -0.70132533f , -0.85192537f , -0.82039718f , -0.85401537f , -0.76376214f , -0.65987739f , -0.48460153f , -0.15410472f , + 0.35003846f , -1.71631424f , -2.46591563f , 0.87758858f , -1.81752528f , 3.13642054f , 1.73032547f , -0.09324163f , -4.01941823f , 1.53280929f , -1.80607033f , 0.38379815f , -0.60599486f , -0.15051943f , -1.06126256f , 0.92416849f , 1.84602853f , 1.75994867f , 0.99060749f , 0.70059849f , 1.55000269f , 0.30898296f , 1.89357287f , 3.39229864f , + 2.30088406f , 0.92343676f , 0.99415615f , 0.95404596f , 0.50656674f , 0.93824653f , 0.48608406f , -0.08446928f , -0.62418615f , -0.92839590f , -0.72113820f , -0.52847345f , -0.12827999f , 0.09174440f , 0.46989097f , 0.23658785f , 0.28508481f , 0.46040256f , 0.61632907f , 0.95774580f , 1.12674250f , 1.33598604f , 1.41647487f , 1.55101744f , + 1.37256353f , 0.97616384f , 0.91935645f , 0.81440269f , 0.66853976f , 0.62246830f , -0.20376912f , 0.03360847f , 0.43571616f , 0.50340338f , 0.23558369f , 0.34148923f , 0.26639247f , -0.42615485f , -0.66797929f , -0.78929117f , -1.01956966f , -1.04967706f , -0.83319766f , -0.38454933f , 0.01908745f , 0.54939284f , 1.31919448f , 1.91397573f , + -1.47177526f , -0.59088313f , -0.29040563f , -0.30391048f , -0.77025357f , -0.91705792f , -1.11779825f , -1.26663583f , -0.88813029f , -0.84447950f , -0.68067351f , -0.12550231f , 0.86719136f , 0.95700684f , 1.32696558f , 1.54042652f , 1.91879305f , 2.53765271f , 2.74382217f , 2.47883719f , 2.13313809f , 1.99482993f , 1.71839367f , 1.55253059f , + -2.18776004f , -2.01842604f , -2.26735458f , -1.91080096f , -2.94652547f , -2.30201691f , -2.55949436f , -2.06940788f , 0.81981691f , 0.88975503f , 1.36019848f , 1.20472608f , 1.42006397f , 0.61493222f , -1.18963425f , 0.41220219f , 4.34572607f , 4.43362932f , 4.07803194f , 5.02807593f , 3.44925570f , -0.33534871f , 0.49574672f , -0.89211792f , + 1.62466606f , 0.12019975f , -0.38782369f , -0.93423193f , 0.16258521f , -0.01564732f , 0.49181187f , 0.20589834f , 0.27352752f , 0.19483395f , 0.32141824f , -0.11470920f , -0.19458687f , -0.27925271f , -0.50960055f , -0.21759523f , -0.31856471f , -0.25540294f , 0.10383356f , 0.63132905f , 1.12834639f , 1.54942785f , 2.10497109f , 2.44084721f , + 1.80221933f , 1.34647425f , 0.68084866f , 0.26131343f , 0.06129242f , -0.20413381f , -0.25012623f , 0.26150026f , 0.34217016f , -0.25077441f , -0.03464205f , 0.00670185f , 0.11970509f , -0.18474450f , -0.02420872f , 0.04947295f , 0.10704821f , 0.12031899f , 0.25733107f , 0.20223825f , 0.14644252f , 0.05014131f , 0.25449839f , 0.53243125f , + 2.46777249f , 2.31564554f , 1.57449051f , -0.02405359f , -0.50178606f , -0.75371618f , 0.14778503f , 0.92907656f , 1.77413761f , 1.44803582f , 0.79871587f , -0.06867376f , -0.36229444f , -0.24911098f , -0.80167236f , -1.29799461f , -1.06250807f , -1.04778427f , -0.99914314f , -1.09969569f , -0.87609022f , -0.93824122f , -0.95461855f , -0.91327026f , + 0.43633316f , 0.85535629f , 0.60581035f , 0.16065427f , -0.07901143f , -0.12715680f , 0.03021654f , 0.07928964f , 0.11271867f , -0.14335296f , -0.24219156f , -0.11821250f , -0.20715557f , -0.14096772f , -0.04794024f , 0.21199596f , 0.67185756f , 1.28693268f , 1.69253449f , 2.02169124f , 2.03489721f , 2.18782692f , 2.32510550f , 2.13471256f , + 5.19702515f , 0.11666770f , -0.23856561f , -0.40839191f , -0.43762919f , -0.47738566f , -0.08391318f , -0.28626545f , 0.00298357f , 0.04540739f , 0.31909785f , 0.21196383f , 0.24548536f , -0.08426235f , 0.13111045f , 0.13639205f , 0.27647873f , 0.33171126f , 0.46017809f , 0.54387048f , 0.61603267f , 0.57095620f , 0.68776632f , 0.65010973f , + 0.58235537f , 0.52562482f , 1.05922702f , 1.60193935f , 0.43144897f , -2.92550999f , -2.57110854f , -1.17753807f , 0.19698968f , 1.02966008f , 0.68834236f , -0.11567313f , -1.07423611f , 1.53722962f , 2.83106005f , 0.31270547f , 0.83691800f , 0.60620087f , 0.21605402f , -0.37564956f , 0.38963810f , -0.55569948f , -0.83510003f , -0.45007941f , + -0.90035383f , 0.70316556f , 1.58896986f , 2.00202833f , 0.66804071f , -0.32729105f , 0.20493044f , -0.45491115f , -0.51617330f , -0.18761885f , -0.13361848f , 0.06806675f , -0.08803656f , -0.27485407f , -0.08086164f , 0.47587476f , 0.64596634f , 1.37554511f , 1.64271082f , 1.13804275f , 0.62642705f , 0.27157260f , 0.15530333f , -0.04178223f , + 2.19562225f , 0.68349947f , 0.14785409f , 0.07266666f , -0.11144618f , -0.52658551f , -0.77916859f , -0.76098098f , -0.55947105f , -0.61767060f , -0.18020839f , -0.26320634f , -0.03154415f , 0.41832030f , 0.98036861f , 1.17153463f , 1.26081153f , 1.58669565f , 1.96844912f , 2.21868662f , 1.28843850f , 0.48905790f , 0.12804274f , -0.25383240f , + 0.96587648f , 1.45558990f , 0.31977941f , -0.95024822f , -1.59243377f , -0.35590271f , -0.57251864f , -0.20900643f , 0.39660737f , 0.51169138f , 0.41734874f , -0.03711820f , 0.43311570f , 0.50214417f , 0.08955252f , 0.09513494f , 0.32141616f , 0.43401876f , 0.86976131f , 1.39503347f , 1.54833843f , 1.52864127f , 1.46114291f , 1.21933526f , + 1.78766271f , 1.61870712f , 2.29243952f , 1.45106025f , -0.02202545f , 0.12396735f , 0.05180173f , -0.74274249f , -0.04132082f , -0.01646827f , 0.04051846f , 0.10680231f , 0.03361298f , -0.26263042f , 0.29610433f , 0.25222625f , 0.18019271f , -0.22323513f , -0.68162437f , -0.96880693f , -1.29349030f , -1.78825246f , -2.63819014f , -3.24193152f , + -5.14372601f , 2.35480301f , 2.57594417f , 3.31674200f , 5.64389287f , 5.57674458f , 3.59322110f , -1.28598587f , -1.68632976f , -2.12796852f , -2.98396833f , -4.09489145f , -4.00821759f , -0.23400052f , 1.27890396f , 0.77129006f , -0.44287462f , -1.47029001f , -2.18546499f , -2.54400987f , -3.37996978f , -1.92988631f , -3.15537156f , -4.51816327f , + -0.35333284f , 0.05714033f , 1.24834935f , 0.52566638f , 0.41396899f , 0.74990328f , 0.95628046f , 0.44418709f , -0.34231956f , -0.14250584f , -0.59768493f , -0.64758317f , -0.22890844f , 1.10009034f , 0.66447430f , -1.03679499f , -1.33177125f , 1.17542516f , 2.21270353f , 1.90162759f , 1.20419817f , 0.83319667f , -0.52929949f , -2.16298435f , + 5.19114552f , 3.69595577f , 2.40462618f , 1.01495594f , 0.03903091f , 0.32991808f , -0.22330707f , -0.60000816f , -0.42237486f , -0.09093864f , 0.19458627f , 0.42022925f , 0.27603710f , 0.12695518f , 0.13428003f , -0.11234558f , -0.07201685f , -0.08582543f , -0.00938781f , 0.00835335f , 0.26546185f , 0.48668790f , 0.55514085f , 0.42743906f +}; + +const float cdk_37bits_3[1536] = +{ + -0.39555686f , -0.03651739f , -0.44779209f , 0.28023722f , 0.00089126f , -0.66214790f , 2.59448215f , -0.79382669f , -0.12742901f , -0.11647842f , 0.01833394f , 0.16500005f , -0.09845495f , -0.28459353f , -0.36237538f , 0.11970795f , -0.45285373f , -0.10504899f , -0.11812969f , 0.38858637f , 0.86990072f , 0.65514891f , 1.11998296f , 1.21258496f , + 0.22127561f , 0.04345828f , -0.01534097f , -0.09898785f , -0.26169093f , -1.42940674f , -0.62833523f , -0.43722472f , -0.03759617f , -0.48777744f , -0.21315437f , -0.50978248f , -0.03448283f , 1.37885110f , 2.31984917f , 0.94767797f , -0.60793975f , -1.49725519f , -0.82404584f , -0.79191239f , -0.41285081f , -0.57794113f , -0.59258055f , -0.52142849f , + -2.04397465f , -0.73672438f , -1.22406020f , -0.60820965f , -0.66350776f , -0.63508874f , 0.11396081f , 0.27852903f , 0.02122066f , -0.36929472f , -0.09692458f , -0.59306388f , -0.03445818f , 0.22347759f , 0.50874437f , 0.79690333f , 0.44886168f , -0.21185937f , -0.22593929f , 0.10528155f , 0.46293555f , 0.91816687f , 0.81749785f , 0.52952675f , + -0.83745738f , -1.08740279f , -0.81741019f , -0.19035650f , 0.26494816f , -0.53562479f , 0.07089504f , 0.57372383f , 0.54761482f , 0.03039794f , -0.04447253f , 0.12483594f , 0.21652272f , -0.29093744f , -0.18196704f , -0.42015965f , -0.35529408f , -0.64256034f , -0.65492788f , -0.67987885f , -0.90903026f , -1.04259245f , -1.11997561f , -1.06502927f , + 0.35909764f , -0.87235994f , -0.84471723f , -0.71941795f , -0.63106065f , -0.13584873f , 0.00035122f , 0.92117956f , 0.23226720f , 0.38257788f , 0.53266968f , 1.00892757f , -0.01254911f , -0.72578637f , -0.87564652f , -0.59001429f , -0.10713772f , 0.64583948f , 2.23457520f , 2.05203337f , -1.05813794f , -0.53728713f , -0.98376127f , -2.32960660f , + -0.37609544f , 0.57819159f , 0.36973473f , -1.59244337f , -1.38928585f , 0.17356612f , 0.05708517f , 0.55433790f , 0.59850517f , 0.28868283f , 0.11861574f , 0.18433235f , -0.05806802f , -0.05763413f , -0.27751060f , -0.18177730f , -0.00964178f , -0.38778247f , -0.57380279f , -0.56566098f , -0.62571613f , -0.59413960f , -0.61423645f , -0.79876589f , + 0.83478463f , -0.27534215f , 0.01524335f , -0.21639948f , -0.24423974f , -0.23618527f , -0.33317320f , -0.47935624f , -0.15249438f , -0.20363495f , 0.10344548f , -0.31742304f , -0.80171882f , -0.52313955f , 0.00839865f , 1.52844134f , 1.65181493f , -1.32088237f , -0.92249349f , -1.06298456f , -0.07484235f , -0.16968152f , -0.27904781f , -0.28263495f , + -0.35596324f , 0.22314830f , 0.17976713f , 0.03198763f , -0.12387166f , 0.15347508f , -0.07824379f , -1.73831583f , 0.24945724f , 0.50825939f , 0.37505775f , 0.09671258f , -0.42450737f , -0.00807859f , 0.43247130f , 0.47374177f , 0.08198413f , -0.17182369f , -0.24951122f , -0.40607268f , -0.34400714f , -0.49624679f , -0.37255649f , -0.39973249f , + -1.17006196f , -0.13172492f , -0.00974038f , 0.34580927f , -0.44057385f , 0.93062397f , 0.69327166f , 0.08607482f , -0.08210773f , -0.04718499f , -0.07694656f , -0.11915558f , -0.27321781f , -0.38372565f , -0.17058554f , -0.11705279f , 0.00039928f , -0.05191028f , -0.21529579f , -0.57393337f , -0.82568921f , -1.24107379f , -1.47599343f , -1.53248379f , + -0.21719645f , -0.19291913f , -0.75004495f , -0.71951649f , 0.47553953f , 1.38096577f , 1.04033311f , -0.03221815f , -0.86572179f , -0.39911324f , 0.01402460f , 0.13262858f , -0.09635214f , 0.32714710f , -0.23837385f , -0.85773163f , -0.88110961f , -0.98073890f , -0.79564795f , -0.61482268f , -0.51303751f , -0.17108237f , 0.13139182f , 0.33062304f , + -0.65971615f , -0.36376531f , -0.48204612f , -0.96580829f , -0.38529047f , -0.02620179f , -0.58558478f , -0.71688128f , -0.19952990f , -0.35258890f , 0.23812036f , 0.76018967f , 0.76511691f , -0.04406894f , 0.27021687f , 0.17352452f , 0.10253468f , 0.11128335f , 0.11180254f , 0.02374565f , 0.06920751f , 0.16750231f , 0.07976935f , 0.01873091f , + -0.56879426f , -0.30163117f , -0.21853853f , -0.53731934f , 1.94762983f , -0.40486765f , -0.45665477f , -0.68446479f , 0.29429121f , 0.03909750f , 0.15870855f , 0.44189594f , 0.50054032f , -0.21856641f , -1.18939515f , -0.79884717f , 0.37048428f , 0.68697692f , -0.60894758f , 0.22049746f , -0.40599348f , -0.85599586f , -1.02469575f , -1.24963523f , + -0.59195437f , -0.70945563f , -0.15260636f , -0.11149946f , -0.27565596f , -0.07645921f , 0.39497828f , 1.24678661f , 1.18358424f , 0.31430952f , -0.55975403f , -1.31101207f , -0.69091358f , 0.28078628f , -0.21792173f , -0.25137229f , -0.03764299f , -0.16055917f , -0.23425462f , -0.30830760f , -0.03132299f , -0.07131420f , 0.12064408f , 0.03452070f , + 0.64730537f , 0.25294955f , 0.59073653f , -0.02889400f , 0.46909137f , 0.64173464f , 0.30648456f , 0.11024926f , 0.62116350f , 0.28226056f , 0.21516616f , -0.18069190f , -0.26872093f , -0.28573023f , -0.55069608f , -0.59818666f , -0.76225667f , -0.64631598f , -0.73617734f , -0.72489209f , -0.60849158f , -0.66871466f , -0.59332250f , -0.53455648f , + -0.07107892f , -0.12362226f , -0.21667130f , 0.08342061f , -0.26377510f , -0.22955671f , 0.28415481f , -0.59587984f , 0.76501116f , 0.53927870f , -0.41773182f , -0.62604889f , 1.72550145f , 0.83771852f , -1.09720899f , -0.92889980f , 0.00835226f , -0.53818200f , -0.40166509f , -0.77584442f , -0.86058879f , -1.07506625f , -0.75645733f , -0.37900991f , + -0.86391437f , -1.56875806f , -0.59737022f , 1.47103303f , 0.58013388f , -0.61125685f , 0.21215056f , -0.82381155f , -1.02435909f , 0.44360022f , 0.46674660f , -0.24399003f , 0.05535292f , -0.13537148f , 0.53716959f , 0.38570703f , 0.15789830f , 0.82344300f , 0.71725375f , -0.08478097f , -0.19045110f , -0.30913951f , -0.71208241f , -0.41211249f , + 0.28300838f , 0.07819052f , -2.59554850f , 0.01513969f , 0.02275068f , -0.41900901f , 0.35308403f , -0.22328483f , -0.08406000f , -0.23448738f , -0.01463282f , 0.10979483f , 0.06169874f , 0.11653196f , 0.19591528f , 0.38801499f , -0.27219161f , -0.03580387f , -0.39412610f , -0.54966348f , -0.43187400f , -0.26346025f , 0.10805189f , 0.47603876f , + -0.44926755f , -0.27303642f , -0.70688129f , -0.60385437f , 2.03834457f , -0.29886385f , -0.37220015f , -0.40157890f , 0.00114372f , -0.55682607f , 0.18940701f , -0.90851567f , -0.11558088f , -0.30509965f , 0.37725906f , 0.36395947f , -0.01158594f , -0.11778388f , -0.08166158f , -0.00099729f , -0.03361890f , 0.17877023f , 0.46953351f , 0.60661120f , + -2.32090231f , 0.31006497f , 0.43589911f , 0.16050441f , 0.04916749f , -0.07132427f , -0.10907864f , -0.15235030f , -0.34310944f , -0.38589894f , -0.22420356f , 0.28262581f , 0.26288112f , 0.10104567f , 0.30661547f , 0.15586639f , 0.12838052f , 0.16339047f , 0.31122445f , 0.21703946f , 0.05094335f , -0.36066770f , -0.52001051f , -0.85195920f , + 0.81157773f , -0.87377611f , 0.35897335f , 0.97922466f , 0.21161336f , 0.61189108f , 0.09975497f , 0.85557541f , 0.44633554f , -0.06799683f , -0.82196168f , 0.18733624f , -0.11555839f , -0.46227977f , -0.84455317f , -0.28718848f , 0.18823232f , 0.02081597f , 0.20496005f , -0.18321698f , -0.53186346f , -0.76751019f , -0.82707771f , -0.93511852f , + -0.62789782f , -1.02899916f , -0.83398776f , 0.34736659f , -0.82847318f , -0.55517102f , 0.73944715f , 0.51603042f , -0.17541205f , -0.51297491f , -0.28031225f , 0.37534747f , 1.33255256f , 0.85299363f , -0.49866574f , -0.70931713f , -0.25347802f , 1.18650471f , 0.96320283f , 0.17951998f , 0.50223738f , 0.94745145f , 0.71031145f , 0.35981922f , + 0.25960499f , 0.20085615f , 0.66071489f , -0.39300998f , -1.04584452f , 0.68763487f , 0.24341422f , -0.44681709f , -0.42478638f , 0.35809846f , 0.23651606f , 0.24690213f , 0.02840220f , 0.15533695f , 0.09128538f , -0.06270472f , -0.06713015f , -0.25335122f , -0.38172369f , -0.13095063f , 1.38549753f , 1.56595584f , -0.79491152f , -1.69456364f , + 0.10124015f , 0.44268052f , 0.41947170f , 0.06998858f , -0.44403538f , -0.53833083f , -0.18012515f , 0.19801548f , 0.02848198f , 0.10328039f , 0.05547373f , -0.08134220f , -0.11347284f , 0.18716972f , 0.15052121f , 0.45578915f , 0.17825613f , -0.62982728f , -1.25893192f , -1.72372974f , -1.52843742f , -1.14720248f , -0.59782030f , 0.41304965f , + -0.65791072f , 0.50448348f , -0.22790188f , 0.65577284f , -0.41604305f , 0.48294798f , -0.01782262f , 0.11258538f , 0.45414723f , 0.46990532f , 0.18373223f , -0.25480101f , -0.03967844f , 0.14242292f , -0.18186310f , -0.44759830f , -0.48848859f , -0.23499694f , -0.00449827f , 0.06947204f , 0.24366262f , 0.18799436f , 0.16493984f , 0.07341900f , + -0.17084500f , -0.52693384f , -0.15426250f , -0.36638752f , -0.08888879f , 0.42508938f , 0.70488045f , 0.35337658f , -0.31440288f , -0.95905412f , -1.39777356f , -0.73044215f , -0.21780251f , 0.16276937f , 1.17947648f , 0.62166831f , 0.26018916f , -0.29948472f , -0.58195133f , 0.45241574f , -0.06192729f , -0.35749657f , -0.32541389f , -0.31290178f , + 1.03333306f , -1.91050021f , -0.13109130f , -0.32248959f , -0.38101335f , 0.00494321f , -0.25107010f , -0.01681079f , 0.21943144f , 0.25121705f , 0.18563785f , 0.03636768f , -0.10100837f , 0.06649688f , -0.00664293f , 0.05595170f , -0.06422094f , -0.11002354f , -0.10109236f , 0.01090687f , 0.06631093f , 0.07976458f , 0.15739108f , 0.10857007f , + -0.33199571f , -0.56448889f , -0.45287501f , -0.05693402f , 0.05942782f , -0.02093585f , -0.20271071f , 0.55906399f , -1.15218041f , 0.70760814f , 0.15200578f , 0.36721991f , -0.31006992f , 0.02414406f , 0.01873367f , -0.06168544f , -0.14084190f , 0.06391549f , -0.04024367f , -0.07702959f , -0.02899824f , -0.00754099f , 0.01931078f , 0.01310811f , + 0.69225346f , 0.84703204f , -0.19222695f , 0.59171381f , 0.90355259f , 1.04460186f , 0.42894358f , -0.70178829f , -0.37391764f , -0.32821766f , -0.50107079f , -0.39470843f , -0.47521936f , -0.30884997f , -0.01935248f , 0.29822241f , 0.42715252f , 0.30438803f , 0.02378992f , -0.17775730f , -0.46267559f , -0.55927080f , -0.39468999f , -0.38547224f , + 0.04236230f , 0.43024591f , 0.23320886f , -0.03322528f , 0.26547627f , 0.40419917f , -1.88256953f , 0.33336965f , 0.43032431f , 0.34945524f , 0.14640688f , 0.26111890f , 0.09050959f , 0.02378679f , 0.10374918f , -0.14167201f , -0.38323030f , -0.20424346f , -0.07877651f , -0.15358523f , -0.29084030f , -0.28534203f , -0.27854188f , -0.38414543f , + -1.35067299f , 0.93458694f , 1.52963743f , -0.47674751f , 0.63038639f , 0.04082455f , 0.01396927f , 0.26394766f , 0.21929233f , 0.30917185f , -0.05098944f , -0.21646126f , -0.06968916f , -0.21403511f , -0.42684368f , -0.24236372f , -0.25734336f , -0.24137196f , -0.18847818f , 0.05790433f , 0.47029098f , 0.74262516f , 1.02334770f , 1.07200952f , + 1.83813338f , 0.07329820f , -0.57353904f , -1.04253446f , -0.37247340f , 0.27885340f , -0.44127016f , -0.52596624f , -0.25949219f , -0.21831662f , -0.08737252f , 0.35876725f , 0.27309909f , 0.22976268f , 0.34570166f , 0.21284816f , 0.20626047f , -0.06110003f , -0.17056277f , -0.33205968f , -0.17877150f , -0.36375995f , -0.42667310f , -0.49148755f , + -0.22303223f , -0.61782734f , 0.07221479f , 1.17445515f , 2.13609068f , 1.76589885f , -0.17154121f , -0.54143140f , 0.11077396f , -0.12473649f , -0.52786787f , -0.05194147f , -0.44717763f , -0.76381778f , -0.72611078f , -0.52076079f , -0.13782787f , 0.23657528f , 0.01943847f , 0.24767381f , 0.39174174f , 0.63263104f , 0.63997347f , 0.76935917f , + 0.38916423f , 0.50423553f , -0.21980701f , -0.78548685f , 0.21972204f , -1.43872473f , -0.00193477f , 0.36744541f , 0.16700668f , 0.15377980f , 0.47950705f , 0.29978828f , -0.11417606f , 0.16176485f , -0.11482538f , -0.05361745f , -0.12586636f , -0.09325236f , -0.14811836f , -0.05048373f , 0.10243041f , 0.21861802f , 0.33250117f , 0.27345191f , + -0.16468513f , -0.37910979f , 0.57141664f , 0.42620144f , 0.44428971f , -0.54448346f , -0.05612505f , -0.02298608f , 0.53916950f , 0.25456592f , -1.10661655f , 0.40146315f , 0.12765698f , 0.17879679f , -0.07731271f , 0.01866167f , -0.15740825f , -0.28894193f , -0.34340439f , -0.43682656f , -0.22326149f , -0.09309579f , 0.16725751f , 0.19673331f , + -0.65757909f , -0.55769769f , 0.11252773f , -0.72975912f , -0.94079760f , -0.62713476f , -0.11981244f , -0.17247533f , -0.14738685f , -0.31158412f , 0.07368734f , 0.03103339f , -0.13215125f , 0.34103810f , 0.63393867f , 0.60552884f , 0.76554800f , 0.90960605f , 0.91659500f , 0.66527593f , 0.30424524f , 0.11961615f , -0.11209393f , -0.30051986f , + -0.82645253f , -0.59100209f , 0.39970568f , 0.22244794f , -1.28440435f , -0.46429652f , -0.43824168f , -0.32298820f , 0.10465933f , 0.69271672f , 0.92760147f , 0.82494517f , 0.34287482f , 0.34953026f , 0.02628626f , -0.35943701f , -0.39877485f , -0.31291814f , -0.37557165f , -0.14676958f , -0.17425675f , -0.18461930f , -0.05110559f , -0.07497296f , + 0.63983165f , -0.34339191f , -1.28647231f , -0.91450456f , -0.67728709f , 0.49126298f , 0.96821534f , 0.31300605f , 0.20917849f , 0.12659990f , -0.36342261f , -0.39963395f , 0.03244120f , -0.41837324f , -0.14271340f , -0.19770449f , 0.05878109f , 0.55231761f , 1.04404725f , 1.05536545f , 0.78016416f , 0.27780151f , 0.09224589f , -0.32156570f , + 1.30003273f , 1.10615566f , 0.93319181f , -0.31410562f , -1.16956697f , 0.45520743f , 0.46104645f , 0.18090068f , 0.31535574f , 0.12164263f , -0.04591607f , -0.26863484f , -0.02921210f , -0.15765476f , -0.25295046f , 0.08951494f , 0.29990800f , 0.46529486f , 0.49388104f , 0.48334578f , 0.56975339f , 0.86976618f , 0.99832143f , 1.00030209f , + -0.55945569f , -0.48562099f , -0.51312465f , 0.17718364f , -0.05557705f , -0.12420531f , -0.24644329f , -0.21879889f , 0.30085953f , 0.00211036f , -0.18180571f , 1.26296385f , 0.36245046f , -1.20467536f , -1.38107334f , 0.51651968f , 0.96691210f , -0.21489415f , -0.08106702f , 0.07733171f , 0.44486220f , 0.65985117f , 0.65337579f , 0.40205936f , + -0.30605618f , 0.02127030f , 0.13771863f , 0.12191376f , 0.08563477f , -0.00381708f , -0.81881216f , -0.82260335f , -0.43603699f , 1.36965455f , 4.16686363f , -1.70970343f , -0.32019699f , -0.11951735f , -0.80947648f , -0.47446757f , -0.10775129f , 0.04114059f , -0.30054633f , 0.64175035f , 0.82115142f , 0.62944370f , 1.08179899f , 1.57667179f , + -0.66788387f , -0.77237720f , 1.52623021f , 0.85040444f , 0.35492746f , 0.85358404f , 0.78207517f , 0.43130368f , -0.54845102f , -0.71654944f , -0.60068901f , -0.12408427f , -0.01179498f , 0.53882278f , 0.31915828f , -0.32987316f , -0.94788725f , -0.40099308f , -0.01063294f , -0.38326806f , -0.01161978f , -0.21941390f , 0.02258487f , 0.25904448f , + 0.79869030f , -0.85517012f , -0.65115608f , -0.04355956f , -0.43731619f , -0.71616470f , -0.30302847f , 0.88809204f , 0.05112801f , 0.10303432f , 0.13671577f , 0.57965072f , 0.32487238f , 0.33649929f , 0.01540811f , -0.25814148f , -0.72026311f , -1.15836561f , -1.20004844f , -0.81812408f , 0.41446837f , 1.03057194f , 1.42461866f , 1.82616342f , + 0.17675536f , -0.27924845f , 0.71723708f , 0.57533161f , -0.11526653f , 0.43395839f , -0.24166179f , -0.76071716f , -1.50945411f , -1.22484500f , -0.26852216f , 1.13903054f , 1.01376035f , 0.64844913f , 0.40121308f , 0.49004723f , -0.00594971f , -0.16285024f , -0.35446584f , -0.43396060f , -0.49929653f , -0.30312166f , -0.52537515f , -0.70337166f , + -0.01631724f , 0.04545139f , 0.53843851f , -1.98110624f , 0.42385228f , 1.10982161f , 0.08204933f , -0.22120343f , 0.22170428f , -0.13084571f , -0.38312127f , -0.33942169f , -0.35304155f , -0.04620752f , -0.20644844f , -0.11783954f , -0.03944293f , 0.22733974f , 0.19411990f , 0.20591734f , 0.35857215f , 0.26680777f , 0.13225980f , 0.03751274f , + 1.65876005f , 0.44487285f , 0.74939639f , 0.18365303f , -0.43020202f , -0.60237220f , -0.25419435f , 0.68333923f , 1.41188058f , 0.97222943f , 0.24472516f , -1.22113362f , -0.78612825f , -0.11991861f , 0.13256744f , -0.36248959f , 0.33181909f , 0.32143886f , 0.23857089f , 0.00232431f , 0.32728111f , 0.18236067f , 0.19458883f , -0.13449373f , + 1.01250205f , 0.78159362f , 0.01261799f , 0.68249798f , 0.04319542f , 0.35059328f , 0.74464616f , 0.84844350f , -0.11329224f , 0.41294739f , 0.18293144f , 0.20984708f , -0.58769014f , -0.80150375f , -0.51500468f , -0.35048400f , -0.42362303f , -0.36779032f , -0.28994050f , -0.23359131f , -0.06578403f , -0.05881381f , 0.08966738f , 0.00019544f , + 0.70403072f , 0.78285193f , 0.28511894f , 0.00755209f , -0.37995087f , -0.72155263f , -0.99707384f , -0.74737344f , -0.22877183f , -0.13565785f , -0.46966212f , 0.04900542f , 0.26640966f , 1.14596859f , 0.60401715f , 0.82513938f , 0.79006003f , 0.37851130f , 0.22098744f , 0.20295618f , 0.31645545f , 0.57600633f , 0.77757957f , 0.75482137f , + -0.31257984f , -0.82866492f , 0.10257062f , 1.11051690f , -0.28919177f , -0.56055958f , -0.92349260f , 0.14536629f , 0.59860128f , 0.38979660f , 0.36223511f , -0.54044378f , -0.36717720f , -0.11683797f , 0.76699709f , 0.24571187f , 0.28893468f , 0.47314073f , 0.42211323f , 0.40023200f , 1.13398057f , 1.09318885f , 0.78306966f , 0.51052587f , + 0.64453179f , 0.37582288f , -1.11900539f , 0.74031316f , 1.04873921f , -0.40828504f , -0.81838582f , -0.17966094f , -0.05226590f , -0.65864031f , -0.31516753f , 0.18237239f , -0.05159927f , 0.21789484f , 0.08749049f , 0.24120803f , 0.70600965f , 0.64124786f , 0.42083380f , -0.09773141f , -0.23606513f , -0.38900548f , -0.47036719f , -0.54328594f , + 0.19215906f , 0.37207957f , 0.52832092f , -0.35006098f , 0.09333668f , -0.08723831f , 0.13342910f , 0.37870962f , 0.31836369f , -1.28479417f , 0.33703877f , 0.14237789f , 0.05993876f , 0.02873350f , 0.23865068f , -0.04501394f , -0.31343410f , -0.18101341f , -0.24548541f , -0.25187640f , -0.07255855f , -0.10957046f , -0.11231929f , -0.28412748f , + -0.68394190f , 1.32649088f , -0.20251428f , 0.26341125f , 0.12047780f , -0.18276225f , 0.16509523f , 0.52338615f , 0.59701878f , -0.23303681f , -0.39329168f , -0.08757063f , -0.16628726f , -0.65649992f , -0.39211601f , 0.17386600f , 0.53243333f , 0.71723255f , 0.49078614f , 0.24827219f , 0.06289971f , -0.05734434f , -0.11833561f , -0.22187979f , + 0.39633308f , 0.04156044f , 1.06101733f , 0.27315319f , 0.59336180f , -0.53703174f , 0.16228868f , 0.13114487f , 0.27822076f , 0.36752801f , 0.19860881f , 0.02973693f , -0.43825412f , -0.58401569f , -0.28187681f , 0.04818616f , 0.03285983f , 0.13037889f , 0.11038839f , 0.02272515f , -0.23535124f , -0.61140662f , -0.80591081f , -1.04033145f , + -0.13968644f , -0.06564459f , 0.18157254f , 0.33968636f , -1.65427724f , -0.73513587f , 1.04378907f , 1.88232308f , -0.37664399f , -0.27362352f , -0.33476530f , 0.38907833f , 0.34755286f , -0.33257534f , -0.02008915f , 0.33980081f , -0.27671777f , -0.19240561f , -0.07016053f , 0.46780800f , 0.13346733f , 0.34947591f , 0.60154010f , 0.24323917f , + -0.39262699f , 0.20645882f , 0.64129296f , -0.83583673f , -0.02829965f , -0.15644726f , 0.05838216f , 0.14551091f , 0.14988963f , 0.11803820f , -0.32326940f , 0.68272158f , 0.31487041f , 0.19785659f , -0.39751586f , -0.35328008f , -0.40849303f , -0.08677978f , 0.86709071f , 2.23822727f , 1.53306955f , 0.78362429f , -0.23530753f , -0.72391215f , + 0.65081318f , -0.18880278f , -0.46498433f , 0.26852197f , -0.77114484f , 0.03361544f , -0.35148506f , 0.22060019f , 0.18248041f , -0.12293613f , -0.11807126f , 0.14429704f , 0.05679295f , 0.22972542f , 0.12354306f , 0.16318102f , 0.20910602f , 0.08354589f , -0.24387542f , -0.29604028f , -0.70475015f , -1.05341049f , 0.01797512f , 4.10874675f , + 0.45835477f , 0.01993812f , -0.04065773f , -0.15665852f , -0.42264630f , -0.36060614f , -0.43907429f , -0.66069837f , -0.24237031f , 0.15215315f , 0.03612217f , 0.24708032f , 0.55884560f , 0.72918318f , 1.75786010f , -0.70099106f , -0.65499421f , 0.89851270f , 1.07676113f , 0.70864260f , -0.27784651f , -0.35596115f , -0.12995875f , 0.20579609f , + 0.41191636f , 0.62621815f , 0.09298962f , 0.55341001f , 0.56857786f , 0.43563939f , 0.36112747f , 0.91004762f , -0.20875537f , -0.76286980f , -0.80355493f , -0.57667740f , -0.12055277f , 0.03202311f , 0.30982039f , 0.02801005f , -0.17407837f , 0.00238884f , -0.00072431f , 0.20627903f , 0.75917669f , 0.94538134f , 1.07598898f , 1.25330200f , + 1.62660683f , -0.09939473f , 0.66227464f , 0.58551798f , 0.70671700f , 0.17084690f , -0.20901679f , -0.40736809f , -0.48424703f , 0.03110675f , 0.17837373f , 0.15654547f , 0.05523718f , -0.00011673f , -0.03885655f , -0.10282160f , -0.05607837f , -0.02472319f , -0.02603773f , 0.16068736f , 0.49195589f , 0.53877406f , 0.64916929f , 0.58349185f , + -0.19541004f , 0.72348145f , 0.18424396f , -0.24664098f , -0.06871482f , 0.69420972f , 0.47406100f , -0.17312110f , -2.04415513f , -0.25411034f , -0.27524224f , 0.06647737f , 0.24326809f , 0.16942888f , 0.40718778f , 0.35988573f , 0.40128652f , 0.49142944f , 0.60191512f , 0.34882977f , 0.16989975f , 0.24984840f , 0.27163863f , 0.15321543f , + -0.44196663f , -0.26819397f , 0.67190611f , -0.18646133f , 0.45381660f , 1.11913414f , -0.16504930f , -0.57004245f , 0.12959909f , 0.01138749f , -0.36040681f , -0.97442716f , -0.87831396f , -0.14292832f , 0.42648657f , 0.25148162f , 0.69831357f , 1.48191698f , 1.27272976f , 0.11336886f , -0.87051097f , -0.59490814f , -0.81852032f , -1.19619968f , + -0.25757408f , 0.54305128f , -0.79688385f , -0.60924273f , -0.12316087f , 0.11158591f , -0.87972153f , -0.44243737f , 0.18336137f , 0.70958050f , 0.65996224f , -0.03788380f , -0.46562482f , -0.32237563f , -0.18491199f , 0.26669422f , 0.52467917f , 0.59451930f , 0.79600063f , 0.90689924f , 1.13895471f , 1.44288125f , 1.66630190f , 1.46406996f , + 0.88003703f , 2.56458597f , 1.71193850f , 1.65285002f , 0.72084892f , 0.38643126f , 0.14318446f , 0.28667315f , -0.19288261f , -0.16566274f , -0.31005972f , -0.49025502f , -0.18453165f , -0.14612403f , -0.04808515f , 0.01128747f , -0.01064585f , -0.12855927f , -0.22958706f , -0.19555403f , 0.02963856f , -0.01023782f , -0.12652262f , -0.10513883f , + 0.66279753f , 2.42221261f , -0.08766251f , -0.72413474f , -0.21245882f , -0.28173391f , -0.45644329f , -0.27322613f , -0.26135706f , -0.00095259f , 0.27722008f , 0.50181970f , 0.53741922f , 0.02301582f , 0.05101261f , 0.08308112f , 0.01205931f , 0.03237543f , -0.19025538f , -0.25886072f , -0.65187116f , -0.67398548f , -1.14025176f , -1.58932661f , + 0.17921058f , 0.08258647f , 0.33959227f , 1.72037280f , 1.38344521f , -0.23430972f , -0.50065409f , 0.00856925f , 0.28114664f , 0.27461748f , 0.31709158f , 0.82901212f , -0.15113492f , -0.25813352f , -0.41877594f , -0.81233724f , -0.71788760f , -0.16907758f , 0.19973863f , 0.33985209f , 0.02718327f , 0.32739235f , 0.74128769f , 0.93245569f +}; + +const float cdk_37bits_4[1536] = +{ + -0.08826527f , -0.68186913f , 0.10838073f , -0.43643363f , -0.41527175f , -0.55730727f , -0.34319791f , -0.40335689f , -0.41236590f , -0.43762241f , -0.34979692f , 0.20670516f , 0.56648629f , 0.45153526f , 0.24057949f , 0.52851143f , 0.92657151f , 0.59941681f , -0.15803439f , -0.97113347f , -0.53306250f , -0.15122053f , -0.25212109f , -0.21018566f , + 0.39520775f , -0.06876283f , -0.05296158f , 0.73104266f , 1.42403499f , 0.45421406f , -0.17043922f , -0.74733849f , -0.66305214f , -0.55365607f , -0.35289753f , -0.04055727f , -0.10593728f , -0.05024752f , 0.12627425f , 0.32227232f , 0.35862945f , -0.33025092f , -0.42097571f , -0.51789189f , -0.43150446f , -0.42237163f , -0.31356874f , -0.35919061f , + -1.66468995f , 0.28333893f , -0.63138470f , 0.25282895f , 0.81464016f , 0.43544261f , 0.16598498f , 0.21343499f , 0.04430694f , 0.04005313f , -0.09506983f , -0.40633891f , -0.37109338f , -0.10155129f , -0.25586130f , -0.50829977f , 0.02467106f , -0.22449907f , 0.00822338f , 0.18455191f , 0.25447269f , 0.12288496f , -0.09567011f , -0.30095943f , + -1.15666522f , -0.30930290f , 0.13432561f , -0.59224171f , -0.36982119f , -0.52250238f , 0.01911206f , -0.29889977f , 0.45230096f , 0.40142558f , 0.43793893f , 0.22627276f , 0.37598261f , 0.32984874f , -0.34803841f , -0.44638526f , -0.25723637f , -0.50369445f , -0.26783820f , -0.30872225f , -0.55499601f , -0.40533391f , -0.26323584f , -0.01148310f , + -0.04584967f , -0.38971238f , -0.56823951f , -0.32006352f , 0.38538708f , 0.18254611f , -0.62235892f , 0.18540613f , 0.48716625f , 0.35551317f , -0.19313758f , 1.16846919f , -0.41238633f , -0.43448740f , -0.28924472f , -0.56314872f , -0.24952920f , -0.08133851f , -0.17676199f , -0.70674324f , -0.52120829f , -0.49147628f , -0.40464508f , -0.25295616f , + -0.12422787f , -0.29459301f , -0.33474318f , 0.11311031f , -0.95766270f , 2.14261486f , -0.53791490f , -0.26163905f , -0.11342229f , -0.12540336f , -0.14724319f , -0.04078408f , -0.08162598f , 0.06846590f , 0.12489534f , -0.11390681f , 0.04214135f , -0.23484961f , -0.25483115f , 0.02702444f , -0.54449830f , 0.02294024f , -0.03270780f , -0.30881716f , + -0.51664184f , 0.87599163f , -0.82321314f , -0.48734917f , -0.18432637f , -0.09096773f , 0.20625230f , -0.20173932f , -0.40150868f , -0.29584636f , -0.57602568f , 0.25241069f , 0.25168301f , 0.41489722f , -0.15401326f , 0.31749293f , 0.46187393f , 0.14218968f , 0.29387424f , 0.35642876f , -0.05757794f , -0.25296762f , -0.36044236f , -0.53221886f , + 0.51447760f , -0.80338660f , -0.87861055f , 0.14544497f , 0.05095110f , -0.51385736f , 0.05449902f , 0.17409103f , 0.19329486f , -0.46366308f , -0.07068299f , 0.20485704f , -0.47646816f , 0.35635013f , 0.34452862f , 0.42683101f , -0.28134904f , -0.21080113f , 0.00849886f , 0.33035851f , 0.26195824f , 0.51184835f , 0.52439902f , 0.46235637f , + 0.32433320f , -0.77116443f , -0.37467928f , -0.05050502f , -0.47203456f , 0.07970732f , 0.03804198f , -0.34236150f , 0.41937760f , 0.42124343f , -0.03903765f , -0.03019702f , -0.13800061f , -0.47850547f , -0.79736222f , 0.61109423f , 0.72782314f , -0.09672306f , -0.16557727f , 0.16492016f , -0.11908040f , -0.37060885f , -0.80248368f , -1.06315439f , + 0.61844207f , -0.52687155f , -0.68500569f , 0.65092780f , 0.43851285f , -0.21063978f , -0.35770140f , 0.29858871f , -0.24062148f , 0.02631244f , -0.33422324f , -0.66271400f , 0.44374236f , 0.53668473f , 0.31036600f , -0.08124190f , -0.16668944f , -0.32551675f , -0.33450272f , -0.55269795f , -0.29912814f , -0.14136754f , 0.00094991f , 0.10863138f , + -1.02908550f , -1.08600196f , -0.00829438f , -0.14868032f , -0.00876750f , 0.35258516f , 0.23126957f , -0.61722565f , 0.07518664f , 0.16350336f , -0.12544307f , -0.06302285f , -0.20747087f , 0.16364178f , 0.11301830f , 0.14409114f , -0.22179807f , 0.02183975f , 0.08651544f , 0.10457808f , 0.28231708f , 0.45543402f , 0.44769940f , 0.39725637f , + -0.54707227f , -0.02419958f , -0.37616905f , -0.46877412f , -0.64214865f , 0.24761536f , 0.28016618f , 0.62399842f , -0.01700123f , -0.06949885f , -0.19266995f , 0.09365999f , 0.49890228f , 0.24080752f , 0.23087678f , -0.34184149f , -0.95236318f , -0.94491904f , -0.91565308f , -0.37099678f , 0.27911164f , 0.41946017f , -0.09527805f , -0.32953030f , + -0.01218671f , 0.22317147f , 0.12463154f , -0.28374239f , -0.37139030f , -0.11082455f , -0.20149460f , 0.02373646f , -0.33497796f , -0.14613409f , 0.84054162f , -0.89918850f , 0.07544184f , 0.26598709f , 0.27674891f , 0.20394454f , 0.37767382f , -0.42106119f , -0.34271983f , -0.11246076f , 0.03134837f , -0.21267097f , -0.66433234f , -0.79249183f , + 0.68565476f , -0.34282863f , -0.68036436f , -0.63475767f , -0.29231604f , -0.10656705f , 0.47040998f , 1.11298872f , 0.05838917f , -0.14239264f , -0.38985619f , -0.25211584f , -0.07283441f , -0.47047779f , -0.10102956f , -0.06816871f , 0.25442684f , 0.17135717f , 0.18068089f , 0.10725115f , -0.11463252f , -0.09624811f , 0.03206543f , 0.07087342f , + -0.29936977f , -0.49951612f , 0.56346184f , 1.11727567f , 0.05118005f , -0.78169038f , -0.22318233f , -0.13012064f , 0.42376494f , 0.27511994f , -0.06809198f , 0.10660060f , -0.13063709f , -0.08794603f , 0.26570905f , 0.03292540f , 0.26637413f , -0.19894586f , -0.46401960f , -0.28512188f , -0.39238542f , -0.32134023f , -0.64138162f , -0.88237115f , + -0.84203625f , 0.64837205f , -0.17913585f , -0.02044868f , 0.01755708f , 0.10928040f , -0.42224314f , -0.62418953f , -0.76712318f , 0.28173569f , 0.49961967f , 0.56539632f , 0.38946613f , -0.52975196f , -0.01398100f , 0.29168654f , 0.20212686f , -0.45414046f , -0.32780637f , -0.17832453f , -0.04055271f , 0.14063062f , 0.09399186f , 0.04073656f , + -0.59723568f , -0.77426417f , 0.23870880f , -1.09302554f , -0.22352372f , -0.10808799f , -0.30228652f , 0.70554939f , 0.06689791f , -0.27543124f , -0.16109074f , 0.39983998f , 0.14600029f , 0.02701649f , -0.30161728f , -0.00219904f , 0.02886825f , -0.00025967f , 0.06332021f , 0.53722019f , 0.26361456f , 0.43646772f , 0.61394343f , 0.42109711f , + -0.43760700f , -0.21770975f , -0.32449972f , 0.91826996f , 0.24783245f , -0.14194616f , 0.59717550f , -0.04725228f , -0.61148813f , 0.06530696f , 0.35852872f , 0.21424802f , 0.01537298f , -0.15430889f , -0.27459726f , -0.13011870f , -0.13872373f , -0.36362740f , -0.43974823f , -0.43751521f , -0.54202762f , -0.19719673f , 0.06386372f , 0.18442456f , + -0.08864543f , -0.55051998f , 0.10076329f , 0.20816090f , 0.53932942f , 0.15080000f , 0.00551145f , 0.12469664f , 0.10528548f , -0.05291477f , 0.52671815f , 0.10465375f , -0.40110729f , -0.11191133f , 0.98775607f , -0.67510753f , -1.30383213f , 1.28526656f , 0.19125450f , -0.16824100f , -0.63934107f , -0.41185818f , -0.34166262f , 0.14722503f , + -0.16958138f , -0.70266121f , -0.61550966f , -0.70951491f , 0.42067433f , -0.58598257f , -0.58567156f , -0.37146356f , -0.36153853f , 0.34830089f , 0.34255947f , 0.14665779f , -0.08274605f , 0.14596150f , 0.21786608f , 0.24560479f , 0.11959326f , 0.23920513f , 0.20309485f , 0.35852167f , 0.22083612f , -0.09433997f , -0.51773984f , -0.76810711f , + 0.09032751f , 0.42679636f , -0.28534103f , 0.21660665f , 0.47417813f , -0.81135171f , -0.99303930f , 1.17719925f , 0.70112272f , 0.00612786f , -0.26326442f , -0.41083270f , 0.28491165f , -0.02087201f , -0.14822163f , 0.12923365f , -0.12446203f , -0.33986599f , -0.41895285f , -0.31072727f , -0.31061808f , -0.24015583f , -0.23486759f , -0.36395849f , + -0.07413177f , -0.34521290f , -0.06577322f , -0.64923405f , 0.33496936f , 0.33223433f , -0.43032623f , -0.15153657f , -0.14532386f , 0.04384948f , -0.14353961f , -0.38067294f , -0.90445571f , 0.05745547f , 0.26321275f , 0.13427661f , 0.99048885f , 0.70150503f , 0.21638320f , -0.53518619f , -0.89368294f , -0.06732509f , 1.44618313f , 1.52346980f , + -0.28620228f , -0.41428071f , 0.03283058f , 0.28330900f , 0.28721719f , 0.17075826f , 0.19511151f , -0.13348216f , -0.35836936f , -0.41912925f , -0.65172261f , -0.20553457f , -0.41361716f , 0.03912969f , 0.74818546f , 0.38929433f , 0.35198685f , -0.18892266f , -0.42973273f , -0.08121690f , 2.93312199f , -0.89377191f , -1.04200958f , -0.38574966f , + -0.45622789f , 0.07453795f , -0.34784213f , -0.29222109f , -0.09713884f , -0.10453434f , 0.40596355f , -0.23133264f , 0.41138969f , -1.10624661f , 0.19522464f , -0.26295831f , 0.14668871f , 0.07972137f , 0.02069833f , 0.17917700f , 0.36376602f , 0.04686613f , 0.14326025f , -0.04095238f , -0.08246401f , 0.10201219f , 0.02758839f , -0.05655397f , + 0.29630435f , 0.03831385f , -0.10935451f , -0.91468053f , -0.14403908f , 0.12338524f , -0.16558686f , -0.53411536f , 0.34582072f , 0.52105737f , -0.73269102f , 0.15549081f , 0.34042874f , -0.08059104f , 0.05497700f , -0.00373706f , 0.11991085f , -0.06473005f , -0.19246960f , -0.28678310f , -0.43241128f , -0.23538086f , -0.03713469f , 0.08379386f , + 0.24034079f , -0.09568759f , -0.02338538f , -0.28961237f , 0.06180378f , 0.64449270f , -0.53964132f , -0.44965638f , 0.57702251f , -0.03990858f , 0.57093562f , -0.24702367f , 0.69686569f , -0.17564347f , -0.35201424f , -0.37152787f , -0.37484725f , -0.30144848f , -0.16064783f , -0.31374403f , -0.12815488f , 0.29541890f , 1.03104505f , 1.30178989f , + -0.18534500f , -0.41427735f , 0.20831804f , 0.44386174f , 0.06978829f , -0.00025745f , 0.37126911f , 0.56198427f , 0.54344631f , 0.75983386f , 0.08924900f , -0.25144457f , -0.16739214f , -0.47225391f , -0.61115204f , -0.61044836f , -0.28294647f , -0.15658827f , 0.07254076f , 0.04689538f , -0.03222463f , 0.00609252f , -0.03612525f , -0.09035452f , + 0.60889737f , 0.57807827f , 0.48410386f , -0.25108080f , -0.40924958f , 0.41713615f , 0.28334831f , 0.28268008f , 0.18075099f , -0.57117890f , -0.14971473f , 0.56189026f , -0.05567028f , 0.08252752f , -0.38305721f , -0.11908417f , -0.11953224f , -0.37400723f , -0.53048221f , -0.67201768f , -0.81958382f , -0.72027064f , -0.69311476f , -0.64712434f , + 0.22806651f , -0.36466423f , 0.42139538f , -0.34809071f , 0.16113471f , 0.17305177f , 0.79041909f , 0.11514622f , 0.04984584f , -0.14552208f , -0.37364685f , -0.61589400f , -0.26900080f , 0.26941075f , 0.20621872f , 0.13740956f , -0.49840209f , -0.54283296f , -0.52674918f , -0.53961784f , -0.37838808f , -0.22626697f , -0.23072639f , -0.20714483f , + 0.22144144f , 0.45530098f , 0.02934419f , -0.39899990f , 0.47181905f , 0.60295507f , -0.31589266f , 0.03503805f , 0.49654681f , -0.28248396f , -0.72402223f , -0.56858893f , 0.36486216f , 0.18158649f , -0.28256161f , -0.05020847f , 0.07122169f , 0.39556004f , 0.21779191f , 0.05943418f , 0.03455314f , -0.20122464f , -0.56175660f , -0.70861941f , + -0.12710089f , -0.34168755f , 0.51452312f , -0.34309463f , -0.18691030f , 0.49423846f , 0.78364805f , -0.16785659f , -0.68812345f , -0.24302951f , 0.18166059f , 0.09288723f , 0.25148875f , -0.56074443f , -0.33594006f , 0.09135379f , 0.28739172f , 0.63070785f , 0.16827578f , -0.09962802f , -0.38532235f , -0.56717197f , -0.69999986f , -0.97131938f , + -0.20318779f , -0.43550878f , 0.28264744f , -0.23992796f , 0.53190281f , -1.67612143f , 0.16592080f , 0.32242290f , 0.02740567f , 0.27409947f , -0.33298480f , -0.17137320f , 0.21066429f , 0.33840225f , -0.04092118f , 0.12976302f , 0.22063896f , 0.16238007f , 0.17740193f , 0.08810713f , -0.07588522f , 0.07136235f , 0.03907713f , 0.05669444f , + 0.74722369f , -0.21436950f , 0.74573008f , -0.38452217f , -0.62996036f , -0.61276966f , -0.34962832f , 0.01277742f , -0.04862746f , -0.36596994f , 0.22701717f , 0.22604413f , 0.19192867f , 0.43170927f , 0.32434957f , 0.29115238f , 0.30256436f , 0.32053789f , 0.47183832f , 0.56834074f , 0.41355131f , 0.30787160f , -0.05129232f , -0.37603415f , + 0.80624702f , -0.27464628f , 0.11826867f , 0.51984849f , 0.30134746f , 0.32731312f , 0.63578587f , -1.05098699f , -0.28256566f , 0.33641143f , 0.13788720f , 0.12207550f , 0.20964871f , -0.01396386f , -0.00315097f , -0.38868646f , -0.33190516f , 0.01254611f , 0.31412245f , 0.37172503f , -0.22028709f , -0.31539130f , -0.40227820f , -0.43477628f , + 0.48923265f , 0.77885034f , 0.09105701f , 0.57339326f , 0.40328303f , 0.76432879f , 0.86958428f , 0.61756568f , 0.03118874f , -0.56167934f , 0.04763708f , -0.27535056f , -0.56173692f , -0.35211845f , -0.21863091f , -0.57438481f , -0.18963688f , -0.01259367f , 0.18407625f , 0.57694011f , 0.26272878f , -0.04854515f , -0.05438820f , -0.03358252f , + -0.32142589f , 0.79436655f , -0.02373648f , 0.14911871f , 0.27451076f , -0.21064653f , -0.58233970f , -0.20841755f , -0.04707995f , 0.10160263f , 0.52370023f , 0.13469981f , 0.48437770f , 1.02370491f , -0.06404425f , -0.46008443f , -0.96962303f , 0.11051949f , 0.15222102f , -0.53779110f , -0.69372709f , -0.56309673f , -0.29040815f , -0.29949982f , + -0.02231366f , 0.22164658f , -0.18303626f , 0.03930299f , 0.85381138f , -0.35733905f , 0.09213505f , 0.01422806f , 0.45077065f , 0.33125549f , 0.13969212f , 0.00376337f , -1.11355683f , -0.42167326f , -0.19924204f , 0.06780255f , 0.13817913f , -0.13055957f , -0.04191829f , -0.08880165f , 0.10967999f , 0.21611496f , 0.31814813f , 0.31439510f , + 0.42170246f , 0.33624593f , -0.22613320f , 0.60027671f , -1.43986794f , 0.19361445f , 0.38787661f , 0.02591482f , 0.79456209f , 0.02551988f , -0.24845033f , -0.02790537f , 0.03271750f , -0.04445081f , 0.20502713f , 0.08570910f , 0.00909955f , -0.01248239f , -0.03298340f , -0.22777710f , -0.18913055f , 0.02764977f , 0.28305459f , 0.38851360f , + 0.25563805f , 0.33212894f , -0.80098121f , 0.09743245f , 0.06159913f , 0.59881048f , -0.33440346f , -0.49422089f , -0.26800689f , -0.34799111f , 0.00914211f , -0.24239391f , -0.35363956f , 0.18782859f , 0.53150753f , 0.27966626f , 0.37170277f , 0.02903349f , 0.11708475f , 0.18129252f , 0.35350094f , 0.51909923f , 0.57702624f , 0.56023430f , + -0.25681505f , 0.10481743f , 0.07691052f , -0.09602954f , -0.12447488f , -0.40272478f , -0.23240515f , -0.09172820f , -0.10406663f , 0.06799629f , 0.27877064f , 0.65360435f , 0.03477472f , -0.16610473f , 0.19640957f , 1.14225362f , -1.25460658f , -0.02280781f , 0.26718410f , 0.23326014f , -0.33868542f , -0.77563600f , -0.57910551f , 0.35682550f , + -0.44901076f , -0.41537996f , -0.76495288f , 0.42209785f , -0.90605030f , -0.39625885f , -0.28278183f , -0.06062198f , 0.12423915f , 0.20756261f , 0.19484825f , 0.03259953f , 0.41379186f , 0.19062025f , -0.02691834f , 0.12202985f , 0.38700297f , 0.61084418f , 0.41389101f , 0.42854542f , 0.07894843f , -0.08730420f , -0.19947308f , -0.20746447f , + 0.35263591f , -0.04388326f , -0.07294209f , -0.12542102f , -0.45217599f , -0.41959012f , -0.16900409f , 0.23194458f , 0.50540516f , 0.34564113f , -0.05519304f , -0.13052083f , -0.52610268f , 1.51200111f , 0.14243612f , -0.89107328f , -0.09550049f , -0.11976748f , 0.61738910f , 0.29385419f , -0.11218523f , -0.32931430f , -0.63743116f , -0.70832695f , + -0.52572193f , -0.16054333f , 0.67450855f , -0.68123993f , -1.06059852f , 0.25289129f , 0.72282093f , -0.17789928f , -0.04826238f , 0.65623860f , 0.30053556f , -0.04214508f , -0.65996229f , -0.19030221f , -0.07583416f , -0.15972053f , 0.48267006f , 0.29268192f , 0.54289151f , 0.30262687f , 0.55040148f , 0.38139609f , 0.22629776f , -0.10333201f , + -0.27722537f , 0.16931190f , -0.18986341f , 0.46255996f , 0.03451865f , 0.64648839f , 0.27927689f , -0.04817246f , -0.29637504f , 0.15848257f , -1.17177626f , 0.76705595f , 0.04986266f , -0.23619169f , 0.02130871f , -0.09247797f , -0.11246955f , -0.06979877f , -0.02858714f , 0.14146741f , 0.19316987f , 0.19281260f , 0.10108870f , 0.10991318f , + 0.57222024f , -0.09056345f , 0.31630312f , 0.09441631f , -0.48881639f , -0.26079169f , 0.28649904f , 0.47374236f , -0.92331796f , 0.56274886f , 0.19988114f , -0.33923171f , 0.45935192f , 0.66439754f , 0.09172813f , -0.58992377f , -0.13650098f , -0.00871775f , 0.05177348f , 0.29646543f , 0.22271673f , 0.29255650f , 0.32416359f , 0.37254208f , + 0.69873728f , 0.67827523f , -0.09873129f , -0.19519793f , -0.20388503f , -1.14639862f , 1.00268628f , -0.34199196f , 0.32858454f , 0.30752466f , -0.20180165f , -0.78353972f , -0.46150042f , 0.07066704f , 0.27017563f , 0.59315620f , 0.56514267f , 0.61730776f , -0.04109619f , -0.10375384f , 0.17107510f , 0.00671267f , -0.14460000f , -0.15704504f , + -1.08061540f , 0.25499966f , 1.21906248f , 0.18773257f , -0.32071123f , 0.34341071f , -0.31815992f , -0.09070897f , 0.28772196f , -0.36343715f , -0.43262838f , -0.03519430f , -0.08578842f , 0.04235681f , 0.22568464f , 0.41761967f , 0.33042161f , -0.16644760f , -0.20508813f , -0.34930117f , -0.25591130f , -0.03775689f , -0.04290093f , -0.14027967f , + 0.08954841f , 0.28400971f , 0.09640325f , 0.28015051f , -0.28901197f , -0.15938324f , -0.08647304f , 0.07096579f , -0.01533652f , 0.16784761f , 0.40365967f , 0.69056044f , -0.07072517f , -1.35839862f , 0.69003689f , 0.27081222f , -0.31318076f , -0.34628327f , -0.20433566f , -0.03988210f , 0.00227372f , 0.31880868f , 0.48586232f , 0.50530210f , + -0.10787652f , -0.54593003f , -0.06872456f , 0.08196332f , 0.32589906f , 0.59080671f , -0.46869291f , 0.51602298f , -0.65588957f , -1.15841782f , 0.46249030f , 0.28794341f , 0.03773606f , -0.22824300f , 0.08237000f , 0.11514488f , 0.09347876f , 0.31037616f , 0.25764090f , 0.16707290f , -0.00830484f , -0.01436382f , 0.04324129f , 0.08340130f , + 0.03635043f , 0.84751295f , 0.19029027f , 0.81160060f , 0.30403111f , -0.74745208f , 0.29141206f , 0.02554821f , -0.18681161f , -0.31641374f , -0.22117775f , 0.29307885f , 0.09884843f , -0.01001690f , 0.22991570f , 0.23960184f , -0.00030044f , -0.15515938f , -0.08622738f , 0.18116527f , 0.27032171f , 0.46691225f , 0.50791118f , 0.39209784f , + -0.58545217f , 0.80964945f , -0.18596625f , 0.05021434f , -0.60299753f , 0.01922541f , -0.09160450f , 0.71858494f , -0.20405914f , 0.12967029f , -0.19928245f , -0.41958358f , -0.73480796f , 0.27037925f , 0.59526072f , 0.43722623f , 0.08228142f , 0.13617314f , 0.16733195f , -0.17519530f , -0.15926519f , -0.04255070f , 0.08047599f , 0.02040241f , + -0.00463376f , 0.49611447f , -1.05764249f , -0.45817246f , 0.34650208f , -0.41315007f , 0.05117591f , -0.11590274f , 0.37210637f , 0.48788495f , 0.24580028f , -0.23874213f , 0.25067272f , 0.14486146f , -0.39195005f , -0.32974271f , -0.40998318f , -0.01004687f , 0.30386464f , 0.58853426f , 0.58687081f , 0.54124172f , 0.43891894f , 0.42482843f , + 0.06344340f , -0.06291464f , 0.30075410f , -0.01321988f , 0.11824609f , -0.36844623f , -0.22861175f , 0.44459133f , -0.10414380f , -0.41394982f , -0.26948513f , 0.10771022f , 2.01283344f , -0.48227800f , -0.85226571f , -0.05678206f , 0.09386327f , -0.32036269f , -0.09589284f , 0.11469854f , -0.02254415f , 0.26286370f , 0.24740398f , 0.30259810f , + 0.33675212f , 0.40803791f , 0.04656053f , 0.26235019f , 0.19124535f , 0.26174937f , -0.25007840f , -0.02874094f , 0.42657886f , 0.23713035f , 0.49137649f , -0.40631813f , -0.19729730f , -0.47353514f , -0.68684985f , -0.22225676f , 0.65537217f , 0.85454345f , 0.28736774f , -0.76858865f , -0.51993839f , -0.41223097f , -0.20210503f , 0.20680273f , + -0.32962876f , 0.99852252f , 0.90359799f , -0.72414673f , 0.40343042f , -0.04753735f , 0.12703283f , -0.50454354f , -0.49092182f , 0.07106628f , 0.04340118f , -0.20701432f , -0.00051299f , 0.41281149f , 0.48992497f , -0.07229812f , -0.22500199f , -0.38166508f , 0.00136486f , 0.19527238f , 0.46266022f , 0.52478433f , 0.49346943f , 0.55712590f , + 0.31231089f , -0.39507041f , 0.09233836f , 0.29644040f , 0.63936696f , -0.05632462f , 0.45315617f , -0.80271529f , 0.87935975f , -0.65177909f , -0.03975780f , 0.24344094f , 0.09139584f , -0.12641456f , -0.28974809f , -0.00440121f , -0.33446897f , 0.27455940f , 0.26598867f , 0.38959619f , 0.56355605f , 0.28858433f , -0.01329721f , -0.28521977f , + 1.21529134f , 0.05567950f , 0.26633834f , 0.01854368f , -0.56750884f , -0.64133765f , 0.12896192f , -0.25287368f , 0.00098562f , 0.46355571f , 0.30342317f , 0.60024559f , 0.45154622f , -0.23111479f , -0.07558175f , 0.04573468f , -0.22655397f , -0.38765071f , -0.39593191f , -0.33701184f , -0.03367326f , -0.00117395f , -0.08805175f , -0.08317989f , + 0.50206060f , -0.26397493f , 0.62403702f , 0.18840209f , -0.03554397f , 0.51126843f , -0.93620939f , 0.11466485f , -0.32354822f , 0.83573095f , 0.44043951f , -0.03326486f , -0.30990227f , -0.17807718f , -0.15678795f , 0.05137581f , 0.01928613f , 0.10898749f , 0.05153834f , 0.41224367f , 0.33750201f , 0.31515600f , 0.18742162f , -0.00543668f , + -0.32506550f , 1.39874024f , 1.05365357f , 0.20758975f , -0.52204159f , 0.23139865f , 0.89916776f , 0.88500307f , 0.58319149f , 0.64447478f , 0.60029914f , -0.39017287f , -0.48396982f , -0.45642499f , -0.41136891f , -0.85726305f , -0.72300890f , -0.76044173f , -0.54961686f , 0.13241207f , -0.38074475f , -0.31668368f , 0.18757575f , 0.89325609f , + 0.91423867f , 0.16949588f , -0.34930052f , -0.67767124f , 0.56381557f , 0.23625492f , 0.19384698f , 0.11556592f , -0.81768557f , -0.12373743f , 0.28726562f , 0.47434410f , 0.01976064f , -0.20909300f , -0.17968366f , -0.16456765f , -0.39581902f , -0.17030977f , -0.12522965f , 0.10547945f , 0.19050607f , 0.32547806f , 0.37610928f , 0.47194674f , + 0.50904911f , -0.87540838f , 0.44606989f , 0.16315214f , 0.04897779f , 0.44593548f , 0.58835263f , 0.23188759f , -0.04829018f , -0.47929534f , 0.01140653f , -0.52090906f , -0.08282465f , -0.47750687f , 0.00555375f , -0.02147925f , 0.29824067f , -0.09639830f , 0.04586002f , 0.81704610f , 1.02414420f , 1.00254358f , 0.93128379f , 0.86145793f , + 1.39640260f , 0.48600888f , 0.05812317f , 0.43032939f , 0.28626623f , -0.02572580f , -0.71026460f , -0.08052560f , -0.00321850f , -0.06166357f , -0.14918683f , 0.02044791f , 0.20449299f , -0.07389050f , 0.20856068f , 0.37499893f , 0.00961555f , 0.34856300f , 0.38826685f , 0.17380148f , 0.08518823f , 0.24834931f , 0.18030421f , 0.02885498f , + -0.14822571f , 0.59831391f , 0.80084782f , 0.65079236f , -0.37659866f , 0.02590007f , -0.43987457f , -0.47916614f , -0.09009334f , 0.00944784f , 0.38989625f , 0.72812391f , -0.25740561f , 0.30660597f , -0.10786678f , -0.04283082f , 0.33341247f , 0.56382527f , 0.36883485f , 0.19482792f , 0.20864518f , 0.30357803f , 0.21469035f , -0.00709814f , + -0.55721230f , -0.02926194f , 0.02222842f , 0.65955295f , 0.85507986f , 0.02606033f , -0.38236616f , 0.08681374f , -0.37079998f , 0.08312060f , -0.32595363f , -0.28424983f , 0.08744855f , 0.15171748f , -0.41262446f , 0.16415023f , 0.32175904f , 0.54372269f , 1.03276331f , 0.88586548f , 0.61435324f , 0.53755072f , 0.50108183f , 0.43471867f +}; + +const float cdk_37bits_5[1536] = +{ + -0.08458486f , 0.28094300f , -0.74427850f , -0.27121451f , 0.26225532f , 0.58828870f , 0.49469996f , 0.00671892f , 0.49956583f , -0.09194914f , -0.14439356f , -0.21589493f , -0.71932281f , -0.31712426f , -0.17322443f , -0.02668573f , -0.16316907f , -0.26011802f , -0.29961334f , -0.04510044f , -0.03045680f , -0.07408609f , -0.04966348f , 0.02019735f , + 0.16785217f , -0.12154415f , -0.11294764f , -0.50188502f , 0.37048745f , 0.01220048f , -0.42438767f , -0.39739743f , -0.09963068f , -0.01937236f , -0.38029066f , -0.09631205f , 0.17779303f , 0.55220057f , -0.27361767f , -0.01993755f , 0.59841836f , -0.81488799f , -0.50629196f , 0.04276219f , 0.50927647f , 0.32204460f , -0.05252335f , 0.00479347f , + -0.70183618f , -0.55990950f , -0.21828823f , 0.06948525f , -0.25175959f , 0.38514843f , 0.03565709f , -0.02286728f , -0.65965565f , -0.11708316f , 0.08641334f , -0.03958833f , -0.28740740f , 0.11907652f , 0.76730012f , 0.00002225f , -0.01526722f , 0.19057067f , -0.00116506f , -0.29043894f , -0.20613074f , -0.36670968f , -0.38149597f , -0.21397652f , + -0.20108924f , 0.01696758f , -0.63540490f , 0.48931316f , -0.10610658f , -0.30699680f , 0.42198382f , -0.11596909f , 0.56113924f , -0.19428230f , -0.31623064f , 0.01575740f , 0.47412599f , 0.01231773f , 0.03554178f , 0.04445166f , -0.52597131f , -0.38112781f , -0.41082892f , 0.02325108f , -0.03762488f , -0.10886600f , -0.30284977f , -0.25935547f , + -0.06153986f , -0.50865639f , 0.00873904f , -0.53985972f , -0.17321488f , -0.20024719f , -0.43903590f , 0.30867295f , 0.15257025f , 0.50412756f , 0.15585453f , 0.18716871f , 0.04465249f , 0.05395055f , 0.02286270f , -0.10569980f , -0.51109990f , -0.62598156f , -0.29411790f , -0.40475676f , -0.34305943f , -0.21692205f , -0.39934499f , -0.51704391f , + -0.73658870f , -0.68665226f , -0.06126038f , 0.66114991f , 0.35329723f , -0.17434640f , -0.20490335f , 0.00027985f , 0.04182559f , -0.12920453f , 0.35128407f , 0.36339554f , 0.47399902f , -0.25062146f , -0.38289190f , -0.23332452f , -0.20826575f , -0.16079639f , -0.14129191f , 0.18519827f , 0.08984042f , 0.01018800f , -0.07526643f , 0.16613248f , + 0.24459641f , -0.54593305f , -0.17413054f , 0.01221675f , -0.28335532f , -0.03597407f , -0.12785960f , -0.20546625f , 0.69946433f , 0.14655906f , -0.07567982f , -0.41903852f , -0.05404835f , -0.57786831f , 0.75099347f , 0.04385018f , 0.13817541f , 0.54561726f , 0.22589567f , 0.09746529f , 0.26583628f , 0.26558035f , 0.21082406f , 0.14352723f , + -0.61059536f , 0.25826720f , 0.08276875f , -0.29062272f , -0.22379136f , 0.27302107f , -0.39399985f , -0.90988239f , 0.68577814f , -0.07398823f , 0.29343711f , -0.02555969f , 0.17350828f , 0.10446548f , 0.05915310f , -0.12814425f , 0.16515519f , 0.23084429f , -0.07631257f , -0.12135962f , -0.32154020f , -0.35925975f , -0.31657161f , -0.17517095f , + -0.31345423f , 0.04713846f , -1.07240463f , 0.55819357f , 0.25919851f , -0.17080554f , -0.44683706f , 0.42549491f , -0.24160926f , 0.39135254f , -0.27273104f , -0.08747624f , -0.17073595f , -0.64858648f , 0.31353107f , 0.40731596f , 0.24294678f , -0.16681178f , 0.01469568f , -0.30776696f , -0.15317629f , -0.18218388f , -0.16911268f , -0.19813229f , + 0.25482069f , -0.02943669f , -0.39498625f , -0.32329009f , 0.10426426f , -0.22095104f , 0.29062234f , -0.15434571f , -0.12708599f , -0.10669553f , 0.33786459f , -0.20904693f , 0.49652844f , -0.62850056f , 0.21568910f , -0.21446226f , 0.21630725f , -0.08720906f , -0.52065307f , -0.35255320f , -0.59625366f , -0.43541450f , -0.28092364f , -0.00125747f , + 0.31917512f , -0.03488145f , -0.21380884f , -0.22835427f , -0.66217994f , -0.29555406f , 0.17821074f , -0.34530315f , -0.20166763f , -0.01021963f , 0.39444938f , -0.06786073f , -0.22698498f , 0.34432475f , 0.51326058f , 0.57986123f , -0.20027416f , -0.13834155f , -0.20880162f , 0.06494356f , -0.27871271f , -0.15747416f , -0.07939462f , 0.08519511f , + -0.57600983f , 0.33019806f , 0.38068317f , 0.13486793f , 0.61770011f , -0.42574210f , -0.17565397f , 0.32588004f , -0.07069465f , -0.12991907f , 0.10503579f , -0.53981949f , 0.27628270f , -0.40433813f , 0.56048034f , -0.11134494f , -0.02721288f , -0.02679116f , -0.03457161f , 0.00691900f , 0.35272657f , 0.02987130f , -0.37220393f , -0.73576355f , + -0.31901782f , -0.23550305f , 0.50511762f , 0.07681936f , -0.20832096f , -0.16180683f , 0.33639474f , 0.24607809f , 0.51978014f , -0.51511613f , 0.53433180f , -0.38461866f , -0.30344206f , 0.21738925f , 0.23262923f , -0.26642016f , -0.24689764f , -0.35119228f , -0.37163953f , -0.19926461f , -0.12294480f , -0.07264335f , -0.14869303f , 0.01600622f , + -0.32318991f , -0.06337691f , -0.16327790f , 0.01679607f , 0.54615398f , -0.13948782f , -0.07235812f , -0.31344026f , 0.21344099f , -0.56249237f , -0.54817142f , -0.38900153f , 0.08560375f , 0.51752999f , 0.09695531f , 0.45163870f , 0.11365917f , -0.03998578f , -0.10961891f , -0.25154202f , -0.53037031f , -0.51729631f , -0.12010728f , 0.27211617f , + -0.21869866f , -0.20612331f , -0.17148894f , -0.69131811f , -0.48874096f , 0.17532938f , 0.65606235f , 0.17337859f , 0.21369284f , -0.02261284f , -0.23113547f , -0.37691677f , 0.06425787f , 0.33138072f , -0.19000900f , -0.50235478f , 0.19744901f , -0.01426938f , 0.25673560f , 0.14800389f , 0.08629656f , -0.05995416f , -0.01856833f , 0.09638624f , + -0.68051548f , 0.42111210f , 0.16966116f , -0.18012337f , -0.66642379f , 0.11078652f , 0.51684818f , 0.04482584f , -0.37389220f , 0.07070225f , -0.22594402f , -0.24882296f , 0.28791258f , 0.16045673f , 0.13211217f , 0.30258098f , -0.11104291f , -0.34144481f , -0.61517912f , -0.45406688f , 0.24175899f , 0.43530490f , 0.33387051f , 0.31684453f , + -0.12348130f , 0.28844356f , -0.15230272f , -0.92611369f , 0.15595514f , 0.40309213f , -0.21089949f , -0.12710732f , -0.20149432f , 0.08709137f , 0.79880608f , 0.16826794f , -0.10477000f , -0.40397699f , -0.33124317f , -0.16915306f , -0.06502590f , 0.05657812f , 0.16028923f , 0.14994150f , 0.07722317f , 0.24695981f , 0.20225272f , 0.10946385f , + -0.31130776f , 0.09164996f , -0.10763487f , 0.00805002f , -0.37620293f , 0.04961005f , 0.18879671f , 0.12802431f , -0.14881133f , 0.00106507f , 0.20381895f , -0.01208542f , -0.02377667f , 0.48285147f , -1.19207093f , 0.60998154f , 0.08913394f , 0.16312199f , -0.15986004f , -0.18489974f , -0.26700574f , -0.10480556f , -0.03699614f , 0.39930124f , + -0.45078318f , -0.11456599f , -0.27898753f , -0.42503588f , 0.17516712f , -0.19617643f , 0.31818611f , -0.08178737f , -0.05417727f , -0.23405407f , -0.39611520f , 0.32937074f , -0.20757027f , -0.46769544f , 0.04745269f , 0.30856677f , 0.45826247f , 0.41349579f , 0.21491292f , 0.22174480f , 0.16553832f , 0.28625395f , 0.24514041f , 0.37926658f , + 0.24936771f , -0.04104704f , 0.27238824f , 0.16392268f , -0.06110497f , -0.02187308f , -0.14403711f , 0.49428075f , 0.66634565f , 0.04308588f , 0.20773125f , -0.07283823f , -0.03584369f , -0.15180729f , -0.21954145f , -0.16147124f , -0.54353183f , 0.31850719f , 0.70992696f , 0.77482366f , -0.73614329f , -0.70442321f , -0.77208369f , -0.52036749f , + -0.40407749f , -0.55580682f , 0.40834797f , 0.13313598f , 0.11194755f , -0.02575282f , 0.56373574f , -0.17680698f , -0.31347570f , 0.88388781f , -0.66229966f , 0.14478038f , -0.15586756f , -0.36242692f , -0.35125580f , -0.05976233f , 0.40268536f , -0.01780960f , -0.30415813f , -0.40711933f , -0.20657081f , -0.11416314f , -0.11392091f , 0.03499209f , + -0.02442649f , 0.00289107f , -0.42318484f , -0.77861141f , -0.21018343f , -0.02530250f , -0.05457845f , 0.29013785f , 0.27545606f , -0.54534532f , -0.28075430f , 0.48908889f , 0.44803264f , -0.23493075f , 0.30537914f , -0.17571639f , -0.28136367f , 0.41087545f , 0.06067306f , -0.07891926f , 0.13675464f , -0.23523981f , -0.64950230f , -0.84513939f , + 0.33320458f , -0.21239429f , 0.16584185f , 0.20947136f , -0.84373112f , -0.18662477f , -0.39277353f , 0.27160507f , 0.33045634f , -0.07972757f , 0.26989965f , -0.31828606f , 0.29166908f , 0.02792893f , -0.23589507f , 0.24680072f , 0.61805079f , 0.29297283f , -0.46279502f , -0.38853021f , -0.06845241f , 0.13809046f , 0.18584514f , 0.19851158f , + -0.01509547f , -0.42006585f , -0.02742765f , 0.01387587f , 0.04496372f , 0.33032099f , -1.33568146f , 0.04497330f , -0.13953978f , 0.17866902f , -0.22504135f , 0.03714148f , 0.42265213f , 0.48557283f , 0.09517080f , 0.08189501f , -0.02136855f , 0.18181835f , 0.26310442f , 0.14522422f , -0.00551997f , -0.08059227f , -0.01368360f , 0.19964321f , + 0.06879672f , -0.16572126f , -0.21275410f , -0.00047311f , 0.38956134f , 0.68791295f , 0.06981244f , 0.44725155f , -0.37536280f , -0.07016804f , -0.31450647f , -0.12757190f , 0.15884699f , -0.28116715f , -0.24072947f , 0.06964482f , -0.41365933f , -0.30556059f , 0.01412066f , 0.09088293f , -0.05730716f , 0.11902320f , 0.49328583f , 0.76218521f , + 0.14607820f , 0.36882839f , 0.31158718f , -0.18015097f , 0.37885733f , 0.09807226f , -0.69643398f , 0.00209062f , 0.07841871f , -0.15108867f , -0.16550965f , 0.49051298f , -0.13918703f , -0.16017141f , 0.15622856f , 0.32246753f , -0.21434589f , -0.12839098f , -0.62492818f , -0.41789280f , -0.33687252f , 0.15910414f , 0.40538907f , 0.45768888f , + -0.18246786f , 0.69660292f , -0.53239726f , -0.39785530f , 0.09269434f , -0.20090783f , 0.24169380f , 0.14920210f , -0.20929912f , 0.37639575f , -0.02298151f , 0.29037766f , -0.30134500f , 0.12924066f , 0.34148084f , -0.65422266f , -0.23263549f , 0.15293804f , -0.12172724f , -0.29655807f , -0.15215394f , -0.01750734f , -0.02878360f , 0.05063806f , + -0.26703187f , -0.12751254f , -0.03617813f , 0.00622364f , 0.22547815f , -0.57779029f , -0.13343456f , 1.59832374f , -0.86975741f , -0.37492672f , -0.39567028f , 0.18249899f , 0.04481957f , 0.29481366f , 0.13046647f , -0.10097157f , -0.02397564f , 0.04106330f , -0.32215387f , -0.06647077f , -0.19483820f , -0.47627356f , -0.28788121f , -0.35042823f , + 0.02227780f , -0.19386416f , -0.30157912f , 0.12610552f , 0.56722223f , -0.09994132f , -0.02285657f , -0.61753835f , 0.08410488f , 0.73128591f , 0.37298647f , -0.77570729f , -0.22843919f , 0.11891633f , -0.03551507f , -0.10041180f , 0.00489754f , -0.03082396f , -0.09347646f , -0.15507942f , -0.14360267f , -0.08927711f , -0.16377833f , -0.01469311f , + 0.56852461f , 0.23796399f , 0.13182028f , -0.25577917f , -0.33910792f , 0.34056262f , -0.02495276f , -0.05880465f , 0.05430314f , -0.53287936f , -0.34110034f , 0.15113928f , 0.54187888f , -0.26468157f , -0.01685372f , 0.57037827f , -0.07951393f , -0.27830922f , -0.20152098f , -0.00077798f , -0.04509011f , -0.12945183f , -0.22631022f , -0.11626274f , + -0.25019709f , 0.07915240f , 0.19342024f , 0.04977732f , -0.10307638f , -0.04911927f , 0.08460541f , 0.35299883f , 0.10558745f , 0.32964006f , 0.16392423f , -0.03030527f , -0.17918726f , -0.50040107f , 0.40349289f , -0.25886676f , -0.31911232f , -0.10072948f , 0.17941945f , 0.11358761f , -0.65821799f , -0.13049456f , 2.00511443f , -1.24662935f , + -0.25357033f , -0.52592150f , 0.49923249f , -0.16543271f , -0.00633755f , -0.23552079f , -0.33411617f , -0.24207035f , -0.05030731f , -0.07071177f , -0.09419244f , 0.02464220f , -0.01943557f , -0.41801617f , 0.03064668f , 1.18121471f , 0.23528827f , -0.79209131f , -0.20405955f , 1.14624028f , 0.39747635f , 0.85849404f , -0.04127540f , -0.50865399f , + 0.42229826f , -0.01473649f , 0.33422709f , 0.02941697f , 0.19965112f , 0.72713450f , 0.30384642f , -0.11286505f , 0.14747407f , 0.14751665f , 0.11932647f , -0.00264711f , -0.31504995f , -0.56415263f , -0.31330112f , 0.01942224f , -0.35638639f , 0.03432383f , -0.11977819f , -0.30638549f , 0.34671321f , 0.83570186f , 0.17469280f , -1.01495899f , + -0.01251236f , -0.01487474f , -0.16676968f , 0.08574318f , 0.11892522f , 0.84392270f , 0.07864696f , -0.91941698f , -0.54281393f , -0.10333463f , -0.18582849f , -0.26050308f , 0.66395133f , 0.42733714f , -0.24646344f , -0.19052737f , 0.31638957f , 0.07897013f , 0.04027109f , -0.25458239f , 0.20940366f , 0.17480388f , 0.16462327f , 0.22726978f , + -0.02974486f , -0.54604962f , 0.16929759f , -0.25102018f , 0.23723617f , -0.34661947f , -0.07598653f , -0.25231308f , -0.73500058f , -0.06708141f , 0.18697737f , 0.14282300f , 0.66886685f , 0.39198866f , 0.20429507f , -0.16054968f , -0.19399421f , 0.25548963f , -0.01871442f , 0.24332515f , 0.11001194f , 0.17128458f , 0.05301268f , 0.13370518f , + 0.06218397f , -0.11075064f , -0.47179494f , 0.44241371f , 0.02355115f , -0.03595332f , 0.06122175f , -0.89128427f , 0.30088747f , -0.16859130f , 0.25866312f , 0.50627502f , -0.10794532f , -0.21779689f , 0.18817072f , 0.03690803f , 0.04519087f , 0.11081125f , -0.16063397f , -0.29465752f , 0.07392634f , 0.19278544f , 0.34698486f , 0.61990484f , + 0.93310946f , -0.16003930f , -0.20232301f , -0.09149716f , -0.07742202f , 0.10544444f , 0.21543944f , -0.23192273f , 0.37584518f , 0.41668097f , 0.03315939f , -0.08464584f , 0.23874101f , 0.46904518f , -0.37717436f , -0.46519362f , -0.61713348f , 0.00253734f , -0.05435577f , -0.08905407f , -0.16726849f , -0.06183335f , -0.05902828f , -0.03528791f , + 0.27678118f , -1.22172710f , 0.33045954f , 0.00746992f , 0.02805380f , 0.37593685f , 0.03388730f , -0.30662300f , 0.20852594f , -0.26058111f , -0.05686500f , 0.26594392f , 0.13317456f , -0.21898256f , -0.24070719f , -0.23323971f , 0.27086818f , 0.15492204f , 0.28738611f , -0.10515406f , -0.17282966f , -0.16200061f , -0.15211483f , -0.08975717f , + 0.59311421f , -0.26642352f , -0.18351175f , 0.27817437f , 0.89836102f , -0.16570591f , -0.42252147f , 0.18559697f , 0.28409112f , -0.18921990f , 0.26375529f , -0.31791665f , -0.33115116f , -0.01469640f , -0.21691511f , -0.04101336f , 0.06816547f , -0.25758291f , 0.10261781f , 0.06210271f , 0.13856623f , 0.09669133f , 0.13691740f , 0.19601167f , + -0.47155089f , 0.72985836f , 0.20031390f , 0.60596157f , 0.37698777f , 0.31374835f , -0.04335831f , -0.19781138f , -0.35092304f , -0.19434376f , 0.20558302f , 0.09649664f , -0.41125462f , -0.31417023f , 0.14557422f , 0.13059497f , 0.24351408f , 0.45606066f , 0.19630429f , 0.04599059f , -0.10842569f , -0.01246157f , 0.09745947f , 0.19255215f , + -0.00592573f , 0.30808529f , -0.82755020f , 0.27196540f , -0.04397044f , 0.35031490f , -0.46245949f , 0.43218639f , 0.08949413f , -0.33531101f , 0.30153585f , -0.06912019f , 0.05157704f , 0.21559056f , -0.09478249f , -0.29283107f , -0.14210772f , 0.16107997f , -0.05714190f , -0.07436813f , -0.17587718f , -0.17911354f , -0.01118712f , 0.30263406f , + 0.59479190f , 0.43737796f , -0.53906079f , -0.09284007f , 0.11222222f , -0.70909913f , -0.32143749f , -0.10079180f , -0.20953687f , -0.04742476f , 0.16795483f , 0.54332818f , 0.27138756f , -0.04876020f , -0.15045069f , 0.12165485f , 0.37118663f , 0.28905161f , 0.48206821f , 0.04496926f , -0.32548961f , -0.26704421f , -0.14151166f , 0.04643725f , + 0.01857789f , 0.22380572f , -0.47831518f , 0.10523282f , -0.02303693f , 0.06579947f , 0.64486948f , -0.30766532f , -0.74577310f , -0.77953682f , 0.57447145f , 0.39403713f , -0.58964771f , 0.62821123f , -0.11929129f , 0.10954929f , 0.14699721f , -0.32854065f , -0.04573394f , -0.09611846f , -0.01925603f , -0.17973013f , -0.39814740f , -0.46576115f , + 0.35954529f , 0.21214434f , 0.29992890f , -0.43470418f , 0.22297513f , -0.74780053f , 0.29579016f , 0.38031695f , 0.70929833f , 0.17791374f , -0.31068973f , 0.03106903f , 0.02159010f , -0.32680013f , -0.05137091f , -0.35753644f , -0.04484695f , -0.12900523f , -0.08431778f , -0.06684064f , -0.13653506f , 0.11526736f , 0.41857603f , 0.60634687f , + -0.39857847f , 0.04884917f , 0.23406115f , 0.05538860f , 0.28382844f , -0.00189639f , 0.13911105f , 0.08498889f , 0.38084943f , -0.04839120f , 0.03137059f , 0.61768252f , -0.60458777f , 0.17599675f , -0.38910593f , -0.29574408f , -0.37344875f , -0.20375998f , -0.20238216f , 0.44496885f , 0.52761883f , 0.49054914f , 0.28209688f , 0.15957444f , + -0.09304443f , -0.24829008f , 0.01258115f , 0.25256399f , -0.33883889f , -0.24896392f , -0.05437653f , 0.19084219f , 0.57863216f , 0.39405103f , -0.77089337f , 0.12169591f , -0.54527825f , 0.19831126f , 0.08552984f , 0.24274638f , 0.14652491f , -0.01698693f , 0.17500050f , -0.05044189f , -0.10649361f , -0.14945507f , -0.17028214f , -0.02330724f , + 0.03708941f , -0.24037606f , 0.02610502f , 0.50618133f , 0.10793551f , -0.09837616f , 0.62190481f , 0.34616106f , -0.28267161f , -0.14290071f , 0.01530348f , -0.83226343f , 0.23366780f , 0.04347097f , -0.00300625f , -0.02718166f , 0.01892830f , 0.11549693f , 0.36192046f , 0.50541829f , 0.06636938f , -0.09251533f , -0.22221864f , -0.12965501f , + -0.47277684f , 0.24188752f , 0.24883904f , -0.02549111f , -0.17021090f , 0.26120838f , -0.17437786f , -0.12898937f , -0.09122841f , 0.58977574f , 0.11843505f , -0.68052107f , 0.69093722f , -0.45942130f , -0.33210729f , 0.59582125f , -0.21973689f , 0.45672258f , 0.17061853f , 0.09529478f , -0.14791095f , 0.22877969f , 0.23364199f , 0.17934426f , + 0.16186852f , 0.95532223f , 0.24207322f , -0.28038649f , -0.16606584f , 0.28705368f , -0.00385633f , 0.10024520f , 0.38606721f , 0.00630603f , -0.08918537f , -0.48762895f , -0.25520072f , -0.07233131f , -0.06791555f , 0.02988899f , 0.33242516f , 0.31840295f , 0.31437593f , 0.28920587f , 0.20710554f , 0.12154078f , 0.09165915f , 0.13540520f , + -0.13814042f , 0.76333362f , 0.47866377f , 0.69056795f , 0.37920652f , -0.08336837f , 0.11207624f , 0.09821375f , 0.10128568f , 0.04094478f , -0.15253392f , -0.11078606f , 0.25057753f , 0.22663675f , -0.61364190f , -0.15546409f , -0.09300050f , -0.16430823f , -0.19195716f , -0.31084762f , -0.10423817f , -0.12525492f , -0.23057864f , -0.28477374f , + 0.19153891f , -0.50596450f , -0.06105779f , 0.12200239f , -0.10106136f , -0.25277965f , 0.30874573f , 0.40660354f , -0.20056468f , 0.17407976f , 0.60265008f , -0.00174689f , -0.44985204f , -0.31371702f , -0.45581285f , 0.36180230f , -0.07689721f , 0.80922589f , 0.34920387f , -0.21634606f , 0.06852205f , 0.36029737f , 0.53860772f , 0.69593094f , + 0.15218961f , 0.07083646f , 0.38471465f , 0.14311856f , 0.51050633f , 0.02631960f , 0.07150340f , -0.05204054f , 0.01036712f , 0.03753337f , 0.12604818f , 0.04316599f , -0.04454527f , 0.25901986f , 0.20620898f , -0.25183978f , -0.94415183f , -0.48608996f , 1.99323108f , -0.11741995f , 0.09381593f , 0.24836984f , -0.11990959f , 0.40198786f , + 0.35937586f , 0.05698778f , 0.55993579f , -0.68942177f , -0.00843969f , 0.47116294f , -0.17925245f , -0.41881521f , -0.20778331f , 0.27187634f , -0.19950871f , 0.56109975f , -0.73314410f , 0.36645381f , 0.13542026f , -0.12859018f , 0.07003305f , 0.17282595f , 0.33447531f , 0.32716011f , -0.39068553f , -0.25495327f , -0.44464316f , -0.44631278f , + -0.24788508f , 0.44993219f , 0.49633852f , 0.14573879f , -0.82145522f , 0.08447045f , 0.24653278f , 0.20233825f , -0.08079227f , -0.31036126f , 0.09619263f , 0.78127448f , 0.27956930f , -0.05376367f , -0.24537081f , -0.24071734f , 0.06264366f , -0.00648643f , 0.14649115f , 0.22075554f , 0.00215430f , -0.16835304f , -0.14400020f , 0.05455559f , + 0.51475177f , -0.19511684f , -0.41661102f , 0.02887458f , -0.64696667f , 0.12493084f , 0.01019607f , 0.19888837f , -0.37880058f , 0.64135459f , 0.11055137f , 0.09557428f , -0.07711050f , 0.13238949f , -0.18005007f , -0.18262300f , 0.15084340f , -0.21503629f , 0.15653282f , 0.45708075f , 0.39918436f , 0.40428185f , 0.37849166f , 0.37443886f , + -0.37551659f , 0.34117536f , 0.04118741f , -0.11257164f , -0.12653529f , -0.87344655f , -0.56010800f , -0.07645484f , 0.14471437f , 0.20262780f , 0.29380185f , -0.02943048f , 0.10854716f , 0.43270966f , 0.25877519f , 0.11175582f , 0.11265276f , 0.12112616f , 0.32109879f , 0.25352173f , 0.28658481f , 0.29681278f , 0.39509407f , 0.43777195f , + 0.17504785f , 0.10160864f , -0.32996848f , 0.33545472f , 0.10088654f , 0.32002010f , -0.06513018f , 0.09378440f , 0.30444515f , 0.06564463f , -0.59311997f , 0.13934191f , 0.17049039f , -0.38526222f , -0.13285144f , -0.34127257f , 0.32308732f , 0.29646451f , -0.08667292f , 1.27873237f , 1.21492697f , -3.11928954f , 0.45762280f , -0.93594879f , + 0.17132808f , 0.08085753f , 0.26151050f , 1.03721715f , -0.25337638f , 0.26779752f , -0.61935064f , 0.10496638f , -0.18282397f , 0.00232460f , 0.17820442f , 0.20638928f , 0.07611441f , 0.12056159f , 0.20529210f , -0.06270324f , -0.04360808f , -0.42305491f , -0.41339045f , -0.00383610f , -0.19449359f , -0.25682704f , -0.37569311f , -0.21433847f , + 0.64365986f , 0.31456070f , -0.39495602f , -0.24863426f , 0.09837217f , -0.36609886f , 0.17111936f , 0.24419541f , -0.24359150f , -0.27882768f , -0.09002564f , -0.30691102f , -0.22673738f , 0.56321328f , 0.22388027f , 0.03208856f , 0.17981274f , 0.06991222f , -0.67356769f , -0.64900669f , 1.15113193f , 0.72776059f , 0.27327753f , 1.08582469f , + 0.41187807f , 0.20392498f , 1.09655483f , -0.34930742f , 0.20771295f , -0.06429869f , 0.08115226f , 0.22625148f , -0.72095719f , -0.02848530f , 0.42792136f , -0.04720602f , -0.22585980f , -0.29439740f , 0.06057192f , 0.13137013f , 0.24620234f , -0.13734663f , -0.12645317f , -0.30625075f , -0.14167838f , -0.11199965f , -0.18411244f , 0.12411211f , + 0.52310170f , 0.17749282f , 0.93116306f , 0.43734813f , -0.11189475f , -0.12583315f , -0.15636518f , -0.45970964f , 0.29811984f , 0.05623999f , 0.26734923f , -0.16388298f , -0.04470326f , 0.13948379f , 0.11499794f , 0.17243067f , 0.01441213f , -0.18039908f , -0.09565125f , 0.16544291f , 0.06548930f , 0.22771091f , 0.45780362f , 0.52809090f , + 0.28956302f , -0.16486587f , 0.29599013f , 0.32685118f , -0.28935868f , -0.00152686f , 0.55430159f , 0.03727197f , 0.10804969f , -0.54544071f , -0.79114628f , 0.10752299f , 0.05522333f , 0.63833259f , 0.49017560f , 0.02881627f , -0.39313059f , 0.50983607f , 0.34015996f , -0.08459223f , -0.28493761f , 0.10604944f , 0.27351683f , 0.32437791f , + -0.25283796f , -0.04532098f , 0.15075344f , 0.11408519f , 0.00916449f , -0.10310231f , 0.19258483f , 0.02635541f , -0.27218167f , 0.12402945f , 0.03511427f , 0.17636894f , -0.54939311f , 0.33454589f , -0.06691437f , -0.76895070f , 0.86149576f , -0.11074096f , 0.14506447f , -0.65269171f , 0.42690885f , 2.34010106f , -0.53713287f , -0.56076371f , + 0.34158378f , 0.24525259f , 0.18233515f , -0.01918052f , -0.38850956f , -0.10382009f , 0.23314099f , -0.44393411f , -0.22817265f , 0.43890661f , -0.35766222f , 0.12772962f , 0.29184572f , -0.35914868f , 0.41036163f , 0.13940763f , 0.24037289f , 0.31034789f , 0.39892172f , 0.45673361f , 0.25700279f , -0.23583305f , -0.56430632f , -0.63542661f +}; + +const float cdk_37bits_6[1536] = +{ + 0.02199370f , -0.29796617f , 0.05716792f , 0.13680255f , 0.26597120f , -0.02744179f , 0.20163618f , 0.55538992f , 0.22634719f , 0.31737301f , 0.16680373f , -0.09734626f , -0.23572572f , -0.44456075f , -0.32174953f , -0.27927807f , -0.32748565f , -0.18735586f , -0.18267408f , -0.46321102f , -0.04612331f , 0.01365363f , 0.19391054f , 0.39090135f , + -0.78693393f , -0.13121488f , -0.28380698f , -0.26404304f , -0.10486512f , 0.28404174f , -0.20661527f , -0.42204880f , -0.30458489f , 0.08583926f , 0.07085793f , 0.33480410f , -0.03611454f , 0.07957323f , -0.24515140f , -0.07119076f , 0.53589973f , -0.22960446f , 0.07406971f , -0.05459778f , -0.34032829f , -0.26754071f , 0.22258555f , 0.30461029f , + -0.40719188f , -0.52149744f , -0.06225098f , -0.58002850f , 0.18087742f , 0.16048132f , 0.33633101f , -0.27793274f , 0.29766130f , 0.23267788f , -0.40627837f , -0.11859464f , -0.33658426f , -0.08944806f , 0.07416164f , 0.12096620f , -0.17419709f , -0.33394555f , -0.01993099f , 0.18415306f , -0.00706952f , -0.18114484f , -0.17223192f , -0.00314600f , + 0.09136000f , 0.34482257f , -0.38038690f , 0.51845639f , 0.22194266f , -0.06195248f , 0.01057897f , -0.25864445f , -0.13813348f , 0.15711108f , 0.37305034f , -0.46508572f , 0.21910366f , 0.14590390f , -0.15011887f , -0.08081632f , 0.02686570f , -0.52447967f , -0.44642803f , -0.09356439f , 0.07841264f , -0.09014590f , -0.08406397f , -0.21549966f , + -0.10973105f , -0.34775792f , -0.20573880f , -0.13604716f , 0.02371719f , -0.25091561f , -0.39884717f , -0.11293660f , 0.35125293f , -0.23847405f , 0.75991690f , -0.00398242f , -0.37499879f , -0.16571879f , -0.17163070f , 0.28161005f , 0.30079809f , 0.08127173f , -0.21076595f , -0.41977393f , -0.20607863f , -0.13121646f , -0.05219850f , -0.20041567f , + -0.23929288f , 0.00328474f , -0.16404527f , 0.13343873f , -0.04468995f , -0.12674227f , 0.28141003f , 0.18544988f , 0.02601550f , -0.21845606f , -0.11057949f , -0.08909572f , -0.13195824f , -0.18487778f , 0.09887948f , 0.53205644f , -0.22134305f , -0.05746605f , -0.44707332f , -0.06333598f , -0.98347835f , 1.60965371f , -0.38440494f , 0.37345285f , + 0.18956874f , -0.63812607f , 0.04131005f , -0.45442314f , -0.54875750f , 0.04287724f , 0.25537551f , 0.08570099f , -0.08813623f , -0.09284444f , 0.03722275f , 0.36512077f , -0.09165936f , -0.03956157f , -0.01444716f , 0.03320064f , 0.05602971f , 0.12944547f , -0.08791108f , -0.21281390f , 0.02256362f , 0.21794416f , 0.49420878f , 0.51874581f , + -0.61939062f , -0.36501718f , 0.13770557f , -0.03873456f , 0.24524354f , -0.22114161f , 0.17262135f , -0.01018526f , 0.00734267f , -0.03028249f , -0.10222293f , -0.56027275f , 0.21981567f , 0.30177736f , -0.00599960f , -0.13637831f , 0.12005585f , 0.21762903f , 0.21013194f , -0.29453710f , 0.06570005f , 0.02671005f , 0.18952852f , 0.33755592f , + 0.14788881f , 0.00059595f , 0.03869057f , -0.08077903f , -0.12203289f , -0.84498958f , 0.47581358f , 0.02514588f , 0.04825696f , -0.01455508f , -0.01746364f , 0.27725910f , 0.12457264f , 0.11218197f , 0.26527797f , -0.25741487f , -0.07216861f , -0.32943112f , -0.08385290f , -0.36172079f , -0.42572896f , -0.53073631f , -0.32133031f , -0.11301412f , + -0.35066897f , -0.11415958f , -0.59117357f , -0.14095716f , -0.42297703f , -0.39599254f , 0.11101885f , 0.54908359f , 0.00983404f , -0.16570627f , 0.35167384f , 0.03659831f , 0.00451556f , 0.13297592f , -0.03455431f , 0.05151250f , -0.22783505f , -0.26878480f , -0.09719185f , 0.26294703f , 0.24726886f , 0.09052345f , -0.07129501f , -0.20450022f , + -0.04472087f , -0.37269265f , 0.03231240f , 0.03463392f , -0.33039098f , 0.03217782f , -0.35545027f , 0.13915732f , 0.21687252f , -0.70171718f , -0.39380045f , 0.29808315f , -0.10154988f , 0.58687688f , 0.36738223f , -0.01455050f , 0.25767865f , -0.13939968f , -0.18503719f , 0.06199296f , 0.11118295f , 0.01396018f , 0.09425776f , -0.03092734f , + -0.25728637f , 0.47463459f , 0.06581158f , -0.61445073f , 0.28805874f , 0.07087341f , 0.22849783f , 0.14652334f , -0.17916038f , -0.45793031f , -0.13375702f , 0.04741016f , 0.34305011f , 0.18609517f , 0.15796519f , -0.32119576f , -0.37724212f , -0.29019392f , -0.16584456f , 0.06247499f , -0.17973441f , -0.11871502f , 0.07256450f , 0.13822121f , + 0.20531600f , -0.09627213f , -0.35132620f , -0.03667359f , -0.25798228f , 0.21115819f , 0.03354110f , -0.02417022f , 0.43198429f , -0.23070254f , -0.12670631f , 0.15840355f , -0.09384404f , -0.11238464f , -0.08953585f , 0.10896049f , -0.00837215f , -0.46861227f , 1.49760729f , -0.67351773f , -0.52192511f , 0.01262532f , 0.20121502f , -0.39083539f , + 0.10656396f , -0.26831105f , -0.81601202f , 0.26397269f , 0.26863321f , -0.04846112f , 0.40399165f , -0.08820703f , 0.14718938f , -0.29278618f , -0.38479467f , 0.02420765f , -0.10191832f , -0.03998542f , 0.09718148f , -0.38999213f , 0.40517232f , 0.29658010f , 0.07025753f , -0.06541290f , -0.17956727f , -0.20362973f , -0.10716584f , -0.04799112f , + -0.08098934f , 0.01809647f , -0.31889640f , 0.20306658f , 0.05187569f , 0.03260165f , -0.28014725f , -0.09888837f , 0.24610335f , 0.17700122f , -0.30915327f , -0.08942879f , -0.50003116f , 0.85468538f , -0.27952271f , 0.40219755f , -0.20697633f , -0.22376407f , -0.24075343f , -0.23806655f , 0.09503069f , 0.19400941f , 0.29979874f , 0.26995405f , + -0.27054449f , 0.39277758f , -0.03760489f , 0.02099845f , -0.35791555f , -0.28760379f , 0.22223327f , -0.11251071f , -0.02563508f , 0.46326287f , -0.14502000f , -0.07375028f , -0.32793294f , -0.56372840f , 0.30213757f , 0.47683337f , 0.42993785f , 0.02200265f , -0.43110723f , -0.31763877f , 0.25984030f , 0.13257308f , 0.23346193f , -0.17362047f , + -0.12926955f , 0.23035254f , 0.14954128f , -0.15270953f , 0.01666258f , 0.25669412f , 0.26953793f , 0.47425752f , -0.09722404f , -0.12678088f , -0.27006791f , 0.06245438f , 0.11482178f , -0.51002017f , -0.55002144f , -0.13134853f , 0.49162370f , -0.20822342f , -0.09189974f , -0.03360844f , 0.08050459f , 0.08539808f , -0.01338071f , -0.32112911f , + -0.07384309f , 0.14700645f , -0.33549907f , -0.17107820f , -0.36567878f , 0.28540929f , -0.11645077f , -0.06093537f , 0.10704230f , 0.60475923f , 0.31110592f , 0.03294181f , 0.24602888f , -0.16878060f , -0.37308097f , -0.38852147f , -0.11457933f , -0.01155936f , -0.20566079f , -0.11646696f , -0.43156667f , -0.48332839f , -0.40869530f , -0.30176313f , + -0.04009388f , -0.48515311f , -0.01564117f , -0.22107208f , 0.26498770f , 0.32028506f , -0.06025879f , 0.53444487f , -0.52361462f , -0.13790355f , -0.00869928f , -0.37067541f , -0.00525305f , 0.34369466f , -0.11140079f , -0.21802883f , -0.02738621f , 0.09487138f , -0.18305111f , 0.21257672f , 0.19224339f , 0.13669179f , -0.07833677f , -0.43596981f , + -0.31269603f , 0.18817889f , -0.14017449f , -0.36643116f , 0.51493670f , -0.26894972f , 0.38067942f , -0.47165660f , -0.03935884f , -0.15393758f , 0.33966349f , -0.07858441f , 0.08218318f , -0.14083074f , -0.39968104f , 0.46984889f , -0.23459315f , -0.01561374f , 0.04443121f , -0.08906745f , -0.05813711f , -0.21827283f , -0.17460819f , -0.22917539f , + -0.32481184f , 0.18110865f , -0.03288883f , -0.13973233f , 0.27902282f , -0.11023560f , -0.16625632f , 0.02743534f , 0.10865317f , -0.10518495f , 0.26027757f , -0.15223339f , -0.35257469f , -0.01938217f , 0.46256528f , -0.27598628f , 0.04443960f , 1.07920395f , -1.13925232f , 0.36635637f , 0.35955458f , 0.25146378f , 0.11693719f , -0.28918251f , + -0.01140797f , -0.00108123f , 0.53664312f , -0.07884630f , 0.06610974f , 0.46994377f , -0.21062843f , -0.06753632f , -0.27422686f , -0.02290268f , -0.18794805f , -0.46650251f , -0.14397198f , -0.00227405f , 0.10488283f , 0.31441692f , 0.42101389f , 0.25235460f , -0.29244026f , -0.56175069f , -0.28002115f , -0.17549467f , -0.12071683f , -0.23331646f , + -0.14210038f , 0.15898131f , 0.34745032f , -0.39617165f , -0.04076848f , 0.18838182f , -0.13777208f , 0.22936475f , 0.41604669f , -0.29976263f , 0.25071099f , -0.15777986f , 0.01895400f , -0.00797168f , -0.55609191f , 0.33651175f , -0.23976909f , -0.55267202f , -0.20759468f , 0.05624592f , 0.01093081f , 0.08073438f , 0.28567820f , 0.30232551f , + 0.28315788f , -0.74308327f , 0.25294543f , 0.19940974f , 0.24760844f , -0.02307767f , 0.00394023f , -0.27240988f , -0.55346147f , 0.06135889f , -0.10476035f , 0.49139353f , 0.02862492f , 0.14164419f , -0.26209567f , 0.29521976f , -0.05334845f , -0.16688330f , -0.02634194f , -0.01985854f , -0.11432133f , -0.12121091f , -0.13386215f , -0.39429955f , + 0.01675275f , -0.07538106f , -0.33922440f , 0.34966904f , 0.15763570f , 0.08306612f , 0.62591343f , -0.03583112f , -0.43789635f , -0.06885643f , -0.00346875f , -0.06640113f , -0.32232724f , -0.18063079f , 0.53312831f , -0.00572204f , -0.27992509f , -0.50312951f , 0.12672777f , 0.16960075f , -0.11581876f , 0.02517662f , 0.13602646f , 0.24387275f , + -0.35732816f , -0.22019513f , -0.26829496f , 0.31166748f , -0.23832104f , 0.56149308f , 0.20096730f , -0.14980617f , 0.04728897f , -0.22598474f , -0.36740325f , 0.14028484f , 0.32691879f , 0.00451707f , -0.11546712f , 0.20652154f , -0.39073278f , 0.05148622f , -0.29347409f , -0.21830651f , 0.40790228f , -0.24466325f , -0.37143514f , -0.35725594f , + -0.34807000f , -0.00324691f , -0.06021802f , 0.27592230f , 0.20065100f , -0.31797201f , -0.48602388f , 0.05361142f , 0.30839620f , 0.41057671f , -0.47412603f , 0.10542789f , 0.20596832f , -0.20747184f , 0.40038595f , -0.20068089f , 0.00240007f , -0.38309980f , -0.05001577f , 0.17124043f , 0.09018175f , 0.07050526f , 0.22914929f , 0.15810766f , + 0.15361042f , 0.16095058f , 0.11590520f , -0.10531069f , -0.54075671f , 0.33490327f , 0.37034921f , -0.22227724f , -0.09516189f , -0.12944095f , 0.61220382f , -0.39342831f , 0.07187587f , 0.14034139f , 0.15782975f , 0.06333909f , -0.37017017f , 0.21683365f , 0.12401762f , -0.25136319f , -0.14144992f , -0.11683977f , 0.08998918f , 0.02907554f , + -0.75114647f , 0.03978493f , 0.76048864f , 0.09830364f , -0.18442047f , -0.01149302f , -0.08377934f , 0.01287934f , -0.10587886f , 0.02074821f , 0.24442453f , 0.25099252f , 0.04656507f , 0.10263959f , -0.00445999f , -0.09991211f , -0.18874159f , -0.04573901f , 0.12928997f , 0.08644625f , -0.19611160f , -0.27382974f , -0.29394396f , -0.47761274f , + 0.14765675f , 0.26358158f , -0.29464188f , 0.01676762f , -0.12098202f , 0.56991418f , -0.43628314f , 0.29279445f , -0.51684512f , -0.06979763f , 0.22084398f , 0.33328609f , -0.44667171f , -0.13234452f , 0.03221020f , 0.34402421f , -0.06995129f , -0.10237066f , -0.03757679f , 0.08387845f , 0.07625326f , -0.18566472f , -0.25481511f , -0.35690924f , + 0.36027465f , -0.14361307f , -0.01060078f , -0.14321892f , 0.47607774f , -0.21917094f , -0.19024330f , 0.35483351f , 0.00343023f , 0.16704908f , 0.09217343f , -0.36458287f , -0.68525894f , -0.06920128f , 0.13485445f , 0.16439202f , 0.13577501f , -0.06075085f , 0.02266803f , 0.26611340f , -0.37850955f , -0.49541492f , -0.48481104f , -0.30493937f , + 0.04767197f , 0.17098898f , -0.03724685f , -0.76939534f , -0.52710450f , -0.26151755f , -0.36749599f , 0.19673299f , 0.11499191f , 0.25563946f , -0.18105024f , -0.11440595f , 0.27962189f , 0.12349943f , 0.04827891f , 0.17421978f , 0.25830670f , 0.15467508f , 0.17983330f , 0.17053327f , 0.01501125f , -0.21006919f , -0.24807426f , -0.27314815f , + -0.24896720f , 0.19371740f , 0.06879568f , 0.44049451f , 0.14914746f , 0.03856987f , 0.06978715f , 0.40612007f , 0.28010982f , -0.56749281f , -0.01993429f , 0.46728351f , -0.36770014f , -0.15189625f , -0.02595528f , -0.16408195f , -0.11358236f , 0.34475368f , 0.37996789f , -0.23334622f , -0.02333946f , -0.29586512f , -0.08357343f , 0.01075083f , + 0.01442941f , -0.19995191f , -0.25851229f , -0.29267926f , 0.50501148f , 0.07809462f , -0.35000787f , 0.00232180f , 0.25576742f , 0.22026677f , -0.28505912f , 0.32678020f , 0.14230208f , -0.25462591f , -0.52430874f , 0.00733528f , -0.12371759f , 0.46221140f , 0.03726347f , 0.06724595f , 0.38257606f , 0.29300802f , 0.20146742f , 0.05769846f , + 0.46566196f , -0.22129182f , 0.48408131f , -0.08771705f , 0.34179928f , -0.03570483f , 0.28260230f , -0.37152490f , 0.24002550f , -0.37004615f , 0.04007914f , 0.14066291f , 0.03156739f , -0.40473859f , 0.24504260f , -0.12061618f , -0.01911784f , -0.09587775f , -0.20311630f , 0.25305578f , -0.02444684f , -0.17360130f , -0.33200194f , -0.56919023f , + 0.40911162f , -0.26402836f , -0.43905076f , -0.53557497f , 0.19016209f , -0.01532019f , -0.46281760f , -0.26868248f , 0.12319043f , -0.03526231f , 0.14611501f , -0.35525234f , 0.34301743f , 0.10756893f , 0.38690216f , 0.01304076f , -0.17233959f , -0.26353334f , -0.32623011f , -0.13634929f , 0.06881118f , -0.03647389f , 0.13860696f , 0.21618306f , + 0.58044419f , -0.31542590f , 0.13749045f , 0.15061296f , -0.24506767f , -0.10488291f , -0.37675292f , -0.04226534f , -0.16466027f , 0.20334112f , 0.62047117f , -0.07748292f , -0.23123208f , 0.22647883f , 0.46423202f , -0.53987978f , 0.26867801f , 0.17570387f , 0.22624788f , -0.06808559f , -0.09873793f , 0.00241821f , 0.05209155f , 0.02604012f , + -0.18720130f , -0.00619393f , 0.08934188f , 0.18479801f , 0.00631687f , 0.35401594f , -0.22430546f , -0.17052726f , -0.27404318f , 0.34842459f , 0.06523245f , -0.22607999f , 0.38438344f , 0.31775172f , 0.00274227f , -0.32430710f , -0.25886046f , -0.22780138f , 0.00599115f , 1.13173049f , -1.16090310f , 0.31502644f , 0.39054668f , -0.12545157f , + 0.08495448f , -0.08111156f , 0.13201128f , 0.10631004f , -0.62508184f , 0.49447676f , 0.05698153f , 0.57661737f , 0.16100334f , 0.29281953f , -0.42535641f , -0.34334011f , -0.21130696f , -0.11053404f , 0.29449021f , -0.00923741f , -0.15178458f , -0.03327836f , 0.04623104f , 0.06728107f , 0.07479295f , -0.09249471f , -0.01129765f , -0.02381652f , + 0.58733539f , 0.15083492f , -0.07170902f , 0.07265805f , 0.25686979f , -0.00362956f , 0.16478015f , 0.10189929f , -0.35758569f , 0.34626172f , -0.76537636f , -0.14748849f , 0.23675893f , 0.10373267f , 0.09933094f , -0.01851098f , -0.01787937f , -0.12160932f , -0.09891368f , -0.10410372f , 0.04554984f , 0.08997877f , 0.12949773f , 0.02665334f , + 0.29472382f , 0.55621057f , -0.25157141f , -0.08071915f , -0.33720618f , -0.07969815f , -0.09542065f , -0.03385662f , 0.57363003f , 0.21066071f , -0.26291676f , 0.64510933f , -0.24141325f , -0.10243829f , -0.10243462f , 0.03275380f , -0.20748095f , -0.21739693f , -0.02629787f , 0.14996425f , -0.18327383f , 0.03844543f , -0.12298422f , -0.48155671f , + -0.03002892f , 0.10542293f , 0.06159204f , 0.27084880f , 0.33088023f , -0.39709374f , 0.40602594f , 0.01355505f , -0.21134955f , 0.38680071f , 0.42354405f , 0.13430508f , 0.04568189f , -0.43410657f , -0.13995521f , -0.32088491f , -0.23742271f , 0.13613850f , 0.22766366f , 0.52067443f , 0.36422193f , -0.09820343f , -0.25055881f , -0.32764668f , + -0.03031539f , 0.33911970f , 0.00121262f , 0.23395660f , 0.10188493f , 0.35700308f , -0.26121354f , 0.04562318f , 0.08861375f , -0.19333300f , -0.17460139f , -0.06438315f , 0.08512698f , -0.28212770f , 0.58969600f , -1.01876488f , 0.72771298f , -0.24186158f , -0.25474736f , -0.05188159f , 0.35800295f , -0.07855298f , -0.01848759f , 0.30122272f , + -0.16488121f , 0.39899154f , -0.43527753f , 0.06350178f , -0.25145471f , -0.13442742f , -0.05695327f , 0.05515276f , -0.53947634f , 0.10452757f , -0.00613783f , 0.09941644f , 0.48768605f , 0.23880974f , 0.15991320f , -0.08188036f , -0.07454521f , 0.46447496f , 0.20306282f , -0.35729603f , -0.19729891f , 1.15029004f , 0.78677730f , -0.96063281f , + 0.31021050f , -0.38542028f , 0.38342353f , 0.13604497f , -0.07567226f , -0.23168737f , -0.02250859f , -0.04684466f , 0.02122357f , 0.36396360f , -0.03570663f , -0.41257090f , 0.57597067f , 0.13936689f , -0.44959133f , -0.14512843f , 0.31888158f , -0.68434472f , 0.36855275f , 0.34229507f , 0.14749025f , -0.13593595f , -0.02198259f , 0.03092032f , + 0.04127156f , -0.30338390f , -0.36945017f , 0.09750128f , 0.03159281f , -0.09756566f , -0.00189927f , -0.12775820f , 0.11355232f , -0.16024788f , 0.32150415f , 0.19535993f , 0.22702237f , 0.26433052f , -0.08518964f , -0.13355330f , -0.54717674f , 0.18386017f , 0.53068186f , 0.35196477f , -0.36756679f , -0.69260204f , 0.19830746f , 0.92671624f , + -0.09461538f , 0.67447380f , 0.12354656f , 0.17963388f , 0.15317263f , 0.19433224f , 0.16035999f , -0.50697166f , 0.22832688f , -0.03638860f , -0.31139766f , -0.15364902f , -0.16277929f , 0.09079846f , 0.36114558f , 0.19448427f , -0.21078568f , -0.04243481f , 0.26104266f , 0.46369813f , 0.26334525f , -0.14251361f , -0.10575649f , -0.10844448f , + -0.04642582f , -0.10287474f , 0.07590817f , 0.04960837f , -0.05287987f , -0.15988848f , -0.08701719f , 0.14028344f , -0.27072892f , -0.02715588f , 0.24338776f , 0.20341433f , 0.43004675f , -1.02991828f , 0.27940707f , 0.21700241f , 0.11492563f , 0.27903919f , 0.26058323f , -0.34700893f , 0.07076686f , -0.10221847f , 0.05257812f , 0.55040312f , + -0.00947855f , 0.16201946f , 0.01530995f , 0.21655645f , -0.39190608f , -0.53475683f , 0.27626723f , -0.10828040f , -0.11491983f , -0.37356045f , 0.23110876f , 0.23915995f , 0.26409657f , 0.05516764f , -0.26520423f , 0.23157479f , 0.49045853f , 0.07154379f , 0.24906795f , 0.48215117f , 0.36682427f , 0.30977279f , 0.41199849f , 0.35374660f , + 0.11035037f , 0.12792077f , 0.34911446f , 0.03095177f , -0.26708115f , 0.01926537f , 0.06581393f , -0.83391569f , 0.11407886f , 0.34947774f , -0.06272482f , 0.45584926f , 0.35208593f , 0.02210972f , 0.03663452f , -0.16326364f , -0.08863411f , -0.12989747f , -0.24846516f , 0.02403637f , 0.24144266f , 0.21460052f , 0.21802777f , 0.17582350f , + 0.17586580f , -0.03883077f , 0.41247141f , 0.20117164f , 0.49169701f , 0.55456607f , -0.33339198f , -0.15935525f , 0.11000758f , 0.03881595f , -0.08086591f , 0.08127779f , -0.21850527f , 0.25204265f , 0.02918388f , -0.46406159f , -0.30149637f , -0.28716264f , -0.01652976f , -0.21430167f , -0.05257479f , -0.11894064f , 0.12104770f , 0.21200677f , + 0.05077562f , 0.64049606f , 0.29166977f , -0.14882998f , 0.23041791f , -0.17570776f , -0.25126896f , 0.15320959f , -0.50542113f , 0.51581805f , 0.29050952f , 0.02906798f , -0.21707118f , 0.08731647f , -0.26192461f , 0.08930377f , 0.01540895f , -0.11515550f , -0.13173228f , 0.04443261f , 0.14861127f , 0.15145403f , 0.38816557f , 0.40757716f , + 0.31175167f , 0.17090647f , 0.17998268f , -0.19899135f , 0.28615557f , -0.13419397f , 0.07062408f , -0.18842182f , -0.15533919f , -0.48813043f , 0.33410690f , 0.14699633f , 0.07321804f , 0.60685754f , -0.42827502f , -0.43054167f , 0.30547944f , 0.50321733f , -0.20117562f , -0.07447133f , -0.00135400f , 0.05786543f , -0.01808385f , -0.10533247f , + 0.05054332f , -0.14047735f , -0.07415119f , 0.44066546f , -0.02324372f , -0.09192828f , -0.18097335f , 0.09834903f , -0.26580813f , -0.02556763f , -0.37105934f , 0.12150755f , -0.11848442f , 0.04784313f , -0.11220379f , 0.39803073f , 0.52224090f , 0.10595610f , 0.18711063f , 0.29425741f , -0.12712275f , -0.75269106f , -0.62164375f , 1.49229636f , + -0.05263376f , 0.01551319f , -0.01862667f , 0.39621319f , 0.00775791f , 0.19443440f , -0.37005598f , 0.09947225f , 0.17067061f , -0.59100529f , -0.09194870f , -0.41824230f , 0.54676965f , 0.01393038f , 0.32793066f , 0.12752974f , -0.01761483f , 0.26099604f , 0.18632115f , 0.17752999f , -0.12037572f , -0.19613144f , -0.11840061f , -0.09740210f , + 0.09912611f , -0.24884033f , 0.19434008f , 0.16192972f , 0.05004326f , -0.59081926f , -0.41278435f , 0.10837713f , 0.06286063f , 0.17897341f , -0.09549655f , -0.11946937f , 0.19636290f , 0.10840741f , 0.12514136f , 0.91209643f , -0.52293308f , 0.24102239f , 0.14117183f , -0.19578756f , 0.29083443f , 0.08063250f , -0.15288813f , -0.30169128f , + 0.01584630f , -0.11259531f , 0.39416192f , 0.56959415f , -0.29736651f , 0.10790402f , 0.64124109f , -0.30225328f , 0.10444127f , 0.04559679f , 0.04662132f , -0.13559913f , -0.47705291f , 0.24948308f , -0.09175683f , -0.12182940f , 0.23087559f , -0.04229615f , -0.10186917f , 0.07827786f , 0.09243493f , 0.11202796f , 0.04243676f , 0.08887602f , + -0.38219650f , -0.11461189f , -0.18648336f , 0.19816038f , -0.09732223f , 0.52544356f , -0.13255010f , -0.13256714f , 0.46163208f , -0.08822080f , 0.30489642f , -0.27441353f , -0.17900853f , -0.37170730f , -0.16593309f , -0.05832152f , 0.20792097f , 0.02230373f , 0.39776652f , 0.32480143f , 0.56771378f , 0.28147085f , 0.12035847f , -0.06198797f , + 0.16289063f , 0.29806667f , 0.12344487f , 0.11272351f , 0.03410954f , -0.30062456f , 0.06877076f , -0.06004153f , 0.62082084f , 0.47068710f , -0.30298966f , -0.26674229f , -0.10333087f , 0.13814787f , -0.18170023f , -0.26286846f , 0.14643367f , 0.69028091f , 0.12706668f , -0.06000300f , -0.15983614f , -0.16308927f , 0.06054026f , 0.24605632f , + 0.71272052f , 0.52242539f , -0.04818476f , 0.31193593f , -0.15987333f , -0.06222937f , -0.05672104f , 0.53241922f , 0.05925126f , -0.20570464f , 0.11569695f , -0.11659635f , 0.17015156f , 0.03835440f , -0.10022938f , 0.00626121f , -0.22082679f , -0.10482121f , -0.03046492f , -0.07362554f , 0.16480680f , -0.02745797f , -0.23714652f , -0.40036483f , + 0.00774041f , 0.02630024f , 0.85679294f , -0.16620543f , 0.13390597f , -0.43418821f , 0.27099640f , 0.29601681f , -0.05468039f , 0.00123578f , -0.34476791f , 0.20548883f , 0.12690026f , -0.12125541f , -0.24822526f , 0.32121761f , -0.15281912f , 0.18448249f , 0.30215241f , 0.12566250f , 0.06993898f , -0.03997524f , 0.17346822f , 0.40869366f , + 0.50810094f , 0.24316475f , -0.32829494f , -0.52128186f , 0.13028426f , 0.29952885f , 0.46293804f , -0.26433277f , -0.37140799f , -0.12921967f , -0.20423017f , -0.11719085f , 0.08305804f , -0.12334944f , -0.23731075f , 0.22837853f , 0.24340316f , 0.43535913f , 0.30959620f , 0.04173569f , -0.57982693f , -0.34522367f , 0.14683522f , 0.05595596f , + 0.02237034f , -0.06316542f , -0.01048143f , -0.27361876f , 0.01327775f , 0.01156603f , -0.02656291f , -0.30384147f , -0.39207165f , 0.02401410f , -0.01835587f , 0.05743541f , -0.37923460f , 0.21265931f , 0.57306648f , 0.29538200f , -0.06625719f , 0.44038905f , 0.54409558f , 0.06943242f , 0.86241612f , 0.52782911f , 0.13063215f , -0.00969728f , + 0.11622122f , 0.02224264f , 0.32680233f , 0.00674035f , -0.18269996f , -0.07149903f , -0.38216845f , 0.11519523f , 0.15289458f , 0.02026007f , 0.31202256f , 0.38286848f , 0.06066707f , -0.11169249f , -0.10677312f , -0.20147411f , 0.01167547f , 0.11246367f , -0.70525138f , -0.69991387f , 1.00946560f , 0.95344512f , -0.75251996f , 0.27342287f +}; + +const float * const cdk_37bits[] = { cdk_37bits_1, cdk_37bits_2, cdk_37bits_3, cdk_37bits_4, cdk_37bits_5, cdk_37bits_6 }; + + +/* Sine tables for FFT */ +/* for (j=0 ; jfftlen/2+1 ; j++) hs->fftSineTab[j] = (float)sin(2.0*EVS_PI*j/hs->fftlen); */ + + +const float fftSineTab640[321] = +{ + 0.0000000000000000000000000f, 0.0098173199221491814000000f, 0.0196336936205625530000000f, 0.0294481739401817320000000f, 0.0392598174512386320000000f, 0.0490676760673522950000000f, 0.0588708035647869110000000f, 0.0686682611703872680000000f, 0.0784590989351272580000000f, 0.0882423743605613710000000f, + 0.0980171412229537960000000f, 0.1077824681997299200000000f, 0.1175374016165733300000000f, 0.1272810101509094200000000f, 0.1370123475790023800000000f, 0.1467304825782775900000000f, 0.1564344763755798300000000f, 0.1661233752965927100000000f, 0.1757962852716445900000000f, 0.1854522377252578700000000f, + 0.1950903236865997300000000f, 0.2047096043825149500000000f, 0.2143091559410095200000000f, 0.2238880544900894200000000f, 0.2334453761577606200000000f, 0.2429801821708679200000000f, 0.2524915933609008800000000f, 0.2619786560535430900000000f, 0.2714404463768005400000000f, 0.2808761000633239700000000f, + 0.2902846932411193800000000f, 0.2996652722358703600000000f, 0.3090170025825500500000000f, 0.3183389306068420400000000f, 0.3276301920413970900000000f, 0.3368898630142211900000000f, 0.3461170792579650900000000f, 0.3553109169006347700000000f, 0.3644705116748809800000000f, 0.3735949695110321000000000f, + 0.3826834559440612800000000f, 0.3917350172996521000000000f, 0.4007488489151001000000000f, 0.4097240269184112500000000f, 0.4186597466468811000000000f, 0.4275551140308380100000000f, 0.4364092648029327400000000f, 0.4452213346958160400000000f, 0.4539905190467834500000000f, 0.4627159237861633300000000f, + 0.4713967442512512200000000f, 0.4800321459770202600000000f, 0.4886212646961212200000000f, 0.4971632659435272200000000f, 0.5056573748588562000000000f, 0.5141027569770813000000000f, 0.5224985480308532700000000f, 0.5308440327644348100000000f, 0.5391383171081543000000000f, 0.5473806858062744100000000f, + 0.5555702447891235400000000f, 0.5637062788009643600000000f, 0.5717879533767700200000000f, 0.5798145532608032200000000f, 0.5877852439880371100000000f, 0.5956993103027343800000000f, 0.6035559773445129400000000f, 0.6113544106483459500000000f, 0.6190939545631408700000000f, 0.6267738342285156300000000f, + 0.6343932747840881300000000f, 0.6419516205787658700000000f, 0.6494480371475219700000000f, 0.6568819284439086900000000f, 0.6642524600028991700000000f, 0.6715589761734008800000000f, 0.6788007616996765100000000f, 0.6859771013259887700000000f, 0.6930873990058898900000000f, 0.7001308202743530300000000f, + 0.7071067690849304200000000f, 0.7140145897865295400000000f, 0.7208536267280578600000000f, 0.7276231050491333000000000f, 0.7343225479125976600000000f, 0.7409511208534240700000000f, 0.7475083470344543500000000f, 0.7539935111999511700000000f, 0.7604059576988220200000000f, 0.7667451500892639200000000f, + 0.7730104923248291000000000f, 0.7792012691497802700000000f, 0.7853169441223144500000000f, 0.7913569211959838900000000f, 0.7973206639289856000000000f, 0.8032075762748718300000000f, 0.8090170025825500500000000f, 0.8147485256195068400000000f, 0.8204014301300048800000000f, 0.8259753584861755400000000f, + 0.8314696550369262700000000f, 0.8368837833404541000000000f, 0.8422172665596008300000000f, 0.8474695682525634800000000f, 0.8526401519775390600000000f, 0.8577286005020141600000000f, 0.8627343773841857900000000f, 0.8676570057868957500000000f, 0.8724960088729858400000000f, 0.8772509098052978500000000f, + 0.8819212913513183600000000f, 0.8865066170692443800000000f, 0.8910065293312072800000000f, 0.8954205513000488300000000f, 0.8997483253479003900000000f, 0.9039893150329589800000000f, 0.9081431627273559600000000f, 0.9122095108032226600000000f, 0.9161879420280456500000000f, 0.9200780987739563000000000f, + 0.9238795638084411600000000f, 0.9275919198989868200000000f, 0.9312149286270141600000000f, 0.9347481727600097700000000f, 0.9381913542747497600000000f, 0.9415440559387207000000000f, 0.9448060393333435100000000f, 0.9479769468307495100000000f, 0.9510565400123596200000000f, 0.9540444016456604000000000f, + 0.9569403529167175300000000f, 0.9597440361976623500000000f, 0.9624552726745605500000000f, 0.9650737047195434600000000f, 0.9675990939140319800000000f, 0.9700312614440918000000000f, 0.9723699092864990200000000f, 0.9746148586273193400000000f, 0.9767658710479736300000000f, 0.9788227677345275900000000f, + 0.9807853102684021000000000f, 0.9826532602310180700000000f, 0.9844265580177307100000000f, 0.9861049652099609400000000f, 0.9876883625984191900000000f, 0.9891765117645263700000000f, 0.9905693531036377000000000f, 0.9918667078018188500000000f, 0.9930684566497802700000000f, 0.9941744804382324200000000f, + 0.9951847195625305200000000f, 0.9960990548133850100000000f, 0.9969173073768615700000000f, 0.9976395368576049800000000f, 0.9982656240463256800000000f, 0.9987954497337341300000000f, 0.9992290139198303200000000f, 0.9995663166046142600000000f, 0.9998072385787963900000000f, 0.9999517798423767100000000f, + 1.0000000000000000000000000f, 0.9999517798423767100000000f, 0.9998072385787963900000000f, 0.9995663166046142600000000f, 0.9992290139198303200000000f, 0.9987954497337341300000000f, 0.9982656240463256800000000f, 0.9976395368576049800000000f, 0.9969173073768615700000000f, 0.9960990548133850100000000f, + 0.9951847195625305200000000f, 0.9941744804382324200000000f, 0.9930684566497802700000000f, 0.9918667078018188500000000f, 0.9905693531036377000000000f, 0.9891765117645263700000000f, 0.9876883625984191900000000f, 0.9861049652099609400000000f, 0.9844265580177307100000000f, 0.9826532602310180700000000f, + 0.9807852506637573200000000f, 0.9788227677345275900000000f, 0.9767658710479736300000000f, 0.9746148586273193400000000f, 0.9723699092864990200000000f, 0.9700312614440918000000000f, 0.9675990939140319800000000f, 0.9650736451148986800000000f, 0.9624552130699157700000000f, 0.9597440361976623500000000f, + 0.9569402933120727500000000f, 0.9540444016456604000000000f, 0.9510564804077148400000000f, 0.9479769468307495100000000f, 0.9448060393333435100000000f, 0.9415440559387207000000000f, 0.9381912946701049800000000f, 0.9347481727600097700000000f, 0.9312149286270141600000000f, 0.9275919198989868200000000f, + 0.9238795042037963900000000f, 0.9200780391693115200000000f, 0.9161879420280456500000000f, 0.9122095108032226600000000f, 0.9081431627273559600000000f, 0.9039892554283142100000000f, 0.8997482657432556200000000f, 0.8954205513000488300000000f, 0.8910064697265625000000000f, 0.8865066170692443800000000f, + 0.8819212317466735800000000f, 0.8772509098052978500000000f, 0.8724959492683410600000000f, 0.8676570057868957500000000f, 0.8627343773841857900000000f, 0.8577286005020141600000000f, 0.8526401519775390600000000f, 0.8474695086479187000000000f, 0.8422172069549560500000000f, 0.8368837237358093300000000f, + 0.8314695954322814900000000f, 0.8259752988815307600000000f, 0.8204014301300048800000000f, 0.8147484660148620600000000f, 0.8090169429779052700000000f, 0.8032075166702270500000000f, 0.7973206043243408200000000f, 0.7913568615913391100000000f, 0.7853168845176696800000000f, 0.7792012095451355000000000f, + 0.7730104327201843300000000f, 0.7667450904846191400000000f, 0.7604058980941772500000000f, 0.7539934515953064000000000f, 0.7475082874298095700000000f, 0.7409510612487793000000000f, 0.7343224883079528800000000f, 0.7276230454444885300000000f, 0.7208535671234130900000000f, 0.7140145301818847700000000f, + 0.7071067094802856400000000f, 0.7001307606697082500000000f, 0.6930873394012451200000000f, 0.6859770417213439900000000f, 0.6788007020950317400000000f, 0.6715589165687561000000000f, 0.6642524003982543900000000f, 0.6568818688392639200000000f, 0.6494479775428772000000000f, 0.6419515609741210900000000f, + 0.6343932151794433600000000f, 0.6267737746238708500000000f, 0.6190938949584960900000000f, 0.6113543510437011700000000f, 0.6035558581352233900000000f, 0.5956992506980896000000000f, 0.5877851843833923300000000f, 0.5798144936561584500000000f, 0.5717878937721252400000000f, 0.5637062191963195800000000f, + 0.5555701851844787600000000f, 0.5473806262016296400000000f, 0.5391382575035095200000000f, 0.5308439731597900400000000f, 0.5224984884262085000000000f, 0.5141026973724365200000000f, 0.5056573152542114300000000f, 0.4971632063388824500000000f, 0.4886211752891540500000000f, 0.4800320565700531000000000f, + 0.4713966846466064500000000f, 0.4627158641815185500000000f, 0.4539904296398162800000000f, 0.4452212452888488800000000f, 0.4364091753959655800000000f, 0.4275550246238708500000000f, 0.4186596572399139400000000f, 0.4097239673137664800000000f, 0.4007487595081329300000000f, 0.3917349278926849400000000f, + 0.3826833665370941200000000f, 0.3735949099063873300000000f, 0.3644704222679138200000000f, 0.3553108274936676000000000f, 0.3461169898509979200000000f, 0.3368897736072540300000000f, 0.3276301026344299300000000f, 0.3183388411998748800000000f, 0.3090169131755828900000000f, 0.2996652126312255900000000f, + 0.2902846038341522200000000f, 0.2808760106563568100000000f, 0.2714403867721557600000000f, 0.2619785666465759300000000f, 0.2524915039539337200000000f, 0.2429801076650619500000000f, 0.2334452867507934600000000f, 0.2238879650831222500000000f, 0.2143090665340423600000000f, 0.2047095298767089800000000f, + 0.1950902342796325700000000f, 0.1854521632194519000000000f, 0.1757961958646774300000000f, 0.1661233007907867400000000f, 0.1564343869686126700000000f, 0.1467303931713104200000000f, 0.1370122581720352200000000f, 0.1272809207439422600000000f, 0.1175373122096061700000000f, 0.1077823787927627600000000f, + 0.0980170592665672300000000f, 0.0882422849535942080000000f, 0.0784590095281600950000000f, 0.0686681717634201050000000f, 0.0588707178831100460000000f, 0.0490675866603851320000000f, 0.0392597280442714690000000f, 0.0294480863958597180000000f, 0.0196336060762405400000000f, 0.0098172323778271675000000f, + -0.0000000874227765734758580f +}; + +/* Analysis windows for overlap-add */ +/* ener = 0.f; + for (j=0 ; jfftlen ; j++) + { + hs->olapWinAna[j] = (float)sin(EVS_PI*((float)j+0.5f)/(float)(hs->fftlen)); + ener += hs->olapWinAna[j]*hs->olapWinAna[j]; + } + ener = (float)sqrt( ener / (float)hs->fftlen ); + for (j=0 ; jfftlen ; j++) + { + hs->olapWinAna[j] /= ener; + } */ +const float olapWinAna512[512] = +{ + 0.0043387459591031075000000f, 0.0130160758271813390000000f, 0.0216929148882627490000000f, 0.0303689353168010710000000f, 0.0390438176691532140000000f, 0.0477172248065471650000000f, 0.0563888400793075560000000f, 0.0650583282113075260000000f, 0.0737253651022911070000000f, 0.0823896303772926330000000f, + 0.0910507962107658390000000f, 0.0997085273265838620000000f, 0.1083625108003616300000000f, 0.1170124113559722900000000f, 0.1256579011678695700000000f, 0.1342986673116684000000000f, 0.1429343819618225100000000f, 0.1515647023916244500000000f, 0.1601893156766891500000000f, 0.1688079088926315300000000f, + 0.1774201542139053300000000f, 0.1860256940126419100000000f, 0.1946242451667785600000000f, 0.2032154798507690400000000f, 0.2117990404367446900000000f, 0.2203746438026428200000000f, 0.2289419323205947900000000f, 0.2375006377696991000000000f, 0.2460503578186035200000000f, 0.2545908391475677500000000f, + 0.2631217241287231400000000f, 0.2716427147388458300000000f, 0.2801534831523895300000000f, 0.2886536717414856000000000f, 0.2971430122852325400000000f, 0.3056211769580841100000000f, 0.3140878379344940200000000f, 0.3225426375865936300000000f, 0.3309853076934814500000000f, 0.3394155502319335900000000f, + 0.3478329777717590300000000f, 0.3562373220920562700000000f, 0.3646282255649566700000000f, 0.3730054795742034900000000f, 0.3813686370849609400000000f, 0.3897174298763275100000000f, 0.3980515301227569600000000f, 0.4063706994056701700000000f, 0.4146745502948761000000000f, 0.4229627549648284900000000f, + 0.4312350451946258500000000f, 0.4394911527633667000000000f, 0.4477306604385376000000000f, 0.4559533298015594500000000f, 0.4641588330268859900000000f, 0.4723468720912933300000000f, 0.4805171191692352300000000f, 0.4886692464351654100000000f, 0.4968029856681823700000000f, 0.5049180388450622600000000f, + 0.5130140781402587900000000f, 0.5210908055305481000000000f, 0.5291479229927063000000000f, 0.5371851325035095200000000f, 0.5452020764350891100000000f, 0.5531984567642211900000000f, 0.5611740946769714400000000f, 0.5691285729408264200000000f, 0.5770615935325622600000000f, 0.5849729180335998500000000f, + 0.5928622484207153300000000f, 0.6007292270660400400000000f, 0.6085735559463501000000000f, 0.6163949966430664100000000f, 0.6241932511329650900000000f, 0.6319679617881774900000000f, 0.6397189497947692900000000f, 0.6474457979202270500000000f, 0.6551482677459716800000000f, 0.6628261208534240700000000f, + 0.6704789996147155800000000f, 0.6781066060066223100000000f, 0.6857087016105651900000000f, 0.6932849884033203100000000f, 0.7008351087570190400000000f, 0.7083588838577270500000000f, 0.7158560752868652300000000f, 0.7233262658119201700000000f, 0.7307691574096679700000000f, 0.7381845116615295400000000f, + 0.7455722093582153300000000f, 0.7529317140579223600000000f, 0.7602629661560058600000000f, 0.7675655484199523900000000f, 0.7748392224311828600000000f, 0.7820837497711181600000000f, 0.7892987728118896500000000f, 0.7964841723442077600000000f, 0.8036395311355590800000000f, 0.8107646703720092800000000f, + 0.8178592920303344700000000f, 0.8249230980873107900000000f, 0.8319557905197143600000000f, 0.8389572501182556200000000f, 0.8459270596504211400000000f, 0.8528650403022766100000000f, 0.8597708344459533700000000f, 0.8666443228721618700000000f, 0.8734852671623230000000000f, 0.8802932500839233400000000f, + 0.8870680332183837900000000f, 0.8938094973564147900000000f, 0.9005173444747924800000000f, 0.9071912169456481900000000f, 0.9138309359550476100000000f, 0.9204362630844116200000000f, 0.9270069003105163600000000f, 0.9335426688194274900000000f, 0.9400433301925659200000000f, 0.9465085864067077600000000f, + 0.9529381394386291500000000f, 0.9593318104743957500000000f, 0.9656894207000732400000000f, 0.9720106720924377400000000f, 0.9782953858375549300000000f, 0.9845431447029113800000000f, 0.9907538890838623000000000f, 0.9969274401664733900000000f, 1.0030633211135864000000000f, 1.0091614723205566000000000f, + 1.0152215957641602000000000f, 1.0212435722351074000000000f, 1.0272270441055298000000000f, 1.0331718921661377000000000f, 1.0390777587890625000000000f, 1.0449445247650146000000000f, 1.0507719516754150000000000f, 1.0565599203109741000000000f, 1.0623079538345337000000000f, 1.0680160522460937000000000f, + 1.0736839771270752000000000f, 1.0793114900588989000000000f, 1.0848982334136963000000000f, 1.0904443264007568000000000f, 1.0959492921829224000000000f, 1.1014128923416138000000000f, 1.1068351268768311000000000f, 1.1122156381607056000000000f, 1.1175543069839478000000000f, 1.1228508949279785000000000f, + 1.1281052827835083000000000f, 1.1333171129226685000000000f, 1.1384862661361694000000000f, 1.1436126232147217000000000f, 1.1486958265304565000000000f, 1.1537358760833740000000000f, 1.1587324142456055000000000f, 1.1636853218078613000000000f, 1.1685944795608521000000000f, 1.1734596490859985000000000f, + 1.1782805919647217000000000f, 1.1830571889877319000000000f, 1.1877892017364502000000000f, 1.1924765110015869000000000f, 1.1971189975738525000000000f, 1.2017163038253784000000000f, 1.2062685489654541000000000f, 1.2107752561569214000000000f, 1.2152363061904907000000000f, 1.2196516990661621000000000f, + 1.2240210771560669000000000f, 1.2283445596694946000000000f, 1.2326216697692871000000000f, 1.2368522882461548000000000f, 1.2410365343093872000000000f, 1.2451739311218262000000000f, 1.2492644786834717000000000f, 1.2533079385757446000000000f, 1.2573043107986450000000000f, 1.2612532377243042000000000f, + 1.2651547193527222000000000f, 1.2690086364746094000000000f, 1.2728147506713867000000000f, 1.2765728235244751000000000f, 1.2802829742431641000000000f, 1.2839449644088745000000000f, 1.2875584363937378000000000f, 1.2911235094070435000000000f, 1.2946400642395020000000000f, 1.2981077432632446000000000f, + 1.3015266656875610000000000f, 1.3048964738845825000000000f, 1.3082171678543091000000000f, 1.3114887475967407000000000f, 1.3147107362747192000000000f, 1.3178833723068237000000000f, 1.3210064172744751000000000f, 1.3240796327590942000000000f, 1.3271030187606812000000000f, 1.3300764560699463000000000f, + 1.3329998254776001000000000f, 1.3358730077743530000000000f, 1.3386958837509155000000000f, 1.3414683341979980000000000f, 1.3441903591156006000000000f, 1.3468616008758545000000000f, 1.3494822978973389000000000f, 1.3520522117614746000000000f, 1.3545711040496826000000000f, 1.3570390939712524000000000f, + 1.3594559431076050000000000f, 1.3618216514587402000000000f, 1.3641359806060791000000000f, 1.3663990497589111000000000f, 1.3686106204986572000000000f, 1.3707706928253174000000000f, 1.3728791475296021000000000f, 1.3749359846115112000000000f, 1.3769409656524658000000000f, 1.3788940906524658000000000f, + 1.3807953596115112000000000f, 1.3826445341110229000000000f, 1.3844418525695801000000000f, 1.3861869573593140000000000f, 1.3878798484802246000000000f, 1.3895204067230225000000000f, 1.3911087512969971000000000f, 1.3926446437835693000000000f, 1.3941282033920288000000000f, 1.3955593109130859000000000f, + 1.3969377279281616000000000f, 1.3982635736465454000000000f, 1.3995368480682373000000000f, 1.4007574319839478000000000f, 1.4019253253936768000000000f, 1.4030404090881348000000000f, 1.4041025638580322000000000f, 1.4051119089126587000000000f, 1.4060683250427246000000000f, 1.4069718122482300000000000f, + 1.4078224897384644000000000f, 1.4086199998855591000000000f, 1.4093644618988037000000000f, 1.4100558757781982000000000f, 1.4106942415237427000000000f, 1.4112794399261475000000000f, 1.4118115901947021000000000f, 1.4122905731201172000000000f, 1.4127163887023926000000000f, 1.4130889177322388000000000f, + 1.4134082794189453000000000f, 1.4136744737625122000000000f, 1.4138875007629395000000000f, 1.4140472412109375000000000f, 1.4141536951065063000000000f, 1.4142069816589355000000000f, 1.4142069816589355000000000f, 1.4141536951065063000000000f, 1.4140472412109375000000000f, 1.4138875007629395000000000f, + 1.4136744737625122000000000f, 1.4134082794189453000000000f, 1.4130889177322388000000000f, 1.4127163887023926000000000f, 1.4122905731201172000000000f, 1.4118115901947021000000000f, 1.4112794399261475000000000f, 1.4106942415237427000000000f, 1.4100558757781982000000000f, 1.4093644618988037000000000f, + 1.4086199998855591000000000f, 1.4078224897384644000000000f, 1.4069718122482300000000000f, 1.4060683250427246000000000f, 1.4051119089126587000000000f, 1.4041025638580322000000000f, 1.4030402898788452000000000f, 1.4019252061843872000000000f, 1.4007574319839478000000000f, 1.3995368480682373000000000f, + 1.3982635736465454000000000f, 1.3969377279281616000000000f, 1.3955591917037964000000000f, 1.3941282033920288000000000f, 1.3926446437835693000000000f, 1.3911087512969971000000000f, 1.3895204067230225000000000f, 1.3878798484802246000000000f, 1.3861868381500244000000000f, 1.3844418525695801000000000f, + 1.3826445341110229000000000f, 1.3807953596115112000000000f, 1.3788940906524658000000000f, 1.3769409656524658000000000f, 1.3749359846115112000000000f, 1.3728791475296021000000000f, 1.3707706928253174000000000f, 1.3686106204986572000000000f, 1.3663990497589111000000000f, 1.3641359806060791000000000f, + 1.3618216514587402000000000f, 1.3594559431076050000000000f, 1.3570389747619629000000000f, 1.3545711040496826000000000f, 1.3520520925521851000000000f, 1.3494822978973389000000000f, 1.3468616008758545000000000f, 1.3441903591156006000000000f, 1.3414683341979980000000000f, 1.3386958837509155000000000f, + 1.3358730077743530000000000f, 1.3329998254776001000000000f, 1.3300764560699463000000000f, 1.3271030187606812000000000f, 1.3240796327590942000000000f, 1.3210062980651855000000000f, 1.3178833723068237000000000f, 1.3147107362747192000000000f, 1.3114886283874512000000000f, 1.3082171678543091000000000f, + 1.3048964738845825000000000f, 1.3015265464782715000000000f, 1.2981077432632446000000000f, 1.2946399450302124000000000f, 1.2911235094070435000000000f, 1.2875584363937378000000000f, 1.2839448451995850000000000f, 1.2802829742431641000000000f, 1.2765728235244751000000000f, 1.2728147506713867000000000f, + 1.2690086364746094000000000f, 1.2651547193527222000000000f, 1.2612532377243042000000000f, 1.2573041915893555000000000f, 1.2533078193664551000000000f, 1.2492643594741821000000000f, 1.2451738119125366000000000f, 1.2410364151000977000000000f, 1.2368522882461548000000000f, 1.2326216697692871000000000f, + 1.2283444404602051000000000f, 1.2240210771560669000000000f, 1.2196515798568726000000000f, 1.2152363061904907000000000f, 1.2107751369476318000000000f, 1.2062684297561646000000000f, 1.2017163038253784000000000f, 1.1971189975738525000000000f, 1.1924765110015869000000000f, 1.1877892017364502000000000f, + 1.1830570697784424000000000f, 1.1782804727554321000000000f, 1.1734595298767090000000000f, 1.1685943603515625000000000f, 1.1636853218078613000000000f, 1.1587324142456055000000000f, 1.1537357568740845000000000f, 1.1486958265304565000000000f, 1.1436125040054321000000000f, 1.1384861469268799000000000f, + 1.1333171129226685000000000f, 1.1281051635742187000000000f, 1.1228507757186890000000000f, 1.1175541877746582000000000f, 1.1122155189514160000000000f, 1.1068350076675415000000000f, 1.1014127731323242000000000f, 1.0959491729736328000000000f, 1.0904442071914673000000000f, 1.0848982334136963000000000f, + 1.0793113708496094000000000f, 1.0736838579177856000000000f, 1.0680160522460937000000000f, 1.0623078346252441000000000f, 1.0565598011016846000000000f, 1.0507718324661255000000000f, 1.0449445247650146000000000f, 1.0390776395797729000000000f, 1.0331717729568481000000000f, 1.0272269248962402000000000f, + 1.0212434530258179000000000f, 1.0152214765548706000000000f, 1.0091613531112671000000000f, 1.0030632019042969000000000f, 0.9969273209571838400000000f, 0.9907538294792175300000000f, 0.9845430850982666000000000f, 0.9782953262329101600000000f, 0.9720106124877929700000000f, 0.9656893610954284700000000f, + 0.9593317508697509800000000f, 0.9529380798339843800000000f, 0.9465084671974182100000000f, 0.9400432705879211400000000f, 0.9335426092147827100000000f, 0.9270067811012268100000000f, 0.9204362034797668500000000f, 0.9138308763504028300000000f, 0.9071910977363586400000000f, 0.9005171656608581500000000f, + 0.8938094377517700200000000f, 0.8870679140090942400000000f, 0.8802930712699890100000000f, 0.8734850883483886700000000f, 0.8666442632675170900000000f, 0.8597707748413085900000000f, 0.8528649210929870600000000f, 0.8459268808364868200000000f, 0.8389570713043212900000000f, 0.8319557309150695800000000f, + 0.8249229192733764600000000f, 0.8178591728210449200000000f, 0.8107645511627197300000000f, 0.8036394119262695300000000f, 0.7964840531349182100000000f, 0.7892987132072448700000000f, 0.7820836901664733900000000f, 0.7748391628265380900000000f, 0.7675654292106628400000000f, 0.7602628469467163100000000f, + 0.7529316544532775900000000f, 0.7455720901489257800000000f, 0.7381844520568847700000000f, 0.7307690382003784200000000f, 0.7233260869979858400000000f, 0.7158559560775756800000000f, 0.7083588242530822800000000f, 0.7008350491523742700000000f, 0.6932848691940307600000000f, 0.6857085824012756300000000f, + 0.6781064867973327600000000f, 0.6704788804054260300000000f, 0.6628260016441345200000000f, 0.6551482081413269000000000f, 0.6474456787109375000000000f, 0.6397188305854797400000000f, 0.6319679021835327100000000f, 0.6241931319236755400000000f, 0.6163948774337768600000000f, 0.6085734367370605500000000f, + 0.6007291078567504900000000f, 0.5928621292114257800000000f, 0.5849727988243103000000000f, 0.5770615339279174800000000f, 0.5691284537315368700000000f, 0.5611739754676818800000000f, 0.5531983971595764200000000f, 0.5452019572257995600000000f, 0.5371850132942199700000000f, 0.5291478037834167500000000f, + 0.5210906863212585400000000f, 0.5130139589309692400000000f, 0.5049179196357727100000000f, 0.4968028664588928200000000f, 0.4886691272258758500000000f, 0.4805169999599456800000000f, 0.4723467230796814000000000f, 0.4641586840152740500000000f, 0.4559532105922699000000000f, 0.4477305412292480500000000f, + 0.4394910335540771500000000f, 0.4312349855899810800000000f, 0.4229626357555389400000000f, 0.4146744310855865500000000f, 0.4063705503940582300000000f, 0.3980514407157897900000000f, 0.3897172808647155800000000f, 0.3813685178756713900000000f, 0.3730053603649139400000000f, 0.3646281659603118900000000f, + 0.3562372326850891100000000f, 0.3478328585624694800000000f, 0.3394154310226440400000000f, 0.3309852182865142800000000f, 0.3225425183773040800000000f, 0.3140876889228820800000000f, 0.3056210577487945600000000f, 0.2971428930759429900000000f, 0.2886535525321960400000000f, 0.2801533639430999800000000f, + 0.2716425955295562700000000f, 0.2631216049194335900000000f, 0.2545907199382782000000000f, 0.2460502535104751600000000f, 0.2375005036592483500000000f, 0.2289418131113052400000000f, 0.2203745096921920800000000f, 0.2117989212274551400000000f, 0.2032153606414794900000000f, 0.1946241259574890100000000f, + 0.1860255748033523600000000f, 0.1774200350046157800000000f, 0.1688077896833419800000000f, 0.1601892113685607900000000f, 0.1515645831823349000000000f, 0.1429342478513717700000000f, 0.1342985481023788500000000f, 0.1256577819585800200000000f, 0.1170122846961021400000000f, 0.1083623841404914900000000f, + 0.0997084006667137150000000f, 0.0910506695508956910000000f, 0.0823895111680030820000000f, 0.0737252458930015560000000f, 0.0650582015514373780000000f, 0.0563887134194374080000000f, 0.0477171018719673160000000f, 0.0390436910092830660000000f, 0.0303688123822212220000000f, 0.0216927900910377500000000f, + 0.0130159519612789150000000f, 0.0043386225588619709000000f +}; + +const float olapWinAna640[640] = +{ + 0.0034709984902292490000000f, 0.0104129118844866750000000f, 0.0173545740544795990000000f, 0.0242958199232816700000000f, 0.0312364790588617320000000f, 0.0381763875484466550000000f, 0.0451153740286827090000000f, 0.0520532727241516110000000f, 0.0589899159967899320000000f, 0.0659251436591148380000000f, + 0.0728587806224823000000000f, 0.0797906517982482910000000f, 0.0867206156253814700000000f, 0.0936484783887863160000000f, 0.1005740910768508900000000f, 0.1074972823262214700000000f, 0.1144178733229637100000000f, 0.1213357225060463000000000f, 0.1282506436109542800000000f, 0.1351624578237533600000000f, + 0.1420710384845733600000000f, 0.1489761769771575900000000f, 0.1558777391910553000000000f, 0.1627755314111709600000000f, 0.1696694195270538300000000f, 0.1765592098236084000000000f, 0.1834447383880615200000000f, 0.1903258562088012700000000f, 0.1972023993730545000000000f, 0.2040741592645645100000000f, + 0.2109410166740417500000000f, 0.2178028076887130700000000f, 0.2246593385934829700000000f, 0.2315104454755783100000000f, 0.2383559793233871500000000f, 0.2451957911252975500000000f, 0.2520296573638916000000000f, 0.2588574886322021500000000f, 0.2656790614128112800000000f, 0.2724942266941070600000000f, + 0.2793028354644775400000000f, 0.2861047089099884000000000f, 0.2928997278213501000000000f, 0.2996876239776611300000000f, 0.3064683377742767300000000f, 0.3132416605949401900000000f, 0.3200074136257171600000000f, 0.3267655074596405000000000f, 0.3335156738758087200000000f, 0.3402578532695770300000000f, + 0.3469918072223663300000000f, 0.3537174165248870800000000f, 0.3604344725608825700000000f, 0.3671428561210632300000000f, 0.3738423883914947500000000f, 0.3805329203605651900000000f, 0.3872142732143402100000000f, 0.3938862979412078900000000f, 0.4005488157272338900000000f, 0.4072017371654510500000000f, + 0.4138447940349578900000000f, 0.4204779267311096200000000f, 0.4271008670330047600000000f, 0.4337135851383209200000000f, 0.4403158128261566200000000f, 0.4469074010848999000000000f, 0.4534882903099060100000000f, 0.4600581824779510500000000f, 0.4666170477867126500000000f, 0.4731646478176116900000000f, + 0.4797008633613586400000000f, 0.4862254858016967800000000f, 0.4927383959293365500000000f, 0.4992394745349884000000000f, 0.5057284832000732400000000f, 0.5122053027153015100000000f, 0.5186697840690612800000000f, 0.5251218080520629900000000f, 0.5315611362457275400000000f, 0.5379876494407653800000000f, + 0.5444012284278869600000000f, 0.5508016943931579600000000f, 0.5571888685226440400000000f, 0.5635626316070556600000000f, 0.5699228048324585000000000f, 0.5762692093849182100000000f, 0.5826017856597900400000000f, 0.5889202952384948700000000f, 0.5952246189117431600000000f, 0.6015146374702453600000000f, + 0.6077901124954223600000000f, 0.6140509843826293900000000f, 0.6202970147132873500000000f, 0.6265281438827514600000000f, 0.6327440738677978500000000f, 0.6389448642730712900000000f, 0.6451302766799926800000000f, 0.6513000726699829100000000f, 0.6574541926383972200000000f, 0.6635924577713012700000000f, + 0.6697147488594055200000000f, 0.6758209466934204100000000f, 0.6819108128547668500000000f, 0.6879842281341552700000000f, 0.6940411329269409200000000f, 0.7000812292098999000000000f, 0.7061045169830322300000000f, 0.7121107578277587900000000f, 0.7180998921394348100000000f, 0.7240716814994812000000000f, + 0.7300260066986084000000000f, 0.7359628081321716300000000f, 0.7418818473815918000000000f, 0.7477830052375793500000000f, 0.7536661028861999500000000f, 0.7595310807228088400000000f, 0.7653777003288269000000000f, 0.7712059617042541500000000f, 0.7770156264305114700000000f, 0.7828065156936645500000000f, + 0.7885786294937133800000000f, 0.7943316698074340800000000f, 0.8000655770301818800000000f, 0.8057801723480224600000000f, 0.8114753961563110400000000f, 0.8171511292457580600000000f, 0.8228070735931396500000000f, 0.8284432291984558100000000f, 0.8340594172477722200000000f, 0.8396555185317993200000000f, + 0.8452314138412475600000000f, 0.8507869243621826200000000f, 0.8563219308853149400000000f, 0.8618362545967102100000000f, 0.8673298358917236300000000f, 0.8728026151657104500000000f, 0.8782541751861572300000000f, 0.8836847543716430700000000f, 0.8890939354896545400000000f, 0.8944817185401916500000000f, + 0.8998479843139648400000000f, 0.9051925539970397900000000f, 0.9105152487754821800000000f, 0.9158160686492919900000000f, 0.9210947751998901400000000f, 0.9263513088226318400000000f, 0.9315855503082275400000000f, 0.9367973208427429200000000f, 0.9419865608215332000000000f, 0.9471529722213745100000000f, + 0.9522966742515564000000000f, 0.9574174284934997600000000f, 0.9625151157379150400000000f, 0.9675895571708679200000000f, 0.9726406931877136200000000f, 0.9776684641838073700000000f, 0.9826726913452148400000000f, 0.9876530766487121600000000f, 0.9926097989082336400000000f, 0.9975425601005554200000000f, + 1.0024513006210327000000000f, 1.0073359012603760000000000f, 1.0121961832046509000000000f, 1.0170321464538574000000000f, 1.0218435525894165000000000f, 1.0266302824020386000000000f, 1.0313923358917236000000000f, 1.0361295938491821000000000f, 1.0408418178558350000000000f, 1.0455290079116821000000000f, + 1.0501909255981445000000000f, 1.0548275709152222000000000f, 1.0594388246536255000000000f, 1.0640245676040649000000000f, 1.0685845613479614000000000f, 1.0731189250946045000000000f, 1.0776274204254150000000000f, 1.0821099281311035000000000f, 1.0865663290023804000000000f, 1.0909965038299561000000000f, + 1.0954004526138306000000000f, 1.0997780561447144000000000f, 1.1041290760040283000000000f, 1.1084536314010620000000000f, 1.1127513647079468000000000f, 1.1170222759246826000000000f, 1.1212662458419800000000000f, 1.1254832744598389000000000f, 1.1296732425689697000000000f, 1.1338359117507935000000000f, + 1.1379711627960205000000000f, 1.1420791149139404000000000f, 1.1461595296859741000000000f, 1.1502122879028320000000000f, 1.1542373895645142000000000f, 1.1582345962524414000000000f, 1.1622040271759033000000000f, 1.1661453247070312000000000f, 1.1700586080551147000000000f, 1.1739436388015747000000000f, + 1.1778002977371216000000000f, 1.1816288232803345000000000f, 1.1854286193847656000000000f, 1.1892000436782837000000000f, 1.1929427385330200000000000f, 1.1966567039489746000000000f, 1.2003418207168579000000000f, 1.2039979696273804000000000f, 1.2076252698898315000000000f, 1.2112232446670532000000000f, + 1.2147921323776245000000000f, 1.2183318138122559000000000f, 1.2218420505523682000000000f, 1.2253229618072510000000000f, 1.2287741899490356000000000f, 1.2321958541870117000000000f, 1.2355878353118896000000000f, 1.2389501333236694000000000f, 1.2422825098037720000000000f, 1.2455849647521973000000000f, + 1.2488573789596558000000000f, 1.2520997524261475000000000f, 1.2553119659423828000000000f, 1.2584939002990723000000000f, 1.2616454362869263000000000f, 1.2647666931152344000000000f, 1.2678573131561279000000000f, 1.2709175348281860000000000f, 1.2739471197128296000000000f, 1.2769459486007690000000000f, + 1.2799140214920044000000000f, 1.2828512191772461000000000f, 1.2857576608657837000000000f, 1.2886329889297485000000000f, 1.2914773225784302000000000f, 1.2942904233932495000000000f, 1.2970724105834961000000000f, 1.2998231649398804000000000f, 1.3025425672531128000000000f, 1.3052306175231934000000000f, + 1.3078873157501221000000000f, 1.3105123043060303000000000f, 1.3131058216094971000000000f, 1.3156676292419434000000000f, 1.3181978464126587000000000f, 1.3206962347030640000000000f, 1.3231627941131592000000000f, 1.3255974054336548000000000f, 1.3280001878738403000000000f, 1.3303710222244263000000000f, + 1.3327096700668335000000000f, 1.3350162506103516000000000f, 1.3372906446456909000000000f, 1.3395328521728516000000000f, 1.3417427539825439000000000f, 1.3439202308654785000000000f, 1.3460655212402344000000000f, 1.3481782674789429000000000f, 1.3502584695816040000000000f, 1.3523062467575073000000000f, + 1.3543214797973633000000000f, 1.3563039302825928000000000f, 1.3582537174224854000000000f, 1.3601709604263306000000000f, 1.3620551824569702000000000f, 1.3639067411422729000000000f, 1.3657253980636597000000000f, 1.3675111532211304000000000f, 1.3692638874053955000000000f, 1.3709838390350342000000000f, + 1.3726705312728882000000000f, 1.3743242025375366000000000f, 1.3759448528289795000000000f, 1.3775322437286377000000000f, 1.3790863752365112000000000f, 1.3806074857711792000000000f, 1.3820952177047729000000000f, 1.3835495710372925000000000f, 1.3849706649780273000000000f, 1.3863584995269775000000000f, + 1.3877127170562744000000000f, 1.3890335559844971000000000f, 1.3903210163116455000000000f, 1.3915749788284302000000000f, 1.3927953243255615000000000f, 1.3939821720123291000000000f, 1.3951354026794434000000000f, 1.3962548971176147000000000f, 1.3973408937454224000000000f, 1.3983932733535767000000000f, + 1.3994117975234985000000000f, 1.4003967046737671000000000f, 1.4013478755950928000000000f, 1.4022653102874756000000000f, 1.4031487703323364000000000f, 1.4039986133575439000000000f, 1.4048146009445190000000000f, 1.4055966138839722000000000f, 1.4063447713851929000000000f, 1.4070591926574707000000000f, + 1.4077396392822266000000000f, 1.4083861112594604000000000f, 1.4089987277984619000000000f, 1.4095773696899414000000000f, 1.4101220369338989000000000f, 1.4106327295303345000000000f, 1.4111093282699585000000000f, 1.4115520715713501000000000f, 1.4119608402252197000000000f, 1.4123353958129883000000000f, + 1.4126759767532349000000000f, 1.4129825830459595000000000f, 1.4132552146911621000000000f, 1.4134936332702637000000000f, 1.4136980772018433000000000f, 1.4138684272766113000000000f, 1.4140048027038574000000000f, 1.4141069650650024000000000f, 1.4141751527786255000000000f, 1.4142091274261475000000000f, + 1.4142091274261475000000000f, 1.4141751527786255000000000f, 1.4141069650650024000000000f, 1.4140048027038574000000000f, 1.4138684272766113000000000f, 1.4136980772018433000000000f, 1.4134936332702637000000000f, 1.4132550954818726000000000f, 1.4129825830459595000000000f, 1.4126759767532349000000000f, + 1.4123353958129883000000000f, 1.4119607210159302000000000f, 1.4115520715713501000000000f, 1.4111093282699585000000000f, 1.4106327295303345000000000f, 1.4101220369338989000000000f, 1.4095773696899414000000000f, 1.4089987277984619000000000f, 1.4083861112594604000000000f, 1.4077396392822266000000000f, + 1.4070591926574707000000000f, 1.4063447713851929000000000f, 1.4055966138839722000000000f, 1.4048146009445190000000000f, 1.4039986133575439000000000f, 1.4031487703323364000000000f, 1.4022653102874756000000000f, 1.4013477563858032000000000f, 1.4003967046737671000000000f, 1.3994117975234985000000000f, + 1.3983932733535767000000000f, 1.3973408937454224000000000f, 1.3962548971176147000000000f, 1.3951354026794434000000000f, 1.3939821720123291000000000f, 1.3927953243255615000000000f, 1.3915748596191406000000000f, 1.3903210163116455000000000f, 1.3890335559844971000000000f, 1.3877127170562744000000000f, + 1.3863583803176880000000000f, 1.3849706649780273000000000f, 1.3835495710372925000000000f, 1.3820950984954834000000000f, 1.3806074857711792000000000f, 1.3790863752365112000000000f, 1.3775322437286377000000000f, 1.3759448528289795000000000f, 1.3743242025375366000000000f, 1.3726705312728882000000000f, + 1.3709837198257446000000000f, 1.3692638874053955000000000f, 1.3675111532211304000000000f, 1.3657253980636597000000000f, 1.3639067411422729000000000f, 1.3620551824569702000000000f, 1.3601708412170410000000000f, 1.3582537174224854000000000f, 1.3563039302825928000000000f, 1.3543213605880737000000000f, + 1.3523062467575073000000000f, 1.3502584695816040000000000f, 1.3481782674789429000000000f, 1.3460655212402344000000000f, 1.3439202308654785000000000f, 1.3417427539825439000000000f, 1.3395328521728516000000000f, 1.3372905254364014000000000f, 1.3350161314010620000000000f, 1.3327096700668335000000000f, + 1.3303709030151367000000000f, 1.3280001878738403000000000f, 1.3255974054336548000000000f, 1.3231626749038696000000000f, 1.3206962347030640000000000f, 1.3181978464126587000000000f, 1.3156676292419434000000000f, 1.3131058216094971000000000f, 1.3105123043060303000000000f, 1.3078871965408325000000000f, + 1.3052306175231934000000000f, 1.3025425672531128000000000f, 1.2998231649398804000000000f, 1.2970724105834961000000000f, 1.2942904233932495000000000f, 1.2914772033691406000000000f, 1.2886328697204590000000000f, 1.2857575416564941000000000f, 1.2828512191772461000000000f, 1.2799140214920044000000000f, + 1.2769459486007690000000000f, 1.2739471197128296000000000f, 1.2709175348281860000000000f, 1.2678573131561279000000000f, 1.2647665739059448000000000f, 1.2616454362869263000000000f, 1.2584937810897827000000000f, 1.2553118467330933000000000f, 1.2520996332168579000000000f, 1.2488572597503662000000000f, + 1.2455849647521973000000000f, 1.2422825098037720000000000f, 1.2389501333236694000000000f, 1.2355878353118896000000000f, 1.2321958541870117000000000f, 1.2287741899490356000000000f, 1.2253228425979614000000000f, 1.2218420505523682000000000f, 1.2183316946029663000000000f, 1.2147921323776245000000000f, + 1.2112232446670532000000000f, 1.2076251506805420000000000f, 1.2039978504180908000000000f, 1.2003417015075684000000000f, 1.1966565847396851000000000f, 1.1929427385330200000000000f, 1.1891999244689941000000000f, 1.1854286193847656000000000f, 1.1816287040710449000000000f, 1.1778002977371216000000000f, + 1.1739435195922852000000000f, 1.1700584888458252000000000f, 1.1661452054977417000000000f, 1.1622039079666138000000000f, 1.1582344770431519000000000f, 1.1542372703552246000000000f, 1.1502121686935425000000000f, 1.1461594104766846000000000f, 1.1420789957046509000000000f, 1.1379710435867310000000000f, + 1.1338357925415039000000000f, 1.1296731233596802000000000f, 1.1254831552505493000000000f, 1.1212662458419800000000000f, 1.1170221567153931000000000f, 1.1127512454986572000000000f, 1.1084535121917725000000000f, 1.1041289567947388000000000f, 1.0997780561447144000000000f, 1.0954004526138306000000000f, + 1.0909965038299561000000000f, 1.0865662097930908000000000f, 1.0821098089218140000000000f, 1.0776273012161255000000000f, 1.0731188058853149000000000f, 1.0685844421386719000000000f, 1.0640244483947754000000000f, 1.0594387054443359000000000f, 1.0548274517059326000000000f, 1.0501908063888550000000000f, + 1.0455288887023926000000000f, 1.0408416986465454000000000f, 1.0361294746398926000000000f, 1.0313922166824341000000000f, 1.0266302824020386000000000f, 1.0218434333801270000000000f, 1.0170320272445679000000000f, 1.0121960639953613000000000f, 1.0073357820510864000000000f, 1.0024513006210327000000000f, + 0.9975425004959106400000000f, 0.9926097393035888700000000f, 0.9876530170440673800000000f, 0.9826725125312805200000000f, 0.9776684045791626000000000f, 0.9726406335830688500000000f, 0.9675894975662231400000000f, 0.9625149965286254900000000f, 0.9574173688888549800000000f, 0.9522966146469116200000000f, + 0.9471529126167297400000000f, 0.9419864416122436500000000f, 0.9367972612380981400000000f, 0.9315854907035827600000000f, 0.9263512492179870600000000f, 0.9210947155952453600000000f, 0.9158159494400024400000000f, 0.9105151891708374000000000f, 0.9051924347877502400000000f, 0.8998478651046752900000000f, + 0.8944816589355468800000000f, 0.8890938758850097700000000f, 0.8836846351623535200000000f, 0.8782541155815124500000000f, 0.8728024363517761200000000f, 0.8673297166824340800000000f, 0.8618361353874206500000000f, 0.8563218116760253900000000f, 0.8507867455482482900000000f, 0.8452312946319580100000000f, + 0.8396554589271545400000000f, 0.8340593576431274400000000f, 0.8284431099891662600000000f, 0.8228070139884948700000000f, 0.8171509504318237300000000f, 0.8114752769470214800000000f, 0.8057801127433776900000000f, 0.8000654578208923300000000f, 0.7943315505981445300000000f, 0.7885785102844238300000000f, + 0.7828064560890197800000000f, 0.7770155668258667000000000f, 0.7712058424949646000000000f, 0.7653776407241821300000000f, 0.7595309019088745100000000f, 0.7536660432815551800000000f, 0.7477828264236450200000000f, 0.7418816685676574700000000f, 0.7359626293182373000000000f, 0.7300259470939636200000000f, + 0.7240716218948364300000000f, 0.7180998325347900400000000f, 0.7121106386184692400000000f, 0.7061043977737426800000000f, 0.7000811696052551300000000f, 0.6940410137176513700000000f, 0.6879841089248657200000000f, 0.6819106936454772900000000f, 0.6758208274841308600000000f, 0.6697146296501159700000000f, + 0.6635923385620117200000000f, 0.6574540734291076700000000f, 0.6512999534606933600000000f, 0.6451301574707031300000000f, 0.6389448046684265100000000f, 0.6327440142631530800000000f, 0.6265279650688171400000000f, 0.6202968955039978000000000f, 0.6140508651733398400000000f, 0.6077899932861328100000000f, + 0.6015145182609558100000000f, 0.5952244997024536100000000f, 0.5889201760292053200000000f, 0.5826016664505004900000000f, 0.5762690901756286600000000f, 0.5699226856231689500000000f, 0.5635625123977661100000000f, 0.5571887493133544900000000f, 0.5508015751838684100000000f, 0.5444011092185974100000000f, + 0.5379875302314758300000000f, 0.5315610170364379900000000f, 0.5251216888427734400000000f, 0.5186696648597717300000000f, 0.5122051835060119600000000f, 0.5057283639907836900000000f, 0.4992393255233764600000000f, 0.4927382767200470000000000f, 0.4862253665924072300000000f, 0.4797007441520690900000000f, + 0.4731644988059997600000000f, 0.4666169285774231000000000f, 0.4600581228733062700000000f, 0.4534881711006164600000000f, 0.4469073116779327400000000f, 0.4403156936168670700000000f, 0.4337134659290313700000000f, 0.4271008074283599900000000f, 0.4204778075218200700000000f, 0.4138446748256683300000000f, + 0.4072016179561615000000000f, 0.4005487561225891100000000f, 0.3938861787319183300000000f, 0.3872141540050506600000000f, 0.3805327713489532500000000f, 0.3738422691822052000000000f, 0.3671427369117736800000000f, 0.3604343533515930200000000f, 0.3537172675132751500000000f, 0.3469916582107543900000000f, + 0.3402577340602874800000000f, 0.3335155844688415500000000f, 0.3267653882503509500000000f, 0.3200073242187500000000000f, 0.3132415413856506300000000f, 0.3064682185649871800000000f, 0.2996875047683715800000000f, 0.2928995788097381600000000f, 0.2861045897006988500000000f, 0.2793027162551879900000000f, + 0.2724941074848175000000000f, 0.2656789422035217300000000f, 0.2588573694229126000000000f, 0.2520295381546020500000000f, 0.2451956570148468000000000f, 0.2383558601140976000000000f, 0.2315103262662887600000000f, 0.2246592044830322300000000f, 0.2178026735782623300000000f, 0.2109408974647522000000000f, + 0.2040740400552749600000000f, 0.1972022652626037600000000f, 0.1903257369995117200000000f, 0.1834446042776107800000000f, 0.1765590757131576500000000f, 0.1696692854166030900000000f, 0.1627754122018814100000000f, 0.1558776050806045500000000f, 0.1489760577678680400000000f, 0.1420709043741226200000000f, + 0.1351623386144638100000000f, 0.1282505095005035400000000f, 0.1213355958461761500000000f, 0.1144177615642547600000000f, 0.1074971556663513200000000f, 0.1005739644169807400000000f, 0.0936483591794967650000000f, 0.0867204889655113220000000f, 0.0797905325889587400000000f, 0.0728586539626121520000000f, + 0.0659250169992446900000000f, 0.0589897930622100830000000f, 0.0520531460642814640000000f, 0.0451152473688125610000000f, 0.0381762608885765080000000f, 0.0312363542616367340000000f, 0.0242956969887018200000000f, 0.0173544511198997500000000f, 0.0104127889499068260000000f, 0.0034708750899881124000000f +}; + +/* Synthesis windows for overlap-add */ +/* for (j=0 ; jfftlen ; j++) hs->olapWinSyn[j] = (float)sin(EVS_PI*((float)j+0.5f)/(float)(hs->fftlen); */ +const float olapWinSyn256[256] = +{ + 0.0061358846f, + 0.0184067299f, + 0.0306748032f, + 0.0429382569f, + 0.0551952443f, + 0.0674439196f, + 0.0796824380f, + 0.0919089565f, + 0.1041216339f, + 0.1163186309f, + 0.1284981108f, + 0.1406582393f, + 0.1527971853f, + 0.1649131205f, + 0.1770042204f, + 0.1890686641f, + 0.2011046348f, + 0.2131103199f, + 0.2250839114f, + 0.2370236060f, + 0.2489276057f, + 0.2607941179f, + 0.2726213554f, + 0.2844075372f, + 0.2961508882f, + 0.3078496400f, + 0.3195020308f, + 0.3311063058f, + 0.3426607173f, + 0.3541635254f, + 0.3656129978f, + 0.3770074102f, + 0.3883450467f, + 0.3996241998f, + 0.4108431711f, + 0.4220002708f, + 0.4330938189f, + 0.4441221446f, + 0.4550835871f, + 0.4659764958f, + 0.4767992301f, + 0.4875501601f, + 0.4982276670f, + 0.5088301425f, + 0.5193559902f, + 0.5298036247f, + 0.5401714727f, + 0.5504579729f, + 0.5606615762f, + 0.5707807459f, + 0.5808139581f, + 0.5907597019f, + 0.6006164794f, + 0.6103828063f, + 0.6200572118f, + 0.6296382389f, + 0.6391244449f, + 0.6485144010f, + 0.6578066933f, + 0.6669999223f, + 0.6760927036f, + 0.6850836678f, + 0.6939714609f, + 0.7027547445f, + 0.7114321957f, + 0.7200025080f, + 0.7284643904f, + 0.7368165689f, + 0.7450577854f, + 0.7531867990f, + 0.7612023855f, + 0.7691033376f, + 0.7768884657f, + 0.7845565972f, + 0.7921065773f, + 0.7995372691f, + 0.8068475535f, + 0.8140363297f, + 0.8211025150f, + 0.8280450453f, + 0.8348628750f, + 0.8415549774f, + 0.8481203448f, + 0.8545579884f, + 0.8608669386f, + 0.8670462455f, + 0.8730949784f, + 0.8790122264f, + 0.8847970984f, + 0.8904487232f, + 0.8959662498f, + 0.9013488470f, + 0.9065957045f, + 0.9117060320f, + 0.9166790599f, + 0.9215140393f, + 0.9262102421f, + 0.9307669611f, + 0.9351835099f, + 0.9394592236f, + 0.9435934582f, + 0.9475855910f, + 0.9514350210f, + 0.9551411683f, + 0.9587034749f, + 0.9621214043f, + 0.9653944417f, + 0.9685220943f, + 0.9715038910f, + 0.9743393828f, + 0.9770281427f, + 0.9795697657f, + 0.9819638691f, + 0.9842100924f, + 0.9863080972f, + 0.9882575677f, + 0.9900582103f, + 0.9917097537f, + 0.9932119492f, + 0.9945645707f, + 0.9957674145f, + 0.9968202993f, + 0.9977230666f, + 0.9984755806f, + 0.9990777278f, + 0.9995294175f, + 0.9998305818f, + 0.9999811753f, + 0.9999811753f, + 0.9998305818f, + 0.9995294175f, + 0.9990777278f, + 0.9984755806f, + 0.9977230666f, + 0.9968202993f, + 0.9957674145f, + 0.9945645707f, + 0.9932119492f, + 0.9917097537f, + 0.9900582103f, + 0.9882575677f, + 0.9863080972f, + 0.9842100924f, + 0.9819638691f, + 0.9795697657f, + 0.9770281427f, + 0.9743393828f, + 0.9715038910f, + 0.9685220943f, + 0.9653944417f, + 0.9621214043f, + 0.9587034749f, + 0.9551411683f, + 0.9514350210f, + 0.9475855910f, + 0.9435934582f, + 0.9394592236f, + 0.9351835099f, + 0.9307669611f, + 0.9262102421f, + 0.9215140393f, + 0.9166790599f, + 0.9117060320f, + 0.9065957045f, + 0.9013488470f, + 0.8959662498f, + 0.8904487232f, + 0.8847970984f, + 0.8790122264f, + 0.8730949784f, + 0.8670462455f, + 0.8608669386f, + 0.8545579884f, + 0.8481203448f, + 0.8415549774f, + 0.8348628750f, + 0.8280450453f, + 0.8211025150f, + 0.8140363297f, + 0.8068475535f, + 0.7995372691f, + 0.7921065773f, + 0.7845565972f, + 0.7768884657f, + 0.7691033376f, + 0.7612023855f, + 0.7531867990f, + 0.7450577854f, + 0.7368165689f, + 0.7284643904f, + 0.7200025080f, + 0.7114321957f, + 0.7027547445f, + 0.6939714609f, + 0.6850836678f, + 0.6760927036f, + 0.6669999223f, + 0.6578066933f, + 0.6485144010f, + 0.6391244449f, + 0.6296382389f, + 0.6200572118f, + 0.6103828063f, + 0.6006164794f, + 0.5907597019f, + 0.5808139581f, + 0.5707807459f, + 0.5606615762f, + 0.5504579729f, + 0.5401714727f, + 0.5298036247f, + 0.5193559902f, + 0.5088301425f, + 0.4982276670f, + 0.4875501601f, + 0.4767992301f, + 0.4659764958f, + 0.4550835871f, + 0.4441221446f, + 0.4330938189f, + 0.4220002708f, + 0.4108431711f, + 0.3996241998f, + 0.3883450467f, + 0.3770074102f, + 0.3656129978f, + 0.3541635254f, + 0.3426607173f, + 0.3311063058f, + 0.3195020308f, + 0.3078496400f, + 0.2961508882f, + 0.2844075372f, + 0.2726213554f, + 0.2607941179f, + 0.2489276057f, + 0.2370236060f, + 0.2250839114f, + 0.2131103199f, + 0.2011046348f, + 0.1890686641f, + 0.1770042204f, + 0.1649131205f, + 0.1527971853f, + 0.1406582393f, + 0.1284981108f, + 0.1163186309f, + 0.1041216339f, + 0.0919089565f, + 0.0796824380f, + 0.0674439196f, + 0.0551952443f, + 0.0429382569f, + 0.0306748032f, + 0.0184067299f, + 0.0061358846f +}; +const float olapWinSyn320[320] = +{ + 0.0049087191000580788000000f, 0.0147256832569837570000000f, 0.0245412290096282960000000f, 0.0343544110655784610000000f, 0.0441642776131629940000000f, 0.0539698898792266850000000f, 0.0637703016400337220000000f, 0.0735645666718482970000000f, 0.0833517387509346010000000f, 0.0931308791041374210000000f, + 0.1029010415077209500000000f, 0.1126612871885299700000000f, 0.1224106773734092700000000f, 0.1321482658386230500000000f, 0.1418731212615966800000000f, 0.1515842974185943600000000f, 0.1612808704376220700000000f, 0.1709618866443634000000000f, 0.1806264370679855300000000f, 0.1902735829353332500000000f, + 0.1999023705720901500000000f, 0.2095119059085845900000000f, 0.2191012501716613800000000f, 0.2286694645881652800000000f, 0.2382156550884246800000000f, 0.2477388679981231700000000f, 0.2572382092475891100000000f, 0.2667127549648284900000000f, 0.2761616110801696800000000f, 0.2855838239192962600000000f, + 0.2949785292148590100000000f, 0.3043448030948638900000000f, 0.3136817514896392800000000f, 0.3229884505271911600000000f, 0.3322640359401702900000000f, 0.3415075838565826400000000f, 0.3507182002067565900000000f, 0.3598950505256652800000000f, 0.3690371811389923100000000f, 0.3781437575817108200000000f, + 0.3872138857841491700000000f, 0.3962467014789581300000000f, 0.4052413105964660600000000f, 0.4141968786716461200000000f, 0.4231125116348266600000000f, 0.4319873750209808300000000f, 0.4408206045627594000000000f, 0.4496113359928131100000000f, 0.4583587348461151100000000f, 0.4670619666576385500000000f, + 0.4757201671600341800000000f, 0.4843325316905975300000000f, 0.4928981959819793700000000f, 0.5014163851737976100000000f, 0.5098862051963806200000000f, 0.5183069109916687000000000f, 0.5266776680946350100000000f, 0.5349976420402526900000000f, 0.5432660579681396500000000f, 0.5514820814132690400000000f, + 0.5596449971199035600000000f, 0.5677539706230163600000000f, 0.5758082270622253400000000f, 0.5838069319725036600000000f, 0.5917494297027587900000000f, 0.5996348857879638700000000f, 0.6074625253677368200000000f, 0.6152316331863403300000000f, 0.6229414343833923300000000f, 0.6305911540985107400000000f, + 0.6381801366806030300000000f, 0.6457076072692871100000000f, 0.6531728506088256800000000f, 0.6605751514434814500000000f, 0.6679137349128723100000000f, 0.6751880049705505400000000f, 0.6823971867561340300000000f, 0.6895405650138855000000000f, 0.6966174840927124000000000f, 0.7036272883415222200000000f, + 0.7105692625045776400000000f, 0.7174427509307861300000000f, 0.7242470979690551800000000f, 0.7309816479682922400000000f, 0.7376457452774047900000000f, 0.7442387342453002900000000f, 0.7507599592208862300000000f, 0.7572088837623596200000000f, 0.7635847926139831500000000f, 0.7698870897293090800000000f, + 0.7761152386665344200000000f, 0.7822685241699218800000000f, 0.7883464694023132300000000f, 0.7943483591079711900000000f, 0.8002737760543823200000000f, 0.8061220049858093300000000f, 0.8118925094604492200000000f, 0.8175848126411438000000000f, 0.8231983184814453100000000f, 0.8287324905395507800000000f, + 0.8341867327690124500000000f, 0.8395606279373168900000000f, 0.8448535799980163600000000f, 0.8500651121139526400000000f, 0.8551946878433227500000000f, 0.8602418899536132800000000f, 0.8652061223983764600000000f, 0.8700870275497436500000000f, 0.8748840093612670900000000f, 0.8795967102050781300000000f, + 0.8842245936393737800000000f, 0.8887673020362854000000000f, 0.8932242989540100100000000f, 0.8975952267646789600000000f, 0.9018796682357788100000000f, 0.9060771465301513700000000f, 0.9101873040199279800000000f, 0.9142097830772399900000000f, 0.9181441068649292000000000f, 0.9219899177551269500000000f, + 0.9257469177246093800000000f, 0.9294146299362182600000000f, 0.9329928159713745100000000f, 0.9364810585975647000000000f, 0.9398790597915649400000000f, 0.9431864023208618200000000f, 0.9464029073715210000000000f, 0.9495282173156738300000000f, 0.9525619745254516600000000f, 0.9555038809776306200000000f, + 0.9583537578582763700000000f, 0.9611112475395202600000000f, 0.9637760519981384300000000f, 0.9663480520248413100000000f, 0.9688268303871154800000000f, 0.9712122678756713900000000f, 0.9735041260719299300000000f, 0.9757021665573120100000000f, 0.9778060913085937500000000f, 0.9798158407211303700000000f, + 0.9817311167716980000000000f, 0.9835518002510070800000000f, 0.9852776527404785200000000f, 0.9869085550308227500000000f, 0.9884443283081054700000000f, 0.9898848533630371100000000f, 0.9912299513816833500000000f, 0.9924795627593994100000000f, 0.9936334490776062000000000f, 0.9946916103363037100000000f, + 0.9956538677215576200000000f, 0.9965202212333679200000000f, 0.9972904324531555200000000f, 0.9979646205902099600000000f, 0.9985425472259521500000000f, 0.9990242719650268600000000f, 0.9994097352027893100000000f, 0.9996988177299499500000000f, 0.9998915791511535600000000f, 0.9999879598617553700000000f, + 0.9999879598617553700000000f, 0.9998915791511535600000000f, 0.9996988177299499500000000f, 0.9994097352027893100000000f, 0.9990242719650268600000000f, 0.9985425472259521500000000f, 0.9979646205902099600000000f, 0.9972904324531555200000000f, 0.9965201616287231400000000f, 0.9956538677215576200000000f, + 0.9946916103363037100000000f, 0.9936334490776062000000000f, 0.9924795031547546400000000f, 0.9912299513816833500000000f, 0.9898848533630371100000000f, 0.9884443283081054700000000f, 0.9869085550308227500000000f, 0.9852776527404785200000000f, 0.9835517406463623000000000f, 0.9817311167716980000000000f, + 0.9798157811164856000000000f, 0.9778060913085937500000000f, 0.9757021069526672400000000f, 0.9735041260719299300000000f, 0.9712122678756713900000000f, 0.9688268303871154800000000f, 0.9663479924201965300000000f, 0.9637760519981384300000000f, 0.9611111879348754900000000f, 0.9583536982536315900000000f, + 0.9555038809776306200000000f, 0.9525619149208068800000000f, 0.9495281577110290500000000f, 0.9464029073715210000000000f, 0.9431864023208618200000000f, 0.9398790001869201700000000f, 0.9364809989929199200000000f, 0.9329927563667297400000000f, 0.9294146299362182600000000f, 0.9257468581199646000000000f, + 0.9219899177551269500000000f, 0.9181440472602844200000000f, 0.9142097234725952100000000f, 0.9101873040199279800000000f, 0.9060771465301513700000000f, 0.9018796086311340300000000f, 0.8975952267646789600000000f, 0.8932242989540100100000000f, 0.8887672424316406300000000f, 0.8842245936393737800000000f, + 0.8795966506004333500000000f, 0.8748839497566223100000000f, 0.8700869679450988800000000f, 0.8652060627937316900000000f, 0.8602418303489685100000000f, 0.8551946878433227500000000f, 0.8500650525093078600000000f, 0.8448535203933715800000000f, 0.8395605683326721200000000f, 0.8341866731643676800000000f, + 0.8287324309349060100000000f, 0.8231982588768005400000000f, 0.8175847530364990200000000f, 0.8118925094604492200000000f, 0.8061219453811645500000000f, 0.8002737164497375500000000f, 0.7943482995033264200000000f, 0.7883464097976684600000000f, 0.7822684645652771000000000f, 0.7761151790618896500000000f, + 0.7698870301246643100000000f, 0.7635847330093383800000000f, 0.7572088241577148400000000f, 0.7507598996162414600000000f, 0.7442386746406555200000000f, 0.7376456856727600100000000f, 0.7309815883636474600000000f, 0.7242470383644104000000000f, 0.7174426913261413600000000f, 0.7105692028999328600000000f, + 0.7036272287368774400000000f, 0.6966174244880676300000000f, 0.6895405054092407200000000f, 0.6823971271514892600000000f, 0.6751879453659057600000000f, 0.6679136753082275400000000f, 0.6605750918388366700000000f, 0.6531727910041809100000000f, 0.6457075476646423300000000f, 0.6381800770759582500000000f, + 0.6305910944938659700000000f, 0.6229413151741027800000000f, 0.6152315139770507800000000f, 0.6074624657630920400000000f, 0.5996347665786743200000000f, 0.5917493700981140100000000f, 0.5838068723678588900000000f, 0.5758081078529357900000000f, 0.5677539110183715800000000f, 0.5596449375152587900000000f, + 0.5514820218086242700000000f, 0.5432659983634948700000000f, 0.5349975824356079100000000f, 0.5266776084899902300000000f, 0.5183068513870239300000000f, 0.5098861455917358400000000f, 0.5014163255691528300000000f, 0.4928981363773345900000000f, 0.4843324422836303700000000f, 0.4757201075553894000000000f, + 0.4670618772506713900000000f, 0.4583586752414703400000000f, 0.4496112763881683300000000f, 0.4408205151557922400000000f, 0.4319873154163360600000000f, 0.4231124520301818800000000f, 0.4141968190670013400000000f, 0.4052412509918212900000000f, 0.3962466120719909700000000f, 0.3872138261795043900000000f, + 0.3781436979770660400000000f, 0.3690371215343475300000000f, 0.3598949611186981200000000f, 0.3507181406021118200000000f, 0.3415074944496154800000000f, 0.3322639465332031300000000f, 0.3229883611202240000000000f, 0.3136816620826721200000000f, 0.3043447136878967300000000f, 0.2949784696102142300000000f, + 0.2855837643146514900000000f, 0.2761615216732025100000000f, 0.2667126953601837200000000f, 0.2572381198406219500000000f, 0.2477387785911560100000000f, 0.2382155656814575200000000f, 0.2286693751811981200000000f, 0.2191011607646942100000000f, 0.2095118165016174300000000f, 0.1999022960662841800000000f, + 0.1902734935283660900000000f, 0.1806263476610183700000000f, 0.1709618121385574300000000f, 0.1612807810306549100000000f, 0.1515842080116272000000000f, 0.1418730318546295200000000f, 0.1321481764316558800000000f, 0.1224105954170227100000000f, 0.1126612052321434000000000f, 0.1029009595513343800000000f, + 0.0931307896971702580000000f, 0.0833516493439674380000000f, 0.0735644772648811340000000f, 0.0637702122330665590000000f, 0.0539698041975498200000000f, 0.0441641919314861300000000f, 0.0343543216586112980000000f, 0.0245411414653062820000000f, 0.0147255966439843180000000f, 0.0049086315557360649000000f +}; + + +/*-------------------------------------------------------------------* + * AMR-WB ISF codebook - common 1st stage for 46bit and 36bit codebooks, + * 2 splits + * + * codebook vector dimension number of vectors + * ~~~~~~~~ ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~ + * 1_1 9 256 + * 1_2 7 256 + *-------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------* + * 1nd stage, 1st split: ISF0 to ISF8 + *-------------------------------------------------------------------*/ + +const float dico1_isf[] = +{ + 226.1477f, 422.2338f, 404.4563f, 152.3442f, 1.2553f, -102.5648f, -77.5073f, -32.1403f, 14.9134f, + 6.9890f, -26.5711f, -4.8001f, 122.2654f, 297.4533f, 158.0168f, 97.1963f, 43.4786f, -29.4927f, + 289.1461f, 493.4574f, 504.5048f, 393.1421f, 389.3840f, 397.8990f, 397.4072f, 381.0959f, 360.5083f, + -35.6482f, 323.0566f, 370.2882f, 252.9499f, 239.6172f, 209.0563f, 203.9713f, 191.4865f, 164.6219f, + 16.1026f, -17.1264f, -109.6817f, -184.2085f, 254.5133f, 208.7087f, 75.3774f, 52.8718f, -35.2364f, + 15.8336f, -47.0775f, -139.1713f, -23.5561f, 259.0049f, 120.0214f, 23.8825f, -18.5948f, -134.3813f, + 217.4017f, 369.5988f, 409.6801f, 338.5433f, 330.4056f, 386.7012f, 434.5276f, 492.7760f, 484.6164f, + -46.1429f, -79.6218f, 128.1106f, 199.9543f, 339.7710f, 309.8338f, 238.4430f, 156.8895f, 72.7742f, + 61.1308f, 114.6106f, 28.7939f, -131.9070f, -185.5015f, -350.3943f, -232.0556f, -62.9803f, -194.0513f, + 88.2757f, 51.2294f, -53.9555f, 120.0698f, 65.9863f, -105.8813f, -64.0929f, -151.0651f, -243.7652f, + 24.1201f, -12.6302f, -23.7808f, -98.2577f, -211.1396f, -323.5447f, -401.0499f, -204.4768f, -258.4671f, + 39.7202f, -23.9607f, 55.2442f, 43.6804f, -105.4100f, -97.8749f, -211.3002f, 9.7097f, -58.7138f, + 2.1766f, -51.7480f, -138.9340f, -268.1601f, -37.5098f, -125.8675f, -203.7929f, -12.2603f, -127.2472f, + -14.0622f, -81.7822f, -203.4806f, -89.5766f, 119.8931f, -51.7010f, -2.1055f, -38.5536f, -149.8808f, + 23.6196f, -19.7370f, -92.7527f, -260.9933f, -380.1402f, -158.8319f, -276.5396f, -29.3644f, -67.0346f, + 10.0869f, -54.0238f, -104.0772f, 43.4993f, -118.0066f, 16.7674f, -108.4172f, -138.9907f, -140.3299f, + 222.5364f, 321.1411f, 193.8368f, -60.0340f, -121.7460f, -35.9078f, 53.6514f, 109.0639f, 145.0366f, + -57.1173f, 143.6362f, 159.6491f, 26.6189f, 2.3305f, 30.0608f, 65.3329f, 78.8683f, 63.4622f, + 247.1436f, 350.7171f, 389.0685f, 295.2953f, 258.6614f, 266.7955f, 305.9202f, 355.1905f, 389.1698f, + -40.0882f, 114.6876f, 237.0104f, 161.9769f, 188.5636f, 180.3751f, 187.4189f, 168.3521f, 159.5175f, + -46.7654f, -132.1011f, -238.9261f, -204.8685f, 228.1911f, 129.1599f, 36.0960f, 169.1651f, 107.7902f, + -69.5087f, -114.5055f, -60.0494f, -15.9078f, 105.1520f, 39.1060f, -3.6140f, 83.1345f, 62.4498f, + 324.4036f, 287.6214f, 108.7328f, 320.4871f, 489.7306f, 267.9902f, 278.2168f, 405.7287f, 184.7344f, + -85.2571f, -118.8197f, 180.9905f, 177.4239f, 154.8864f, 106.5995f, 78.7528f, 111.5907f, 106.4840f, + -90.5891f, 2.5823f, 2.5231f, -151.4854f, -184.4761f, -166.9757f, -147.6148f, -65.2055f, -39.1239f, + -114.9974f, -71.3698f, 52.3087f, -18.1814f, 39.4264f, -34.2483f, -32.8691f, -45.8165f, -1.2029f, + 22.1063f, 6.7469f, -79.0146f, -247.7831f, -386.2835f, -437.2287f, -208.2931f, 68.6375f, -14.1447f, + 46.7840f, -11.0692f, 9.1612f, 43.4278f, -124.5574f, 124.1172f, -8.5368f, -30.1898f, 103.7909f, + -105.9007f, -181.3862f, -169.7189f, -257.0920f, -250.0032f, -150.2815f, -150.4918f, -38.5650f, -26.7658f, + -77.3138f, -101.1008f, -103.9903f, -17.1337f, -15.2577f, -54.2134f, -53.5373f, 66.9219f, 25.6872f, + 3.6265f, -56.7222f, -147.2143f, -330.5455f, -390.5518f, -43.3139f, -126.9112f, 133.5488f, 52.7399f, + -31.5816f, -111.6706f, -148.4743f, 75.1588f, -22.0969f, 119.9764f, 29.6891f, -9.5309f, -54.7378f, + 264.5383f, 274.1302f, 96.5690f, 21.7008f, 97.2691f, 55.1255f, -40.9705f, -92.2272f, -38.6482f, + 13.8969f, -15.1538f, -27.1357f, 135.8413f, 77.4989f, -36.1739f, 125.8114f, 35.5744f, -28.2436f, + 196.2991f, 345.8166f, 588.9347f, 510.5197f, 500.8432f, 457.6244f, 436.9384f, 472.1788f, 414.4815f, + 162.4519f, 280.7038f, 386.4482f, 479.3623f, 390.8287f, 411.1292f, 372.5701f, 289.3485f, 407.8594f, + -49.5343f, -147.0080f, -256.8338f, 54.1618f, 243.5530f, 87.1110f, 195.7264f, 119.5070f, 85.9479f, + -43.9641f, -150.1866f, -310.9041f, 196.7455f, 171.2780f, 33.0834f, 83.3645f, -32.4579f, -75.7126f, + 228.4330f, 442.3277f, 481.6548f, 426.3000f, 487.1132f, 559.8019f, 590.4699f, 565.5949f, 513.3911f, + -68.0544f, -164.7799f, 2.8141f, 451.2739f, 425.3554f, 461.7245f, 391.6532f, 369.1004f, 314.9413f, + 3.2743f, -49.3561f, -123.9568f, -40.1754f, -137.2377f, -271.6588f, -38.4305f, -104.5226f, -209.8071f, + 12.8092f, -40.2922f, -113.2953f, 65.4057f, -15.2443f, -159.0118f, 17.0998f, -81.3044f, -146.3446f, + 40.4305f, -8.9102f, -24.9719f, -113.7701f, -248.7160f, -332.5068f, -423.4328f, -23.8073f, -43.9266f, + -29.4866f, -119.6504f, -169.5775f, 85.2585f, -57.7724f, -138.3062f, -265.4940f, -52.0935f, -84.4635f, + -47.3285f, -147.4516f, -280.5169f, -38.0164f, -50.7237f, -141.1316f, -60.9737f, -147.8608f, -233.9212f, + -22.0146f, -99.1479f, -228.8716f, 91.6618f, 61.1343f, -83.5247f, 4.2834f, -101.7035f, -58.0283f, + -48.6094f, -104.2664f, -155.2664f, -226.4858f, -231.7223f, -205.7180f, -314.6280f, -150.3995f, 135.1819f, + -75.2552f, -171.9896f, -276.5969f, -137.0060f, -55.2086f, -99.5797f, -195.1097f, -57.2647f, -72.3255f, + 174.9245f, 258.0028f, 192.8297f, 81.3562f, 198.8450f, 180.2081f, 132.0824f, 113.5126f, 58.1412f, + -87.2559f, 34.2946f, 130.7081f, 62.1078f, 82.7816f, 74.4854f, 111.6818f, 120.3099f, 80.1334f, + -11.9671f, 183.3834f, 313.7754f, 257.2813f, 241.7612f, 256.9710f, 329.4492f, 385.5374f, 434.7875f, + -66.8195f, -94.6890f, 200.6887f, 141.3063f, 115.2635f, 204.7280f, 215.7973f, 270.9673f, 228.4647f, + -24.9070f, -120.1441f, -175.1481f, -8.0896f, 110.9215f, 307.0280f, 174.2457f, 112.7169f, 35.9639f, + -85.1717f, -152.2496f, -2.5803f, 66.0904f, 80.5138f, 128.8919f, 137.5303f, 159.4245f, 139.7766f, + -14.1396f, 274.4125f, 374.6268f, 335.3957f, 336.4666f, 435.5791f, 495.5083f, 529.9642f, 509.9389f, + -51.7794f, -133.3125f, -25.4473f, 264.8054f, 162.9175f, 171.9332f, 189.6735f, 202.1561f, 304.5228f, + 12.7820f, -17.2653f, -74.5083f, -134.5510f, -180.1133f, -294.9349f, -78.6120f, 84.8225f, -12.0772f, + -137.7282f, -213.7303f, -17.3509f, 48.2225f, -23.9524f, -26.4293f, -30.7054f, 11.1575f, 23.4229f, + 28.3886f, -22.3550f, -158.4269f, -299.3692f, -485.7126f, -469.8884f, 93.8213f, 156.3351f, 64.4156f, + -28.7029f, -110.1881f, -234.8032f, -83.3735f, -66.7772f, -146.3531f, 129.8178f, 13.7979f, -40.1959f, + -11.2220f, -81.0542f, -215.8795f, -186.0052f, -249.1487f, -354.7951f, 67.0249f, -8.7287f, -52.7080f, + -75.1895f, -93.5102f, -63.8842f, -40.2971f, -43.3423f, -18.3122f, 59.9384f, 48.9469f, 42.9198f, + -0.3036f, -79.3921f, -222.4614f, -402.4193f, -556.4007f, -208.9512f, 60.4822f, 0.2592f, 57.2596f, + -130.2469f, -254.9911f, -337.7263f, -76.9102f, -61.5888f, -8.3782f, -17.2822f, 37.1637f, 42.0772f, + 151.9460f, 229.6417f, 191.5279f, 12.9809f, -92.7110f, -204.7091f, -245.2630f, -53.2589f, -101.3680f, + 15.8084f, -69.0148f, -180.2926f, 176.9411f, 336.6405f, 148.3504f, 51.2260f, -50.6708f, -158.2893f, + 328.7315f, 655.2856f, 719.0299f, 605.1412f, 575.6907f, 490.5742f, 422.8277f, 353.4364f, 289.8675f, + 144.5240f, 474.8398f, 690.7612f, 638.0545f, 473.3627f, 248.6244f, 8.4810f, -128.9032f, 27.8837f, + -29.8052f, -109.6768f, -289.4402f, -289.9344f, 350.9098f, 241.8981f, 108.0220f, 27.7568f, -86.8368f, + -12.5998f, -103.5273f, -217.2510f, -9.8401f, 388.4400f, 266.5437f, 118.9818f, 49.1643f, -64.3603f, + 28.5445f, 288.4229f, 348.8730f, 378.0052f, 387.8595f, 690.6161f, 887.8799f, 718.7092f, 543.2699f, + -27.0127f, -136.3472f, -228.6534f, 91.4073f, 452.4637f, 352.8853f, 244.5759f, 199.3164f, 97.9452f, + -0.2574f, -38.8124f, -106.0784f, -81.9691f, -235.3859f, -136.9961f, -210.8024f, -316.9619f, -149.7671f, + -6.3268f, -89.9384f, -197.0412f, 160.1820f, 58.3899f, -80.1867f, -134.0614f, -254.4108f, -249.4793f, + 40.1439f, -3.4822f, -88.7857f, -80.2522f, -219.3521f, -305.1500f, -421.5967f, -471.9935f, -60.7522f, + 55.8529f, 24.5260f, -52.9174f, -26.1113f, -123.8744f, -235.0002f, -306.0707f, -450.7246f, -249.8812f, + -56.2297f, -152.7118f, -263.1169f, -243.0294f, -78.2260f, -99.3225f, -257.7953f, -369.9445f, -154.2971f, + -15.4570f, -97.8124f, -244.1879f, 10.4628f, 212.1971f, 36.6411f, -51.0200f, -150.9477f, -262.8206f, + -47.9169f, -145.0780f, -295.8412f, -176.3119f, -220.4176f, -239.8767f, -162.2583f, -277.5646f, -13.5098f, + -45.4312f, -120.7871f, -231.7391f, -104.6837f, 93.3399f, -13.0435f, -131.8873f, -253.9684f, -52.8010f, + 36.7261f, 97.8902f, 216.2452f, 22.2667f, -121.9688f, -165.2371f, -60.1795f, -22.1111f, 91.7368f, + -104.8126f, -27.6777f, 148.6412f, 44.3956f, -17.0786f, -34.0943f, 48.6552f, 67.5896f, 52.1341f, + 590.8627f, 669.3461f, 483.5975f, 208.4471f, 107.7190f, 123.1392f, 179.9797f, 179.2124f, 198.5541f, + -51.3512f, -7.3050f, 448.6575f, 261.8456f, 189.7417f, 139.0593f, 120.8041f, 144.0752f, 115.5179f, + -87.2434f, -195.6786f, -351.1762f, -282.1990f, -27.3961f, 2.1866f, 51.0065f, 120.9792f, 154.0704f, + -38.7878f, -118.5436f, -201.9035f, 97.1421f, 24.9785f, -20.8748f, 52.5830f, -4.3230f, 177.0334f, + -57.4864f, -155.8205f, -285.0674f, -156.5139f, 319.0307f, 288.4199f, 313.3522f, 292.7644f, 224.7193f, + -60.1766f, -170.1086f, -288.5482f, 312.6666f, 231.6275f, 142.7810f, 206.6260f, 124.0985f, 127.5073f, + -87.3474f, 17.7221f, -15.2086f, -151.2513f, -201.3116f, -202.2629f, -237.4979f, -150.1082f, -125.3288f, + -123.1549f, -147.2588f, 55.9560f, -39.6018f, -44.1818f, -147.1130f, -69.1241f, -56.1722f, -4.4924f, + 45.5201f, 15.5222f, -93.3382f, -254.1893f, -410.5618f, -226.8515f, -287.7839f, -386.6172f, -128.1340f, + 10.1233f, -19.6005f, -61.5127f, -8.8349f, -177.1218f, -110.5849f, -207.5041f, -213.2586f, 74.8075f, + -98.2741f, -195.7624f, -290.1091f, -230.1600f, -244.7515f, -194.7701f, -128.1076f, -46.1729f, -28.2903f, + -126.3800f, -193.1177f, -95.3231f, -119.6219f, -56.1586f, -69.0881f, -102.1922f, -52.5595f, -30.4027f, + -13.9604f, -91.5188f, -202.7529f, -375.3352f, -503.8488f, -122.5019f, -187.2047f, -144.9473f, -17.6464f, + -37.1158f, -113.9219f, -208.9531f, -3.1283f, -117.0010f, 43.6858f, -64.0984f, -108.2942f, 77.5131f, + -38.6401f, -49.9736f, 343.9084f, 326.3879f, 226.1680f, 136.9212f, 9.0736f, -37.1756f, -84.7974f, + -10.5004f, -100.6890f, 48.4106f, 394.7867f, 233.0419f, 165.9509f, 56.3291f, 2.7924f, -28.5845f, + 164.3221f, 505.0226f, 640.4844f, 633.9930f, 680.5828f, 631.7908f, 585.4574f, 501.5025f, 393.1295f, + -37.0300f, 293.6539f, 656.3401f, 612.9729f, 632.0821f, 560.9024f, 468.8401f, 382.9867f, 278.2211f, + -26.9959f, -117.0381f, -266.9459f, -169.9414f, 442.3678f, 351.1593f, 196.7216f, 129.6217f, 42.5401f, + -28.9160f, -126.1295f, -248.8180f, 219.9974f, 419.6462f, 237.5276f, 144.8018f, 41.0794f, -19.0438f, + -30.6524f, 324.5342f, 466.4269f, 433.6403f, 538.3355f, 578.5025f, 582.9940f, 533.2873f, 475.3817f, + -101.0867f, -47.3945f, 562.3863f, 521.2437f, 635.9947f, 581.9960f, 561.7294f, 477.7560f, 364.4759f, + -32.1078f, -119.5424f, -239.6324f, -86.9073f, -147.6602f, -263.4799f, -212.9377f, -261.9229f, -330.2635f, + 20.8260f, -48.5704f, -135.4246f, 164.8506f, 20.4817f, -48.8885f, -105.4348f, -206.6621f, 3.6375f, + 30.9311f, -34.7599f, -124.8998f, -258.7565f, -390.0532f, -468.4556f, -485.3543f, -264.1984f, -115.9895f, + -26.5921f, -106.6166f, -238.7686f, 53.4977f, -56.8913f, -155.1848f, -245.0791f, -329.9394f, -85.9503f, + -43.8040f, -135.2615f, -311.2635f, -322.8195f, 91.5184f, -51.5741f, -73.3097f, -108.7735f, -204.0501f, + -61.9589f, -158.0212f, -286.8211f, -163.7011f, 114.5577f, 29.0545f, -65.0919f, -65.1646f, 71.9506f, + -59.8760f, -170.6047f, -325.2270f, -421.8182f, -131.3054f, -184.2594f, -219.1312f, -132.9352f, -98.8301f, + -65.8626f, -165.1987f, -320.2537f, -353.1492f, -51.0331f, -7.3456f, -135.3074f, -235.8573f, 12.1485f, + 12.8460f, -11.9241f, 121.7405f, 24.2470f, -57.8971f, 19.1365f, -23.0243f, 220.3897f, 189.9156f, + -119.6102f, -129.9914f, 75.9549f, -17.3359f, 26.2798f, 28.0181f, 57.3185f, 79.8925f, 95.0199f, + -81.0524f, -19.0879f, 531.3251f, 384.0082f, 378.6000f, 387.1200f, 396.1896f, 433.4382f, 379.9696f, + -82.3204f, -67.1148f, 345.0646f, 244.9884f, 277.8043f, 263.1406f, 275.4622f, 311.7924f, 291.4141f, + -34.2889f, -127.1388f, -298.1820f, -380.4511f, 268.4245f, 354.6007f, 200.7670f, 149.3555f, 67.1469f, + -114.0830f, -239.0252f, -314.3921f, 24.6004f, 51.2722f, 105.4223f, 101.1157f, 137.3569f, 135.9245f, + -91.7432f, -32.7591f, 373.1560f, 319.3955f, 437.4347f, 503.4907f, 608.7997f, 578.2119f, 502.0230f, + -70.3367f, -179.9099f, -239.7652f, 256.5794f, 269.9891f, 291.1810f, 333.6932f, 305.8695f, 278.4421f, + -38.0671f, -120.8247f, -186.4547f, -239.7784f, -303.6527f, -286.7954f, -300.0361f, -205.3057f, -184.5087f, + -134.2125f, -185.9339f, -13.8119f, -65.8529f, 19.0133f, -30.1823f, -58.4970f, -93.5678f, -55.1841f, + -20.3990f, -104.7817f, -249.4716f, -358.9899f, -499.3363f, -434.6861f, -133.7299f, -130.1813f, -59.0671f, + -26.7201f, -94.4739f, -228.6340f, -28.5857f, -81.7289f, -186.7961f, -62.0135f, -167.5409f, 51.9732f, + -76.8652f, -194.8085f, -392.5224f, -495.1741f, -106.3757f, -87.6781f, -40.9442f, -25.9922f, 6.6919f, + -141.6526f, -241.2805f, -161.8672f, -45.4915f, -24.1067f, 7.6906f, 3.7741f, 45.2149f, 42.3436f, + -76.2028f, -185.3649f, -353.8127f, -492.3104f, -348.1328f, -172.4144f, -108.0814f, -55.5374f, -10.8210f, + -88.1331f, -202.9139f, -371.2243f, -273.3005f, -107.5773f, -103.9134f, -45.1607f, -40.9613f, 31.8985f, + 157.9412f, 199.7964f, 203.2689f, 127.6304f, 6.7547f, -75.7475f, -130.0489f, -209.2208f, -228.8015f, + -44.6527f, -50.6749f, 107.6295f, 92.4422f, 79.8121f, 133.5672f, 52.5620f, -6.2270f, -43.2877f, + 261.9115f, 472.0228f, 456.3473f, 335.7553f, 289.8814f, 234.7976f, 206.1187f, 157.4174f, 120.7698f, + 155.2229f, 242.6315f, 377.1642f, 293.6065f, 226.0318f, 155.2748f, 156.4116f, 128.6701f, 98.5061f, + 74.5256f, 70.1303f, -53.6869f, -182.3488f, 106.1648f, 41.5585f, -37.0232f, 6.5336f, -75.1722f, + -31.2252f, -113.3890f, -244.5892f, 75.8334f, 233.5228f, 76.5742f, 8.2886f, -109.6154f, 29.9907f, + 199.0678f, 337.3158f, 432.8418f, 315.2969f, 366.8018f, 352.4917f, 361.4405f, 280.1715f, 187.7336f, + 53.4911f, 143.3279f, 208.4704f, 298.2910f, 261.7387f, 149.2119f, 115.7060f, 59.9002f, 32.6898f, + 118.3519f, 194.3090f, 56.3174f, -33.3258f, -48.8783f, -210.5418f, -188.4141f, -181.0565f, -298.4099f, + 91.1937f, 135.5274f, 26.3852f, -57.5649f, 66.0117f, -82.2194f, -94.6889f, -88.3680f, -188.1230f, + 119.8292f, 164.8051f, 60.2985f, -68.4990f, -150.8028f, -282.2156f, -282.8785f, -353.0452f, -396.4856f, + 120.5806f, 120.4464f, 62.5068f, -23.5466f, -183.4260f, -164.0083f, -233.7240f, -309.0768f, -85.4341f, + 26.4925f, 47.3529f, -53.5415f, -218.9011f, -56.8672f, -174.1118f, -201.0902f, -193.1382f, -284.6390f, + 50.9597f, 20.8274f, -88.6445f, 17.8450f, 185.2710f, 12.4814f, -62.7698f, -74.9989f, -191.3486f, + 83.3881f, 63.9878f, -27.8680f, -181.7226f, -342.0545f, -62.8876f, -178.1327f, -229.1320f, -18.6240f, + 85.1419f, 45.8095f, 15.3667f, 69.0366f, -75.9137f, -34.4539f, -88.4330f, -163.4411f, 19.3370f, + 81.8880f, 213.5459f, 222.3313f, 109.1533f, 47.1884f, -17.2578f, -19.4486f, 3.7457f, -32.8905f, + 22.8266f, 54.6145f, 70.9314f, -2.0301f, 104.3592f, 45.7102f, 41.3375f, 82.5320f, 77.2795f, + 210.7176f, 326.3462f, 356.6618f, 280.9097f, 240.9705f, 212.4392f, 230.9905f, 220.8317f, 250.9306f, + 59.6089f, 218.2601f, 340.5622f, 179.8372f, 86.7106f, 42.1021f, 73.5578f, 70.2340f, 71.3620f, + 61.9071f, 46.6476f, 111.0709f, -59.8230f, -105.9862f, 89.4424f, 34.0065f, 42.7793f, -22.3657f, + -71.5290f, 31.9224f, 46.2106f, 8.2769f, 5.2717f, 15.6736f, 45.9446f, 74.5921f, 72.2933f, + 63.1228f, 347.0971f, 255.3817f, 42.2624f, -13.4026f, 95.4917f, 190.7911f, 219.1920f, 207.8866f, + 63.7817f, 21.7322f, 237.9311f, 133.1283f, 19.5484f, 128.6760f, 26.4302f, 103.7761f, 85.3130f, + 39.2312f, 80.2880f, 7.1932f, -118.9054f, -41.8213f, -170.3956f, -190.1681f, -25.3174f, -119.5246f, + -33.4058f, 60.1838f, 52.1765f, -11.5418f, -17.6690f, -28.5228f, -40.5342f, -31.3702f, -37.5340f, + 95.6257f, 128.8044f, 3.7503f, -171.8902f, -331.7014f, -422.7089f, 30.8156f, 15.6229f, -103.6316f, + 76.5623f, 145.2620f, 106.4321f, -70.8798f, -192.7731f, -152.0614f, 107.2952f, 31.2426f, -23.0299f, + 0.9016f, -4.6471f, -96.0447f, -197.1141f, -39.1036f, -170.4243f, 8.3031f, -73.0702f, -168.4342f, + -86.2673f, -18.7660f, 13.9540f, -105.8362f, -72.7468f, -57.3178f, -42.7630f, 10.3291f, 27.6536f, + 83.1109f, 54.8163f, 28.1776f, -137.0164f, -242.1605f, -32.9744f, -141.6118f, 26.8712f, 17.8517f, + 35.5325f, 65.1065f, -1.1122f, -37.2264f, -38.7638f, -41.0658f, -18.6295f, 44.3877f, 57.2718f, + 101.1713f, 97.2361f, 67.3819f, 236.9884f, 158.4350f, 20.2720f, 23.0851f, -73.7010f, -124.8067f, + 44.9800f, -33.1049f, -21.2276f, 224.2546f, 49.9567f, 88.2466f, -23.1899f, -98.6740f, 50.9732f, + -24.3959f, 403.6523f, 511.0127f, 404.3978f, 440.2577f, 428.9172f, 401.8223f, 375.5111f, 321.4924f, + 15.1345f, 142.1195f, 295.8327f, 367.1741f, 284.5674f, 257.7681f, 257.3533f, 227.7437f, 300.6506f, + -44.9562f, -131.9449f, -296.8129f, -184.1626f, 153.8183f, 14.5297f, 172.3343f, 69.5618f, 2.2208f, + -22.2475f, -119.2772f, -205.2499f, 310.9423f, 177.0844f, 73.5587f, -1.5010f, -44.3403f, 96.9000f, + 27.7742f, 173.5793f, 311.4776f, 285.5815f, 427.9854f, 452.0145f, 477.2097f, 401.7775f, 316.6574f, + 52.6696f, 140.2801f, 215.3995f, 166.1714f, 292.6204f, 318.2898f, 341.5682f, 274.8850f, 196.1860f, + 51.5561f, 96.4057f, -0.0610f, -80.6567f, -175.2689f, -292.8310f, -100.7723f, -200.9591f, -247.1591f, + 96.6859f, 97.0977f, 35.4401f, 47.1563f, -76.2811f, -194.8284f, -34.9894f, -110.1535f, -169.8929f, + 30.4654f, 7.6447f, -108.2569f, -243.2014f, -383.8708f, -478.0505f, -162.0353f, -178.7682f, -249.4727f, + 135.4580f, 198.9998f, 81.4247f, -69.9475f, -181.4226f, -284.4768f, -29.8270f, -92.7044f, -189.7940f, + -40.1188f, -133.9427f, -295.2091f, -278.5829f, -103.4496f, -237.8449f, -74.7856f, -155.3338f, -248.5054f, + -47.4470f, -149.6037f, -292.4242f, 221.6694f, 98.4280f, -14.0849f, -138.2963f, -163.0445f, -19.4243f, + 79.5896f, 39.1792f, -58.2936f, -253.9809f, -422.3516f, -18.3412f, -2.7302f, -102.9275f, 43.5500f, + -17.9005f, -70.1182f, -104.1536f, -126.4881f, -219.3935f, -153.8877f, -270.2488f, 155.3837f, 114.2388f, + 188.3484f, 261.8459f, 266.6991f, 243.5570f, 172.7795f, 64.3333f, 45.3547f, 14.1479f, -58.3812f, + 42.3610f, 96.6123f, 113.8369f, 96.5219f, 138.7232f, 47.5273f, 42.4855f, 87.4416f, 115.5724f, + -5.4013f, 368.9961f, 386.7844f, 312.8328f, 294.8554f, 318.4847f, 330.7657f, 356.5357f, 348.3268f, + 113.9440f, 136.1339f, 283.1776f, 188.4109f, 151.5282f, 128.5029f, 167.5631f, 242.2409f, 260.3565f, + -13.3113f, 76.9204f, 83.0527f, -49.6054f, 32.9182f, 193.1624f, 242.1413f, 224.6298f, 146.4784f, + 49.3300f, 80.8438f, 67.2940f, 65.3665f, 141.4567f, 78.9471f, 115.6802f, 154.3108f, 177.7814f, + -2.1684f, 97.5184f, 210.7061f, 182.4635f, 248.3353f, 312.9833f, 448.6478f, 502.5403f, 436.6044f, + 10.4934f, 93.6577f, 144.0456f, 109.2677f, 171.7553f, 160.5641f, 247.6292f, 348.4738f, 372.3836f, + 62.0393f, 66.4595f, -22.8432f, -154.2429f, -311.1715f, -269.7167f, 30.1724f, -82.4276f, -130.4250f, + -1.8658f, -10.8456f, -5.2486f, -28.7596f, -130.9176f, -235.6978f, 116.9998f, 34.2436f, -79.9885f, + 32.1393f, -12.8439f, -142.0784f, -272.6861f, -469.8031f, -450.3773f, 42.8701f, -56.9028f, -113.0164f, + 44.2438f, 0.5177f, -95.0709f, -229.7896f, -388.2228f, -193.8794f, 161.5550f, 62.3152f, 16.3412f, + -21.7573f, -96.5696f, -171.8374f, -270.5201f, -389.2275f, -187.1907f, 4.2880f, -69.4009f, -139.6222f, + -59.1336f, -137.9044f, -127.8821f, -82.4177f, -132.8951f, 55.2591f, 25.2046f, 165.8443f, 176.7896f, + 13.1713f, -65.9463f, -177.8707f, -363.8923f, -474.4700f, 53.7845f, 194.7626f, 99.8684f, 126.7437f, + 26.4565f, 54.2781f, -5.8084f, -213.5320f, -186.7453f, 6.5259f, 119.4530f, 196.2039f, 188.0246f, + -12.3442f, -52.3945f, 174.0135f, 50.5399f, -55.6784f, -95.2558f, -196.2955f, -198.2056f, -234.0973f, + 23.6446f, -54.5462f, -134.7219f, 193.6175f, 178.7128f, -0.9450f, 7.7510f, -88.8611f, -200.7396f, + 154.0881f, 689.2718f, 650.6971f, 522.8596f, 436.5025f, 314.9000f, 250.7824f, 187.1628f, 148.5410f, + 83.9959f, 202.8234f, 359.2843f, 411.3538f, 425.6817f, 308.8017f, 206.3666f, 113.2320f, 60.3929f, + -21.1689f, -91.1694f, -252.6742f, -235.0333f, 249.5398f, 114.6655f, -0.7796f, -65.2547f, -172.8182f, + -30.5567f, -123.2070f, -309.0227f, -44.0884f, 320.4634f, 157.6161f, 61.6828f, -45.3025f, -139.1032f, + 206.4974f, 723.0883f, 782.3015f, 479.5419f, 242.9557f, -15.8222f, -162.4184f, 134.4517f, 319.9661f, + -41.0232f, -148.1419f, -92.0839f, 478.0700f, 348.8458f, 292.6417f, 221.8808f, 139.1332f, 83.7320f, + -6.8324f, -77.6477f, -56.3444f, 19.3478f, -110.6184f, -96.5414f, -225.9007f, -330.6617f, -424.5623f, + 26.9337f, -4.4548f, -148.8763f, -80.3516f, 81.8311f, -110.8947f, -150.9911f, -162.4880f, -279.5481f, + 15.4135f, -1.8583f, -56.8319f, -146.1688f, -266.5346f, -355.1809f, -419.6793f, -456.7536f, -416.2208f, + 112.1756f, 88.2059f, 26.0259f, -86.2333f, -258.4741f, -66.9660f, -164.5662f, -250.9281f, -276.0475f, + -51.5026f, -135.9180f, -210.3467f, -175.0943f, -7.7200f, -1.5529f, -138.1960f, -292.0197f, -364.5311f, + 1.6098f, -29.3697f, -112.8375f, -233.4716f, 123.6812f, 20.4676f, -81.0632f, -116.0258f, -218.5294f, + -34.1878f, -103.0825f, -139.6876f, -229.9859f, -246.3806f, -96.8411f, -204.4168f, -321.0166f, -418.4522f, + 27.1891f, -2.9717f, 21.2254f, -122.5167f, -201.1399f, 36.0115f, -56.9192f, -106.8464f, -192.5580f, + 77.7097f, 24.2840f, 152.6398f, 61.5673f, -54.9359f, 27.7810f, -85.7347f, -79.4392f, -81.0366f, + 59.2315f, 15.7636f, 128.6461f, 63.2966f, -11.4618f, 18.7670f, -58.2229f, 42.0642f, 49.7434f, + 247.9855f, 413.3163f, 345.0402f, 192.3750f, 145.4847f, 121.6956f, 123.6805f, 107.2007f, 94.2462f, + 104.2558f, 282.0381f, 490.4723f, 344.7097f, 244.1310f, 96.7224f, 2.9896f, -31.7180f, -23.3323f, + -22.5118f, -53.8832f, -113.5013f, -234.2837f, -4.7630f, -0.8369f, -15.3972f, 57.4113f, 45.6486f, + -41.6155f, -134.7804f, -200.2841f, 179.2444f, 29.8214f, 36.0840f, -106.4028f, 151.5328f, 102.1621f, + 141.5078f, 201.5805f, 79.4698f, -159.8402f, -279.6548f, -324.4731f, -129.3751f, 72.2403f, 81.4769f, + -45.8403f, -152.7728f, -116.5580f, 262.2678f, 114.2470f, 210.0651f, 100.2266f, 64.9777f, -14.6634f, + -39.9272f, -124.8000f, -75.7294f, -110.6360f, -223.7299f, -102.2257f, -226.1053f, -85.4944f, -173.4764f, + -91.6640f, 30.6543f, 4.1065f, -65.4408f, -39.3890f, -89.5364f, -102.5911f, -125.5036f, -48.1974f, + 27.2660f, 19.3735f, -66.4810f, -233.9350f, -388.9383f, -229.7098f, -102.6715f, -201.6806f, -177.6036f, + 153.9685f, 141.8902f, 89.4281f, -53.1892f, -209.9941f, 8.0810f, -71.3509f, -135.8233f, -78.6157f, + -48.4004f, -143.6756f, -250.1705f, -343.5184f, -330.9693f, -81.7413f, -159.8642f, -192.9882f, -201.0525f, + -49.7401f, -133.3727f, -211.5154f, -166.0789f, -199.3352f, -4.0380f, -98.3591f, -184.6634f, -113.6087f, + 32.7128f, -26.7812f, -78.3951f, -264.0457f, -339.2219f, 40.1904f, -121.6728f, -51.6241f, -125.0696f, + 1.8568f, -67.7562f, -73.4413f, -115.9242f, -245.2522f, 77.1352f, -22.1839f, 2.7514f, -4.3203f, + 19.0296f, -62.4543f, 21.8088f, 217.8850f, 43.1886f, 12.7766f, -121.5772f, -171.9543f, -180.7850f, + -0.3986f, -96.1580f, -120.0616f, 336.5914f, 176.9306f, 54.3062f, -66.4501f, -138.8101f, -90.7495f, + 109.0295f, 377.1798f, 641.5853f, 577.4881f, 571.3625f, 438.8002f, 310.6432f, 204.9863f, 132.6160f, + -76.9013f, -15.0371f, 664.7503f, 520.0686f, 489.1051f, 371.2256f, 270.3431f, 196.9454f, 166.5973f, + -42.2498f, -134.3667f, -336.4376f, -457.6409f, 173.4562f, 138.1508f, 34.3921f, -18.1609f, -85.9677f, + -20.8727f, -125.4622f, -192.7956f, 434.5861f, 290.6413f, 142.0824f, 77.1623f, -13.2305f, -29.4274f, + 178.7104f, 373.0402f, 459.7581f, 474.3989f, 557.5211f, 569.2194f, 525.4768f, 358.3187f, 210.4229f, + -26.8194f, 77.7574f, 350.3222f, 445.4183f, 524.4524f, 462.1511f, 381.7293f, 289.9692f, 204.0649f, + 47.7632f, 17.1803f, -105.1057f, 10.4223f, -60.5128f, -219.3625f, -119.8198f, -230.6158f, -301.9153f, + 60.2078f, 16.2198f, -62.5382f, 98.4891f, -50.3729f, -119.2299f, -183.9794f, -286.1903f, -145.0719f, + 52.5866f, 72.1675f, -32.1273f, -162.5446f, -282.0867f, -356.6873f, -196.9938f, -290.2792f, -343.8752f, + 58.1756f, 83.5942f, -32.7989f, -128.5429f, -265.7008f, -326.2490f, -166.5130f, -258.2744f, -31.7978f, + -49.8436f, -148.3240f, -287.2763f, -389.7832f, -131.7967f, 6.5863f, -71.1640f, -182.3324f, -272.4139f, + -32.6407f, -113.2022f, -199.3120f, -231.3794f, 5.2103f, 172.0263f, 60.2526f, -14.7182f, -108.9096f, + 27.2077f, -23.7367f, -95.9858f, -283.8613f, -409.0134f, -31.3871f, -148.6489f, -208.9727f, -274.8275f, + 69.4333f, -0.7143f, -57.0494f, -261.8966f, -366.3107f, 188.4734f, 53.9671f, 24.5447f, 25.3948f, + -4.4283f, 5.6792f, 301.6043f, 172.8969f, 55.6507f, -7.7604f, -81.7609f, -49.2316f, -63.0654f, + -12.4033f, -97.3530f, 37.2340f, 215.5548f, 48.4286f, 11.6666f, -133.9813f, 32.1272f, -33.6059f, + 57.9103f, 293.2768f, 591.9909f, 431.5314f, 338.6320f, 236.6151f, 185.2476f, 175.1540f, 156.0322f, + -63.6185f, -100.3640f, 351.1546f, 428.5004f, 353.7403f, 293.3142f, 196.1020f, 152.1965f, 114.6518f, + -20.0721f, -100.8514f, -174.7278f, -314.6773f, -143.5646f, 298.1905f, 181.1825f, 142.0341f, 71.3729f, + -64.7951f, -146.2021f, -143.2170f, 33.9854f, 13.8056f, 156.0337f, 163.4005f, 334.1913f, 325.3497f, + -79.9064f, -121.2133f, 229.6626f, 303.8755f, 306.8218f, 415.8466f, 436.8824f, 486.2830f, 451.8081f, + -67.6130f, -122.0631f, 41.7635f, 134.7727f, 156.2778f, 308.4236f, 340.0357f, 434.5742f, 391.1108f, + -2.6037f, -46.9405f, -151.3320f, -160.0405f, -239.8193f, -368.3138f, -88.0921f, -150.1500f, -191.7920f, + -79.3309f, -112.6262f, -20.0215f, -129.1640f, -35.3227f, -69.4806f, -159.3188f, -223.7142f, -132.1779f, + 21.9835f, -11.3374f, -106.7910f, -244.8813f, -406.4640f, -311.7320f, -96.4711f, -182.5312f, 57.8956f, + 25.8713f, -0.7151f, -79.9440f, -80.0111f, -224.4878f, -136.2209f, -22.1062f, -137.4635f, -22.6838f, + -17.4638f, -88.0421f, -183.7897f, -361.0791f, -194.1127f, 29.9571f, -12.3110f, 17.3506f, -52.9132f, + -108.1431f, -191.9295f, -193.9598f, -196.0948f, -165.6809f, -79.0258f, -53.5949f, 30.1916f, 37.3619f, + 10.0420f, -70.0023f, -183.1197f, -393.7681f, -492.0758f, 102.2096f, -13.6587f, -51.6821f, -101.1752f, + -25.8195f, -90.5090f, -174.4579f, -208.3670f, -308.3139f, -74.5783f, -38.9631f, -104.3672f, 142.1591f +}; + +/*-------------------------------------------------------------------* + * 1nd stage, 2nd split: ISF9 to ISF15 + *-------------------------------------------------------------------*/ + +const float dico2_isf[] = +{ + 530.1115f, 512.7983f, 443.8771f, 306.1447f, 171.2327f, 70.8250f, 56.8183f, + 248.5479f, 252.9719f, 260.5429f, 221.7305f, 172.6754f, 84.8419f, 141.5120f, + 166.9014f, 171.9745f, 263.4265f, 204.8570f, 129.5061f, 45.8705f, -162.9417f, + 47.0761f, 115.3926f, 182.9788f, 181.5048f, 89.7111f, 17.3276f, -86.2999f, + -57.3148f, -93.7950f, 58.2071f, 31.0844f, 152.3217f, 108.6931f, 41.3677f, + -163.1767f, -217.0378f, 215.5667f, 199.7393f, 91.8320f, 56.3535f, -37.1534f, + 16.9371f, 75.2105f, 106.8429f, 58.4518f, 26.0167f, 13.3113f, -106.5544f, + -16.6336f, -49.0904f, 66.7054f, 162.6404f, 110.2851f, 24.4686f, -138.4124f, + -145.3240f, -33.7683f, -134.5548f, -42.3167f, -36.8413f, -70.9451f, -34.7360f, + -234.5519f, -328.1575f, -78.2304f, 181.4482f, 100.8272f, -4.3886f, -98.7986f, + -18.7314f, 128.6640f, 38.0685f, -113.4033f, -211.9919f, -310.5748f, -138.0866f, + -222.6271f, -45.5429f, 72.9616f, 3.9276f, -52.1214f, -162.3586f, -29.6134f, + -241.3416f, -50.3196f, -96.3331f, -145.0456f, 17.4087f, -29.8105f, 108.3555f, + -399.1142f, -421.4348f, 49.0965f, 185.0085f, 99.2830f, 49.7543f, 20.2726f, + -109.7596f, 29.7695f, -65.3607f, -141.1745f, -110.3974f, -215.1475f, -110.3518f, + -46.4209f, -20.4624f, -0.5266f, 52.1919f, -12.3074f, -79.8395f, -162.1720f, + 415.6808f, 323.0418f, 248.6461f, 267.3440f, 181.1869f, 81.5855f, 4.8347f, + 188.1995f, 162.5893f, 175.4467f, 144.9775f, 131.0177f, 114.8023f, 75.6850f, + 280.8494f, 225.0358f, 142.4128f, 52.8503f, 44.0619f, 35.6548f, -77.7252f, + 116.2722f, 68.6422f, 192.5792f, 142.9262f, 75.7274f, 63.5846f, 13.9314f, + -13.4854f, -92.0420f, -101.3018f, -13.9503f, -1.5377f, 38.4848f, 59.2146f, + -38.0921f, -119.6284f, -10.4956f, 88.8682f, 35.1836f, 43.2013f, -33.7051f, + 35.4547f, 5.0305f, -82.4376f, -100.9264f, -41.5222f, 33.5725f, -24.8381f, + 28.3963f, -13.4840f, -22.4480f, -11.9734f, 63.1961f, 13.8177f, -75.0030f, + -42.4115f, -130.9516f, -245.5204f, -25.9129f, -23.6896f, -49.8110f, 125.7094f, + -193.2334f, -261.3991f, -284.3770f, 75.4337f, 11.9830f, -86.1044f, 47.5069f, + 126.4967f, 37.0484f, -34.7501f, -35.5687f, -159.6523f, -277.2735f, -60.1203f, + -0.1156f, -91.4527f, 35.7808f, 12.8593f, -134.0804f, -237.8749f, -85.9030f, + -134.0644f, -159.5199f, -185.8239f, -255.9559f, -59.8235f, 31.9001f, 86.5795f, + -191.3466f, -290.9137f, -99.7657f, 18.9475f, -18.6283f, 52.5484f, -49.6458f, + 46.4725f, -26.2220f, -128.3100f, -152.1911f, -106.3316f, -212.7650f, -21.8051f, + -22.1899f, -50.6587f, -4.0987f, -2.7160f, -63.9780f, -18.1671f, -8.5809f, + 384.5044f, 415.7100f, 375.3419f, 221.7875f, 82.0605f, -10.5889f, 6.1831f, + 316.8826f, 269.9225f, 294.6225f, 200.5877f, 87.3740f, -13.6950f, 64.9923f, + 258.7122f, 274.8100f, 241.2115f, 150.6316f, 22.2879f, -82.2525f, -100.3677f, + 199.2028f, 140.2225f, 163.4630f, 153.3341f, 35.3954f, -56.3718f, -6.8714f, + -75.2059f, -12.0741f, -10.5019f, 87.1330f, 34.8811f, -55.7089f, 9.3485f, + -43.9131f, -38.3306f, 184.0508f, 124.7862f, 72.2168f, 1.2740f, 68.2432f, + 98.5331f, 56.9808f, -18.2386f, 106.3234f, 18.7400f, -82.2337f, -91.2981f, + 56.8543f, 26.8486f, 79.2505f, 142.2529f, 26.5547f, -20.1961f, 20.0251f, + -101.2805f, -186.8430f, -272.0712f, -136.2303f, -296.2366f, -195.7741f, 24.4320f, + -195.6167f, -300.4726f, -112.7403f, 30.7313f, -121.6459f, -194.0080f, -41.2612f, + 98.2285f, 20.7275f, -91.7240f, -183.2970f, -349.5879f, -345.3007f, 56.7721f, + -162.4512f, -215.0840f, 54.6896f, -51.9437f, -204.1752f, -302.6133f, 17.1211f, + -127.3559f, -165.3954f, -278.6780f, -194.2370f, -33.4488f, -168.4021f, 38.6555f, + -295.7049f, -301.6402f, -62.3113f, -29.8345f, -17.8150f, -12.4093f, 147.9211f, + 33.3799f, -13.6109f, -78.2303f, -156.7363f, -259.0581f, -406.3858f, -96.3685f, + -70.3287f, -128.8603f, -35.8870f, -146.8926f, 10.7114f, -71.6699f, -42.8127f, + 499.4422f, 424.3595f, 305.0398f, 196.0019f, 126.5760f, 63.9795f, 61.1516f, + 266.3734f, 181.9720f, 175.4860f, 108.0995f, 56.9864f, 10.7695f, 159.6035f, + 247.9333f, 184.5145f, 152.3734f, 41.9318f, -90.6959f, -210.2689f, -54.1531f, + 76.7519f, 154.5846f, 129.7565f, 83.0209f, 81.7690f, -11.2691f, -31.6182f, + 58.5084f, -37.0541f, -121.7467f, 29.7202f, -30.0062f, -124.9186f, -19.6730f, + 18.1514f, 3.4725f, 18.4977f, 68.3406f, 54.2768f, 11.6546f, 150.1885f, + 85.0507f, 80.6332f, -9.5051f, -97.5608f, -37.4477f, -107.8952f, -71.4574f, + 10.1458f, 46.5077f, 14.7448f, 5.4868f, -1.5563f, -51.9743f, -20.1740f, + -186.2883f, -239.8358f, -385.3964f, -279.2732f, -246.3584f, -317.5150f, 77.9409f, + -290.8109f, -394.1977f, -416.1625f, -291.0747f, -246.4900f, -66.6275f, 7.0910f, + -53.3572f, -98.2187f, -188.6130f, -239.5862f, -382.9682f, -469.8791f, 4.8130f, + -236.2064f, -299.8000f, -219.3447f, -267.9179f, -424.8446f, -200.9900f, 22.5746f, + -78.8698f, -167.2648f, -305.5687f, -418.8565f, -37.5231f, -91.3323f, -69.9264f, + -187.4632f, -276.9708f, -417.8298f, -350.3085f, -51.2638f, -35.7869f, 125.5794f, + -56.7695f, -75.4877f, -200.1077f, -284.6027f, -223.5758f, -298.6907f, -81.9158f, + -129.2158f, -228.6000f, -204.9319f, -246.4877f, -109.8989f, -81.0975f, -118.3144f, + 455.1133f, 431.3343f, 366.9250f, 323.3162f, 279.7654f, 166.3696f, 60.4075f, + 2.2427f, -42.4551f, 320.2264f, 303.9626f, 161.9218f, 44.0682f, -10.4932f, + 148.9215f, 132.3074f, 122.6564f, 103.3307f, 47.4590f, -3.4202f, -185.0445f, + -145.6115f, 18.4827f, 228.0817f, 172.5267f, 38.5907f, -90.1562f, -43.9888f, + -193.6085f, -14.9922f, -111.3547f, 102.4688f, 119.0297f, 66.3613f, 1.6199f, + -229.1052f, -217.2523f, 26.9406f, 25.7113f, 183.7947f, 138.0997f, 4.9246f, + -54.0735f, 27.3595f, -6.9751f, 41.3897f, 26.0272f, 65.3047f, -117.9287f, + -173.6861f, -55.0424f, 72.3582f, 74.4772f, 59.1275f, 32.2629f, -52.0966f, + -100.2805f, -203.3997f, -281.1161f, -77.1917f, 52.4149f, -18.1558f, -70.9170f, + -319.7560f, -456.2388f, -303.5891f, 199.8376f, 140.0785f, 37.0556f, -44.1020f, + 53.3338f, -0.8373f, -29.0162f, -53.8806f, -156.4895f, -44.6551f, -144.9031f, + -94.4005f, -181.9505f, 79.8505f, 87.0198f, -12.1349f, -82.6727f, -75.0313f, + -207.6459f, -248.8868f, -181.9412f, -267.7931f, 100.0395f, 108.0778f, -54.3928f, + -445.8355f, -486.1193f, -148.8008f, -29.2654f, -20.9138f, 5.3055f, 34.4656f, + -121.3450f, 45.0588f, -55.9190f, -194.9437f, -134.0013f, 48.6244f, -162.3284f, + -240.5215f, -57.3889f, -52.6141f, 16.9554f, -1.6593f, 47.0915f, -144.2315f, + 326.1222f, 306.0203f, 250.4581f, 152.3629f, 138.5136f, 136.6061f, 24.8198f, + 27.9826f, 75.7094f, 172.8544f, 182.3980f, 170.1943f, 85.7041f, 145.3514f, + 181.4035f, 144.2242f, 74.8556f, 1.4272f, -61.0836f, -28.1913f, -88.2541f, + 22.2453f, 80.4679f, 118.3400f, 80.0672f, 73.2458f, 39.5447f, 103.6288f, + -15.5237f, -80.2624f, -190.5397f, -72.0487f, 107.7333f, 24.8407f, -9.9839f, + -84.5773f, -169.2563f, -115.8907f, 53.5535f, 128.0731f, 120.4292f, -112.8952f, + 147.5641f, 31.5040f, -120.2366f, -181.4932f, 22.0867f, -14.3306f, 88.8276f, + -38.8943f, 9.5208f, -14.2124f, -59.1263f, 77.8884f, 3.1099f, 55.9227f, + -166.2941f, -272.4271f, -413.5079f, -51.9034f, 151.3775f, 62.8211f, 125.4737f, + -251.4761f, -399.5025f, -496.4470f, 15.1387f, 25.6129f, -47.9447f, 27.2588f, + 145.3730f, 69.2023f, -67.5157f, -217.2383f, -216.1160f, -118.5795f, -73.6690f, + -45.7917f, -144.0127f, -166.1374f, -47.5218f, -180.4311f, -59.2610f, -28.7005f, + -253.6976f, -332.1650f, -464.5507f, -299.7163f, 194.1511f, 140.7432f, 86.8261f, + -311.8663f, -444.9106f, -568.2597f, -74.2214f, 168.0938f, 91.5796f, 69.8801f, + 16.2576f, -36.8680f, -158.1385f, -270.2551f, 14.7501f, -79.0270f, -96.1519f, + -66.0490f, -143.0125f, -113.3699f, -34.3890f, -25.0086f, 12.5482f, -114.0537f, + 394.4650f, 360.5732f, 366.5918f, 277.4828f, 181.5850f, 89.9984f, 133.6822f, + 84.7064f, 117.2216f, 411.7273f, 263.7720f, 26.7575f, -178.8131f, -69.9364f, + 30.5200f, 177.1075f, 123.5531f, 7.2231f, -92.4543f, -193.6012f, -94.9796f, + 65.2717f, 8.1559f, 165.7135f, 84.0440f, -35.7379f, -118.5377f, -66.5232f, + -113.0977f, -31.5885f, -27.3286f, -26.0692f, 15.5114f, 21.2791f, -23.2414f, + -138.0497f, -166.9724f, -35.1916f, 20.7464f, 36.6236f, 3.5627f, 20.9882f, + -11.0900f, 124.4114f, 110.4337f, 5.6888f, -93.7853f, -22.5026f, 30.8623f, + -29.4226f, -47.2009f, 89.3512f, 13.6996f, 22.5131f, 2.3075f, -51.7825f, + -137.2009f, -200.8273f, -290.6017f, -325.7113f, -275.5810f, -53.4554f, 64.1025f, + -438.9569f, -542.2731f, -412.1423f, -89.9884f, -28.4069f, 15.6647f, 13.8672f, + -63.4932f, -90.8672f, -207.9037f, -306.7191f, -456.9608f, -272.1003f, 37.6908f, + -307.9492f, -374.7438f, -96.2506f, -168.0490f, -243.8695f, -64.5296f, -3.1349f, + -334.4494f, -210.9558f, -246.0072f, -354.2072f, -131.6393f, -27.1645f, 29.5091f, + -366.0860f, -407.0811f, -257.3381f, -286.1801f, -81.4441f, 77.6511f, -10.1480f, + -204.4162f, 30.5330f, -38.3922f, -195.6373f, -339.5407f, -347.7475f, -31.6897f, + -243.6551f, -274.7409f, -17.3959f, -136.0264f, -9.8248f, 34.1080f, -72.7180f, + 392.4115f, 321.3055f, 213.3703f, 97.3249f, 35.2497f, -8.7278f, 80.8223f, + 116.4944f, 155.2541f, 148.9464f, 124.6089f, 78.0606f, 24.1574f, 118.5191f, + 184.6981f, 148.0850f, 51.9562f, -96.3499f, -247.0329f, -172.3801f, 29.4305f, + 110.9024f, 81.4259f, 152.8654f, 45.1114f, -9.8257f, 17.3401f, 36.9414f, + -27.9329f, 30.8783f, -37.1648f, -24.5270f, -50.2764f, -114.4973f, 79.3175f, + -64.1897f, -136.2614f, 44.8825f, 47.6375f, 26.8591f, -0.2729f, 147.6527f, + 135.7539f, 66.4931f, 38.8074f, 22.5599f, -70.1020f, -117.9085f, 73.4314f, + -74.1601f, -0.9165f, 58.6634f, 8.8413f, -20.0486f, -4.3857f, 84.5215f, + -240.3710f, -336.9822f, -425.7879f, -557.5921f, -313.4519f, -18.6503f, -2.2911f, + -375.5428f, -498.5622f, -604.7405f, -284.0899f, -22.5439f, 21.7506f, 87.1215f, + -48.5853f, -99.7448f, -219.1610f, -385.9877f, -498.9206f, -58.0072f, -32.0391f, + -187.4733f, -257.8106f, -348.0662f, -465.0402f, -523.0202f, -126.9367f, 7.9922f, + -242.4066f, -358.0976f, -506.2984f, -527.3067f, 103.2345f, 112.8789f, 19.5721f, + -329.7812f, -399.2909f, -525.3788f, -519.3241f, -114.6023f, 18.0531f, 108.4014f, + -101.3959f, -182.8774f, -323.7689f, -459.4139f, -208.2967f, -218.5872f, -30.6618f, + -83.9128f, -188.9391f, -321.0572f, -481.5454f, -309.1473f, 5.7541f, -53.7133f, + 508.3954f, 514.6412f, 492.8828f, 409.4624f, 279.6907f, 139.5316f, -25.0946f, + 225.7716f, 321.9763f, 361.4909f, 313.2012f, 246.2739f, 141.2217f, 40.0333f, + 183.5499f, 361.1524f, 299.5782f, 200.8792f, 127.5401f, 74.2915f, -43.7510f, + 87.8314f, 192.1731f, 193.5542f, 170.6556f, 233.6155f, 150.0142f, -17.3959f, + 16.6972f, 31.8549f, -16.4255f, 68.2118f, 202.5792f, 133.4167f, -24.8757f, + -118.5934f, -60.2884f, 62.2425f, 224.9154f, 157.3277f, 86.2001f, 127.8335f, + 83.3985f, 95.4353f, 47.7289f, -24.4079f, 122.0239f, 35.9347f, -62.3200f, + 85.0292f, 81.2156f, 121.2625f, 104.6399f, 119.6594f, 126.2998f, -77.7217f, + -111.4887f, -105.1822f, -30.9685f, -48.2729f, -55.9544f, -59.5831f, 92.3539f, + -80.0937f, -149.8609f, -166.3557f, 134.5224f, 22.8807f, -72.2311f, -71.7019f, + -106.2400f, 96.5443f, 49.1033f, -82.1511f, -202.4001f, -182.6395f, 30.4307f, + -38.6498f, -47.0332f, 196.2347f, 62.6390f, -109.4412f, -217.5327f, 118.6330f, + -165.3289f, -6.5073f, -110.5468f, -172.9718f, 83.9014f, 82.6244f, -54.8262f, + -220.1304f, -267.2490f, -88.9432f, 199.2986f, 140.8517f, 50.8656f, 126.1685f, + -167.2625f, 130.8662f, 38.2409f, -25.2887f, 14.1618f, -84.0247f, -96.2550f, + -141.5362f, 19.9235f, 142.0336f, -6.1892f, -91.4426f, 58.7228f, -64.2743f, + 356.9441f, 345.0619f, 293.3749f, 255.2251f, 264.2440f, 181.1552f, -59.9296f, + 246.4391f, 212.9810f, 208.9891f, 281.1677f, 232.7401f, 140.5526f, -31.7890f, + 305.7318f, 278.3117f, 199.8758f, 171.6015f, 133.0515f, 98.0317f, -152.6052f, + 194.0116f, 162.7764f, 97.4355f, 145.3808f, 115.4215f, 67.7161f, -75.3193f, + 50.0116f, -43.0169f, -150.4608f, 36.4008f, 15.3428f, 67.7103f, -90.2827f, + 84.1801f, -22.9641f, -98.8488f, 180.4238f, 151.9562f, 59.9903f, 26.9906f, + 177.5510f, 105.3890f, -1.4605f, -131.7380f, -19.1906f, 90.9329f, -125.9315f, + 119.9137f, 55.8859f, 20.5790f, 85.2794f, 50.1218f, 92.1433f, -60.8729f, + -14.4439f, -72.6866f, -93.8542f, -160.4042f, -42.8567f, 3.3977f, 156.0409f, + -54.5578f, -142.4629f, -245.2400f, 100.6745f, 148.4848f, 83.6861f, 108.3569f, + 51.3106f, 177.4475f, 69.0944f, -111.1996f, -202.9647f, 42.3005f, -83.6978f, + 30.1802f, -55.2034f, 78.5647f, -47.9833f, -191.5273f, -51.2293f, 23.2575f, + -5.5372f, -75.8171f, -203.4011f, -289.5156f, 106.7613f, 141.4280f, -13.0810f, + -141.4010f, -221.2458f, -112.2780f, -89.1527f, 63.0527f, 92.4026f, 123.8935f, + -105.1256f, 76.2826f, -29.3279f, -146.3319f, -79.8275f, 4.2937f, 30.2187f, + -50.0448f, -103.1965f, -61.1121f, -87.1858f, -185.4814f, 103.5567f, 10.4906f, + 483.7709f, 447.9613f, 357.9065f, 269.2391f, 168.5860f, 81.9800f, -109.5565f, + 312.3829f, 259.3732f, 343.4722f, 283.4192f, 160.6555f, 62.4472f, -64.0786f, + 177.4189f, 268.0235f, 209.2622f, 107.3129f, 57.2866f, 17.7874f, 43.3733f, + 118.3413f, 189.8245f, 200.1482f, 138.5254f, 93.9936f, 70.6362f, -26.8448f, + 30.9857f, 35.8345f, 11.3604f, 57.5567f, 90.9626f, 20.1319f, 6.8180f, + -66.7255f, 112.7395f, 51.2972f, 171.5931f, 105.7922f, 1.0289f, -4.0888f, + 161.4374f, 94.0077f, 56.1444f, 67.9007f, 60.5061f, -0.5993f, 5.5333f, + 22.6145f, 84.7579f, 96.3842f, 85.7332f, 58.1820f, 68.5529f, -7.0445f, + 89.2476f, -2.9310f, -93.5695f, -80.5243f, -200.4216f, -74.7223f, 78.7932f, + -37.6075f, -106.1347f, -177.1898f, 12.7187f, -117.0868f, -224.7555f, 18.0710f, + -3.9184f, -42.1867f, -96.2393f, -135.5441f, -300.7351f, -209.1140f, 3.3638f, + -127.2731f, -168.0130f, -23.6514f, -125.4722f, -275.0623f, -116.8249f, 78.4081f, + -0.3268f, -109.2929f, -235.6517f, -163.5220f, -72.4472f, 7.1522f, -14.1950f, + -201.5567f, -203.8994f, -147.8831f, -113.7655f, -70.6486f, -37.9403f, 10.4648f, + -61.9333f, -122.2785f, -205.0957f, -87.3765f, -199.0248f, -324.4658f, -76.9686f, + -114.1747f, -179.4460f, -22.8678f, -120.9749f, -219.5858f, -55.7430f, -137.0347f, + 416.5525f, 356.2247f, 246.4192f, 151.7590f, 80.9813f, 33.7425f, -87.5668f, + 232.7198f, 199.8298f, 232.8017f, 197.1352f, 122.7492f, 47.7377f, -18.8607f, + 307.4450f, 336.4361f, 172.1882f, -36.4639f, -118.2980f, 12.7783f, -74.1220f, + 100.4413f, 183.0223f, 131.6807f, 19.7279f, 5.8399f, 116.3680f, -36.1637f, + 115.0603f, 28.3727f, -46.6535f, 9.9458f, 14.2165f, 8.8947f, 42.1125f, + -11.0346f, -1.0867f, -12.6705f, 44.5022f, 8.2729f, 72.2938f, 41.9570f, + 188.4713f, 119.1476f, 5.8222f, -109.1441f, -124.7922f, 20.2470f, 37.4241f, + 88.4120f, 18.1026f, 44.8535f, 28.1015f, -53.1688f, 52.0384f, -48.7039f, + 7.0136f, -80.7959f, -218.2056f, -230.6367f, -196.4241f, -188.3921f, 125.5651f, + -223.0832f, -308.3413f, -371.4560f, -67.3406f, -172.4539f, -210.1611f, 44.0330f, + 70.5425f, 5.5613f, -121.1026f, -250.2220f, -391.0280f, -78.8702f, 62.0359f, + -53.2080f, -153.5175f, -168.9519f, -200.2387f, -356.0113f, -56.1841f, -8.4833f, + 28.1989f, -103.3445f, -275.6373f, -372.5401f, -62.2850f, 20.7805f, 129.8285f, + -131.8626f, -230.9837f, -332.7086f, -149.5865f, -154.3909f, 21.7068f, 17.3275f, + 16.7300f, -61.8863f, -181.1369f, -350.5149f, -246.6439f, -61.1861f, -114.9767f, + -62.9283f, -50.0990f, -128.3168f, -223.8037f, -188.6130f, -48.9473f, 4.2910f, + 397.1338f, 354.0856f, 410.7048f, 392.6840f, 265.0492f, 133.1239f, -39.9595f, + 140.3398f, 130.2926f, 612.1718f, 513.2461f, 282.4946f, 41.1820f, 3.7939f, + -25.5253f, 283.5953f, 206.7656f, 117.4847f, 85.9801f, 16.9447f, -106.7023f, + -199.2065f, 170.3263f, 280.7031f, 221.1866f, 139.8684f, 69.7774f, 44.7026f, + -218.6125f, 116.3745f, 51.8822f, -46.6960f, 133.6225f, 87.8249f, 5.3826f, + -351.2338f, -39.4894f, 84.6148f, 241.0717f, 156.3851f, 57.0277f, -22.5485f, + -16.1558f, 137.3482f, 31.9090f, -76.7114f, 15.3505f, 47.2591f, -65.0792f, + -82.6497f, 23.1536f, 174.7281f, 111.0391f, 165.1666f, 97.6276f, -66.0758f, + -144.8786f, -188.8722f, -232.9240f, 11.8115f, -15.8240f, 97.1230f, 8.4134f, + -145.3324f, -253.9705f, -310.2223f, 186.1852f, 173.7029f, 84.4147f, -31.0347f, + -137.6416f, 107.5353f, 6.4667f, -172.8744f, -362.7197f, 36.0251f, 7.3423f, + -273.1752f, -271.7551f, 168.5304f, 103.1478f, -19.2394f, -121.0773f, 71.0605f, + -382.1200f, -84.7432f, -167.9304f, -156.0550f, 39.5436f, 102.1275f, 28.0496f, + -362.7133f, -347.0801f, -139.5875f, -5.2563f, 181.0231f, 147.5667f, 92.1709f, + -322.5983f, 22.0118f, 11.8984f, -116.7982f, -140.8088f, -50.1710f, -20.0495f, + -342.8153f, -116.9352f, -43.2698f, 29.1059f, 25.4655f, 14.1526f, 1.1041f, + 319.3257f, 143.9371f, -9.8398f, 138.1817f, 272.2951f, 230.7682f, -67.6844f, + 120.5561f, 82.8050f, 86.9118f, 293.3890f, 188.8921f, 54.7609f, -21.7199f, + 231.6328f, 148.0905f, 27.2085f, -3.2337f, 100.6721f, 70.2593f, 42.8315f, + 64.4154f, -17.9857f, 99.5439f, 116.0344f, 85.7395f, 106.6537f, 41.0177f, + 62.6236f, -27.4056f, -139.7237f, -70.5707f, 148.2318f, 128.9077f, 124.7000f, + -92.9236f, -144.0688f, -77.1586f, 288.9071f, 226.4347f, 124.6281f, -55.6669f, + 78.3503f, 42.4807f, -79.0042f, -178.3122f, 128.1446f, 107.8855f, -55.1806f, + 79.1238f, 66.4433f, 43.2504f, 16.2992f, 80.8281f, 140.7251f, 73.5809f, + -134.6119f, -155.8599f, -200.3194f, -90.9865f, 253.7969f, 164.9683f, 31.5576f, + -248.1197f, -375.5200f, -476.6351f, 180.7157f, 210.6575f, 79.8609f, 81.7351f, + 78.7261f, -9.7665f, -75.8617f, -194.4922f, -307.4282f, 75.4347f, -56.0501f, + -175.4331f, -210.0029f, 75.9892f, -41.3638f, -129.4197f, 26.7040f, 24.1293f, + -89.1388f, -186.3199f, -327.9780f, -225.0781f, 123.8019f, 49.8056f, 110.5614f, + -262.0009f, -365.9398f, -315.0958f, -44.6833f, 152.6366f, 130.9091f, -24.3555f, + 96.1914f, 0.9431f, -122.7709f, -265.0437f, -118.4077f, 70.4388f, -34.3324f, + -41.7155f, -106.2450f, 35.3080f, -77.1729f, -11.0485f, 113.3317f, -43.5801f, + 345.8234f, 448.9382f, 398.8093f, 278.1467f, 193.7783f, 109.9307f, -32.5084f, + 105.2215f, 192.0218f, 307.4095f, 251.2213f, 135.6460f, 27.1659f, 48.2501f, + 131.1255f, 248.6208f, 194.8135f, 35.9742f, -89.6413f, -70.1114f, 74.4933f, + 10.3277f, 157.1341f, 220.2146f, 132.8669f, 58.2022f, -4.2414f, 52.5998f, + -171.9997f, 219.1700f, 183.7592f, 79.7388f, -28.2743f, -72.7875f, 54.8047f, + -281.0813f, 5.4272f, 138.6439f, 89.6476f, 26.7423f, -52.0621f, 181.8158f, + 42.9908f, 121.1063f, 40.1449f, 4.6961f, 41.3091f, 11.3680f, 61.7374f, + -69.6739f, 44.0933f, 62.9511f, 55.3414f, 47.1718f, 45.0520f, 10.5398f, + -254.2462f, -161.6377f, -252.0311f, -59.3082f, -64.1228f, -5.1355f, -167.6060f, + -249.7012f, -368.7658f, -266.1853f, -40.5172f, -31.5949f, 20.3852f, -73.7292f, + -259.0964f, -63.9727f, -123.4555f, -266.6797f, -372.6790f, -79.9634f, -32.2913f, + -237.8991f, -261.1591f, -67.3100f, -201.9258f, -271.1355f, 110.5556f, -31.4253f, + -252.1870f, -59.5241f, -149.7008f, -264.8359f, -95.9333f, -15.7623f, -55.9292f, + -291.6127f, -310.8436f, -291.0997f, -152.3425f, -38.1903f, 16.9302f, 107.5521f, + -234.1635f, -77.8775f, -155.4929f, -169.1375f, -170.1633f, -210.0618f, 12.2871f, + -432.5516f, -222.0327f, -146.7204f, -103.4423f, -49.3643f, -8.0516f, 0.3778f, + 330.7150f, 223.7578f, 120.2566f, 152.9689f, 119.1688f, 39.3462f, 21.3169f, + 106.4649f, 114.2936f, 78.3297f, 104.4772f, 135.1724f, 78.5670f, 48.1339f, + 284.0033f, 187.5895f, 88.2418f, 0.6583f, -25.3445f, -53.7671f, 63.9802f, + 106.5275f, 81.1295f, 67.7705f, 114.2483f, 4.6206f, 98.6728f, 68.0557f, + 132.7267f, 80.9311f, 70.2013f, 34.2614f, 45.4356f, 17.9487f, 185.5185f, + -179.6926f, -64.9953f, -11.8397f, 5.1401f, 42.9932f, 67.5337f, 154.7699f, + 53.6060f, 34.2805f, 16.7478f, -53.4059f, -36.7348f, 13.1978f, 110.7422f, + 37.6082f, -5.5267f, 88.1530f, 15.7336f, 24.4194f, 27.1976f, 50.6641f, + -182.5485f, -287.0959f, -395.1311f, -458.4781f, -119.8993f, 119.0388f, -26.2634f, + -239.2084f, -359.3420f, -447.6111f, -221.6196f, -3.2312f, 35.8538f, -9.6860f, + -70.9599f, -105.8073f, -192.0091f, -294.5047f, -334.6240f, 111.9638f, -29.3527f, + -193.0902f, -307.5872f, -268.9553f, -266.8591f, -276.8985f, 53.4395f, -127.3159f, + -112.3830f, -214.7503f, -352.5892f, -431.6330f, 130.6462f, 125.3650f, -24.3701f, + -138.4310f, -254.9568f, -325.5955f, -173.9416f, 0.3136f, 147.4202f, -59.5469f, + -63.4081f, -119.3462f, -237.6156f, -366.1194f, -116.1935f, 96.5096f, -74.8714f, + -91.5009f, -186.5192f, -95.3213f, -190.6698f, -103.7853f, 133.5730f, -129.6124f +}; + +/*-------------------------------------------------------------------* + * AMR-WB ISF codebook - 46bits, 2 stages, 1st stage common with the + * 36bit codebook,5 splits in the 2nd stage + * + * codebook vector dimension number of vectors + * ~~~~~~~~ ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~ + * 2_1 3 64 + * 2_2 3 128 + * 2_3 3 128 + * 2_4 3 32 + * 2_5 4 32 + *-------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------* + * 2nd stage, 1st split: ISF0 to ISF2 + *-------------------------------------------------------------------*/ + +const float dico21_isf_46b[] = +{ + 128.4688f, 159.8148f, 97.2755f, + -12.9836f, 197.1542f, 62.3669f, + -11.1370f, -5.4038f, 227.1786f, + -102.5247f, 49.5302f, 138.2452f, + 56.6014f, 92.4597f, 68.2462f, + -59.4614f, 95.8021f, 47.7671f, + 10.6214f, 16.4206f, 132.7432f, + -33.0052f, -36.4880f, 121.6274f, + 111.3621f, 86.8573f, -60.9301f, + 18.4019f, -16.9460f, -196.8595f, + 91.2159f, 47.1568f, 150.3417f, + 40.7444f, -123.8314f, 17.6656f, + 68.7560f, 76.0870f, 3.0834f, + 40.5189f, -22.9558f, -36.8239f, + 68.9463f, 20.8592f, 75.1641f, + -13.4297f, -49.7472f, 59.4394f, + 222.6512f, 108.2263f, -13.1594f, + -26.2678f, -128.5232f, -249.6796f, + -61.3770f, -106.3253f, 180.3803f, + -69.2195f, -180.5594f, 77.3840f, + 125.7118f, 69.8739f, 44.7696f, + -150.6344f, 66.9866f, 7.4132f, + 7.5039f, -4.7150f, 76.2746f, + -46.9159f, -98.2953f, 78.4325f, + 118.5603f, 14.1695f, -131.2373f, + -50.1565f, -86.1739f, -148.3825f, + 66.6965f, -72.1903f, 115.4583f, + -94.5599f, -121.9918f, 8.8523f, + 77.1679f, 15.2443f, 6.1163f, + -1.0987f, -69.2605f, -43.3316f, + 43.3928f, -36.3404f, 29.4998f, + -36.0829f, -87.1134f, 1.6094f, + 69.0548f, 158.6352f, -17.3680f, + -65.7580f, 148.4039f, -58.1224f, + -1.4207f, 106.6547f, 129.4115f, + -163.9787f, 200.5753f, 108.3887f, + 8.0981f, 96.4962f, 18.4523f, + -22.7513f, 51.0308f, -0.8203f, + -1.3389f, 52.2067f, 70.5057f, + -56.5316f, 15.5148f, 68.5082f, + 73.6822f, 28.9345f, -56.5083f, + -10.5212f, -17.6820f, -126.8611f, + 144.6737f, -44.4661f, -8.2446f, + -32.2712f, -161.9950f, -67.5138f, + 29.9266f, 37.2667f, -20.0451f, + -15.7787f, -11.7016f, -26.2432f, + 27.7648f, 34.4647f, 33.4065f, + -13.8614f, -38.4420f, 5.6107f, + 27.0098f, 76.8588f, -130.2875f, + -76.5280f, 30.9527f, -90.1727f, + -135.8326f, -53.3710f, 85.3346f, + -137.4852f, -34.8750f, -33.3215f, + 18.2807f, 78.3958f, -50.7970f, + -64.5101f, 14.5083f, -5.6925f, + -16.6084f, 1.0141f, 33.5889f, + -63.0082f, -42.0433f, 31.0393f, + 32.2577f, 8.3123f, -92.4112f, + -31.6346f, -58.2893f, -92.9305f, + 58.7086f, -72.6659f, -98.0877f, + -72.8089f, -97.1838f, -63.2264f, + -7.5866f, 25.6299f, -54.3822f, + -10.3321f, -19.4552f, -70.7729f, + 9.4725f, 4.3403f, 0.0721f, + -50.7563f, -41.0679f, -38.2745f +}; + +/*-------------------------------------------------------------------* + * 2nd stage, 2nd split: ISF3 to ISF5 + *-------------------------------------------------------------------*/ + +const float dico22_isf_46b[] = +{ + -49.5271f, 121.1295f, 16.4769f, + -94.4022f, 76.8061f, 2.1280f, + -58.8683f, 32.7926f, -6.6703f, + -83.7461f, 49.5749f, -58.1205f, + -96.5332f, -51.1816f, 62.2310f, + -104.6874f, -104.4218f, -36.9709f, + -84.8023f, 0.4441f, -31.0082f, + -105.8907f, -31.0867f, -72.0962f, + -17.4561f, 170.2726f, 62.0341f, + 64.3231f, 77.6492f, 152.6545f, + -13.0558f, 31.6496f, 73.1381f, + -25.9540f, -16.3235f, 138.6579f, + -116.2904f, -22.1347f, 133.9606f, + -42.0923f, -209.9028f, 88.4509f, + -56.0897f, -9.1734f, 75.5450f, + 68.7883f, -157.0452f, 33.8343f, + 20.5838f, 115.6837f, 9.8136f, + -32.8948f, 98.7358f, -40.4656f, + -22.8099f, 41.1383f, -49.3496f, + -66.1700f, 67.9190f, -122.8227f, + -18.8196f, 17.0630f, -114.9884f, + -64.0458f, -162.7084f, -94.5118f, + -54.2084f, 1.0923f, -75.9526f, + -60.5415f, -80.9324f, -82.4130f, + 46.5760f, 125.8621f, 83.1458f, + 129.9934f, 19.7027f, 148.2803f, + 92.6546f, 96.4434f, -0.8040f, + 181.9977f, -6.0791f, 78.6212f, + 93.0392f, -99.5781f, -41.6073f, + 26.0437f, -172.0070f, -58.1634f, + 47.8475f, -34.2895f, -54.2498f, + 34.4187f, -96.6345f, -28.5027f, + -15.8270f, 90.1190f, 65.2787f, + -24.1274f, 60.7006f, 6.3059f, + -25.2307f, 6.3412f, 30.0794f, + -26.6845f, -0.7965f, -24.5917f, + -59.0614f, -117.3599f, 62.4002f, + -7.0821f, -130.0555f, 20.9710f, + -21.7086f, -36.6794f, 1.9468f, + 0.6440f, -74.2564f, 5.5161f, + 35.9276f, 57.9971f, 81.4502f, + 42.2272f, 3.3575f, 106.2218f, + 42.1565f, 13.6719f, 43.0135f, + 55.6116f, -33.1310f, 56.8126f, + 18.4410f, -61.4055f, 109.0841f, + 1.0223f, -125.1248f, 96.1657f, + 16.9404f, -28.1707f, 26.5748f, + 33.5245f, -84.6827f, 52.6704f, + 14.2066f, 54.8716f, 30.7506f, + 21.9479f, 68.4119f, -19.0589f, + 10.1034f, 17.7161f, 1.1122f, + 28.3594f, 21.5207f, -39.3190f, + 42.6619f, -71.6784f, -94.4716f, + -1.6345f, -110.6804f, -94.5938f, + 18.7091f, -26.5385f, -18.5676f, + -2.2267f, -59.7051f, -47.6606f, + 63.0633f, 76.6895f, 37.6845f, + 90.5993f, 31.2041f, 74.2520f, + 64.4418f, 37.7231f, 4.2748f, + 100.9151f, -12.1708f, 27.5607f, + 104.1606f, -30.0584f, -35.7097f, + 121.5339f, -81.6812f, 34.1503f, + 59.3840f, -5.5457f, -8.5514f, + 58.5319f, -58.3782f, 3.4649f, + -126.3823f, 217.4185f, 72.9956f, + -149.8116f, 119.9919f, 17.7920f, + -98.1555f, 10.6050f, 30.1117f, + -142.4950f, 30.1718f, -20.4500f, + -188.3500f, -32.7229f, 62.5055f, + -165.4842f, -201.2336f, -25.1871f, + -114.8346f, -46.6803f, -1.4401f, + -185.9166f, -45.3806f, -42.6756f, + -37.7442f, 124.2892f, 142.7720f, + 41.5423f, 244.7676f, 173.7613f, + -74.1037f, 46.8818f, 112.0588f, + -57.0922f, 25.5056f, 241.9654f, + -166.9268f, 94.6864f, 141.8443f, + -141.0368f, -145.0649f, 168.9254f, + -135.5530f, 39.8468f, 65.4743f, + -245.6494f, 76.1803f, -5.6309f, + -25.5608f, 185.7902f, -18.2246f, + -116.1471f, 125.0659f, -65.5997f, + -21.6448f, 139.2267f, -103.0516f, + -152.7089f, 32.1737f, -111.7466f, + -19.9673f, -12.1771f, -217.1499f, + -69.4452f, -156.0378f, -228.9529f, + -79.9513f, -19.3186f, -140.5787f, + -134.0792f, -92.8863f, -131.5222f, + 85.7696f, 178.6823f, 22.5404f, + 219.0179f, 182.4547f, 100.9819f, + 132.7898f, 105.4102f, -65.5694f, + 175.6583f, 30.2382f, -109.3055f, + 23.2833f, 65.0492f, -161.3234f, + 51.9178f, -98.2708f, -192.0347f, + 84.2797f, 61.1831f, -113.4513f, + 110.0580f, 0.1775f, -193.4730f, + -88.3674f, 114.5595f, 71.3481f, + -61.4713f, 52.7833f, 47.8295f, + -61.8477f, -23.0151f, 15.1016f, + -52.0862f, -46.0690f, -37.7005f, + -129.6202f, -120.6827f, 44.2216f, + -62.4412f, -165.8667f, -2.2683f, + -58.1508f, -82.2449f, 9.3842f, + -31.2569f, -108.3441f, -35.0348f, + -4.4143f, 48.6610f, 132.2242f, + 50.8942f, -27.6676f, 181.6500f, + 2.0066f, -17.6839f, 71.9731f, + 92.7139f, -37.1637f, 98.9732f, + -54.3785f, -76.9789f, 115.8870f, + -7.4354f, -117.3479f, 199.5254f, + -24.6757f, -59.5165f, 54.3134f, + 97.6902f, -113.0194f, 131.1002f, + 48.4163f, 132.4722f, -58.7820f, + 13.3327f, 68.6117f, -81.0715f, + 66.7414f, 64.6961f, -45.2427f, + 36.7779f, 14.7160f, -89.5910f, + 29.2181f, -25.5238f, -132.3077f, + -30.5052f, -80.0320f, -150.5560f, + 0.1157f, -11.7322f, -63.8467f, + -21.6912f, -43.0765f, -94.6223f, + 125.3290f, 95.1208f, 75.9759f, + 197.4010f, 92.9319f, -0.5012f, + 123.8246f, 45.4969f, 25.5317f, + 120.7415f, 34.4155f, -28.8961f, + 176.6600f, -20.0903f, -19.4091f, + 130.6288f, -84.9368f, -113.4633f, + 82.2281f, 16.0388f, -59.4614f, + 93.1589f, -21.5846f, -101.7248f +}; + +/*-------------------------------------------------------------------* + * 2nd stage, 3rd split: ISF6 to ISF8 + *-------------------------------------------------------------------*/ + +const float dico23_isf_46b[] = +{ + -3.8995f, 58.9472f, 140.2168f, + 53.1422f, 116.3810f, 87.0383f, + 99.7094f, -40.4441f, 113.1331f, + 165.1496f, 2.2135f, 71.5223f, + -105.3934f, -104.9144f, -38.2897f, + -20.3247f, -32.1811f, 5.1214f, + -32.0250f, -106.9634f, -37.7452f, + 35.0256f, -95.9288f, -28.2073f, + -116.9343f, -27.2704f, 164.5334f, + -34.2352f, 142.6884f, 167.9453f, + 72.9835f, -124.0776f, 148.8355f, + 148.2748f, 14.5359f, 190.7047f, + -145.5305f, -123.4847f, 30.8224f, + -120.2600f, -39.3306f, 2.0939f, + -52.9049f, -176.3645f, 3.0609f, + 27.9487f, -164.3167f, -60.3281f, + 70.4088f, 66.5042f, -47.2043f, + 24.2507f, 69.1997f, -15.5014f, + 127.5028f, 31.2976f, -40.8233f, + 96.9136f, 102.7271f, -1.9768f, + -65.7818f, -70.8663f, -86.5155f, + -0.6444f, -8.8675f, -61.8361f, + -5.3369f, -58.3089f, -47.3390f, + 46.4765f, -35.6284f, -57.4718f, + 46.3328f, 129.6813f, -59.6592f, + 18.9988f, 118.4842f, 13.3515f, + 172.5430f, -21.3132f, -26.8827f, + 84.7525f, 177.2668f, 22.5077f, + -140.2432f, -73.0634f, -146.3583f, + -16.3786f, 19.6063f, -107.1305f, + -3.0698f, -104.1769f, -97.1330f, + 33.2378f, -33.4660f, -134.9635f, + -29.8971f, -15.7433f, 134.7990f, + 34.9346f, 52.2504f, 85.7197f, + 60.8752f, -31.2562f, 62.5970f, + 42.3279f, 15.7348f, 45.3299f, + -61.8761f, -80.5864f, 11.3831f, + 1.9118f, -12.4255f, 68.2023f, + -25.4049f, -61.6688f, 57.1412f, + 21.3127f, -30.3874f, 28.3554f, + -44.5637f, -86.8534f, 137.9897f, + -18.2977f, 31.6219f, 82.2796f, + 19.0573f, -58.8750f, 104.6892f, + 41.1433f, 1.5028f, 117.9977f, + -102.7489f, -51.4207f, 71.3300f, + -59.0984f, -10.9389f, 78.5554f, + -69.1486f, -120.0273f, 65.0256f, + 39.6252f, -86.2109f, 50.9690f, + 29.0714f, 22.6919f, -38.4256f, + 12.6360f, 17.2986f, 5.2183f, + 75.9445f, 11.6720f, -55.4942f, + 66.2898f, 37.5939f, 3.0594f, + -53.0062f, -46.4272f, -35.4140f, + -25.4219f, 2.9542f, -21.2949f, + 1.3392f, -73.4502f, 4.6640f, + 17.5926f, -24.6153f, -19.1614f, + 58.2567f, -8.0154f, -7.3521f, + 9.4616f, 56.2212f, 37.1474f, + 99.2497f, -8.5999f, 23.5678f, + 62.8908f, 76.5199f, 37.4883f, + -61.5740f, -23.6494f, 18.8743f, + -27.4404f, 12.7151f, 31.8660f, + -8.8214f, -125.3200f, 22.5806f, + 60.3707f, -57.3931f, 1.9729f, + -142.0781f, 128.1134f, 29.9265f, + -8.1434f, 177.0072f, 67.7176f, + -42.2467f, 31.9985f, 246.1330f, + 143.5303f, 102.5801f, 81.3050f, + -117.3709f, -24.3191f, -68.7836f, + -80.1727f, 55.9021f, -61.6700f, + -65.9167f, -159.9841f, -103.0851f, + 100.4774f, -105.1623f, -39.0393f, + -248.4434f, 113.0562f, -0.9632f, + -114.2012f, 244.7349f, 67.3892f, + -149.2039f, -141.9386f, 151.3480f, + 96.8171f, 204.6967f, 174.6282f, + -203.4799f, -43.3805f, -41.7327f, + -154.4080f, 46.2418f, -107.0591f, + -133.7993f, -265.7036f, -48.9596f, + -67.3323f, -174.6485f, -259.0245f, + 29.4362f, 57.7183f, -143.2330f, + -30.9358f, 102.7735f, -36.8946f, + 97.2809f, 57.7730f, -111.7326f, + 148.5371f, 105.7429f, -63.3760f, + -55.6062f, -1.6898f, -72.6741f, + -22.0825f, 43.4697f, -48.9841f, + -13.6583f, -42.0695f, -99.1267f, + 39.0227f, 11.1441f, -94.4170f, + -31.1674f, 118.4450f, -103.1298f, + -30.5761f, 181.1050f, -22.4168f, + 96.8625f, -8.6867f, -192.7743f, + 258.0970f, 258.6485f, 17.2359f, + -75.4867f, -15.7399f, -128.9883f, + -69.4209f, 56.4875f, -131.4587f, + -35.1219f, -77.9249f, -156.1559f, + -15.4754f, -8.8922f, -194.7119f, + -74.8584f, 44.6175f, 122.9601f, + -15.9046f, 95.4389f, 74.2532f, + 34.5640f, -37.7631f, 189.4453f, + 93.9878f, 31.0970f, 82.8675f, + -96.2834f, 15.6201f, 33.9921f, + -60.9930f, 57.5930f, 52.2667f, + -0.7661f, -130.2809f, 93.4385f, + 120.2708f, -79.2677f, 42.9508f, + -179.2200f, 97.8633f, 164.7641f, + -85.0375f, 121.2092f, 89.0752f, + -33.4305f, -135.1092f, 255.3923f, + 71.7349f, 68.5372f, 165.8218f, + -187.7999f, -24.7305f, 65.9037f, + -136.4161f, 45.6197f, 73.4184f, + -48.8887f, -218.9293f, 120.9648f, + 61.8728f, -162.4253f, 36.5784f, + 17.9416f, 66.9736f, -75.1315f, + -24.6266f, 61.4069f, 5.3953f, + 100.0199f, -13.7281f, -105.7749f, + 125.9485f, 48.0431f, 20.6117f, + -83.4273f, 1.6803f, -29.7397f, + -60.9733f, 33.6154f, -6.9071f, + 49.9381f, -77.0001f, -90.5842f, + 103.7070f, -35.1051f, -38.3706f, + -120.2797f, 129.5670f, -56.7507f, + -51.1815f, 120.2600f, 22.5398f, + 198.7324f, 23.1592f, -132.3752f, + 219.6951f, 76.6881f, -5.4836f, + -147.6706f, 39.1117f, -18.2240f, + -91.4913f, 78.8627f, 0.3161f, + 40.5908f, -105.4075f, -192.5737f, + 124.6250f, -81.8382f, -127.0619f +}; + +/*-------------------------------------------------------------------* + * 2nd stage, 4th split: ISF9 to ISF11 + *-------------------------------------------------------------------*/ + +const float dico24_isf_46b[] = +{ + -30.8071f, -34.8458f, -1.7377f, + -66.7509f, 30.0385f, -82.3340f, + 62.4748f, -75.5700f, 38.3392f, + 47.0287f, -40.0671f, 126.1063f, + 12.5178f, -8.7146f, -50.3954f, + 27.9620f, 30.3537f, -104.7235f, + 71.0260f, -29.6231f, -25.7014f, + 120.7753f, 38.6709f, -56.4990f, + -89.5313f, -61.4613f, -32.9542f, + -149.7260f, 38.4143f, -27.8365f, + -35.1587f, -137.6189f, 4.6136f, + -110.8198f, -69.6633f, 69.4652f, + -25.4794f, -48.9702f, -64.6927f, + -34.0250f, -68.5378f, -137.1167f, + 16.3769f, -77.3935f, -18.8382f, + 60.1539f, -54.6626f, -95.0395f, + -29.9828f, 6.8644f, 42.3138f, + -15.0985f, 138.6659f, 35.6532f, + 34.1357f, 3.3162f, 60.3957f, + -1.5046f, 61.8542f, 93.5327f, + 49.8233f, 37.2486f, -21.0923f, + 2.6462f, 96.2433f, -48.4645f, + 100.8559f, 5.8835f, 34.9436f, + 80.3813f, 84.4933f, 38.3143f, + -78.4639f, 3.3495f, 7.0416f, + -121.9442f, 90.8917f, 79.7252f, + -15.2997f, -67.8455f, 60.6317f, + -56.1035f, -3.5687f, 110.7510f, + -22.2741f, 27.4204f, -26.9833f, + -61.1362f, 73.0974f, 7.1390f, + 21.0362f, -11.6205f, 9.0680f, + 9.3252f, 52.8599f, 21.3451f +}; + +/*-------------------------------------------------------------------* + * 2nd stage, 1st split: ISF12 to ISF15 + *-------------------------------------------------------------------*/ + +const float dico25_isf_46b[] = +{ + 65.8574f, 55.5896f, -46.5520f, 44.9019f, + 80.4838f, -7.7875f, 36.7110f, 88.1867f, + -41.5522f, 122.0924f, -8.3769f, 6.2406f, + -24.0605f, 63.0705f, 27.8308f, 99.4548f, + -34.8725f, 39.6270f, -72.1743f, 48.7995f, + 28.2859f, -11.6999f, -78.4246f, 134.1911f, + -100.6717f, 12.7337f, -3.2716f, 31.4897f, + -40.5514f, -60.1846f, 28.1000f, 115.5554f, + 56.1050f, -26.6471f, -104.7202f, -9.7237f, + 31.5196f, -30.3722f, -34.0636f, 41.4375f, + 8.5013f, 60.4295f, -72.4835f, -46.4772f, + -18.1378f, -10.8741f, 10.5206f, 35.6699f, + -44.7247f, -14.6405f, -68.4296f, -12.8925f, + -36.6233f, -86.8592f, -73.8785f, 47.7951f, + -51.6319f, -46.3776f, -74.4907f, -105.4981f, + -67.2817f, -67.7186f, 6.9193f, -16.9668f, + 108.8168f, 52.7624f, -16.3049f, -50.0846f, + 72.9801f, -33.7268f, 89.4150f, -54.0673f, + 62.1588f, 93.8928f, 54.7414f, 17.8328f, + 26.7626f, 9.6218f, 88.5287f, 29.9594f, + 8.1440f, 44.9198f, 5.0806f, 2.9996f, + 26.4759f, -96.7328f, 49.0444f, 31.6496f, + -58.6349f, 53.6024f, 80.8924f, -3.3883f, + -60.0341f, -51.9482f, 112.9073f, 26.0056f, + 55.9483f, -14.6255f, -33.5049f, -127.3506f, + 70.1847f, -12.4499f, 7.3368f, -8.8635f, + 10.1728f, 65.7077f, 45.2101f, -90.9790f, + -12.5750f, -10.0652f, 45.9762f, -30.2995f, + 1.2805f, -3.2898f, -17.5766f, -44.9828f, + 22.1316f, -84.0894f, -21.1065f, -32.5923f, + -81.6581f, 43.6873f, -8.6894f, -65.0775f, + -35.4129f, -58.9663f, 65.8078f, -102.2045f +}; + +/*-------------------------------------------------------------------* + * AMR-WB ISF codebook - 36bits, 2 stages, 1st stage common with the + * 46bit codebook,3 splits in the 2nd stage + * + * codebook vector dimension number of vectors + * ~~~~~~~~ ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~ + * 2_1 5 128 + * 2_2 4 128 + * 2_3 7 64 + *-------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------* + * 2nd stage, 1st split: ISF0 to ISF4 + *-------------------------------------------------------------------*/ + +const float dico21_isf_36b[] = +{ + -20.3147f, -37.6762f, 82.8575f, 122.9161f, -28.4468f, + 31.9756f, -79.5400f, 141.6557f, 53.2923f, -77.0688f, + -49.3360f, -129.1711f, 71.5448f, 85.1944f, 55.7117f, + -19.1147f, -16.1797f, 217.6729f, 89.8943f, 28.1868f, + 0.9668f, -28.5091f, 63.7145f, 147.3305f, 86.3104f, + 52.0605f, 43.3415f, 108.6263f, 83.9071f, -42.8628f, + -39.7734f, -7.6796f, 110.7755f, 44.0677f, 106.4663f, + 32.7239f, 124.4301f, 113.4192f, 7.2217f, 33.0503f, + -9.5746f, -1.9619f, 48.6607f, 51.4268f, -79.8193f, + -14.9729f, -2.0174f, 111.5604f, -3.5774f, -139.2041f, + -54.5000f, -100.1092f, 35.8796f, 45.5500f, -73.7805f, + -56.2694f, 74.4424f, 122.2707f, 20.1155f, -38.3887f, + 65.2094f, -3.9808f, 17.2638f, 96.6362f, 14.0115f, + 148.8982f, 77.1199f, 93.1280f, 28.7596f, 2.2577f, + 14.8324f, -159.4414f, 11.4260f, -1.0211f, -33.2422f, + 35.9112f, 103.8106f, 61.4044f, -9.7034f, -78.2548f, + 62.7658f, -47.4034f, 27.3267f, 32.6865f, -54.7569f, + -6.2693f, -33.7779f, 43.5591f, -36.6678f, -73.8111f, + -104.9376f, -105.4944f, 137.0911f, 41.7979f, -9.4558f, + -26.6750f, -26.3288f, 192.3279f, -40.3915f, -60.3539f, + -20.5168f, -51.3274f, 24.2191f, 47.5655f, 3.7810f, + 52.7448f, 32.7149f, 110.3630f, -21.5464f, -46.7397f, + -4.6471f, -85.4498f, 129.3530f, -31.6973f, 65.0658f, + 85.9795f, -53.2356f, 57.2992f, -67.2997f, -16.4516f, + 54.7607f, -37.1454f, -42.4738f, -34.5633f, -75.7294f, + 0.0517f, -0.6519f, -1.3703f, -12.9917f, -148.9960f, + -25.8564f, -84.6818f, 59.5151f, -72.5006f, -156.8837f, + 95.5045f, 42.2665f, 60.9475f, -54.5273f, -154.2295f, + 44.2810f, -53.2856f, -76.4082f, 42.9736f, -9.5286f, + 83.7851f, 46.2184f, 4.1979f, -25.1575f, -51.0520f, + -43.1590f, -111.8518f, -2.3420f, -129.5042f, 6.3083f, + 36.5568f, 37.9981f, 30.8304f, -113.4959f, -79.9345f, + -1.8493f, -15.3605f, -7.7093f, 98.5986f, -37.6177f, + 29.8557f, 67.8956f, 39.3578f, 63.5122f, 23.6349f, + -27.0502f, -93.1902f, -21.6230f, 155.8476f, 2.5165f, + -44.7515f, 124.6855f, 64.1401f, 107.4525f, 76.4296f, + -5.6913f, 14.2025f, -18.3757f, 129.1303f, 47.2448f, + 88.4045f, 81.8179f, 106.0131f, 126.8375f, 71.9790f, + 5.1288f, -31.2676f, -85.3474f, 183.8293f, 137.8851f, + 112.3553f, 147.7620f, 6.3634f, -19.8307f, 97.9225f, + 68.1479f, 45.1480f, 20.4456f, 58.0360f, -109.0384f, + 91.7441f, 107.7617f, 15.1212f, 47.0576f, -18.7769f, + 0.0359f, -42.2360f, -42.2471f, 94.1364f, -132.5071f, + -36.3673f, 208.5491f, 17.4150f, 13.0281f, -33.9693f, + 75.8679f, 58.1435f, -27.7181f, 158.0312f, -17.2012f, + 159.6027f, 144.6236f, 31.6370f, -72.6323f, -59.9622f, + 9.6094f, -39.8213f, -175.1189f, 48.5059f, -67.6102f, + 8.4503f, 159.5329f, -43.0075f, -121.1605f, -83.4178f, + -10.0988f, 8.8687f, -32.4219f, 44.4166f, 5.5756f, + -42.8299f, 63.9306f, 20.2856f, 86.9213f, -32.1874f, + 14.3835f, -9.6605f, -102.7732f, 119.7146f, -5.8143f, + -181.8677f, 162.2914f, 114.1354f, 64.3820f, -7.2207f, + 11.2529f, -7.2901f, -66.7670f, 60.6365f, 71.2140f, + 69.9911f, 56.0744f, -10.7183f, 90.0489f, 100.9538f, + -40.2531f, -96.6451f, -154.5512f, 92.9078f, 43.9867f, + 146.6528f, -60.2643f, -42.7063f, -1.4891f, 60.9280f, + 38.2143f, 33.0628f, -113.9071f, -1.8860f, -48.5082f, + 45.4740f, 54.2829f, -45.4768f, -38.2865f, -114.7585f, + -5.4061f, -32.4176f, -108.6457f, -45.8426f, -147.6796f, + 41.4813f, 12.9066f, -41.5456f, -134.2382f, -189.2112f, + 46.4330f, 6.8074f, -160.9846f, 53.8969f, 64.9889f, + 149.8519f, 39.6080f, -79.5860f, 34.3934f, -61.0983f, + -47.2568f, -110.8652f, -117.2089f, -0.3717f, -64.7306f, + 109.4393f, 12.8368f, -59.4424f, -122.1797f, -31.4694f, + -14.4126f, 8.5189f, 89.4622f, 59.7035f, 14.3509f, + -23.3690f, -32.3486f, 92.0827f, -3.3169f, -16.0022f, + -66.1460f, -89.0215f, 49.1022f, -7.9295f, 141.6034f, + -91.8393f, 6.6528f, 142.3305f, -60.9383f, 61.1140f, + -9.9035f, -11.7998f, 27.9396f, 56.3528f, 60.7524f, + 59.7717f, -10.3224f, 100.1088f, 37.9471f, 56.4210f, + -8.0706f, -14.3273f, 18.7969f, -25.3479f, 97.6871f, + 24.5711f, 30.0075f, 106.4596f, -49.8085f, 48.5911f, + -50.4430f, -10.2232f, 15.4334f, 3.6211f, -45.0851f, + -2.3100f, 32.1923f, 14.7250f, -35.3260f, -71.2667f, + -131.2863f, -5.1029f, 11.0382f, 61.7451f, 35.4884f, + -11.6345f, 94.0117f, 53.4418f, -66.3264f, -6.6649f, + 57.0155f, 5.4850f, -4.4053f, 12.7554f, 23.6955f, + 74.8564f, 77.0331f, 21.2315f, -32.6182f, 33.2036f, + 9.1670f, -78.1914f, -30.2862f, -11.1652f, 54.5347f, + 47.7388f, 92.4139f, 41.3020f, -133.3741f, 53.0528f, + -22.2909f, -55.2830f, -33.2798f, -6.2896f, -28.8257f, + -23.1116f, -35.0033f, -3.2927f, -72.9685f, -7.7727f, + -82.3073f, -104.1028f, 84.5118f, -69.8221f, -43.1637f, + -19.5349f, -2.7976f, 85.8117f, -104.2825f, -27.2739f, + -22.1902f, -16.4648f, -6.6730f, -5.7920f, 27.7237f, + 12.5658f, 8.3566f, 24.7755f, -53.6096f, 12.7618f, + -53.5741f, -68.1802f, 40.6279f, -26.4454f, 38.0614f, + -26.1757f, -16.7503f, 52.0974f, -117.6298f, 86.4284f, + -45.3502f, -78.0491f, -31.6007f, -35.9389f, -106.1265f, + -24.8954f, -15.9989f, -21.2401f, -95.2454f, -86.1251f, + -112.2460f, -94.4001f, -19.4652f, -33.9923f, -34.6433f, + -95.7000f, 92.3440f, 39.8654f, -64.8912f, -115.0483f, + 25.8969f, 9.4794f, -63.2644f, -27.6289f, 36.9308f, + 25.6901f, 52.9741f, -35.3425f, -86.0458f, -14.2567f, + -38.4101f, -62.7105f, -86.5748f, -73.4519f, 11.4446f, + -7.0262f, 6.9787f, -7.4983f, -161.9427f, 3.4520f, + 19.1677f, 23.8207f, 38.9733f, 15.3764f, -21.7743f, + -43.1688f, 31.9400f, 52.7685f, -11.9674f, 20.1452f, + -35.0128f, -59.7929f, -36.1783f, 73.7702f, 71.2205f, + -83.5945f, 115.1128f, 46.5742f, -28.7420f, 110.8292f, + 0.6347f, 53.5489f, 14.3686f, 18.4025f, 71.1819f, + 35.9728f, 45.7217f, 71.9726f, -20.7319f, 145.8423f, + -8.1019f, -5.6290f, -13.8278f, 53.1928f, 152.8343f, + 57.0881f, 50.3240f, -64.1728f, -11.0774f, 129.9089f, + 36.0925f, 31.0887f, -32.6698f, 39.1693f, -52.3060f, + -3.1405f, 84.8560f, -12.4226f, 1.0655f, -18.3673f, + -58.9719f, 98.0129f, -83.8334f, 55.3139f, 35.7679f, + -87.3652f, 121.2513f, -67.0447f, -107.5562f, 38.2622f, + 62.0513f, 60.4638f, -69.1208f, 43.6854f, 20.7579f, + 79.9694f, 10.7071f, 3.2196f, -93.6621f, 75.1450f, + 66.1122f, 46.9324f, -124.5950f, -78.3322f, 41.3915f, + 4.3229f, 13.8757f, -33.6575f, -92.7601f, 177.5551f, + -42.5067f, -60.2164f, -63.5331f, 67.8862f, -21.5990f, + -14.9811f, 12.6046f, -39.5598f, -30.2755f, -22.9980f, + -80.2668f, -125.5028f, -37.7023f, 27.0213f, 31.0364f, + -121.0989f, 17.0095f, 6.9604f, -72.1639f, 13.2205f, + -45.0105f, -7.6587f, -57.9626f, -15.4159f, 79.2983f, + -11.3128f, 60.2083f, -11.6157f, -61.5281f, 64.7932f, + -17.6502f, -51.3289f, -123.9766f, -9.4275f, 141.7024f, + -64.4806f, -80.0931f, -43.9064f, -86.7513f, 103.4672f, + -12.6910f, -17.1597f, -58.5736f, 21.2452f, -75.2569f, + -2.3195f, -14.7279f, -99.6098f, -65.8753f, -44.8940f, + -103.7556f, 33.9613f, -73.7263f, -13.9038f, -66.1526f, + -23.2670f, -33.9743f, -103.9167f, -170.2949f, -66.2644f, + -26.4354f, -31.7233f, -108.7190f, 9.2282f, 14.7962f, + -9.0340f, -7.5327f, -60.7032f, -100.1385f, 55.1481f, + -23.7530f, -88.2969f, -220.5980f, -68.4569f, 27.6805f, + 3.3643f, -11.1758f, -92.5898f, -201.1381f, 102.8789f +}; + +/*-------------------------------------------------------------------* + * 2nd stage, 2nd split: ISF5 to ISF8 + *-------------------------------------------------------------------*/ + +const float dico22_isf_36b[] = +{ + -116.4826f, -2.3267f, 37.0276f, 11.9585f, + -83.2536f, -34.0855f, -47.5833f, 101.8900f, + 1.6666f, -19.3089f, 81.2133f, 5.5915f, + -50.2199f, -43.0204f, 11.8773f, 45.9389f, + -83.6736f, 100.7533f, 42.9626f, -91.7069f, + -15.8879f, -6.8432f, -49.2481f, 46.8567f, + 40.2748f, 25.3026f, 49.6150f, -14.6042f, + 49.1020f, -13.9172f, -9.5624f, 9.9442f, + -53.7549f, -26.0755f, -108.5515f, -72.7670f, + -64.1594f, -75.7696f, -78.4742f, 30.5700f, + -82.2540f, -34.1100f, -20.0480f, -86.1655f, + -68.0474f, -31.0203f, -36.5615f, -15.3976f, + 8.8102f, -2.3252f, -61.3614f, -93.8460f, + 8.4465f, -43.1451f, -59.6402f, -26.4485f, + 57.8873f, -1.8283f, -0.9150f, -58.1355f, + -0.3760f, -52.6396f, -15.1757f, -69.7872f, + 26.6552f, 140.6710f, -45.5320f, -5.9904f, + 53.5205f, 18.1777f, -108.7393f, 57.1700f, + 53.1281f, 101.4898f, 52.8254f, 25.2450f, + 23.9310f, 45.2712f, -17.5932f, 37.8318f, + 90.1549f, 147.8806f, 33.8829f, -46.8215f, + 132.2255f, 69.0079f, -106.1068f, 1.3402f, + 103.9284f, 60.8167f, 10.9874f, -26.8688f, + 101.6619f, 32.7808f, -33.2101f, 33.7802f, + -103.9522f, 60.0893f, -100.1459f, -71.1324f, + -6.7456f, -25.3835f, -118.9063f, -2.2439f, + -15.7859f, 68.4583f, -59.0835f, -70.2552f, + -10.4160f, 10.4323f, -34.1781f, -24.5999f, + 47.1747f, 44.4596f, -64.8288f, -183.2536f, + 62.0332f, -25.7788f, -126.3596f, -90.0926f, + 83.7341f, 59.4975f, -55.2472f, -82.6595f, + 53.3482f, 14.1273f, -71.7379f, -20.0471f, + -110.1113f, -92.4130f, 15.5809f, 3.7302f, + -18.8013f, -91.7902f, -14.6105f, 98.1369f, + -21.2096f, -126.2513f, 53.1438f, 11.3308f, + -34.3197f, -67.9178f, 83.0592f, 77.2733f, + -152.4262f, 38.6895f, -24.6967f, -146.6594f, + 41.7355f, -66.1454f, -64.2312f, 165.7005f, + 27.0772f, -43.2220f, 54.9943f, -65.1872f, + 28.8899f, -50.2606f, 25.5035f, 56.2652f, + -137.7163f, -80.7691f, -80.0014f, -42.7037f, + -62.3651f, -150.7820f, -138.8149f, 38.1900f, + -68.7802f, -192.5785f, -7.8749f, -55.9578f, + -98.5983f, -168.6083f, -0.7398f, 84.2329f, + -35.1656f, -67.9774f, -65.6374f, -160.6224f, + 4.9446f, -110.8514f, -89.3759f, -62.4133f, + -34.1288f, -108.8451f, 13.3702f, -98.1466f, + -29.4614f, -102.8405f, -22.8325f, -16.4528f, + 163.9105f, 20.5337f, -82.4577f, -139.6505f, + 149.8660f, -13.6016f, -146.1693f, 154.5116f, + 26.6673f, -89.2330f, 126.1283f, -0.6475f, + 65.0738f, -119.9143f, 75.1351f, 75.9130f, + 179.3039f, 128.5647f, -1.9070f, -129.8349f, + 146.4228f, 30.7058f, -2.7357f, 122.1955f, + 110.1199f, -48.4108f, 78.0568f, -35.8715f, + 105.8916f, -63.1848f, -27.3019f, 70.1234f, + -61.4940f, -116.2433f, -200.7709f, -120.8167f, + 22.5673f, -63.6047f, -213.1464f, 7.0661f, + 48.3577f, -141.9964f, 65.3628f, -93.1012f, + 32.5991f, -160.4748f, -45.5903f, 37.6377f, + 54.6730f, -43.7561f, -151.6335f, -243.7797f, + 101.1397f, -52.0073f, -123.8756f, 16.0909f, + 63.7439f, -50.8957f, -25.0308f, -130.5887f, + 88.2969f, -64.3814f, -48.5324f, -43.0123f, + -181.9705f, -24.0096f, 2.3863f, 89.5185f, + -59.5915f, 80.1714f, -56.6992f, 94.5562f, + -62.1659f, 18.9433f, 76.0160f, 57.8553f, + -22.4665f, 10.7743f, 12.0918f, 108.9830f, + -118.1671f, 72.3971f, 109.1443f, -1.3839f, + -23.8459f, 76.9232f, 22.9444f, 33.4435f, + -44.5975f, 47.9554f, 65.6020f, -20.3018f, + 13.6440f, 14.2271f, 38.9794f, 49.0774f, + -159.0490f, 40.0263f, -30.2347f, -15.6526f, + -132.0447f, -0.4802f, -133.5965f, 61.0673f, + -69.7882f, 40.8409f, -13.3128f, -38.0654f, + -72.3667f, 32.7089f, -13.7936f, 42.2054f, + -51.7645f, 41.9187f, -35.3954f, -139.3463f, + -70.4106f, 21.2248f, -89.5260f, 9.2659f, + -17.3511f, 18.5094f, 18.3073f, -71.0465f, + -25.6477f, 4.9120f, 17.7504f, 1.3904f, + -132.5788f, 97.9003f, 25.0501f, 88.4524f, + -16.3421f, 39.3618f, -136.5657f, 107.5423f, + -38.7664f, 155.3425f, 55.5880f, 47.1198f, + 43.2628f, 4.6910f, -39.9914f, 101.5498f, + 0.0830f, 197.2389f, 101.6377f, -36.9070f, + 62.8279f, 111.5018f, -37.6259f, 87.5036f, + -1.4618f, 80.2742f, 122.5196f, 12.8147f, + 65.1409f, 54.2334f, 34.3093f, 79.7332f, + -91.6271f, 123.5048f, -23.6092f, -9.5877f, + -3.2208f, -58.6010f, -121.8443f, 78.4266f, + -14.0112f, 114.0430f, 23.9902f, -40.4777f, + -15.4729f, 68.1635f, -63.4068f, 16.5519f, + -8.1780f, 157.1093f, -11.2800f, -137.0649f, + 8.0606f, 59.4657f, -140.5838f, -36.3320f, + 22.2676f, 74.5499f, 82.8755f, -76.6792f, + 29.5054f, 61.7793f, -8.0867f, -27.0956f, + -128.1797f, -72.1649f, 129.2723f, 46.4323f, + -20.7709f, 111.3353f, 22.0263f, 131.4695f, + -41.9162f, -9.2182f, 158.1064f, 11.2798f, + -7.1545f, 53.6140f, 106.2812f, 108.0610f, + -99.5471f, 8.6443f, 67.7713f, -74.7187f, + 115.0857f, 125.6656f, 126.8208f, 118.1528f, + 8.3489f, -10.6246f, 129.8214f, -69.4937f, + 46.4587f, 5.2711f, 105.7244f, 50.4485f, + -177.6754f, -70.1548f, 45.4547f, -74.5236f, + -88.7724f, 24.0424f, -57.8465f, 204.7888f, + -68.8890f, -112.1224f, 110.3182f, -61.1447f, + -94.7905f, 5.0186f, 77.6790f, 167.9779f, + -23.0125f, -19.1513f, 44.8958f, -142.4394f, + 28.0225f, -67.2659f, -53.6584f, 36.2990f, + -54.0239f, -49.3550f, 55.1522f, -32.8946f, + 2.0792f, -48.4861f, 14.9542f, -7.9957f, + -100.8337f, 121.3744f, 234.8044f, 83.3187f, + 36.5393f, 50.8425f, -23.7400f, 196.1698f, + -0.3059f, -61.1762f, 189.5078f, 122.4017f, + 57.0232f, -28.8934f, 61.7134f, 134.6930f, + 107.9555f, 52.8736f, 109.5032f, -22.1311f, + 191.2912f, 98.4213f, 38.7853f, 16.9729f, + 104.1509f, -28.9315f, 167.6925f, 40.9011f, + 108.7356f, -8.7976f, 46.5837f, 36.6080f, + -211.7768f, 190.5028f, 100.4753f, -45.0833f, + -32.7791f, -95.3684f, -171.2339f, 186.7766f, + -44.0395f, -212.9286f, 151.2602f, 39.5958f, + -37.2152f, -119.5092f, 43.4460f, 194.5965f, + 37.2023f, 64.8673f, 8.5289f, -117.5366f, + 163.8890f, -5.9760f, -22.5312f, -30.3817f, + 105.4272f, 11.3735f, 47.6228f, -110.1422f, + 62.3479f, -93.6059f, 19.4353f, -14.9112f +}; + +/*-------------------------------------------------------------------* + * 2nd stage, 3rd split: ISF9 to ISF15 + *-------------------------------------------------------------------*/ + +const float dico23_isf_36b[] = +{ + 31.6601f, -7.0021f, 26.7324f, -10.6919f, -47.7440f, -109.3316f, -1.6793f, + 17.6152f, -69.1639f, 81.7745f, -11.6557f, -53.0002f, -28.8501f, 51.3155f, + -17.3392f, 39.6296f, -29.4208f, -34.2716f, -18.7475f, -53.4279f, -21.0682f, + -95.6211f, -11.0108f, 24.5639f, -6.9345f, -43.8606f, -40.3930f, 22.5841f, + -30.9469f, -2.2484f, 85.8968f, -25.2118f, 44.4649f, -13.7549f, -19.6283f, + 42.5807f, -25.3893f, 55.9790f, -44.6039f, 50.3451f, 29.5180f, 49.0040f, + 64.7422f, 35.0105f, -24.0120f, -94.6131f, 72.4785f, -29.0560f, -16.8213f, + -17.7762f, -36.1097f, 19.1423f, -88.8131f, 9.4121f, -60.6212f, 15.2182f, + 26.1194f, 33.0214f, 38.6243f, -16.4898f, 20.5108f, -71.7754f, -109.7775f, + 55.6133f, -47.5797f, 0.0746f, 8.1716f, -55.6639f, -5.8260f, -6.7666f, + 86.9148f, 36.0665f, -8.0422f, -18.6522f, -31.9936f, -5.4779f, -65.2340f, + 20.0656f, -14.5303f, -94.7449f, -11.7982f, -35.2031f, 6.9138f, -22.0461f, + 20.9060f, 41.0458f, 29.0299f, 33.4933f, 27.0675f, 5.1646f, -39.4529f, + 76.7175f, 28.2216f, -34.8562f, 16.7304f, 25.2291f, 7.4912f, 15.3906f, + 47.1053f, 13.3625f, 50.9902f, -31.9588f, 9.8596f, 83.1329f, -61.0081f, + 39.4355f, -39.6936f, -53.1235f, -8.1282f, 22.3882f, 83.7131f, 8.6440f, + 13.9302f, -48.4179f, 80.1925f, 79.6573f, 22.8321f, -61.0888f, -32.5848f, + 32.2601f, -45.5857f, 53.4300f, 53.4773f, 33.0895f, 45.4420f, 17.2865f, + -36.0406f, -57.6566f, -26.6841f, 4.2674f, -39.8452f, -76.9236f, -85.9930f, + -29.8696f, -72.1261f, -22.6802f, 51.6689f, -10.3407f, -71.6716f, 33.3209f, + -2.6190f, -11.9459f, -0.7138f, 9.1651f, 80.0695f, -58.7987f, 3.7833f, + -10.6521f, -14.2910f, -1.7854f, -6.9002f, 114.1547f, 51.0851f, 0.4936f, + 45.5988f, -65.6262f, 3.5076f, -36.3037f, 31.3412f, -22.8916f, -48.6823f, + -71.1623f, -95.4642f, 38.3287f, -9.4939f, 52.9002f, -8.4421f, 36.7283f, + 86.2675f, 37.9505f, 41.2317f, 16.4269f, 16.7260f, -62.6682f, 32.6168f, + 9.9181f, -25.0994f, -8.3770f, 2.2985f, 5.3157f, -6.0428f, 60.1555f, + 49.0247f, 6.0545f, -54.7919f, 58.6261f, -3.9732f, -80.9565f, -44.3777f, + 30.6734f, -24.5101f, -82.4513f, -27.4901f, -10.8146f, -84.7650f, 64.6334f, + 18.0553f, 14.7350f, -8.7675f, 109.6707f, 51.4393f, -24.1075f, 42.7732f, + 43.6601f, 21.1278f, -43.7223f, -36.3814f, 81.3688f, 10.3561f, 115.5857f, + 44.7304f, 4.0203f, -57.4008f, 16.1462f, 84.4927f, 16.5958f, -107.7931f, + 19.3887f, -44.8683f, -99.3061f, 65.1051f, 45.6203f, -0.6984f, 23.6828f, + 6.4828f, 56.2769f, 13.3073f, -28.0424f, -72.7066f, -58.5212f, 106.1769f, + -11.1674f, -25.7849f, -34.9574f, -36.9812f, -58.1843f, 50.2182f, 98.0044f, + 47.6759f, 0.1786f, -19.4605f, -91.2611f, -35.5267f, 13.8815f, 10.2127f, + -41.1350f, -39.8329f, -34.1829f, -47.4437f, -91.9939f, -2.6788f, -4.2821f, + -79.6033f, 42.6213f, 2.0653f, -74.4526f, 41.0602f, -5.7905f, 63.6539f, + -31.4071f, 12.4383f, -9.2647f, -81.5461f, 16.0430f, 114.6936f, 27.3863f, + -41.2719f, -36.6253f, -79.4997f, -46.2467f, 46.8034f, -19.4146f, -14.6126f, + -31.9554f, -93.9975f, 17.8233f, -51.0152f, -11.4389f, 58.4455f, -21.6241f, + 12.9670f, 60.7166f, 46.9564f, -34.6928f, -3.1553f, 2.7762f, 24.2978f, + 83.1108f, 31.8670f, 23.6533f, 6.8663f, -63.0785f, 56.1031f, 59.2073f, + 11.6877f, 51.3190f, 25.3083f, -33.9761f, -99.5482f, -6.6294f, -41.7488f, + -3.1041f, 33.3329f, -24.8851f, 20.0947f, -63.3399f, 87.2565f, -20.6208f, + -52.2549f, 102.0059f, 26.9280f, -22.0208f, 85.2782f, 28.3108f, -43.2782f, + 0.8584f, 60.5987f, -44.2357f, -33.9700f, 19.1247f, 33.1631f, -10.8275f, + -63.5371f, 16.2471f, -0.2828f, -76.6458f, 2.8322f, 15.2373f, -95.8412f, + 5.5912f, -53.4989f, -30.8518f, 4.1365f, -62.3116f, 79.0018f, -114.5611f, + -36.8596f, 12.7812f, 81.1609f, 39.2434f, 21.9162f, -17.2064f, 127.1804f, + -30.4279f, -15.8549f, 90.5057f, 4.9324f, -55.6202f, 88.7264f, 31.2457f, + -6.4338f, -33.9992f, 78.4675f, 12.7460f, -51.8920f, 5.7002f, -71.3454f, + -22.6305f, -75.0886f, -18.4430f, 71.6854f, -49.9613f, 51.9112f, 38.5919f, + -80.1990f, 4.2373f, -60.6613f, 30.4453f, 20.4006f, 28.0162f, 55.1546f, + -96.2887f, 10.3433f, 38.5883f, 59.1444f, 23.2247f, 45.0000f, -24.9305f, + -30.9055f, -18.2692f, -6.1201f, -5.6460f, 2.1550f, 18.2502f, -16.8166f, + -28.0966f, -69.3654f, -10.5762f, 63.4193f, 43.8444f, 16.6643f, -67.9380f, + -68.3269f, 93.1501f, 72.8030f, 27.6125f, -21.1484f, -73.4926f, -29.7929f, + -88.0045f, 91.0304f, 15.1885f, -15.1144f, -61.6391f, 47.5526f, 17.2017f, + -10.0973f, 16.8435f, 32.7608f, 50.6231f, -36.3173f, -19.8196f, 8.7833f, + 1.1920f, 35.7643f, -58.4480f, 53.1925f, -71.1458f, -22.3426f, 37.8118f, + -51.2779f, 69.9477f, -30.3236f, 31.2621f, 35.5419f, -64.6025f, 35.1224f, + -0.6572f, 57.9364f, 5.6749f, 50.6782f, 25.3456f, 68.4492f, 45.6955f, + -53.8176f, 44.6419f, -53.4407f, 51.5645f, 1.3456f, -4.0462f, -72.5604f, + 54.6610f, -1.6150f, -14.3009f, 99.1775f, -24.2467f, 36.0557f, -42.7052f +}; + +/*-------------------------------------------------------------------* + * AMR-WB ISF codebook for SID - 28bits, 1 stage, 5 splits + * + * codebook vector dimension number of vectors + * ~~~~~~~~ ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~ + * 1 2 64 + * 2 3 64 + * 3 3 64 + * 4 4 32 + * 5 4 32 + *-------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------* + * 1st stage, 1st split: ISF0 to ISF1 + *-------------------------------------------------------------------*/ + +const float dico1_ns_28b[64*2] = +{ + -105.0619f, -262.8448f, + -86.6322f, -209.7320f, + -91.1931f, -168.0481f, + -53.8753f, -176.1473f, + -82.7923f, -129.2635f, + -75.0845f, -93.9859f, + -33.9476f, -90.3333f, + -74.4463f, -50.0451f, + -27.3422f, -41.3458f, + -64.0658f, -2.5361f, + 28.8179f, -70.0786f, + 10.5059f, -12.8463f, + -39.9581f, 28.7359f, + -63.4034f, 44.7503f, + -36.8732f, 67.0368f, + -2.3563f, 50.6058f, + -55.9412f, 91.2822f, + 5.5577f, 85.1171f, + -25.2586f, 105.6009f, + 34.3216f, 71.1726f, + -48.3043f, 133.1605f, + -17.0366f, 148.8321f, + 14.8305f, 130.6908f, + 45.5592f, 106.8464f, + -43.7865f, 177.4889f, + 28.9675f, 168.2081f, + -1.7812f, 190.4731f, + 68.4806f, 149.8876f, + -32.5396f, 218.9960f, + 47.8438f, 206.6539f, + 8.1960f, 234.8430f, + 89.3668f, 188.0221f, + 90.4035f, 118.3064f, + 88.4263f, 237.5410f, + 117.3136f, 145.4498f, + 82.0645f, 73.1093f, + 119.3943f, 103.4796f, + 128.2321f, 184.8528f, + 149.1563f, 129.2199f, + 144.9058f, 51.5776f, + 54.4305f, 22.6608f, + 142.5451f, 8.2812f, + 97.4966f, -31.8767f, + 173.0963f, 84.9898f, + 188.5170f, 42.9719f, + 166.5772f, 162.2136f, + 226.1740f, 86.5496f, + 202.2992f, 129.9512f, + 223.9365f, 175.1483f, + 177.6235f, 206.6174f, + 267.4435f, 128.4469f, + 129.8694f, 226.5438f, + 232.5047f, 231.7147f, + 182.8960f, 252.1132f, + 297.7026f, 201.9668f, + 127.2108f, 277.0716f, + 189.5906f, 309.6084f, + 50.8926f, 267.2207f, + 262.1367f, 287.8791f, + 138.4480f, 342.2196f, + 34.3804f, 314.8025f, + -25.4771f, 275.9066f, + -13.5804f, 397.0122f, + 103.9035f, 438.8237f +}; + +/*-------------------------------------------------------------------* + * 1st stage, 2ndt split: ISF2 to ISF4 + *-------------------------------------------------------------------*/ + +const float dico2_ns_28b[64*3] = +{ + -322.0252f, -345.3659f, -370.7835f, + -314.5226f, -178.1928f, -163.4712f, + -172.6074f, -171.2812f, -211.3224f, + -84.6538f, -225.6710f, -309.6982f, + -65.7865f, -173.3148f, -227.1618f, + -112.2154f, -192.0593f, -106.9376f, + -215.4487f, -115.9810f, -117.3159f, + -63.6069f, -129.9179f, -139.6890f, + -144.6460f, -90.4563f, -90.4457f, + -68.4568f, -140.0307f, -62.0772f, + -148.8729f, -8.2807f, -139.6018f, + -71.8488f, -61.9658f, -63.2677f, + -20.5518f, -74.4279f, -109.2530f, + 7.0237f, -104.2936f, -83.9866f, + -53.7369f, 23.9918f, -110.5212f, + 27.5927f, -37.1603f, -114.8537f, + 5.1437f, -60.8316f, -213.2375f, + -0.0302f, -32.5161f, -30.9893f, + 17.0532f, 37.8947f, -123.4512f, + 69.4656f, -20.4364f, -83.2673f, + 86.8486f, -101.9140f, -164.6497f, + 92.7595f, -46.0582f, -17.0665f, + 55.0807f, 56.5797f, -51.6089f, + 141.9268f, 31.5952f, -111.9348f, + 83.1350f, 25.3995f, 13.2634f, + -41.6305f, 36.7624f, -1.8806f, + 35.5619f, -11.1360f, 49.0468f, + -138.6944f, 20.1165f, -16.0470f, + -85.7227f, -29.5173f, 56.5419f, + -24.5306f, 39.2035f, 95.3233f, + -280.8913f, 17.3520f, 10.4723f, + -223.4287f, -48.5814f, 60.3781f, + -165.0790f, 52.0898f, 122.9863f, + -358.1462f, 27.5800f, 87.6394f, + -104.6460f, 124.2969f, 51.2676f, + -36.4609f, -74.1586f, 163.9110f, + -38.0255f, 47.6372f, 191.7725f, + -30.7896f, 123.7246f, 138.8302f, + 50.7064f, 39.0454f, 126.9589f, + 33.4334f, -114.5499f, 82.0810f, + 52.0289f, 100.6551f, 62.9260f, + 68.9398f, -28.6776f, 181.7511f, + 76.3353f, 117.0400f, 150.0834f, + 135.9951f, 8.5581f, 86.5077f, + 146.9219f, 71.3024f, 159.6375f, + 147.3144f, 111.7858f, 78.8838f, + 94.6612f, 83.2958f, 257.4856f, + 100.5727f, 220.5308f, 96.9196f, + 134.4751f, 159.3021f, -29.6067f, + 158.3509f, 171.9108f, 198.9399f, + 238.9283f, 150.3837f, 148.0492f, + 209.2346f, 237.2747f, 84.4977f, + -21.9723f, 227.3437f, 75.1847f, + 39.1823f, 202.0239f, 221.5619f, + -142.6753f, 174.8218f, 173.9311f, + 284.1931f, 135.5243f, 4.0420f, + 197.3545f, 139.2970f, 296.6173f, + 248.5921f, 227.1523f, 257.1579f, + 130.8344f, 201.7665f, 332.6679f, + 147.8451f, 316.0691f, 223.3704f, + -76.1983f, 342.8470f, 323.9619f, + 206.5931f, 276.1481f, 385.6192f, + 358.4664f, 283.4258f, 153.2502f, + 488.2212f, 389.4155f, 415.1465f +}; + +/*-------------------------------------------------------------------* + * 1st stage, 3rd split: ISF5 to ISF7 + *-------------------------------------------------------------------*/ + +const float dico3_ns_28b[64*3] = +{ + -314.4522f, -327.3454f, -302.2017f, + -203.9117f, -244.9068f, -323.6309f, + -186.2536f, -189.6962f, -235.4297f, + -115.3995f, -187.7246f, -247.4612f, + -142.8871f, -150.1942f, -153.3509f, + -72.7072f, -161.6552f, -154.8560f, + -92.6058f, -153.8863f, -41.3953f, + -98.5994f, -78.7129f, -107.5332f, + -23.9335f, -69.1898f, -172.7805f, + -32.7960f, -77.3107f, -77.6193f, + -69.7610f, -48.7327f, -12.2728f, + -28.2008f, -18.3660f, -63.7045f, + -116.3960f, -85.9584f, 84.0164f, + -24.9241f, -65.7832f, 98.1712f, + -51.8131f, 60.9599f, -23.0835f, + -11.5386f, -0.7831f, 49.5084f, + 20.9367f, 25.8838f, -24.0191f, + -91.0503f, 8.0161f, 98.1430f, + 81.8089f, -19.4694f, 12.5661f, + 12.6976f, 75.6776f, 53.0320f, + -45.8943f, -7.2062f, 185.7293f, + 78.8625f, 17.9396f, 120.6767f, + 99.9111f, 72.2135f, 20.5674f, + 13.7143f, 77.9979f, 152.4088f, + 78.0738f, 102.8484f, 94.6295f, + -84.5040f, 118.1050f, 114.7064f, + 50.0596f, 139.6647f, -0.1577f, + 7.5966f, 168.3675f, 112.1363f, + 87.3316f, 174.4695f, 109.2434f, + 143.4298f, 64.6162f, 83.1959f, + 155.2307f, 122.7478f, 124.7551f, + 149.4719f, 147.9446f, 29.2261f, + 108.3426f, 127.0695f, 180.3353f, + 153.8867f, 197.0929f, 130.5922f, + 98.1956f, 38.2729f, -83.1688f, + 175.9048f, 59.9165f, 174.8273f, + 220.7233f, 88.4354f, 29.6527f, + 183.5505f, 149.7702f, 195.9197f, + 248.2375f, 152.2900f, 108.7161f, + 92.6034f, 52.6123f, 242.1773f, + 133.7155f, 156.6441f, 253.6524f, + 129.4868f, 215.2826f, 202.4702f, + 50.8526f, 163.2149f, 231.3041f, + 207.4225f, 119.3517f, 287.7008f, + 284.9414f, 152.0429f, 226.6699f, + 194.1092f, 217.5607f, 272.9373f, + 115.7381f, 149.7147f, 341.2299f, + 110.4872f, 243.8135f, 296.4818f, + 49.2583f, 242.9759f, 185.7527f, + 218.4281f, 232.2570f, 184.3956f, + 149.3219f, 300.8763f, 240.4531f, + 280.7402f, 239.3506f, 291.1599f, + 210.7589f, 249.5308f, 362.4219f, + 201.8519f, 322.7530f, 312.7221f, + 267.0336f, 316.7373f, 236.0985f, + 293.8933f, 307.2101f, 334.8007f, + 364.5740f, 258.0872f, 136.8430f, + 271.0491f, 175.6599f, 414.3537f, + 219.3663f, 355.8581f, 410.6574f, + 321.8781f, 317.4617f, 431.4073f, + 295.9753f, 408.9221f, 344.4007f, + 445.2552f, 358.3636f, 347.1212f, + 405.7584f, 486.9081f, 556.9660f, + 579.1823f, 650.5953f, 732.6415f +}; + +/*-------------------------------------------------------------------* + * 1st stage, 4th split: ISF8 to ISF11 + *-------------------------------------------------------------------*/ + +const float dico4_ns_28b[32*4] = +{ + -303.1361f, -333.7803f, -347.8725f, -359.4826f, + -215.7523f, -238.3714f, -259.0660f, -289.4405f, + -125.2913f, -144.5697f, -186.1030f, -220.5702f, + 107.0201f, -62.5400f, -178.2959f, 78.3558f, + 103.6377f, 26.1626f, -62.5396f, -119.5691f, + -2.9518f, -82.1288f, 30.9020f, 106.1641f, + 63.5315f, 92.0127f, 120.0751f, 120.2205f, + 225.8191f, 123.6829f, 24.8449f, 116.4136f, + -3.5121f, 76.7992f, 133.5771f, 242.3746f, + 133.9970f, 90.5385f, 122.6116f, 242.8362f, + 67.7067f, 58.1366f, 214.2467f, 205.7587f, + 139.2159f, 144.6370f, 188.0780f, 146.8699f, + 52.7259f, 173.3530f, 190.5093f, 217.0651f, + 152.5843f, 183.9790f, 190.4016f, 255.0127f, + 89.0815f, 165.5783f, 224.8295f, 325.9805f, + 164.7109f, 145.4724f, 282.2096f, 266.3416f, + 115.0926f, 262.9259f, 270.8098f, 248.1893f, + 210.4561f, 232.8534f, 230.5395f, 175.4710f, + 185.5563f, 241.3006f, 257.2568f, 319.6433f, + 287.0131f, 201.7823f, 191.6938f, 262.7153f, + 234.9706f, 135.0743f, 100.3842f, 342.4814f, + 244.1460f, 248.1535f, 331.5106f, 281.3059f, + 283.8415f, 319.6996f, 272.8347f, 232.3501f, + 255.2254f, 187.9562f, 269.5668f, 445.0594f, + 318.1439f, 297.7580f, 274.9042f, 354.5264f, + 198.0688f, 291.9682f, 350.7645f, 365.4872f, + 331.2469f, 333.9341f, 361.1275f, 306.5865f, + 252.3140f, 405.2271f, 344.4444f, 310.3618f, + 301.5996f, 329.9839f, 399.8752f, 449.5998f, + 442.5639f, 384.1796f, 319.3500f, 359.8945f, + 367.3365f, 417.2813f, 488.9795f, 508.7549f, + 620.4818f, 690.0919f, 671.0975f, 590.9387f +}; + +/*-------------------------------------------------------------------* + * 1st stage, 5th split: ISF12 to ISF15 + *-------------------------------------------------------------------*/ + +const float dico5_ns_28b[32*4] = +{ + -316.2941f, -343.3920f, -368.9643f, -99.0392f, + 97.0450f, 71.7080f, 262.1754f, 50.0767f, + 112.4468f, 274.7287f, 358.7211f, 38.6232f, + 257.1795f, 217.8952f, 258.6022f, 85.4104f, + 215.6079f, 228.7031f, 355.6118f, 81.4276f, + 218.4167f, 314.1638f, 296.3636f, 46.5526f, + 236.5851f, 302.2603f, 359.7074f, -54.3647f, + 305.5962f, 297.4161f, 292.2765f, 81.3061f, + 295.4005f, 276.4861f, 384.1555f, 21.9038f, + 212.3865f, 337.6641f, 394.4713f, 59.4888f, + 287.8841f, 272.8244f, 385.4754f, 116.6899f, + 301.1416f, 360.9641f, 343.2708f, 40.2882f, + 209.5407f, 306.5670f, 375.3650f, 158.1632f, + 260.4655f, 357.6203f, 312.8495f, 128.1323f, + 288.3843f, 275.2455f, 301.9735f, 171.2988f, + 321.4736f, 340.3829f, 387.3967f, 138.5811f, + 250.1021f, 392.3276f, 410.9932f, 144.0109f, + 282.6727f, 320.9480f, 370.8150f, 233.3823f, + 161.9622f, 255.8086f, 284.8333f, 188.2323f, + 393.9827f, 349.8717f, 309.8297f, 141.6719f, + 354.6675f, 313.7792f, 268.4562f, -9.8681f, + 396.7580f, 327.4283f, 395.0635f, 73.8789f, + 369.8889f, 434.5653f, 367.9579f, 86.8706f, + 356.9169f, 409.7761f, 383.1727f, 205.7493f, + 373.4236f, 385.5478f, 394.8253f, -47.0644f, + 305.1456f, 409.5952f, 437.7072f, 36.1164f, + 460.1152f, 411.4012f, 345.2657f, 18.4203f, + 438.6750f, 413.5906f, 461.8582f, 46.2207f, + 364.6111f, 379.8415f, 498.6693f, 139.3899f, + 433.1401f, 358.6805f, 429.9292f, 196.6537f, + 405.9484f, 502.2995f, 476.5874f, 123.6977f, + 527.5430f, 471.6736f, 394.4862f, 127.2615f +}; + + +const float *lsf_means[2] = { means_wb_31bits_ma_lsf, means_nb_31bits_ma_lsf }; + +const lsp_unw_triplet p16_gamma0_92to1[16] = +{ + { 0.00000f, 1.19764f, -0.59173f }, + { -0.91173f, 1.79182f, -0.80921f }, + { -0.51779f, 1.44703f, -0.81871f }, + { -0.44862f, 1.36777f, -0.75103f }, + { -0.45150f, 1.30719f, -0.74220f }, + { -0.43157f, 1.21326f, -0.68538f }, + { -0.43606f, 1.21317f, -0.69131f }, + { -0.39200f, 1.04941f, -0.58674f }, + { -0.45208f, 1.10009f, -0.59175f }, + { -0.42553f, 0.99725f, -0.49992f }, + { -0.50168f, 1.07575f, -0.51401f }, + { -0.49800f, 1.06563f, -0.50592f }, + { -0.53101f, 1.16372f, -0.58033f }, + { -0.48744f, 1.07596f, -0.52531f }, + { -0.51899f, 1.04998f, -0.49495f }, + { -0.47730f, 0.90959f, 0.00000f } +}; + +const lsp_unw_triplet p16_gamma0_94to1[16] = +{ + { 0.00000f, 0.78925f, -0.38537f }, + { -0.57154f, 1.19486f, -0.54136f }, + { -0.33642f, 0.99096f, -0.56792f }, + { -0.29856f, 0.93785f, -0.51255f }, + { -0.29716f, 0.89303f, -0.50509f }, + { -0.28264f, 0.81530f, -0.46020f }, + { -0.27926f, 0.80997f, -0.46378f }, + { -0.25334f, 0.69596f, -0.38969f }, + { -0.29656f, 0.72916f, -0.38888f }, + { -0.27488f, 0.65949f, -0.32999f }, + { -0.32630f, 0.70913f, -0.33659f }, + { -0.33069f, 0.70668f, -0.33105f }, + { -0.35437f, 0.77582f, -0.38003f }, + { -0.31771f, 0.70752f, -0.34216f }, + { -0.35066f, 0.70177f, -0.31664f }, + { -0.33404f, 0.62528f, 0.00000f } +}; + +const float dico_lsf_abs_8b[256*M] = +{ + 377.3749f, 688.0079f, 1147.3799f, 1461.0438f, 1786.7794f, 2143.6711f, 2522.1946f, 2889.7402f, 3263.6023f, 3628.4624f, 4005.4351f, 4379.4170f, 4783.9556f, 5157.1753f, 5555.1797f, 5926.6816f, + 601.5123f, 1066.8242f, 1384.3585f, 1652.9448f, 1978.3910f, 2311.2676f, 2674.0537f, 3010.3896f, 3360.0623f, 3725.9336f, 4093.3335f, 4470.6431f, 4859.1006f, 5210.4717f, 5598.3716f, 5954.4204f, + 552.5036f, 859.7047f, 1355.2023f, 1624.9041f, 1887.5609f, 2173.1638f, 2540.7429f, 2926.8169f, 3323.2173f, 3680.7197f, 4008.3447f, 4330.8442f, 4692.8228f, 5033.9697f, 5443.3467f, 5875.4497f, + 459.4534f, 793.3189f, 1293.7278f, 1617.3970f, 1920.0642f, 2192.2153f, 2487.5627f, 2772.1514f, 3111.3823f, 3461.2671f, 3867.0176f, 4279.8550f, 4741.0664f, 5141.0181f, 5552.8237f, 5933.6934f, + 327.9834f, 430.4954f, 723.9031f, 1528.6172f, 1763.1125f, 2013.7936f, 2334.2153f, 2569.0334f, 3017.9436f, 3308.0610f, 3591.7820f, 3865.5430f, 4693.5786f, 5286.7646f, 5647.7036f, 5987.2305f, + 455.0753f, 606.0817f, 963.7564f, 1374.9937f, 1536.4897f, 1914.7618f, 2376.9631f, 2580.8184f, 2989.1501f, 3258.8386f, 3485.1460f, 3741.1270f, 4297.4912f, 5207.3779f, 5672.3818f, 5980.5322f, + 434.9507f, 558.8508f, 890.7061f, 1355.7625f, 1552.6155f, 1895.7960f, 2222.5579f, 2502.6079f, 2841.8738f, 3137.5264f, 3367.7336f, 3860.7769f, 4795.2554f, 5090.9370f, 5421.8218f, 5874.4287f, + 281.0164f, 404.5417f, 729.2898f, 997.1851f, 1699.8862f, 1961.3673f, 2255.7202f, 2540.9187f, 2804.4553f, 3057.1843f, 3750.2288f, 4340.9893f, 4716.8647f, 5002.7471f, 5477.2998f, 5965.7402f, + 372.2410f, 505.3570f, 762.3755f, 997.3586f, 1174.4255f, 1986.1741f, 2368.1367f, 2624.1733f, 3194.6084f, 3403.2793f, 3877.7622f, 4425.7676f, 4824.7837f, 5158.1606f, 5532.7466f, 5893.5483f, + 367.3766f, 501.1806f, 824.5358f, 1090.6857f, 1271.9792f, 1527.7137f, 2381.4382f, 2694.4634f, 2964.5359f, 3639.4832f, 3946.4038f, 4254.3916f, 4645.8076f, 5033.5396f, 5373.8735f, 5878.4385f, + 229.4505f, 352.5671f, 701.0831f, 1226.4518f, 1678.3601f, 1895.7949f, 2140.0664f, 2526.5515f, 3080.3391f, 3297.8284f, 3845.3987f, 4427.9785f, 4704.4551f, 4997.4155f, 5434.0698f, 5918.4785f, + 336.3082f, 516.7915f, 881.9847f, 1272.5824f, 1505.1870f, 1880.7520f, 2274.9458f, 2611.0083f, 3126.5256f, 3655.5332f, 4183.3877f, 4668.2993f, 5004.0029f, 5305.3491f, 5650.4985f, 5943.7383f, + 296.0867f, 469.6519f, 956.5997f, 1224.1262f, 1443.0049f, 1727.6880f, 2216.1677f, 2689.3677f, 3060.4456f, 3520.9438f, 3916.6050f, 4343.7954f, 4763.8906f, 5156.0132f, 5553.8115f, 5936.9634f, + 407.1503f, 577.5120f, 839.7361f, 1455.3907f, 1665.2137f, 1935.0054f, 2398.0537f, 2652.2605f, 3111.1831f, 3505.5962f, 3766.7554f, 4204.8730f, 4699.1631f, 4970.8652f, 5295.5962f, 5695.6919f, + 281.0083f, 361.8386f, 950.9102f, 1464.1158f, 1634.7019f, 1965.4950f, 2211.1406f, 2662.1055f, 2846.0122f, 3585.8884f, 4048.7148f, 4358.9150f, 4683.8755f, 5046.0908f, 5400.0859f, 5956.1040f, + 279.1811f, 393.9142f, 876.8306f, 1502.2417f, 1673.0590f, 2288.7161f, 2545.3674f, 3028.9507f, 3517.5840f, 3824.4246f, 4144.8486f, 4481.8140f, 4821.2769f, 5162.3975f, 5542.8560f, 5928.5854f, + 379.7892f, 500.9199f, 725.0223f, 998.7143f, 1179.6127f, 1771.9886f, 2775.4812f, 3136.8457f, 3378.6143f, 3674.0188f, 3946.3604f, 4184.4824f, 4521.5454f, 4934.8940f, 5315.5029f, 5759.7544f, + 317.4339f, 442.2628f, 778.7388f, 1167.8633f, 1356.1576f, 1578.5603f, 1840.1584f, 2870.7527f, 3236.1504f, 3502.7249f, 3876.3696f, 4100.5244f, 4650.2632f, 5235.1890f, 5665.2285f, 5999.0649f, + 350.2696f, 492.2163f, 763.0640f, 1264.7550f, 1515.0244f, 1755.7783f, 2489.3274f, 2898.6252f, 3143.1018f, 3643.0640f, 4035.0657f, 4255.0889f, 4641.7231f, 5138.5107f, 5557.1318f, 5920.2402f, + 301.3833f, 464.9852f, 762.3419f, 1012.2126f, 1803.5172f, 2192.4214f, 2651.6287f, 3013.6697f, 3251.3591f, 3539.4675f, 3946.3433f, 4469.3560f, 4890.7446f, 5200.4878f, 5509.6753f, 5910.2397f, + 253.1752f, 356.8990f, 630.3325f, 1163.1683f, 1528.6230f, 2023.4438f, 2488.6001f, 2745.5627f, 2933.7024f, 3237.4414f, 3976.9258f, 4415.2534f, 4789.9131f, 5194.3423f, 5714.6445f, 6032.4160f, + 265.1815f, 364.7549f, 590.0148f, 805.2595f, 1564.7582f, 2150.6536f, 2365.6501f, 2598.7876f, 2861.5334f, 3514.1265f, 4005.6328f, 4609.3091f, 4955.4478f, 5238.4116f, 5519.5884f, 5890.7925f, + 209.3544f, 313.1497f, 503.2642f, 949.4504f, 1729.7280f, 1912.6814f, 2117.5051f, 2498.6272f, 3284.6587f, 3810.8555f, 4105.0195f, 4349.5151f, 4770.3682f, 5210.2910f, 5585.1533f, 5970.3638f, + 302.3150f, 415.6502f, 684.1018f, 922.3598f, 1489.4418f, 2235.6252f, 2449.9773f, 2800.6938f, 3061.3721f, 3526.1001f, 3905.8174f, 4170.7891f, 4446.4209f, 4907.9937f, 5470.7158f, 5914.7261f, + 264.9068f, 366.4342f, 582.8182f, 790.8568f, 1619.4548f, 2034.0782f, 2337.6724f, 2632.1714f, 2933.2356f, 3430.1858f, 3815.0198f, 4276.3931f, 4748.3149f, 5164.0098f, 5553.3320f, 5974.9092f, + 249.6359f, 361.9234f, 581.9844f, 841.1097f, 1657.5543f, 2184.4114f, 2525.9739f, 2820.0503f, 3120.7190f, 3623.7678f, 4050.5435f, 4434.5742f, 4802.6782f, 5171.8438f, 5575.0068f, 5963.7402f, + 290.1085f, 404.2538f, 664.1223f, 878.2748f, 1237.1085f, 2237.4707f, 2497.5647f, 2957.7786f, 3289.3928f, 3626.5276f, 4190.9243f, 4594.6450f, 4981.7456f, 5283.5513f, 5617.1538f, 5938.3760f, + 182.7846f, 270.3831f, 490.2131f, 1070.2524f, 1674.5724f, 2092.4905f, 2524.1472f, 2929.3523f, 3334.8005f, 3712.0061f, 4101.2896f, 4475.7324f, 4866.1919f, 5231.7559f, 5606.4077f, 5960.9644f, + 286.7701f, 386.1487f, 577.4210f, 764.3087f, 1151.2404f, 2014.4502f, 2399.8547f, 2879.0371f, 3160.2502f, 3450.6274f, 3869.8240f, 4368.3618f, 4816.7861f, 5187.6450f, 5564.7231f, 5962.0386f, + 179.9538f, 266.0682f, 647.9122f, 1380.2810f, 1776.1240f, 2208.4592f, 2590.6843f, 2993.6758f, 3368.2034f, 3753.2156f, 4125.2124f, 4508.6050f, 4878.9932f, 5249.3291f, 5612.5049f, 5965.2134f, + 309.2416f, 434.7111f, 724.6614f, 936.5360f, 1264.9886f, 2272.1338f, 2548.4519f, 2904.0798f, 3313.4990f, 3579.7854f, 3914.5811f, 4297.5938f, 4756.9072f, 5163.2017f, 5592.2822f, 5943.7222f, + 256.9009f, 393.7155f, 769.3966f, 1200.9640f, 1774.4797f, 2307.9629f, 2794.6799f, 3165.9431f, 3507.7952f, 3840.5791f, 4142.8877f, 4453.5078f, 4790.6973f, 5142.6123f, 5530.5977f, 5923.2188f, + 394.1425f, 602.0079f, 934.5173f, 1352.9718f, 1813.9639f, 2172.5435f, 2603.7295f, 2963.9590f, 3335.2344f, 3732.0515f, 4120.0151f, 4487.9668f, 4877.6294f, 5238.9336f, 5596.1479f, 5939.6489f, + 373.0307f, 665.4328f, 1227.4684f, 1524.6017f, 1947.3784f, 2361.6384f, 2778.1921f, 3134.5396f, 3462.3992f, 3752.4592f, 4069.0352f, 4404.2720f, 4782.2241f, 5145.0581f, 5541.9980f, 5932.9136f, + 449.9942f, 814.1862f, 1344.2784f, 1682.7061f, 2086.3599f, 2486.9709f, 2916.1177f, 3265.9099f, 3616.3977f, 3919.6345f, 4218.5342f, 4519.2207f, 4857.5220f, 5193.5269f, 5573.7339f, 5934.5400f, + 531.4455f, 965.7403f, 1458.5353f, 1773.3784f, 2236.0146f, 2650.9109f, 3099.2871f, 3467.1567f, 3809.7056f, 4094.6472f, 4378.5811f, 4660.2471f, 4962.5078f, 5270.9863f, 5629.4160f, 5973.6450f, + 565.5986f, 1091.1300f, 1561.4944f, 1983.5482f, 2492.8821f, 2897.5085f, 3233.5361f, 3539.8831f, 3838.6494f, 4093.4460f, 4372.1924f, 4678.2251f, 4999.2646f, 5325.0371f, 5672.8887f, 5998.9990f, + 581.0623f, 976.0275f, 1447.0302f, 1779.9243f, 2148.2158f, 2543.8347f, 2979.5061f, 3373.6099f, 3796.8259f, 4164.8242f, 4510.5493f, 4853.5527f, 5175.6318f, 5465.3647f, 5763.2334f, 6050.6582f, + 429.4613f, 802.5781f, 1229.0529f, 1512.6678f, 1835.8625f, 2216.9915f, 2625.3999f, 2995.9927f, 3379.5146f, 3764.7837f, 4156.1382f, 4532.4570f, 4906.4678f, 5262.8960f, 5626.6519f, 5970.6504f, + 224.5468f, 328.6938f, 615.8844f, 1207.4470f, 1520.9565f, 1865.9806f, 2182.4731f, 2431.4897f, 3239.3486f, 3490.9065f, 3775.7139f, 4291.4312f, 4740.0815f, 5192.0786f, 5532.9302f, 5928.7236f, + 312.1133f, 424.3103f, 716.4448f, 921.9969f, 1244.5491f, 2017.9143f, 2248.4170f, 2840.0688f, 3138.9390f, 3399.7288f, 3723.3479f, 3999.6824f, 4582.2339f, 5148.5166f, 5631.8989f, 6000.7192f, + 373.5378f, 506.7356f, 789.6149f, 942.6201f, 1695.8035f, 2021.6426f, 2323.3867f, 2649.5979f, 2853.1729f, 3169.5815f, 3524.9375f, 3848.6399f, 4261.7319f, 4978.9668f, 5505.4004f, 5924.7939f, + 503.2296f, 724.8124f, 940.3833f, 1220.5646f, 1439.8641f, 1726.9827f, 2215.5464f, 2476.0925f, 2846.8127f, 3232.0950f, 3638.5989f, 3986.3333f, 4371.3052f, 5022.0664f, 5657.4897f, 6040.3452f, + 398.3355f, 530.8898f, 835.5377f, 1058.3699f, 1327.2036f, 1814.9178f, 2114.2439f, 2515.8892f, 2754.9077f, 3094.8794f, 3598.7061f, 3981.2385f, 4605.9160f, 5110.8364f, 5550.1899f, 5953.9600f, + 327.7583f, 454.8903f, 825.9029f, 1025.4349f, 1321.1567f, 1551.4836f, 1978.2037f, 2838.9021f, 3111.9041f, 3417.3940f, 3841.0564f, 4696.0547f, 5126.1641f, 5409.5347f, 5711.7163f, 5968.3394f, + 327.1260f, 431.3983f, 721.9533f, 871.1266f, 1507.7616f, 1847.8716f, 2144.9641f, 2491.1108f, 2702.0847f, 3483.1516f, 3917.5173f, 4254.1260f, 4704.4863f, 4981.6284f, 5450.1035f, 5937.7861f, + 443.5867f, 610.7686f, 818.9614f, 999.3525f, 1181.9182f, 1884.4948f, 2243.3950f, 2522.8867f, 2993.8594f, 3196.6631f, 3835.5020f, 4233.2568f, 4506.8604f, 4985.0249f, 5544.1382f, 5980.0083f, + 395.7788f, 582.9504f, 822.1151f, 1013.0453f, 1224.6812f, 1988.4263f, 2452.4744f, 2686.4263f, 2952.8831f, 3135.0867f, 3562.5471f, 4006.6929f, 4401.7471f, 5038.5654f, 5567.4189f, 5986.0850f, + 264.3071f, 372.0398f, 616.4940f, 842.1705f, 1350.0250f, 1822.1957f, 2165.8896f, 2662.2937f, 3055.4390f, 3502.6787f, 3923.4236f, 4352.6587f, 4772.5068f, 5158.1309f, 5573.9385f, 5972.6895f, + 218.7390f, 325.2024f, 635.0441f, 1103.4701f, 1636.4287f, 2070.2615f, 2274.2910f, 2453.2002f, 3069.4382f, 3615.7065f, 3980.0811f, 4484.8662f, 4848.6416f, 5093.7163f, 5522.6973f, 5907.4048f, + 260.0797f, 461.2137f, 1049.2261f, 1334.1865f, 1628.6233f, 2014.9823f, 2413.4802f, 2844.4973f, 3232.3040f, 3661.0122f, 4069.8274f, 4466.5210f, 4857.6553f, 5234.4463f, 5608.4517f, 5954.7920f, + 301.7969f, 406.3861f, 706.7324f, 1387.1207f, 1581.4719f, 2004.7585f, 2291.9421f, 2548.9978f, 3076.8755f, 3343.1306f, 3623.1770f, 4279.7432f, 4777.6563f, 5084.3960f, 5473.4536f, 5872.0615f, + 344.0269f, 472.3550f, 776.6819f, 1455.1270f, 1611.6870f, 2012.4386f, 2417.4033f, 2621.8564f, 3318.9663f, 3709.0132f, 3944.1958f, 4299.0293f, 4776.4038f, 5184.1089f, 5545.5454f, 5913.9531f, + 332.1463f, 433.0623f, 992.1605f, 1254.8217f, 1498.4819f, 1824.6357f, 2118.3374f, 2444.6484f, 2684.8369f, 2930.4683f, 3557.4851f, 4292.9014f, 4786.7251f, 5138.2168f, 5616.2739f, 5996.8369f, + 281.7202f, 372.7708f, 1074.7051f, 1443.0428f, 1687.6460f, 1980.7075f, 2275.4241f, 2632.2017f, 2848.1765f, 3118.7881f, 3628.5857f, 4522.9585f, 4876.2163f, 5177.2739f, 5600.6675f, 5960.9634f, + 412.0151f, 535.6881f, 768.8618f, 1462.2601f, 1789.1055f, 1947.8196f, 2224.6890f, 2447.9089f, 2834.6140f, 3472.6721f, 3729.8525f, 4008.2893f, 4525.7271f, 4822.9194f, 5204.6611f, 5895.0942f, + 263.8760f, 379.7789f, 825.0498f, 1113.1218f, 1465.8749f, 1846.7463f, 2146.0496f, 2487.2766f, 2845.8447f, 3388.4800f, 3883.8447f, 4440.7603f, 4867.0815f, 5214.7280f, 5535.8149f, 5906.9932f, + 409.8116f, 583.7237f, 859.1983f, 1172.0491f, 1377.6473f, 1984.8322f, 2361.7292f, 2688.9368f, 3238.6563f, 3542.6716f, 3944.3005f, 4441.0840f, 4881.1211f, 5224.6045f, 5604.3711f, 5909.3657f, + 318.0743f, 438.8244f, 852.9153f, 1061.4503f, 1290.7609f, 1552.5408f, 2053.1118f, 2373.2883f, 2926.1560f, 3452.9551f, 4098.6626f, 4585.2773f, 4967.0898f, 5271.2720f, 5644.6709f, 5961.9585f, + 370.3631f, 496.5860f, 932.6390f, 1213.4189f, 1452.6641f, 1803.1532f, 2092.2354f, 2607.5247f, 2883.8086f, 3112.1086f, 3687.5657f, 4525.1274f, 4846.9404f, 5130.0537f, 5416.4141f, 5804.5122f, + 247.8941f, 343.9862f, 751.6780f, 1526.2566f, 1712.5012f, 2038.0667f, 2324.0371f, 2727.9749f, 3005.8975f, 3378.9817f, 3858.2002f, 4339.2017f, 4716.4580f, 5125.0918f, 5564.3589f, 5969.7163f, + 297.6552f, 401.7544f, 891.9346f, 1380.2275f, 1540.3125f, 1782.6058f, 2009.2045f, 2614.2092f, 2899.5396f, 3379.9722f, 3804.1169f, 4284.8540f, 4696.3335f, 5118.4551f, 5525.9839f, 5934.2686f, + 226.1444f, 333.4511f, 682.9995f, 1307.4166f, 1554.1943f, 1849.3679f, 2116.3438f, 2756.3567f, 3204.3018f, 3540.4106f, 4002.1895f, 4402.7734f, 4796.4395f, 5192.6812f, 5600.6841f, 5960.1855f, + 196.3791f, 299.9716f, 572.3173f, 1201.8826f, 1804.7235f, 2012.0171f, 2264.7415f, 2790.3406f, 3272.6926f, 3668.4863f, 4063.0435f, 4442.4419f, 4810.5957f, 5156.0923f, 5512.8501f, 5900.7441f, + 280.1911f, 391.5190f, 705.9903f, 1435.5063f, 1588.2345f, 2116.5032f, 2357.1875f, 2670.7461f, 3299.0071f, 3507.9336f, 4044.3057f, 4591.9023f, 4981.4575f, 5281.1270f, 5654.7158f, 5949.9263f, + 262.5740f, 370.5089f, 654.7243f, 1278.9299f, 1847.3096f, 2087.3394f, 2553.8892f, 2887.8269f, 3254.0747f, 3810.6626f, 4258.4390f, 4528.8022f, 4872.9741f, 5206.0483f, 5565.2876f, 5918.5596f, + 193.6133f, 356.3127f, 1076.8109f, 1485.8608f, 1887.7994f, 2273.1333f, 2676.7832f, 3052.3513f, 3419.1294f, 3792.5024f, 4161.7036f, 4532.6431f, 4898.5176f, 5262.0498f, 5622.8901f, 5976.4863f, + 302.7377f, 409.7598f, 899.1851f, 1176.6501f, 1531.3615f, 1933.6494f, 2229.9561f, 2819.8936f, 3031.6248f, 3807.0129f, 4118.7495f, 4412.7339f, 4704.6758f, 5012.0190f, 5351.4160f, 5892.3232f, + 421.1889f, 587.3521f, 835.9208f, 1248.0127f, 1475.8882f, 1779.3772f, 2330.6294f, 2606.6780f, 3026.0417f, 3513.8035f, 3754.6023f, 4081.0518f, 4536.3438f, 4815.9336f, 5117.6392f, 5802.9902f, + 378.0719f, 722.0884f, 1327.5808f, 1665.8940f, 1954.7782f, 2238.9473f, 2608.8538f, 2958.7910f, 3341.5112f, 3721.2021f, 4095.8457f, 4457.6865f, 4843.8672f, 5212.5142f, 5589.5122f, 5945.3730f, + 468.4631f, 962.3222f, 1541.0238f, 1919.1746f, 2347.4365f, 2650.7366f, 2927.5945f, 3166.4202f, 3451.0664f, 3757.8477f, 4109.2383f, 4467.9443f, 4858.6045f, 5211.8428f, 5593.3311f, 5951.0137f, + 422.2508f, 845.8956f, 1495.2552f, 1811.3933f, 2128.1157f, 2371.2532f, 2656.0715f, 2942.9011f, 3294.5308f, 3652.0935f, 4031.2534f, 4399.2222f, 4801.9497f, 5163.3721f, 5559.4517f, 5934.4063f, + 423.1028f, 661.7286f, 991.1974f, 1204.3813f, 1472.8564f, 2003.0298f, 2443.5833f, 2789.2795f, 3354.1692f, 3722.7822f, 4032.7351f, 4320.9727f, 4621.8140f, 4963.7310f, 5429.8203f, 5900.1465f, + 361.2513f, 485.9720f, 828.4865f, 1340.9952f, 1497.8477f, 2072.8511f, 2437.9839f, 2674.9912f, 3259.3357f, 3539.0474f, 3789.1389f, 4087.5015f, 4404.8867f, 4771.0947f, 5500.2227f, 6015.7041f, + 301.8146f, 392.9569f, 685.1938f, 1783.6246f, 2034.8542f, 2257.1614f, 2519.8713f, 2782.6279f, 3152.1135f, 3400.8662f, 3614.3801f, 3906.7375f, 4233.1968f, 4712.3682f, 5596.0396f, 5998.5742f, + 242.0591f, 371.0809f, 729.0743f, 1190.6813f, 1851.5691f, 2132.6724f, 2334.7773f, 2522.3608f, 3091.8643f, 3621.4614f, 3854.5227f, 4174.7017f, 4490.7510f, 4780.1230f, 5157.6147f, 5865.4756f, + 431.2477f, 562.1808f, 888.5207f, 1034.2062f, 1443.2480f, 2109.8850f, 2337.1443f, 2829.1870f, 3070.1301f, 3252.6370f, 3510.3967f, 4366.2236f, 4843.2139f, 5133.0537f, 5549.8911f, 5850.3252f, + 420.2594f, 668.9339f, 911.1281f, 1218.0372f, 1806.5541f, 2050.8423f, 2394.5708f, 2761.3542f, 3021.1716f, 3414.0020f, 3970.9626f, 4342.2900f, 4691.6074f, 5062.5386f, 5452.6655f, 5792.8384f, + 257.3011f, 370.8905f, 604.8825f, 1096.4209f, 1711.8464f, 1934.4335f, 2319.4717f, 2769.0144f, 3019.0200f, 3354.3726f, 4119.8809f, 4354.8589f, 4557.7979f, 4893.5776f, 5450.3042f, 5910.4136f, + 241.4264f, 347.9253f, 622.2432f, 1248.8121f, 1559.7318f, 1848.8098f, 2315.5635f, 2571.5894f, 2879.5754f, 3624.1069f, 3968.0334f, 4238.9727f, 4713.4746f, 5156.6792f, 5568.5596f, 5975.8716f, + 478.7131f, 629.4184f, 918.1857f, 1342.7815f, 1535.1541f, 1803.0487f, 2483.7764f, 2724.4321f, 2998.1257f, 3634.9932f, 3915.9443f, 4119.2837f, 4327.0283f, 4980.3516f, 5532.6880f, 5964.3052f, + 265.7818f, 373.8575f, 723.3755f, 1186.0619f, 1509.2827f, 2064.2075f, 2298.1992f, 2566.4395f, 2785.7659f, 3423.1396f, 3883.9011f, 4136.8940f, 4463.0386f, 5010.6592f, 5539.0337f, 5931.4414f, + 221.4221f, 347.7610f, 707.4465f, 1187.0800f, 1575.9095f, 1824.3983f, 1979.3307f, 2299.3174f, 2967.6799f, 3472.3381f, 3955.8469f, 4292.6079f, 4794.8745f, 5127.5181f, 5652.6729f, 5953.0132f, + 397.2769f, 510.2605f, 746.8268f, 1588.0735f, 1991.5200f, 2150.6843f, 2439.0486f, 2712.2754f, 2972.5825f, 3501.2673f, 3917.5459f, 4143.6069f, 4443.4414f, 4829.1929f, 5490.0376f, 6028.3794f, + 280.5184f, 370.6464f, 640.7120f, 1721.3899f, 1948.9806f, 2149.9592f, 2400.4678f, 2674.0542f, 3146.3154f, 3419.8850f, 3813.9553f, 4417.4497f, 4818.3652f, 5139.6323f, 5465.0669f, 5879.7183f, + 325.2418f, 431.2627f, 1008.7708f, 1271.9235f, 1527.4150f, 2066.6370f, 2242.3311f, 2883.4065f, 3180.6614f, 3352.5015f, 3756.9688f, 4386.6904f, 4857.6621f, 5189.2212f, 5514.7573f, 5856.8086f, + 451.8427f, 582.4401f, 925.8821f, 1363.4249f, 1503.2460f, 1961.5940f, 2265.6001f, 2574.4414f, 3123.0769f, 3345.1587f, 3634.3022f, 4266.0137f, 4880.8052f, 5223.5776f, 5567.8901f, 5880.3770f, + 411.0873f, 553.3847f, 809.2106f, 1023.4841f, 1189.0618f, 1786.0770f, 2121.8489f, 2454.6458f, 2947.4700f, 3220.3210f, 3828.0911f, 4218.0229f, 4831.2383f, 5322.1445f, 5727.3906f, 6033.3887f, + 310.5608f, 442.2204f, 742.7755f, 1097.5740f, 1340.9608f, 1854.4385f, 2261.6399f, 2634.8315f, 3297.8879f, 3638.6956f, 3925.8770f, 4232.9146f, 4559.9287f, 4893.5830f, 5403.0981f, 5917.7056f, + 377.5583f, 488.4103f, 945.2491f, 1234.1572f, 1416.0774f, 1666.5979f, 1932.9910f, 2746.2000f, 2997.4753f, 3216.6152f, 3559.3999f, 3843.8130f, 4359.6626f, 5014.2920f, 5560.6162f, 5992.7212f, + 285.2173f, 389.6116f, 825.5790f, 1238.8229f, 1459.6588f, 1860.8855f, 2178.6296f, 2519.1597f, 2828.0032f, 3278.8101f, 3560.8286f, 4142.0552f, 4691.0698f, 5117.7778f, 5558.7944f, 5954.6680f, + 465.7002f, 631.7491f, 914.5521f, 1340.0057f, 1562.5760f, 1844.1741f, 2186.1208f, 2483.7080f, 2901.9417f, 3190.3162f, 3474.7651f, 3873.4065f, 4240.1973f, 4761.1255f, 5428.2832f, 5958.5273f, + 340.5456f, 449.2341f, 793.7005f, 1387.7467f, 1555.8701f, 1938.7877f, 2201.6155f, 2579.5762f, 2914.9724f, 3149.8584f, 3699.3984f, 3985.6790f, 4331.7534f, 4999.4805f, 5514.6924f, 5969.4897f, + 395.8350f, 564.1188f, 774.8214f, 1276.3201f, 1721.8716f, 1864.0143f, 2267.5696f, 2790.2031f, 3003.9434f, 3377.6140f, 3917.7395f, 4167.3867f, 4465.2529f, 4936.1138f, 5464.0479f, 5905.0444f, + 324.1844f, 443.0006f, 728.8958f, 1398.6589f, 1584.1820f, 1923.8724f, 2348.0903f, 2561.5554f, 3154.5991f, 3449.1746f, 3771.7927f, 4182.1899f, 4937.0791f, 5361.6509f, 5727.7656f, 6002.7505f, + 267.1790f, 373.7663f, 703.5949f, 1173.7009f, 1390.2002f, 1905.7941f, 2177.4961f, 2703.2627f, 3022.9121f, 3308.9612f, 3798.5823f, 4187.1533f, 4703.2163f, 5136.0918f, 5571.1655f, 5966.6577f, + 272.9294f, 399.3804f, 797.7335f, 1180.1516f, 1426.4850f, 2097.2839f, 2355.4727f, 2793.8774f, 3137.1907f, 3458.7727f, 3893.6628f, 4245.8047f, 4652.3794f, 5106.5293f, 5568.1885f, 5948.3169f, + 324.5529f, 431.7663f, 759.6147f, 1494.8739f, 1668.8168f, 2110.5635f, 2427.4104f, 2672.9270f, 3170.5266f, 3448.2080f, 3717.1240f, 4034.2280f, 4375.3647f, 5041.1372f, 5666.9517f, 6014.7217f, + 306.4759f, 404.5361f, 795.7795f, 1675.9967f, 1835.0950f, 2160.6624f, 2430.8855f, 2734.2646f, 3270.1426f, 3586.1355f, 3821.9670f, 4102.0078f, 4372.9404f, 4918.9146f, 5412.0376f, 5868.5225f, + 421.3803f, 607.7995f, 813.0241f, 1286.8525f, 1827.2451f, 2026.8683f, 2333.9453f, 2730.9817f, 2988.4067f, 3303.8513f, 3759.1897f, 4057.5264f, 4441.5493f, 4890.0078f, 5212.0469f, 5672.2188f, + 423.8560f, 599.5201f, 829.0651f, 1082.6381f, 1245.9272f, 1623.7075f, 2453.0420f, 2855.6631f, 3171.3855f, 3475.5881f, 3715.4219f, 3972.1326f, 4419.1597f, 4894.0283f, 5363.8691f, 5919.2681f, + 441.2789f, 634.8879f, 921.6287f, 1189.0240f, 1368.7466f, 2012.1312f, 2383.7656f, 2638.5222f, 2975.0288f, 3163.6150f, 3433.9958f, 3838.9917f, 4186.6426f, 4856.8477f, 5559.1196f, 5977.2290f, + 349.2039f, 466.2342f, 724.2582f, 904.4043f, 1190.4492f, 1981.7565f, 2226.5554f, 2592.5098f, 2865.5525f, 3195.8196f, 3735.6345f, 4267.1660f, 4810.9893f, 5207.5093f, 5605.1445f, 5952.0361f, + 497.7713f, 719.9073f, 925.0815f, 1146.3021f, 1326.7095f, 1574.5039f, 2306.7678f, 2714.8022f, 2967.5190f, 3400.1121f, 3732.0544f, 3981.7878f, 4553.4819f, 5090.0869f, 5426.2085f, 5833.5220f, + 471.7526f, 648.3213f, 902.1542f, 1245.7086f, 1423.3403f, 1701.1757f, 2125.8530f, 2407.0481f, 2969.5583f, 3294.1296f, 3712.8398f, 4140.7930f, 4808.4668f, 5322.3896f, 5662.1255f, 5950.6211f, + 345.3843f, 485.9887f, 841.2579f, 1035.9401f, 1244.8905f, 1488.1833f, 2340.4253f, 2607.0859f, 2845.4153f, 3223.1768f, 3557.0696f, 4119.7944f, 4666.8896f, 5145.8589f, 5565.7534f, 5976.6875f, + 332.4270f, 427.5984f, 829.9191f, 1138.0469f, 1339.4468f, 1589.0535f, 1926.0630f, 2432.9331f, 2699.7964f, 3311.4355f, 3716.1003f, 4270.4990f, 4760.3647f, 5208.3950f, 5619.2080f, 5971.2715f, + 249.0114f, 381.2982f, 925.7067f, 1520.3356f, 1842.8396f, 2368.2908f, 2783.4033f, 3272.5757f, 3673.7402f, 4046.3950f, 4370.4966f, 4688.0269f, 5002.6772f, 5316.3594f, 5650.2192f, 5977.6587f, + 263.3275f, 451.6255f, 1252.2307f, 1503.0652f, 1786.7695f, 2082.7554f, 2451.1829f, 2804.7590f, 3116.7583f, 3493.8892f, 3884.6575f, 4349.6724f, 4770.0156f, 5143.1636f, 5542.5913f, 5931.5522f, + 252.9447f, 341.5762f, 632.7664f, 1766.8096f, 2084.1511f, 2272.7332f, 2531.1006f, 2765.2080f, 3134.5417f, 3380.6223f, 3640.8015f, 3932.7854f, 4532.1172f, 5245.2070f, 5597.0776f, 5973.6831f, + 234.9979f, 324.6731f, 1239.8643f, 1663.1921f, 1858.7769f, 2171.1614f, 2403.8818f, 2680.6433f, 2836.4985f, 3192.6577f, 3864.8811f, 4385.8066f, 4845.9766f, 5150.2412f, 5631.1519f, 6011.7773f, + 284.5302f, 410.1263f, 985.4119f, 1298.3987f, 1789.4304f, 1996.9287f, 2450.8525f, 2831.6011f, 2994.2073f, 3214.1306f, 3525.0498f, 3819.9141f, 4672.7544f, 5424.3545f, 5691.0732f, 5980.3096f, + 244.2704f, 415.5891f, 1038.3009f, 1317.5186f, 1686.4528f, 2081.3147f, 2476.9873f, 2959.5393f, 3214.9561f, 3569.1431f, 3934.4736f, 4308.7114f, 4728.3687f, 5105.7964f, 5488.1938f, 5908.9443f, + 335.8417f, 468.3464f, 1003.6253f, 1275.0145f, 1534.2854f, 1985.3167f, 2348.3411f, 2743.3169f, 2956.0967f, 3408.5063f, 3866.8574f, 4287.0034f, 4556.7222f, 4922.7832f, 5259.7480f, 5800.2876f, + 388.2726f, 518.0591f, 832.5999f, 1325.0247f, 1528.8624f, 1808.1732f, 2151.0820f, 2486.1331f, 2815.4980f, 3158.5391f, 3635.3606f, 3960.5383f, 4671.7686f, 5371.8140f, 5777.8940f, 6056.4722f, + 506.5153f, 673.0771f, 900.0349f, 1154.2124f, 1378.2689f, 1786.9409f, 2081.9631f, 2398.6965f, 2859.7441f, 3075.4841f, 3546.6563f, 4322.6694f, 4732.0049f, 4992.5542f, 5267.5859f, 5807.1812f, + 487.2466f, 653.6116f, 968.5656f, 1389.2708f, 1601.5822f, 1910.9694f, 2282.4038f, 2608.7063f, 3032.6233f, 3361.9692f, 3629.8552f, 3908.8335f, 4318.4009f, 4646.5781f, 5043.5962f, 5792.7393f, + 432.8733f, 591.7551f, 899.2619f, 1490.1176f, 1789.8751f, 2060.3750f, 2434.8779f, 2840.3374f, 3122.1292f, 3472.8079f, 3830.8870f, 4097.2622f, 4353.5464f, 4650.2075f, 4981.5752f, 5482.9565f, + 378.4767f, 508.5656f, 802.8280f, 947.2892f, 1532.0898f, 2038.8177f, 2349.1965f, 2650.2039f, 2863.8018f, 3591.6697f, 3918.9211f, 4256.6255f, 4604.8467f, 4899.0996f, 5237.6084f, 5791.5029f, + 407.0908f, 546.0364f, 866.1215f, 1098.6927f, 1347.2009f, 1657.1525f, 1965.5845f, 2717.7190f, 3033.4961f, 3509.9031f, 3873.4150f, 4131.4438f, 4389.5693f, 4774.2295f, 5450.1768f, 5977.5151f, + 429.3459f, 568.8134f, 903.5659f, 1099.2942f, 1379.4979f, 2207.5940f, 2479.9919f, 2780.9072f, 3206.3960f, 3425.4084f, 3682.5911f, 3950.1941f, 4324.0840f, 4689.4922f, 5068.2534f, 5787.2852f, + 371.9443f, 524.7249f, 890.0464f, 1670.7485f, 1958.5308f, 2182.7007f, 2558.5007f, 2835.4937f, 3192.0740f, 3634.4817f, 3950.0942f, 4259.6953f, 4628.0049f, 4999.1616f, 5364.9893f, 5801.6855f, + 323.1922f, 451.0327f, 787.1655f, 1011.6555f, 1323.8138f, 2177.6636f, 2401.1392f, 2826.8796f, 3432.8999f, 3653.1851f, 3883.9897f, 4082.7559f, 4361.6753f, 4635.1475f, 5084.7544f, 5823.3062f, + 377.0061f, 524.2181f, 743.6288f, 1378.9187f, 1857.6434f, 2056.4695f, 2453.7949f, 2902.1995f, 3127.2651f, 3463.3523f, 3980.1316f, 4241.2578f, 4528.5859f, 4881.4521f, 5239.3145f, 5580.5986f, + 308.7965f, 403.7058f, 705.9506f, 1823.8571f, 2126.9387f, 2369.2810f, 2647.2048f, 2855.8276f, 3209.7708f, 3498.2310f, 3747.6047f, 3972.8647f, 4254.3325f, 4574.4292f, 5087.3965f, 5890.4219f, + 274.7571f, 383.7251f, 573.6029f, 1142.8372f, 2151.7173f, 2558.8972f, 2751.9468f, 2987.4412f, 3234.3350f, 3526.0127f, 3922.9927f, 4189.0249f, 4483.3774f, 4877.1860f, 5396.7798f, 5921.8125f, + 248.5916f, 423.6264f, 1260.9626f, 1696.0492f, 1972.9108f, 2298.5972f, 2592.9307f, 2947.2292f, 3266.2227f, 3614.3572f, 3980.3892f, 4359.4067f, 4770.2842f, 5158.9058f, 5554.6597f, 5936.9043f, + 320.5471f, 429.6766f, 657.1440f, 1390.1080f, 2194.6426f, 2507.6086f, 2712.3662f, 2980.3408f, 3216.1682f, 3544.8467f, 3956.9790f, 4227.5308f, 4463.7563f, 4745.7124f, 5088.6650f, 5525.8516f, + 245.5478f, 520.3131f, 1177.0693f, 1454.0125f, 1770.2620f, 2160.8779f, 2551.2700f, 2950.2324f, 3326.8621f, 3710.4624f, 4104.3936f, 4481.9971f, 4865.9736f, 5230.6396f, 5608.5649f, 5965.6162f, + 514.5864f, 956.9897f, 1287.9597f, 1520.3473f, 1802.0631f, 2116.4980f, 2509.8552f, 2865.9822f, 3238.7510f, 3611.3108f, 4016.4353f, 4431.8457f, 4860.3442f, 5231.4814f, 5614.6016f, 5963.9976f, + 537.0523f, 932.2803f, 1380.2690f, 1709.4702f, 2079.9902f, 2446.4014f, 2859.4204f, 3229.6975f, 3623.4031f, 4012.5327f, 4373.7568f, 4724.3359f, 5078.2686f, 5397.6040f, 5721.9639f, 6028.1167f, + 452.5153f, 798.2777f, 1099.3080f, 1317.0807f, 1652.6885f, 2059.7708f, 2471.0164f, 2808.5396f, 3146.5076f, 3494.0779f, 3870.6912f, 4310.8281f, 4777.5024f, 5181.2617f, 5574.4912f, 5934.3813f, + 340.3716f, 430.5102f, 872.3513f, 1636.3792f, 1772.8615f, 2074.0161f, 2295.1008f, 2693.0037f, 3177.7710f, 3391.7559f, 3670.8718f, 4224.3926f, 4896.3877f, 5199.9883f, 5580.4512f, 5911.7671f, + 317.8269f, 414.8185f, 881.1970f, 1658.4944f, 1852.0098f, 2136.0415f, 2380.8228f, 2668.9141f, 3046.8027f, 3299.0051f, 3523.0593f, 3758.9412f, 4116.9063f, 5061.2124f, 5624.1777f, 5989.4761f, + 374.0671f, 488.0840f, 734.0546f, 1415.9261f, 1648.7783f, 1852.8462f, 2099.1895f, 2347.5562f, 2954.8359f, 3269.6714f, 3536.7920f, 4116.1743f, 4481.4355f, 4913.8838f, 5467.2817f, 5909.8779f, + 340.4291f, 448.5775f, 1041.4979f, 1426.0011f, 1637.8165f, 1968.6743f, 2210.7976f, 2647.5144f, 2913.8650f, 3131.7698f, 3429.8755f, 3722.6763f, 4104.6479f, 4969.0093f, 5574.2231f, 5978.2070f, + 254.2538f, 412.7710f, 947.8206f, 1209.3683f, 1690.4813f, 2040.7881f, 2401.4314f, 2728.0066f, 3016.2290f, 3530.3865f, 3964.6563f, 4393.6934f, 4804.2168f, 5187.9302f, 5586.4399f, 5954.8950f, + 241.0244f, 347.0750f, 835.2348f, 1601.9089f, 1786.4336f, 2134.3950f, 2396.0139f, 2848.9712f, 3239.9138f, 3623.8250f, 4029.5088f, 4400.3936f, 4797.3564f, 5195.7310f, 5596.6689f, 5965.9878f, + 309.3683f, 453.6776f, 812.9343f, 1125.9915f, 1423.5935f, 2149.2227f, 2514.9277f, 3031.3599f, 3463.7219f, 3790.7839f, 4064.0039f, 4297.9839f, 4653.4551f, 5189.7061f, 5721.2954f, 6033.0752f, + 469.4284f, 730.1902f, 973.0643f, 1170.5016f, 1572.2559f, 2084.2769f, 2567.8604f, 2963.4592f, 3286.9617f, 3580.3228f, 3882.8706f, 4335.5483f, 4859.7197f, 5258.2827f, 5627.9785f, 5957.8623f, + 454.6165f, 795.2360f, 1078.7705f, 1294.9473f, 1761.6650f, 2235.2788f, 2695.8455f, 3095.7695f, 3473.4897f, 3833.0889f, 4185.7290f, 4528.9863f, 4893.0039f, 5240.7627f, 5608.8594f, 5951.0718f, + 563.4587f, 875.8987f, 1139.0026f, 1378.2317f, 1855.7401f, 2279.7683f, 2651.3079f, 2968.4397f, 3279.4453f, 3607.2500f, 3975.5796f, 4358.3574f, 4768.7969f, 5135.3706f, 5525.3501f, 5904.2617f, + 461.7852f, 855.0644f, 1367.4387f, 1702.5593f, 2141.0093f, 2500.9055f, 2853.8596f, 3123.9744f, 3406.0178f, 3694.0481f, 4028.9985f, 4373.1113f, 4768.2891f, 5137.6895f, 5541.3721f, 5921.4507f, + 438.6031f, 753.0179f, 1269.3203f, 1630.4396f, 2027.2959f, 2350.9695f, 2672.1396f, 2957.1809f, 3250.1545f, 3546.5315f, 3894.0161f, 4249.9346f, 4666.2266f, 5061.2524f, 5490.7749f, 5904.6362f, + 543.3182f, 828.4835f, 1239.1818f, 1471.1134f, 1737.8622f, 2037.2484f, 2434.5112f, 2801.3242f, 3162.3250f, 3508.1255f, 3849.0903f, 4165.7588f, 4588.3809f, 5020.0952f, 5475.2813f, 5904.6377f, + 519.5982f, 837.6639f, 1171.2003f, 1363.0320f, 1617.4617f, 1976.1787f, 2472.0303f, 2901.3264f, 3340.7300f, 3736.0830f, 4103.3843f, 4444.8657f, 4800.9482f, 5145.6011f, 5544.2002f, 5933.0981f, + 433.3774f, 582.7663f, 899.6142f, 1150.7437f, 1321.1309f, 1947.8643f, 2557.8604f, 2733.1497f, 3240.4907f, 3634.7915f, 3855.9856f, 4058.0281f, 4364.2568f, 5096.5225f, 5659.0952f, 6013.8145f, + 424.9731f, 604.3164f, 868.1793f, 1207.7882f, 1414.2374f, 1713.2893f, 2520.2900f, 2960.8887f, 3210.8542f, 3584.5403f, 3914.5796f, 4149.8550f, 4505.7705f, 4886.9575f, 5214.5361f, 5597.8389f, + 347.0334f, 494.2440f, 753.7191f, 1451.0435f, 1700.7461f, 1925.4844f, 2605.7988f, 2870.4744f, 3173.7312f, 3758.7219f, 4112.1929f, 4400.3882f, 4866.1016f, 5165.8799f, 5433.0371f, 5781.1509f, + 318.4942f, 464.3939f, 783.5214f, 1491.0234f, 1708.4984f, 2280.2876f, 2533.3354f, 2885.1736f, 3443.7451f, 3669.8506f, 4000.6792f, 4269.6626f, 4571.2739f, 4827.2158f, 5277.3813f, 5850.4736f, + 386.8698f, 519.0056f, 725.0029f, 981.5649f, 1156.1665f, 1500.4691f, 2421.7993f, 2962.4722f, 3175.0166f, 3548.4756f, 3860.7961f, 4146.4150f, 4658.9897f, 5088.3999f, 5531.8945f, 5951.4624f, + 315.9294f, 738.5538f, 1171.9581f, 1553.7167f, 1949.9159f, 2319.6641f, 2707.5493f, 3069.2996f, 3444.6157f, 3811.2139f, 4177.5469f, 4545.6943f, 4905.0444f, 5271.3926f, 5622.6831f, 5974.4141f, + 216.5136f, 598.1122f, 1059.3214f, 1466.4785f, 1880.1747f, 2263.6533f, 2658.3081f, 3030.4099f, 3413.6802f, 3780.1853f, 4157.1455f, 4519.1919f, 4893.5439f, 5244.3530f, 5603.1064f, 5926.8379f, + 375.4021f, 487.0890f, 844.4013f, 1574.3596f, 1794.5249f, 2106.2878f, 2418.5217f, 2657.8938f, 3116.6096f, 3457.8625f, 3691.0596f, 3930.1062f, 4259.5928f, 4592.4370f, 5020.5078f, 5840.3989f, + 474.3148f, 724.2144f, 974.0716f, 1283.4182f, 1521.2632f, 1746.4248f, 2333.0957f, 2874.2966f, 3111.9636f, 3440.0410f, 3752.9678f, 3975.7139f, 4294.7056f, 4821.9893f, 5201.5562f, 5658.8301f, + 400.0291f, 564.9626f, 808.2393f, 1083.2745f, 1300.4403f, 2080.7405f, 2588.6882f, 2858.4629f, 3206.4502f, 3429.8623f, 3746.9080f, 4341.4868f, 4713.2803f, 4986.4258f, 5336.7339f, 5710.1123f, + 354.4416f, 480.1495f, 834.1089f, 1037.7775f, 1350.0652f, 1791.1736f, 2193.0159f, 2504.6775f, 2776.0623f, 3153.0994f, 4108.1357f, 4597.4082f, 4861.9688f, 5092.8613f, 5473.2295f, 5932.0332f, + 237.3935f, 346.9133f, 675.5335f, 1481.0535f, 1716.8414f, 1884.7153f, 2099.3057f, 2725.5403f, 3022.8506f, 3276.2922f, 3639.1001f, 4185.3926f, 4941.6597f, 5292.0093f, 5682.0391f, 5981.0215f, + 367.4981f, 469.7130f, 820.7811f, 1219.7736f, 1368.4479f, 1624.6671f, 1804.2581f, 2607.8589f, 2891.3174f, 3212.2432f, 3760.7290f, 4015.6111f, 4618.0068f, 5129.3213f, 5652.1582f, 6042.1113f, + 312.6796f, 415.8322f, 674.1500f, 853.7709f, 1808.7385f, 2232.5310f, 2497.8157f, 2834.2991f, 3039.7012f, 3301.4050f, 3659.2969f, 4455.9453f, 4841.4912f, 5111.6167f, 5502.2534f, 5924.6357f, + 341.9309f, 471.7513f, 758.1926f, 979.7221f, 1287.4463f, 1737.0303f, 2160.7915f, 2664.5562f, 2961.8315f, 3461.7439f, 3732.6611f, 4109.0928f, 4568.9111f, 5037.4331f, 5511.3169f, 5966.1304f, + 351.3721f, 462.1897f, 765.1075f, 946.3102f, 1322.8093f, 2292.2400f, 2503.6494f, 2819.7234f, 3079.2803f, 3297.6252f, 3571.4668f, 3872.0823f, 4337.6426f, 5079.1504f, 5562.8110f, 5942.7153f, + 435.4323f, 614.4746f, 892.8980f, 1215.9469f, 1395.9762f, 1814.3936f, 2155.9590f, 2465.0427f, 3201.6211f, 3490.9224f, 3853.2620f, 4410.1855f, 4786.0625f, 5095.0181f, 5394.4805f, 5715.3364f, + 294.6053f, 417.1553f, 1046.2922f, 1443.0247f, 1636.7180f, 1956.4248f, 2189.9697f, 2869.8071f, 3129.9385f, 3462.5681f, 3895.2805f, 4213.4541f, 4541.8950f, 5009.1958f, 5472.7642f, 5983.0063f, + 322.1185f, 446.8733f, 689.4188f, 1338.2788f, 1643.1023f, 1903.8652f, 2494.2722f, 2804.6968f, 3103.8682f, 3640.1233f, 3965.9861f, 4172.5596f, 4404.7388f, 4670.7544f, 5240.3682f, 5893.4600f, + 209.7024f, 336.5508f, 729.0126f, 1217.3285f, 1699.0111f, 1891.2837f, 2146.8486f, 2830.0850f, 3108.6204f, 3446.0396f, 3754.1230f, 3945.1038f, 4474.5806f, 5191.6987f, 5613.3076f, 5970.2695f, + 346.6580f, 470.5094f, 663.3455f, 1266.9061f, 2020.5759f, 2270.5173f, 2527.3550f, 2826.9104f, 3078.3403f, 3401.2625f, 3804.3770f, 4100.3091f, 4407.7876f, 4732.2319f, 5150.2749f, 5808.2559f, + 283.7796f, 391.4603f, 1165.6863f, 1456.1125f, 1692.9001f, 2008.4825f, 2322.7837f, 2784.0608f, 2998.5811f, 3268.5164f, 3548.9373f, 4167.1289f, 4643.9878f, 5099.2881f, 5473.0781f, 5929.8242f, + 301.0849f, 383.1578f, 692.0848f, 1648.9374f, 1873.0947f, 2109.6113f, 2345.0110f, 2613.1121f, 2922.0193f, 3170.0020f, 3405.0774f, 3881.9875f, 4778.3154f, 5092.5205f, 5445.7100f, 5920.7896f, + 509.1023f, 750.8580f, 963.8820f, 1295.3452f, 1634.8796f, 1818.7975f, 2151.1250f, 2590.3354f, 2867.5596f, 3238.7666f, 3747.2834f, 4053.8911f, 4457.8164f, 4928.0151f, 5295.3521f, 5789.0571f, + 421.8951f, 547.9814f, 967.4185f, 1153.8607f, 1461.4230f, 1813.0994f, 2155.2703f, 2570.9712f, 2777.6597f, 3048.9863f, 3432.0986f, 3729.3877f, 4395.7461f, 5028.7402f, 5486.4946f, 5951.5024f, + 340.6758f, 445.7014f, 931.8882f, 1253.4775f, 1521.9260f, 1969.5759f, 2267.5332f, 2735.0112f, 2948.7678f, 3236.5166f, 3529.5505f, 3882.3674f, 4699.5781f, 5089.6641f, 5377.7842f, 5880.7778f, + 284.1882f, 408.6918f, 786.3123f, 1670.3220f, 2042.9493f, 2265.2275f, 2691.2012f, 3035.8762f, 3334.1719f, 3863.1194f, 4276.8916f, 4571.0420f, 4996.4404f, 5336.5205f, 5647.9556f, 5944.5996f, + 300.0066f, 616.4817f, 1238.7324f, 1614.8296f, 1997.6188f, 2367.4343f, 2784.5605f, 3168.8354f, 3569.8250f, 3965.6011f, 4336.3804f, 4689.5874f, 5044.2012f, 5365.7456f, 5697.5654f, 6010.6572f, + 242.9420f, 476.8371f, 1250.6661f, 1671.6031f, 2159.6443f, 2637.7417f, 3049.8589f, 3371.6045f, 3674.8706f, 3951.1006f, 4230.6416f, 4543.2827f, 4887.4478f, 5220.5581f, 5595.2686f, 5962.1313f, + 242.6795f, 331.1335f, 635.2861f, 1801.5236f, 2084.1472f, 2264.4692f, 2506.2891f, 2799.4441f, 3236.7134f, 3489.6038f, 3859.3291f, 4424.8008f, 4964.6348f, 5298.6533f, 5640.2031f, 5988.0552f, + 254.0538f, 336.2447f, 1216.6261f, 1717.7201f, 1886.0708f, 2176.6338f, 2405.8547f, 2762.3037f, 2934.8816f, 3167.0657f, 3385.5457f, 3804.4346f, 4848.8198f, 5286.0352f, 5630.5391f, 6086.4492f, + 295.2298f, 426.2079f, 630.7856f, 1155.5609f, 1827.6831f, 2120.5283f, 2462.4373f, 2759.6152f, 2990.9526f, 3253.4216f, 3910.9834f, 4204.2754f, 4462.7944f, 4909.7529f, 5579.9653f, 5985.8579f, + 298.9633f, 410.3875f, 810.1115f, 1346.1040f, 1499.2391f, 2210.3948f, 2467.9424f, 2792.7122f, 3284.0874f, 3493.0740f, 3784.1899f, 4319.6396f, 4860.6548f, 5213.8540f, 5609.8672f, 5949.6890f, + 437.9900f, 575.3093f, 866.0077f, 1104.2080f, 1307.4966f, 1959.9323f, 2293.9365f, 2604.6704f, 2966.6514f, 3228.0056f, 3548.8499f, 4096.4424f, 4769.5420f, 5086.5449f, 5416.5317f, 5853.6909f, + 412.4955f, 569.1867f, 864.0179f, 1117.6798f, 1348.6332f, 1976.5171f, 2334.3960f, 2640.3381f, 3006.5347f, 3327.5784f, 3695.8564f, 4042.1753f, 4362.7837f, 4687.4751f, 5389.8662f, 5966.5825f, + 406.8686f, 542.0319f, 867.3541f, 1436.3810f, 1678.6399f, 2000.1501f, 2358.1204f, 2651.3806f, 3042.1216f, 3339.2766f, 3617.9963f, 3933.3860f, 4249.0278f, 4591.8530f, 5502.0400f, 6020.7910f, + 375.4336f, 519.7731f, 764.5574f, 1215.1381f, 1482.9417f, 1696.8020f, 1957.0332f, 2169.1169f, 2973.4634f, 3687.7449f, 3966.8525f, 4258.8042f, 4680.6567f, 4947.0225f, 5230.9824f, 5843.2466f, + 443.2378f, 574.0562f, 813.3345f, 1282.7894f, 1538.0752f, 1727.8997f, 2007.8584f, 2194.5601f, 2755.8220f, 3460.9243f, 3654.1399f, 4030.5530f, 4572.4727f, 4904.7847f, 5400.6147f, 5934.2656f, + 423.6246f, 540.1947f, 862.8629f, 1386.7659f, 1577.2052f, 1811.0304f, 2046.7363f, 2309.0366f, 3129.1145f, 3533.0020f, 3738.4211f, 4021.1111f, 4357.3677f, 4634.8740f, 5307.2920f, 5944.9155f, + 287.7661f, 401.5490f, 725.6079f, 950.8911f, 1186.5465f, 1490.1750f, 2114.7920f, 2562.4019f, 3028.3977f, 3519.6277f, 3940.5737f, 4339.3086f, 4765.8188f, 5172.3428f, 5582.8022f, 5971.0273f, + 382.6039f, 537.7234f, 836.8093f, 1371.3546f, 1578.9803f, 1869.8213f, 2292.5596f, 2540.8601f, 3032.9834f, 3402.5059f, 3737.0569f, 4053.9937f, 4446.6240f, 5251.8457f, 5710.7935f, 6022.2925f, + 313.2195f, 415.0511f, 690.6860f, 1561.4832f, 1815.6521f, 2059.9187f, 2345.5095f, 2614.8701f, 3006.9604f, 3291.9744f, 3590.4119f, 3996.1516f, 4365.4995f, 4853.4956f, 5465.1572f, 5954.5718f, + 361.7959f, 448.4001f, 921.3198f, 1343.1167f, 1488.6287f, 1736.7700f, 1950.8906f, 2536.0193f, 2768.7393f, 3062.4473f, 3484.6570f, 3888.5618f, 4618.4038f, 5092.6641f, 5523.3657f, 5966.6772f, + 249.5541f, 366.6601f, 684.6592f, 1203.0931f, 1642.2089f, 1961.8837f, 2227.3289f, 2421.1348f, 2660.5676f, 3229.5410f, 3822.5837f, 4232.7266f, 4782.5181f, 5127.2612f, 5570.2676f, 5978.9858f, + 287.4206f, 421.3210f, 704.0352f, 1279.8597f, 1562.7307f, 2115.4241f, 2492.4517f, 2780.9470f, 3317.3616f, 3606.1492f, 4026.6375f, 4337.9014f, 4699.6895f, 4997.2573f, 5431.1787f, 5903.8628f, + 487.9554f, 740.9349f, 1021.9616f, 1327.3262f, 1620.8544f, 1890.7717f, 2269.1218f, 2584.4868f, 2911.2896f, 3424.9221f, 3855.1670f, 4205.9272f, 4707.2466f, 5147.1846f, 5601.1152f, 5953.4673f, + 400.8269f, 513.4500f, 786.8242f, 1269.3298f, 1441.4178f, 1696.9789f, 1911.0537f, 2223.0684f, 2847.1619f, 3113.3845f, 3670.6318f, 4146.2900f, 4555.9204f, 5083.8579f, 5574.8120f, 5987.6030f, + 379.0329f, 487.7222f, 914.8179f, 1130.9854f, 1430.1394f, 1830.0769f, 2088.8796f, 2613.6855f, 2803.1633f, 3457.1777f, 4032.6118f, 4306.7344f, 4662.6899f, 4959.6348f, 5245.5234f, 5787.3940f, + 340.6941f, 451.0338f, 656.2767f, 911.5805f, 1124.9330f, 1733.8730f, 2518.7861f, 2768.6851f, 3211.3733f, 3717.7583f, 3929.6772f, 4176.2993f, 4522.4517f, 5011.5547f, 5575.8784f, 6006.7222f, + 341.5027f, 441.6417f, 807.2695f, 1060.2080f, 1251.2837f, 1478.9895f, 1750.0796f, 2594.8977f, 2924.5027f, 3401.4751f, 3852.0557f, 4292.4683f, 4718.2930f, 5159.4775f, 5562.4067f, 5972.5571f, + 313.8985f, 421.5380f, 667.2407f, 873.6023f, 1110.1119f, 2060.7332f, 2381.0916f, 2746.2288f, 3080.5649f, 3399.9905f, 3897.5884f, 4434.9990f, 5048.1343f, 5390.8149f, 5744.3931f, 6007.9326f, + 252.1832f, 354.2392f, 673.5427f, 1339.1161f, 1554.8853f, 2014.9351f, 2300.4138f, 2829.6182f, 3213.1714f, 3409.5105f, 3604.3242f, 3927.8020f, 4622.3218f, 5103.4565f, 5559.5024f, 5971.5986f, + 385.2648f, 513.7607f, 760.7678f, 983.5819f, 1175.7727f, 2134.7810f, 2592.9614f, 2822.0161f, 3232.2524f, 3445.3516f, 3750.7583f, 4094.6714f, 4401.5830f, 4753.4204f, 5549.2319f, 6034.7148f, + 220.6833f, 314.5706f, 622.2172f, 1350.8225f, 1785.5879f, 2077.5837f, 2504.2158f, 3057.6992f, 3436.0974f, 3695.2976f, 3953.4272f, 4267.8701f, 4660.6865f, 5073.6831f, 5501.9478f, 5929.9780f, + 207.8814f, 310.4071f, 646.2098f, 1270.5835f, 1542.7271f, 2079.3804f, 2440.0339f, 2843.4690f, 3272.4854f, 3657.9851f, 4061.2014f, 4444.9780f, 4841.6060f, 5224.5947f, 5620.9141f, 5972.7261f, + 326.1488f, 456.7737f, 740.3350f, 961.4597f, 1262.7579f, 2190.7178f, 2483.5300f, 2872.4180f, 3328.4910f, 3811.0334f, 4153.1602f, 4441.8271f, 4801.1802f, 5065.2988f, 5381.6309f, 5693.2886f, + 206.2046f, 328.0855f, 618.9507f, 980.9994f, 1695.9775f, 1982.3051f, 2275.5444f, 2806.0271f, 3269.5178f, 3491.2456f, 3722.1775f, 4145.9121f, 4843.1167f, 5266.8677f, 5656.8794f, 5992.1201f, + 308.1086f, 407.7706f, 806.7985f, 1045.7629f, 1401.8912f, 2108.3472f, 2331.7849f, 2952.5391f, 3174.1865f, 3374.0686f, 3645.4260f, 4292.7183f, 4939.2969f, 5250.4829f, 5607.2358f, 5932.8657f, + 267.5990f, 378.7492f, 642.2629f, 871.7917f, 1691.7523f, 2087.5117f, 2423.1462f, 2686.1487f, 3021.7893f, 3724.0247f, 4035.5454f, 4369.5903f, 4680.1167f, 4991.4175f, 5323.6875f, 5811.7471f, + 312.3856f, 437.4281f, 714.5340f, 899.5771f, 1632.7545f, 1938.5369f, 2295.5544f, 2625.6189f, 2900.5576f, 3295.4934f, 3557.1260f, 3960.1123f, 4731.6079f, 5141.8447f, 5502.7793f, 5954.0049f, + 332.2842f, 449.0976f, 875.9957f, 1206.1912f, 1422.6793f, 2097.5745f, 2354.2483f, 2715.8494f, 3093.4697f, 3344.5132f, 3623.4814f, 3889.3655f, 4256.2002f, 4994.5742f, 5593.8428f, 5985.9575f, + 286.9586f, 434.7701f, 781.3996f, 1248.3495f, 1835.5530f, 2137.1155f, 2573.7449f, 2869.9299f, 3126.0564f, 3459.1448f, 3769.4475f, 4138.3076f, 4688.0298f, 5084.9028f, 5436.8086f, 5894.2520f, + 327.0000f, 429.0804f, 663.7327f, 849.7463f, 1174.9340f, 2383.3875f, 2695.9597f, 2941.2026f, 3214.4724f, 3433.6287f, 3778.9312f, 4134.8096f, 4504.8022f, 5066.7559f, 5599.2290f, 5985.7334f, + 244.4052f, 499.2254f, 1294.8232f, 1689.3677f, 2123.5024f, 2572.4958f, 3042.9067f, 3446.8752f, 3836.3740f, 4175.6729f, 4485.3213f, 4792.3755f, 5094.9077f, 5386.1816f, 5699.6411f, 6008.2114f, + 561.9757f, 1020.3204f, 1494.1995f, 1841.8171f, 2297.0906f, 2772.6184f, 3204.8804f, 3565.8628f, 3935.4106f, 4253.4141f, 4559.7021f, 4849.9653f, 5140.2852f, 5428.6934f, 5731.2251f, 6023.5078f, + 581.6182f, 1053.5670f, 1478.5878f, 1784.4789f, 2125.1157f, 2454.5889f, 2809.0256f, 3141.7256f, 3490.7529f, 3848.5923f, 4201.7271f, 4568.7720f, 4945.9619f, 5288.6289f, 5647.7642f, 5981.9341f, + 258.9683f, 364.0963f, 722.5463f, 1763.2114f, 1969.3870f, 2265.5239f, 2532.1821f, 2883.3557f, 3388.1838f, 3725.3120f, 4080.9338f, 4390.3818f, 4716.3599f, 5068.4941f, 5452.2778f, 5847.1401f, + 271.5428f, 401.4228f, 695.5894f, 857.3072f, 1776.5358f, 2008.5603f, 2554.4143f, 2844.4021f, 3018.6877f, 3226.1279f, 3482.3398f, 3810.6858f, 4549.3071f, 5266.2764f, 5614.6157f, 5945.6904f, + 330.3132f, 444.6271f, 669.0279f, 874.5479f, 1102.9247f, 2052.1780f, 2436.2378f, 2711.1165f, 3037.7537f, 3298.2036f, 3898.6858f, 4241.5415f, 4606.7637f, 5086.6919f, 5569.7397f, 5988.6797f, + 232.3014f, 344.5512f, 578.5155f, 1213.9569f, 1880.9729f, 2105.6685f, 2335.4148f, 2550.3965f, 3147.6501f, 3491.9253f, 3791.5613f, 4159.6694f, 4642.2441f, 5103.3340f, 5605.4106f, 5989.7969f, + 346.3687f, 444.8047f, 714.3775f, 889.1195f, 1211.8463f, 2168.7598f, 2430.2490f, 2760.6326f, 3012.4961f, 3268.8750f, 3565.1558f, 4172.5791f, 4781.5391f, 5127.6704f, 5512.6323f, 5911.3779f, + 398.0477f, 553.8537f, 845.8521f, 1119.3066f, 1309.7244f, 1928.3351f, 2351.2095f, 2649.8230f, 3050.6750f, 3297.0566f, 3592.7275f, 3916.1785f, 4723.3325f, 5318.1221f, 5703.9697f, 5996.7651f, + 371.4409f, 471.0789f, 896.4924f, 1197.7544f, 1400.8007f, 1611.1555f, 1867.3550f, 2818.4475f, 3002.5906f, 3250.1440f, 3546.5891f, 4265.0371f, 4890.3369f, 5274.4722f, 5659.3560f, 5946.9644f, + 330.9331f, 448.7211f, 808.3973f, 978.2021f, 1652.6361f, 1969.0725f, 2357.0146f, 2680.4792f, 2859.9165f, 3078.9578f, 3423.6895f, 4233.3169f, 4856.7813f, 5086.5723f, 5393.9961f, 5938.6035f, + 323.9659f, 433.8731f, 1045.5168f, 1369.1907f, 1561.9178f, 1984.2457f, 2224.0959f, 2747.3657f, 2995.0359f, 3242.9248f, 3501.0344f, 4022.2388f, 4847.4985f, 5210.9922f, 5658.1357f, 6005.0718f, + 354.6574f, 501.6520f, 852.5305f, 1020.8707f, 1540.5925f, 1998.5675f, 2253.1487f, 2845.3960f, 3056.5273f, 3305.0466f, 3954.2900f, 4591.7471f, 4915.2856f, 5221.9082f, 5544.7285f, 5879.9150f, + 363.1311f, 474.7310f, 907.5490f, 1106.8586f, 1367.2662f, 1646.6934f, 2031.3650f, 2326.4382f, 2568.6519f, 3030.1091f, 3905.6482f, 4265.9111f, 4716.1831f, 5017.0454f, 5469.8149f, 5958.6182f, + 379.9262f, 524.4459f, 845.4813f, 1275.4414f, 1458.2488f, 1772.5863f, 2067.7981f, 2526.8850f, 3066.4063f, 3307.8713f, 3807.2900f, 4199.1509f, 4452.4653f, 4854.7471f, 5464.8833f, 5947.7842f, + 371.8218f, 483.9148f, 778.2747f, 1208.0812f, 1366.3983f, 1623.4895f, 1798.8777f, 2224.6445f, 3103.7175f, 3386.0408f, 3782.8284f, 4307.4727f, 4698.8994f, 5118.1255f, 5505.1919f, 5921.1724f, + 217.9059f, 323.3224f, 639.7305f, 1026.5331f, 1312.9242f, 1885.6948f, 2361.8403f, 2805.5396f, 3213.2600f, 3631.5017f, 4033.4087f, 4426.3423f, 4821.3203f, 5208.3833f, 5590.5205f, 5956.1538f, + 211.9971f, 311.2018f, 504.6345f, 858.3289f, 1574.7019f, 1934.9866f, 2381.4163f, 2786.2043f, 3238.9326f, 3611.0518f, 4005.2578f, 4401.0615f, 4802.1479f, 5192.5493f, 5587.1479f, 5965.5977f, + 219.3884f, 319.3835f, 604.0102f, 1114.8630f, 1481.3870f, 2036.0469f, 2303.4883f, 2616.1384f, 3253.6335f, 3556.5107f, 3946.6567f, 4520.3555f, 5091.0479f, 5416.3037f, 5748.5737f, 5946.5757f, + 350.3716f, 515.4462f, 756.5206f, 1061.4270f, 1251.9570f, 1723.2751f, 2687.6689f, 3036.2019f, 3273.9678f, 3744.2939f, 4098.6284f, 4391.4160f, 4917.6777f, 5244.2852f, 5551.4976f, 5880.1572f, + 311.6069f, 458.7317f, 795.9418f, 969.5021f, 1511.2507f, 1952.5673f, 2273.6116f, 2795.8657f, 3049.7053f, 3578.0598f, 3911.1873f, 4327.2598f, 4735.3105f, 5122.3423f, 5479.7817f, 5858.1504f, + 267.8399f, 390.6757f, 886.2357f, 1179.5110f, 1466.6409f, 2088.7725f, 2328.1262f, 2993.5786f, 3283.5256f, 3593.2822f, 4095.7588f, 4500.4009f, 4887.5132f, 5219.0859f, 5553.4224f, 5915.6831f, + 279.2209f, 413.3200f, 648.4438f, 1282.1798f, 1793.2556f, 1952.1060f, 2484.9436f, 2857.3630f, 3077.2114f, 3548.2585f, 4045.4526f, 4309.5947f, 4760.2900f, 5208.1948f, 5620.9717f, 5968.3237f, + 306.2321f, 424.7843f, 618.7867f, 1288.7572f, 2110.7849f, 2346.5396f, 2582.5366f, 2833.5730f, 3074.3774f, 3464.7886f, 3984.6379f, 4262.0337f, 4601.5132f, 4999.6992f, 5498.8926f, 5920.4814f, + 259.2613f, 353.6931f, 762.5328f, 1906.2162f, 2088.1213f, 2317.9741f, 2546.5935f, 2880.3687f, 3332.0002f, 3636.9216f, 3946.4287f, 4226.0356f, 4502.1084f, 5007.0601f, 5496.4824f, 5924.8877f, + 244.3871f, 357.0287f, 1114.7865f, 1651.1329f, 1850.2976f, 2200.5942f, 2484.7026f, 2872.6968f, 3092.8455f, 3373.5869f, 3707.5891f, 4180.1289f, 4603.5298f, 5132.2671f, 5554.7617f, 5973.5220f, + 700.5439f, 1363.5277f, 1745.2494f, 2081.9539f, 2379.8628f, 2623.6003f, 2883.6484f, 3133.9824f, 3457.7092f, 3819.0100f, 4191.0537f, 4547.0400f, 4912.5127f, 5241.3423f, 5594.9395f, 5930.6099f, + 268.7704f, 370.8200f, 609.4679f, 1558.5339f, 1961.6279f, 2155.8916f, 2419.4485f, 2655.5103f, 3152.6685f, 3426.9221f, 3716.8181f, 4107.1616f, 4965.5698f, 5384.2026f, 5706.7183f, 6015.6196f, + 305.7638f, 395.9599f, 1103.0944f, 1383.6494f, 1612.9742f, 1915.2496f, 2189.8008f, 2555.3608f, 2720.8220f, 3038.2434f, 3927.1301f, 4263.0518f, 4685.7217f, 4984.1377f, 5272.6162f, 5984.5376f, + 294.0385f, 426.7762f, 814.5162f, 1056.9037f, 1715.3539f, 2005.3177f, 2316.4392f, 2647.4297f, 2893.8242f, 3196.7476f, 3720.0044f, 4186.9790f, 4840.4512f, 5290.1250f, 5684.2139f, 5967.5859f, + 359.5141f, 517.6051f, 807.4898f, 1143.5930f, 1328.1393f, 1814.7098f, 2309.8894f, 2618.8655f, 3160.5962f, 3445.0479f, 3883.2664f, 4235.5200f, 4718.7324f, 5367.3608f, 5765.9331f, 6034.9233f, + 241.5752f, 375.5109f, 818.8776f, 1298.7773f, 1656.9050f, 2169.8962f, 2565.1440f, 3015.9919f, 3437.9463f, 3863.8203f, 4254.4023f, 4637.0952f, 5027.8252f, 5358.3784f, 5685.5000f, 5980.4063f, + 322.5406f, 454.9644f, 963.3659f, 1513.8885f, 1704.5070f, 2235.6599f, 2523.6467f, 2995.0757f, 3287.8682f, 3552.8811f, 3872.4360f, 4201.2227f, 4571.9087f, 5066.6792f, 5562.1206f, 5935.7900f, + 412.5748f, 615.8419f, 1126.9519f, 1455.5172f, 1653.3076f, 1965.2689f, 2240.6904f, 2672.5129f, 3127.3301f, 3477.8540f, 3983.6145f, 4458.6558f, 4896.7998f, 5237.9814f, 5609.1597f, 5939.6416f, + 342.1361f, 470.6100f, 958.3576f, 1195.0166f, 1426.4667f, 1684.2009f, 2194.0950f, 2545.9453f, 2946.1851f, 3415.2820f, 3657.4158f, 4408.6763f, 5097.2251f, 5404.2202f, 5719.9829f, 5977.7959f, + 297.8767f, 386.6347f, 1095.8346f, 1454.3085f, 1651.6417f, 1927.9633f, 2198.4927f, 2583.1694f, 2757.0144f, 3009.6497f, 3310.9514f, 3956.9753f, 4677.3208f, 5122.2222f, 5539.0688f, 5993.0542f, + 334.7170f, 450.1582f, 747.3162f, 1560.2024f, 1808.2147f, 2006.5011f, 2415.2419f, 2680.1956f, 3016.5549f, 3651.1340f, 3975.3625f, 4209.6563f, 4531.0396f, 5121.7212f, 5585.2202f, 5962.3667f, + 256.4101f, 495.5723f, 1341.4860f, 1805.1255f, 2201.8318f, 2514.7769f, 2820.4092f, 3102.3867f, 3414.3872f, 3754.7742f, 4108.2378f, 4465.9258f, 4857.4355f, 5216.2144f, 5592.3076f, 5951.9995f, + 530.7974f, 1017.4255f, 1463.9575f, 1858.6631f, 2360.1265f, 2770.3811f, 3106.0894f, 3379.1919f, 3647.7175f, 3895.9026f, 4188.8652f, 4522.8984f, 4893.7954f, 5241.4312f, 5623.8994f, 5975.3608f, + 597.1553f, 1198.0758f, 1722.7361f, 2128.6658f, 2519.1504f, 2825.5122f, 3086.1943f, 3330.0283f, 3608.2961f, 3906.9929f, 4241.8105f, 4603.1694f, 4972.8159f, 5308.1670f, 5651.1968f, 5976.6704f, + 699.1581f, 1293.3193f, 1637.3395f, 1912.7987f, 2163.3445f, 2425.7944f, 2704.0396f, 3006.5984f, 3358.2126f, 3746.1548f, 4125.0762f, 4489.7485f, 4854.0088f, 5188.5146f, 5558.2056f, 5913.3164f, + 489.0107f, 921.4806f, 1329.8511f, 1644.8383f, 2013.6794f, 2365.2683f, 2746.1553f, 3085.6912f, 3457.0234f, 3825.2183f, 4203.4224f, 4575.9331f, 4950.6606f, 5298.7559f, 5659.8618f, 5997.0015f, + 230.3653f, 389.8415f, 938.1970f, 1294.3594f, 1768.8275f, 2189.1001f, 2597.3755f, 2985.8518f, 3323.6023f, 3705.8533f, 4065.5361f, 4446.4224f, 4818.4502f, 5185.9634f, 5583.2168f, 5954.2573f, + 283.9404f, 400.2146f, 630.6198f, 1491.5646f, 2295.1375f, 2496.3457f, 2726.5803f, 2971.1951f, 3207.2317f, 3634.5439f, 4178.0376f, 4423.5537f, 4836.2109f, 5172.1821f, 5464.0454f, 5777.5801f, + 242.6232f, 351.1541f, 807.9852f, 1621.9950f, 2043.8676f, 2532.5122f, 2860.5505f, 3200.3403f, 3499.8274f, 3760.3772f, 4068.9617f, 4410.7339f, 4778.8413f, 5153.0142f, 5553.1997f, 5932.5996f, + 227.3320f, 323.2667f, 752.3189f, 1572.3750f, 1930.6083f, 2355.0117f, 2717.6223f, 2968.3215f, 3233.4026f, 3551.9622f, 3918.5608f, 4346.0190f, 4778.6880f, 5159.6172f, 5568.5566f, 5980.8086f, + 307.9120f, 439.7297f, 660.0276f, 1243.3854f, 1532.3577f, 1796.3936f, 2437.3232f, 2691.4072f, 3030.3025f, 3524.1379f, 3771.7576f, 4083.2375f, 4601.1567f, 4963.4697f, 5434.8530f, 5942.8315f +}; + +const float lsf_cdk_nb_gc_stg1[] = +{ + -50.2820f, -20.3699f, -85.9016f, -168.2552f, -219.7203f, -228.3721f, -209.7385f, -115.7139f, -70.1936f, 2.9143f, 53.7331f, 204.0881f, 324.2565f, 283.0311f, 194.2415f, 55.6127f, + -7.7024f, 55.3216f, 40.0302f, -2.6173f, -31.0254f, -49.9638f, -89.5104f, -79.9710f, -100.2947f, -84.2426f, -89.8130f, -44.4505f, 8.1330f, 123.3018f, 115.2609f, 17.5947f, + -29.7454f, 23.9522f, -6.6145f, -47.3088f, -83.6021f, -109.3905f, -118.2556f, -70.7910f, -71.2423f, -49.5609f, -49.3213f, 0.8054f, 70.8270f, 167.7499f, 132.1748f, 26.7946f, + -46.7868f, 21.9789f, 17.0331f, 1.6574f, -5.3416f, -1.5485f, -24.7294f, -2.2697f, -36.0918f, -31.9601f, -52.9409f, -18.2356f, -16.6137f, 52.8291f, 99.2958f, 9.2780f, + -48.8451f, -8.8573f, -49.2111f, -93.0997f, -116.0209f, -119.2193f, -130.6934f, -90.0435f, -85.8524f, -49.9080f, -30.8948f, 57.8291f, 207.6663f, 238.5938f, 162.1688f, 42.1291f, + 6.0599f, 96.6534f, 89.7254f, 64.7391f, 47.1759f, 39.3332f, 3.8599f, 12.1104f, -25.8483f, -30.7162f, -54.9950f, -24.3625f, -65.0093f, -91.8893f, 41.2788f, -9.3500f, + -74.6215f, -34.1444f, -45.1607f, -35.7601f, 20.1298f, 61.8053f, 45.9485f, 61.3004f, 23.1269f, 17.0184f, -14.6351f, 11.5369f, 40.6714f, 134.6762f, 127.4157f, 23.2286f, + -53.8382f, -7.1967f, 51.3428f, 149.2781f, 132.0314f, 106.9591f, 40.3082f, 28.7839f, -20.0071f, -32.1960f, -69.3754f, -44.7267f, -19.1058f, 81.8775f, 103.3263f, 11.7826f, + -83.4690f, -58.9994f, -100.6923f, -109.7423f, -77.3123f, -51.0569f, -49.0334f, -11.2254f, -13.7028f, 11.7115f, 17.4433f, 113.4333f, 269.5462f, 270.9727f, 181.4436f, 50.9590f, + 19.0904f, 106.4309f, 78.2419f, 22.1934f, -28.2661f, -71.6118f, -97.8980f, -57.5252f, -73.2944f, -59.0236f, -70.7380f, -30.7879f, -16.6118f, 71.0734f, 102.1686f, 10.6722f, + -44.5958f, 9.5910f, -9.9670f, -35.4491f, -36.7779f, -38.2726f, -71.5033f, -56.3692f, -75.3217f, -60.2630f, -64.3206f, -15.0396f, 51.1008f, 156.1136f, 128.1305f, 24.1397f, + -26.8342f, 50.7102f, 47.9495f, 34.1131f, 33.1750f, 40.6004f, 1.8381f, 6.9380f, -34.5476f, -37.5681f, -63.3813f, -32.2824f, -50.5980f, -25.5098f, 69.6276f, -1.2117f, + 6.7027f, 67.8112f, 38.0872f, -23.7302f, -79.0851f, -119.7724f, -146.1929f, -104.8024f, -107.0018f, -86.5365f, -75.9935f, -16.8613f, 84.1440f, 178.1427f, 133.5219f, 27.8811f, + 46.6789f, 157.1987f, 135.6186f, 86.3393f, 50.7338f, 16.6195f, -30.7043f, -23.0751f, -58.4989f, -58.2831f, -83.9640f, -51.4746f, -40.3803f, 39.6990f, 89.0926f, 5.3683f, + -66.8068f, -25.7930f, -49.4702f, -55.7445f, -47.4219f, -47.2327f, -55.9657f, -21.6380f, -32.0155f, -16.3766f, -23.1897f, 25.9724f, 108.6076f, 192.8678f, 143.8874f, 32.5168f, + -29.4610f, 51.1883f, 125.8174f, 178.0158f, 192.4019f, 200.6733f, 150.3214f, 139.0109f, 70.5642f, 49.0546f, 5.2967f, 10.7600f, -32.3233f, -56.1770f, 38.7244f, -6.3720f, + -90.7935f, -86.8579f, -165.1847f, -206.9982f, -177.3116f, -110.7218f, -60.4555f, 28.9968f, 59.3721f, 111.7430f, 148.9078f, 297.0840f, 382.8354f, 319.0586f, 217.5980f, 66.9906f, + -8.8907f, 51.2038f, 20.6150f, -25.0275f, -6.4919f, 28.5998f, -19.2903f, -28.0775f, -67.6854f, -70.6924f, -91.1332f, -51.9799f, 4.7191f, 121.9776f, 114.5332f, 16.9555f, + -29.5779f, 38.1348f, 16.9460f, -13.1717f, -43.7665f, -58.5053f, -66.8853f, -23.5223f, -47.7123f, -38.4358f, -52.6004f, -12.1781f, -9.5310f, 62.0772f, 102.4962f, 10.5329f, + -51.3839f, 10.1170f, 8.8413f, 7.1799f, 27.0856f, 57.8446f, 40.2151f, 55.8005f, 14.1522f, 8.5107f, -25.3037f, -4.1035f, -34.2602f, -19.2221f, 74.9812f, 1.2982f, + -9.0629f, 39.9632f, -4.2048f, -68.4062f, -125.5652f, -168.4946f, -200.3423f, -148.8132f, -131.2517f, -83.3627f, -43.4004f, 70.8276f, 231.0238f, 241.4682f, 165.0121f, 42.8259f, + 23.0736f, 143.9185f, 165.8485f, 141.1318f, 126.9031f, 113.7775f, 58.7625f, 48.6260f, 0.7530f, -14.8817f, -51.1437f, -31.9407f, -63.3610f, -68.5826f, 42.2195f, -8.3010f, + -64.7372f, -30.3666f, -13.8118f, 64.0613f, 130.9271f, 167.6980f, 130.2968f, 120.2481f, 53.8473f, 30.9594f, -13.2901f, -0.2919f, -12.6298f, 33.0601f, 89.8137f, 7.9164f, + -27.4071f, 46.5739f, 73.0324f, 90.7500f, 97.4257f, 110.0360f, 75.8612f, 77.2110f, 30.1418f, 14.8390f, -22.5191f, -7.5352f, -58.3772f, -104.3289f, 27.0985f, -11.5599f, + -48.6199f, -8.4983f, -71.8930f, -149.9820f, -149.4210f, -44.3473f, 3.8456f, 37.8226f, 11.8655f, 4.7745f, -23.8053f, 15.0402f, 99.2230f, 190.4169f, 143.6005f, 32.2851f, + 15.9306f, 86.2159f, 75.9614f, 40.8587f, 13.8614f, -5.1135f, -53.5447f, -49.2651f, -83.1781f, -77.3701f, -94.7805f, -58.1423f, -37.1552f, 59.5436f, 95.8876f, 7.8334f, + -71.4812f, -18.0191f, -10.6353f, -10.9646f, -4.7830f, 7.0689f, -8.9645f, 17.0751f, -8.9055f, -4.5033f, -26.7167f, 6.5207f, 41.1034f, 136.7648f, 126.6881f, 22.6529f, + -13.3071f, 67.8215f, 50.5701f, 22.0055f, -0.1895f, -16.2081f, -44.2669f, -15.2243f, -42.5961f, -37.7900f, -54.1335f, -14.8001f, -44.7622f, -39.3502f, 68.9017f, -1.9700f, + 54.4719f, 135.4882f, 107.6822f, 37.1723f, -15.7729f, -58.2111f, -117.6718f, -111.5628f, -125.9742f, -95.3344f, -71.1785f, 20.4405f, 178.9972f, 225.0608f, 154.3984f, 37.7039f, + 199.1418f, 301.5473f, 242.3446f, 156.1444f, 129.3343f, 112.5769f, 60.9076f, 24.7294f, -36.1788f, -44.7856f, -49.6138f, 35.8621f, 132.4271f, 180.8326f, 145.9355f, 30.7412f, + -95.8307f, -73.4794f, -76.3260f, -32.8480f, 25.0377f, 53.0367f, 47.9260f, 71.8612f, 48.9617f, 48.0805f, 31.5298f, 92.4644f, 215.5727f, 252.6642f, 172.3081f, 47.3738f, + -2.1387f, 144.6784f, 257.4241f, 293.7984f, 302.9054f, 301.4404f, 234.6555f, 199.2878f, 117.8049f, 82.4572f, 28.1316f, 27.9394f, -20.8952f, -53.5108f, 47.9862f, -3.2292f +}; + +const float lsf_cdk_nb_gc_stg2[] = +{ + -11.7897f, -34.0201f, -78.3915f, -67.4130f, 11.6646f, 27.0897f, + -25.4365f, -16.9519f, 1.3623f, -14.4721f, -40.8934f, -28.8082f, + -17.5541f, -24.8863f, -42.0546f, -57.4396f, -48.2462f, -17.3640f, + -23.4838f, -18.0105f, -23.4463f, -23.8641f, 20.1374f, 22.8944f, + -27.9673f, -51.2149f, -32.0136f, 58.4191f, 66.0445f, 33.8922f, + -28.8229f, -24.7667f, 12.6486f, 32.0241f, 14.4964f, 5.0635f, + 11.7718f, 12.7508f, -18.2755f, -64.0918f, -88.2808f, -46.2724f, + 11.7478f, -4.0560f, -28.8370f, -15.2873f, -17.0688f, -21.2716f, + 21.1704f, 4.6685f, -15.1944f, 19.2773f, 48.9464f, 24.7768f, + -31.9223f, -48.4027f, -40.5826f, -2.3521f, -7.7634f, -9.3639f, + 49.8116f, 38.9864f, -9.6274f, -43.4792f, -14.3368f, 6.7127f, + -17.8859f, 16.5261f, 17.9780f, -18.2431f, -4.9259f, 4.9691f, + 34.1057f, 28.5456f, 37.3357f, 25.9730f, -12.0323f, -14.3174f, + -35.7203f, -11.7712f, 71.0202f, 87.9962f, 53.5089f, 22.0342f, + -29.0835f, 7.8202f, 61.7147f, 30.4243f, -7.0096f, -12.3327f, + 121.0591f, 124.7827f, 86.3632f, 52.5283f, 25.7588f, 2.2977f +}; + +const float lsf_cdk_nb_gc_stg3[] = +{ + -20.1057f, -62.1359f, -90.9211f, -83.2088f, -41.8080f, 4.3801f, 64.9293f, 55.2259f, 18.8953f, 8.4560f, + -12.4851f, -29.8479f, -46.3014f, -59.0597f, -57.9280f, -55.5646f, -16.2912f, 29.7501f, 6.4438f, 1.9289f, + -42.4234f, -57.2848f, -42.1410f, -25.0914f, -20.5850f, -22.9466f, -28.6753f, -9.5206f, -2.8536f, -2.4606f, + 2.9437f, -3.2337f, -19.4418f, -30.8279f, -40.2200f, -54.7107f, -69.2608f, -36.5696f, -14.6763f, -7.4390f, + 56.9685f, 42.9405f, 2.6357f, -28.9316f, -41.7842f, -41.1244f, 7.2469f, 37.7725f, 9.4299f, 3.8716f, + -13.4056f, -11.0915f, -7.8932f, -4.4242f, -3.6432f, -6.2205f, -52.2374f, -101.3244f, -31.8836f, -12.9959f, + -49.5845f, -68.9839f, -40.9861f, -4.8425f, 25.7585f, 49.5206f, 52.3506f, 42.0803f, 18.1566f, 7.3750f, + 7.9175f, 30.0116f, 39.2961f, 39.8519f, 33.8428f, 18.7027f, -42.1156f, -114.4817f, -41.9139f, -14.3475f, + -10.3140f, -13.1813f, -8.6771f, -12.5086f, -7.9996f, 8.1476f, 62.8062f, 70.2916f, 23.1315f, 10.3555f, + 7.8827f, -9.7751f, -27.3751f, -19.0843f, -3.1083f, 5.0911f, -8.9477f, -1.9864f, -0.0476f, -1.0431f, + -25.6990f, -1.3466f, 13.9307f, -1.5450f, -21.5161f, -36.5054f, -27.3657f, 9.1052f, 0.5716f, -0.5675f, + 26.0226f, 39.0806f, 25.3016f, 10.6567f, -7.6451f, -27.7012f, -57.9450f, -49.0041f, -17.4613f, -8.2350f, + 24.7306f, 40.5991f, 39.1729f, 32.6364f, 20.0500f, 9.7588f, 17.8440f, 32.3000f, 10.7014f, 4.0975f, + -31.9825f, -23.6145f, 19.2348f, 43.8139f, 32.4545f, 14.8018f, -12.9031f, -14.2377f, -3.4099f, -2.2026f, + 17.4813f, 29.7370f, 40.6045f, 56.0407f, 77.3266f, 109.6360f, 126.9981f, 90.0105f, 41.2847f, 18.3934f, + 62.0530f, 98.1263f, 103.5605f, 86.5243f, 56.8051f, 24.7345f, -16.4333f, -39.4116f, -16.3685f, -5.1868f +}; + +const float lsf_cdk_nb_vc_stg1[] = +{ + -47.8739f, -33.3324f, -111.7403f, -187.1021f, -217.8067f, -211.2333f, -197.1951f, -112.5993f, -54.4085f, 25.6601f, 103.3922f, 273.8963f, 384.4787f, 321.9756f, 214.8825f, 64.7502f, + 5.7213f, 62.0822f, 4.1813f, -75.3379f, -130.0791f, -169.8000f, -137.2333f, -8.1913f, 9.1551f, 12.5919f, -10.2666f, 24.1670f, 78.8903f, 170.0603f, 136.5900f, 28.5131f, + -61.2759f, -38.8420f, -92.0781f, -106.8447f, -84.5683f, -75.2343f, -90.1177f, -57.8575f, -57.3309f, -23.0973f, -6.5859f, 96.8941f, 263.0488f, 266.3097f, 177.9874f, 48.9404f, + -4.6756f, 65.2555f, 47.7555f, 30.0066f, 28.7910f, 33.2401f, 1.0363f, 13.6479f, -20.0856f, -24.5283f, -44.3793f, -10.0354f, -56.2017f, -77.3347f, 55.5984f, -6.2838f, + -40.8653f, -14.8363f, -92.0112f, -175.7323f, -221.1710f, -161.1121f, -52.8429f, 37.5645f, 41.2468f, 45.5229f, 26.4500f, 86.3998f, 219.2824f, 253.3986f, 172.4165f, 46.3912f, + -35.6673f, 17.5904f, -11.9410f, -25.7858f, -8.8584f, 21.6273f, 0.1729f, 6.5783f, -34.6991f, -36.4150f, -56.0023f, -21.0789f, -19.8846f, 54.1067f, 99.1987f, 9.4728f, + -14.2776f, 27.3931f, -14.6997f, -66.6010f, -99.6813f, -122.6578f, -150.2305f, -113.9728f, -109.1274f, -78.9555f, -60.2257f, 27.8011f, 190.2385f, 229.8084f, 157.2525f, 39.3867f, + 7.6929f, 67.9322f, 38.8456f, -21.1201f, -59.7777f, -99.3488f, -141.1098f, -110.2669f, -114.7237f, -91.8703f, -77.7551f, -15.8694f, 90.5305f, 184.5058f, 136.0935f, 29.0311f, + -81.2402f, -78.5803f, -151.4014f, -172.9501f, -128.6324f, -73.2223f, -54.4444f, -10.0382f, 0.8191f, 49.8313f, 85.4796f, 237.9407f, 375.9963f, 320.3293f, 212.6340f, 64.0690f, + -7.5501f, 56.9796f, 22.4374f, -12.3837f, -25.5942f, -46.4205f, -67.6393f, -25.5805f, -48.1321f, -39.6622f, -53.1014f, -11.2472f, -23.2435f, 35.6549f, 94.7977f, 6.9705f, + -35.2312f, 5.7296f, -40.3538f, -74.0301f, -73.9051f, -78.4101f, -69.6657f, -23.5663f, -38.8351f, -23.3996f, -29.2527f, 14.7714f, 60.7441f, 159.3770f, 132.0680f, 26.1624f, + 63.7916f, 158.4710f, 108.6537f, 49.2831f, 12.4814f, -34.2755f, -68.0055f, -38.2006f, -61.2743f, -54.7496f, -73.2102f, -37.3536f, -2.8530f, 99.6502f, 109.4658f, 14.7136f, + -46.8550f, -17.8951f, -73.5817f, -109.9269f, -59.6995f, 13.9228f, 17.3227f, 37.6147f, 5.2378f, 2.5800f, -15.0369f, 23.6412f, 86.2658f, 178.2385f, 140.5764f, 30.3354f, + -64.0179f, -34.7786f, -33.8634f, 32.5490f, 41.5821f, 30.0052f, 2.8933f, 7.9098f, -23.6020f, -21.4437f, -40.3389f, -5.3147f, 46.4389f, 149.8765f, 129.5062f, 24.3633f, + 53.2208f, 88.2962f, 18.1083f, -68.6983f, -163.9225f, -257.5996f, -286.3273f, -136.1982f, -54.0297f, 17.4621f, 96.5930f, 257.5079f, 374.4247f, 316.8143f, 211.5481f, 63.1783f, + 174.9770f, 220.4714f, 114.9514f, 39.1980f, 15.6628f, -57.4971f, -151.3537f, -151.4255f, -122.5434f, -39.5915f, 43.3476f, 204.8011f, 347.0733f, 300.8141f, 202.2481f, 58.3570f, + -24.8002f, 5.5647f, -51.1305f, -108.2679f, -143.4691f, -168.1934f, -183.0667f, -123.7768f, -105.2566f, -53.2548f, -15.6183f, 132.2483f, 301.9698f, 276.6960f, 185.6425f, 51.4215f, + 63.0767f, 97.9030f, 23.3427f, -27.8271f, -7.6827f, 11.5110f, -9.1648f, -16.5310f, -60.2418f, -68.6020f, -79.4697f, -9.9630f, 143.1208f, 212.2018f, 148.4344f, 34.8853f, + -52.8577f, -17.0901f, -38.4446f, -44.4913f, -48.3650f, -49.3479f, -79.7237f, -66.0328f, -77.9226f, -56.8956f, -48.1326f, 19.1059f, 138.4749f, 210.3387f, 148.5705f, 35.3026f, + 16.4209f, 102.4966f, 100.9513f, 64.0511f, 50.2873f, 36.1014f, -21.6103f, -26.7705f, -65.0290f, -62.8056f, -83.1056f, -46.5621f, -51.3341f, 1.7945f, 78.1135f, 1.0912f, + -75.6609f, -71.8274f, -139.7561f, -117.4244f, -22.4806f, 39.5285f, 53.1389f, 65.2518f, 36.9996f, 37.9781f, 25.3240f, 92.8186f, 227.9041f, 260.3466f, 176.7927f, 48.2170f, + -18.6440f, 33.8824f, 28.5803f, 10.9212f, 5.0722f, 4.4072f, -39.6675f, -38.3990f, -75.6662f, -72.1438f, -87.2765f, -46.7029f, -6.7231f, 107.6602f, 110.8838f, 15.3706f, + 21.3981f, 74.2394f, 19.3760f, -47.0944f, -99.2094f, -138.5254f, -193.3578f, -171.5091f, -176.8980f, -112.0385f, -43.8164f, 79.0272f, 251.8247f, 251.6656f, 170.8083f, 44.5524f, + 67.4133f, 149.9282f, 118.6238f, 30.5943f, -33.2344f, -70.7200f, -120.6338f, -105.4183f, -118.8368f, -86.5003f, -64.0278f, 50.0950f, 231.7671f, 247.4923f, 167.0543f, 43.3706f, + -40.9878f, -39.3167f, -163.9672f, -281.7721f, -267.4339f, -138.3948f, -88.8411f, 0.7440f, 65.0724f, 165.9769f, 269.7260f, 427.8145f, 485.5638f, 388.7820f, 254.5937f, 84.1430f, + 12.9002f, 76.9394f, 62.5283f, 13.6656f, -10.4341f, -35.7194f, -84.1773f, -75.4588f, -98.8663f, -85.0203f, -91.0417f, -43.6094f, 6.1868f, 120.0995f, 114.3634f, 17.2779f, + -21.4884f, 29.4970f, 1.0910f, -37.4928f, -55.1841f, -66.8253f, -92.8491f, -74.1643f, -90.3904f, -72.3158f, -69.6267f, -16.2943f, 51.2075f, 158.6230f, 128.0881f, 24.5940f, + 140.4902f, 213.5873f, 167.7455f, 102.0038f, 85.7659f, 59.5426f, 9.2403f, -0.7622f, -35.6690f, -35.9801f, -58.6565f, -15.1000f, 23.5135f, 101.5155f, 111.5278f, 16.5967f, + -62.8100f, -47.2312f, -97.3130f, -60.9976f, 82.6761f, 193.9902f, 154.0588f, 118.2896f, 43.6828f, 13.9735f, -22.6650f, 0.5943f, 26.8732f, 111.3673f, 120.5305f, 20.1022f, + -44.4747f, -10.4204f, 32.1805f, 131.3261f, 157.9129f, 155.8841f, 90.2107f, 70.7406f, 9.4064f, -4.0535f, -42.4163f, -26.0150f, -39.1314f, 20.5559f, 82.2390f, 4.9553f, + 88.4086f, 134.4090f, 60.3778f, -13.5659f, -72.1912f, -160.4579f, -261.2583f, -247.6886f, -121.4628f, -13.9737f, 35.4003f, 197.3431f, 335.8232f, 294.0672f, 197.4029f, 56.5130f, + 267.3715f, 336.4754f, 224.6896f, 104.9689f, 104.5109f, 94.7971f, -20.0482f, -88.9197f, -142.8754f, -60.7279f, 30.3207f, 189.5033f, 335.5709f, 295.5561f, 200.0838f, 57.2552f +}; + +const float lsf_cdk_nb_vc_stg2[] = +{ + -9.6827f, -17.9738f, -44.2587f, -53.7409f, 10.1005f, 32.4057f, + -29.5803f, -35.3673f, -50.3175f, -49.1053f, -47.5762f, -37.2894f, + -10.3138f, -3.1171f, 2.9317f, -20.2045f, -78.9643f, -84.6932f, + 13.6252f, 8.7360f, -21.5126f, -20.8022f, -14.8279f, -30.9676f, + -28.1089f, -48.1602f, -64.6161f, -0.2872f, 108.6371f, 93.6271f, + -38.2393f, 1.9703f, 14.1451f, -7.5949f, 39.2872f, 33.7052f, + -38.5209f, -10.1299f, 61.9126f, 45.3993f, -7.5115f, -17.0167f, + 26.2164f, 20.2119f, 40.4075f, 45.2381f, -2.3925f, -17.4109f, + -19.1953f, -10.5024f, 12.6622f, -19.8408f, -40.6066f, 1.8757f, + -32.7274f, -41.0545f, -26.1793f, 15.7486f, 1.2783f, -17.0256f, + 3.5921f, 2.2211f, -27.0254f, -81.1776f, -88.9427f, -11.1151f, + 48.7753f, 42.6625f, 3.8241f, -21.1582f, 27.5770f, 36.8815f, + 6.8266f, -6.1852f, -19.6226f, 28.9512f, 50.9852f, 15.2853f, + -33.3786f, -38.1386f, 24.6782f, 95.1954f, 64.2442f, 33.4105f, + 49.0652f, 49.8207f, 29.3688f, -11.7891f, -57.3484f, -44.4722f, + 91.6464f, 85.0063f, 63.6020f, 55.1679f, 36.0606f, 12.7997f +}; + +const float lsf_cdk_nb_vc_stg3[] = +{ + -16.5483f, -67.8691f, -113.3476f, -92.9768f, -18.1549f, 21.7013f, 31.7869f, 25.1431f, 9.0112f, 3.4920f, + -7.8375f, -22.7162f, -45.0895f, -61.3419f, -64.4643f, -67.3643f, -44.8953f, -6.2556f, -7.9342f, -3.9490f, + -63.5255f, -72.6896f, -45.5471f, -30.5803f, -26.8317f, -24.4668f, -15.1301f, 4.8754f, -0.5588f, -0.8157f, + -2.2381f, 13.4403f, 16.0097f, 1.0526f, -24.8448f, -61.3997f, -91.3894f, -39.4637f, -19.2183f, -9.1265f, + -16.0140f, -32.7087f, -45.2478f, -59.4365f, -60.1819f, -31.6687f, 70.4575f, 64.2544f, 19.1841f, 9.3201f, + -8.2141f, 2.4761f, 7.4360f, 11.7049f, 14.0396f, 16.9693f, -53.7166f, -119.3159f, -33.5007f, -15.4114f, + -64.5115f, -52.5888f, 30.5453f, 56.2986f, 31.6535f, 9.3509f, 4.3678f, 13.3055f, 5.1440f, 2.0290f, + 22.3180f, 44.1101f, 48.7477f, 40.2739f, 14.9495f, -7.3707f, -10.3082f, 6.3741f, 1.0122f, 0.2673f, + -42.3440f, -58.8447f, -42.2171f, -8.0384f, 34.3873f, 59.7095f, 50.7660f, 38.7146f, 16.7582f, 7.2512f, + -0.1088f, -28.5624f, -30.3477f, -2.8206f, -1.3093f, -12.9286f, -21.2371f, -1.4331f, -2.6014f, -1.5170f, + -41.2001f, 4.7383f, 13.3788f, -12.5767f, -22.3489f, -14.4064f, 10.9753f, 22.2182f, 6.2625f, 2.5488f, + 63.9302f, 51.1717f, 10.5411f, -23.3105f, -47.9860f, -59.1260f, -29.9675f, 0.0559f, -4.8774f, -2.3217f, + 37.1022f, 14.8587f, -19.5761f, -23.3122f, 2.3273f, 32.9204f, 53.1779f, 43.4994f, 16.5403f, 7.5156f, + 48.8143f, 82.6708f, 85.7133f, 77.5688f, 56.9332f, 24.0950f, -63.9412f, -138.5729f, -45.8026f, -17.6440f, + -4.0024f, 18.2212f, 40.5425f, 57.9095f, 69.5262f, 79.8498f, 71.0971f, 51.3637f, 24.2751f, 10.9558f, + 94.3797f, 104.2925f, 88.4585f, 69.5855f, 42.3052f, 34.1349f, 37.9570f, 35.2368f, 16.3058f, 7.4056f +}; + +const float lsf_cdk_wb_gc_stg1[] = +{ + -21.1721f, -6.9787f, -78.7739f, -158.7331f, -205.5198f, -259.2706f, -287.6161f, -271.9965f, -264.8213f, -231.0206f, -194.9294f, -147.7609f, -117.1413f, -85.8077f, -63.7689f, -31.4680f, + -66.9546f, -30.5144f, -36.8376f, -53.0491f, -36.1642f, -48.5647f, -62.2295f, -55.2760f, -57.6386f, -55.8977f, -55.9952f, -40.6957f, -43.2573f, -33.7185f, -37.3113f, -27.4703f, + -18.0276f, 24.5300f, -3.1374f, -40.7788f, -39.2887f, -55.1486f, -87.4694f, -97.8466f, -113.0920f, -112.2454f, -110.4983f, -92.0446f, -80.8734f, -57.2883f, -52.4648f, -39.3426f, + -14.5043f, 41.4594f, 30.8683f, 19.7189f, 29.0785f, 7.4155f, -21.7427f, -23.9321f, -38.3113f, -41.2907f, -40.8309f, -25.7969f, -29.7702f, -20.8620f, -29.2581f, -26.0135f, + -39.7173f, -14.6068f, -62.7880f, -111.0359f, -122.7799f, -150.6084f, -167.3332f, -164.6087f, -165.9175f, -146.9592f, -135.1085f, -110.8433f, -97.6828f, -72.7079f, -64.6184f, -45.5537f, + -42.5539f, 26.5080f, 31.4593f, 1.2393f, 1.6319f, 6.6465f, 16.6621f, 35.3616f, 33.5966f, 53.0816f, 65.9800f, 78.6870f, 64.5119f, 50.4778f, 20.7076f, 7.5572f, + -2.4650f, 88.7057f, 93.4778f, 47.6900f, 47.2210f, 51.8796f, 27.4629f, 23.3020f, 8.4560f, 12.2382f, 12.4948f, 25.9549f, 18.2040f, 17.5385f, -2.2674f, -6.8910f, + -25.2995f, 40.1554f, 131.5320f, 193.8438f, 224.6298f, 213.8258f, 187.1185f, 169.5623f, 131.4438f, 108.3838f, 93.4648f, 94.1147f, 68.7427f, 48.9293f, 15.1647f, 1.4396f, + -63.4604f, -63.8774f, -152.1996f, -247.2777f, -281.1492f, -288.1032f, -252.3883f, -181.6764f, -141.4441f, -90.3039f, -56.5279f, -23.8054f, -11.9068f, -1.3377f, -7.5474f, -0.6953f, + -77.4333f, -60.8457f, -86.6258f, -86.4012f, -29.1547f, 7.2174f, 40.0438f, 63.6826f, 53.0035f, 51.5329f, 55.6684f, 68.8552f, 50.7040f, 34.0814f, 7.7594f, -2.1278f, + 30.9564f, 87.5489f, 69.5663f, 23.2907f, 13.9146f, -0.9477f, -37.0125f, -58.8950f, -99.1749f, -117.9716f, -127.4967f, -107.3465f, -91.7610f, -62.6527f, -50.4613f, -32.9533f, + -64.2954f, -37.5670f, -21.0138f, 41.6351f, 121.9423f, 170.7496f, 195.4955f, 225.2859f, 224.2241f, 223.8838f, 222.3937f, 225.7590f, 188.7341f, 143.2967f, 83.3796f, 41.8113f, + 10.6654f, 55.4135f, 18.0177f, -53.2381f, -88.7693f, -114.5825f, -122.2372f, -110.6857f, -120.7652f, -124.3872f, -136.2432f, -135.4537f, -132.9560f, -104.3421f, -82.6202f, -57.8286f, + -56.8219f, -2.2176f, 4.5106f, 4.9045f, 63.5084f, 94.3949f, 92.6963f, 98.2198f, 78.5731f, 65.0247f, 60.8502f, 70.0685f, 53.4160f, 34.2990f, 2.3436f, -13.6945f, + 62.5259f, 160.0315f, 153.0699f, 116.3367f, 94.9113f, 59.6879f, 36.7834f, 42.8554f, 34.9832f, 32.1663f, 34.2612f, 46.5764f, 32.6032f, 22.8721f, -2.2313f, -9.0276f, + -17.8885f, 81.5994f, 153.8725f, 203.3483f, 260.8972f, 308.2464f, 337.7084f, 369.5280f, 355.1932f, 340.5538f, 332.7582f, 318.9620f, 261.2268f, 196.0706f, 116.6797f, 63.9204f, + 20.6478f, 57.4084f, 3.7268f, -83.6103f, -145.3750f, -207.9262f, -235.3695f, -209.9292f, -200.7669f, -173.1530f, -148.7498f, -120.9027f, -110.3875f, -91.3718f, -83.8093f, -58.7850f, + -39.9125f, 14.8531f, -3.7779f, -42.3801f, -47.0086f, -54.0654f, -37.4186f, -7.7530f, -2.3503f, 11.8227f, 22.9690f, 37.9258f, 31.1117f, 26.1390f, 3.9131f, -4.7425f, + 13.2679f, 79.8638f, 51.3108f, -15.0032f, -39.4744f, -78.1680f, -87.2337f, -58.9813f, -51.8486f, -39.6199f, -34.6732f, -22.2829f, -24.1548f, -18.6608f, -25.3619f, -24.4411f, + -31.4295f, 11.0108f, 63.6155f, 150.7589f, 166.6739f, 132.7679f, 86.6371f, 71.7386f, 36.6906f, 13.2914f, -2.6491f, 5.5439f, -13.1750f, -13.8798f, -27.3878f, -22.3777f, + -24.3473f, 16.7839f, -21.6102f, -77.9093f, -107.7952f, -144.9666f, -139.6022f, -95.3828f, -79.5686f, -54.4138f, -40.2750f, -17.7668f, -12.9124f, -7.1218f, -21.3606f, -21.7144f, + -3.0221f, 85.8766f, 60.9027f, 16.5821f, 7.9817f, -16.4117f, -11.2119f, 17.4948f, 20.8488f, 33.8053f, 43.5158f, 54.6661f, 45.1287f, 38.3086f, 11.1080f, 2.6446f, + 6.4417f, 122.4950f, 125.6148f, 93.2892f, 108.5553f, 111.2156f, 105.3841f, 113.7573f, 102.0970f, 107.1194f, 105.9578f, 110.0393f, 89.3394f, 67.9986f, 28.3953f, 10.5845f, + 5.3008f, 132.8202f, 246.6148f, 259.5175f, 279.9749f, 270.1955f, 242.3427f, 226.1996f, 198.6216f, 175.1598f, 153.5215f, 148.0765f, 116.8644f, 82.8352f, 39.2114f, 16.4926f, + -77.2826f, -81.0630f, -142.8123f, -175.7374f, -154.6778f, -134.7003f, -107.5754f, -71.3200f, -53.8328f, -25.9739f, -7.0973f, 14.6180f, 12.4415f, 12.6191f, -3.8318f, -4.2210f, + -73.5975f, -49.6810f, -33.1272f, 10.8925f, 60.1080f, 61.8344f, 45.3548f, 45.5924f, 22.6090f, 11.2679f, 6.9455f, 18.9899f, -3.4566f, -13.0973f, -24.6136f, -17.3529f, + 93.3489f, 170.7564f, 135.3343f, 56.2893f, 22.2173f, -20.1927f, -41.3723f, -39.2133f, -50.1699f, -54.9363f, -60.2521f, -47.5990f, -54.0679f, -44.0381f, -47.1772f, -37.0088f, + -27.3811f, 60.8027f, 88.5729f, 82.6088f, 118.1956f, 140.5540f, 153.1990f, 173.3699f, 166.1148f, 168.4157f, 165.4583f, 168.4201f, 141.6623f, 111.7883f, 61.8626f, 28.6598f, + 61.0331f, 119.7275f, 83.9777f, -1.2269f, -56.5834f, -121.3104f, -176.1751f, -202.5282f, -219.9765f, -194.9138f, -167.0230f, -130.8084f, -105.0937f, -81.6082f, -73.9476f, -53.6392f, + -27.5935f, 45.9596f, 43.4074f, 35.4528f, 51.8229f, 58.2166f, 66.0162f, 87.5896f, 84.5125f, 96.2322f, 104.1692f, 116.0263f, 98.4793f, 78.3333f, 38.3067f, 15.3865f, + 174.0302f, 282.5094f, 259.6900f, 204.4108f, 189.3996f, 158.0569f, 123.9944f, 123.1922f, 118.3560f, 110.6961f, 101.0661f, 96.5273f, 78.1838f, 52.7614f, 22.4974f, 2.3781f, + 59.8885f, 245.4498f, 371.2458f, 409.7723f, 455.9382f, 450.3678f, 424.1982f, 412.1477f, 364.9408f, 325.9947f, 285.4946f, 257.5709f, 202.0349f, 150.8332f, 79.0164f, 39.6259f +}; + +const float lsf_cdk_wb_gc_stg2[] = +{ + -30.3104f, -56.7575f, -84.1487f, -72.1960f, -22.8352f, 3.3243f, + -46.3791f, -58.1840f, -25.7428f, -7.3327f, -15.5902f, -11.0671f, + -25.6715f, -22.2643f, -12.1418f, -44.6014f, -57.5933f, -25.0539f, + 20.6377f, 3.9627f, -56.7740f, -110.5344f, -99.0040f, -23.5388f, + -33.0807f, -65.7310f, -43.7344f, 59.6097f, 60.3127f, 29.3885f, + 12.2596f, 64.5636f, 86.5834f, 56.7668f, 33.1992f, 8.0321f, + -27.2580f, -0.3414f, 60.0624f, 27.3071f, -13.3937f, -18.6842f, + 24.2406f, 11.7818f, 14.7099f, 38.2644f, 1.7464f, -12.1068f, + 7.3676f, -14.0551f, -58.7823f, -43.8456f, 44.8481f, 49.4476f, + -27.1385f, -20.1290f, 3.2930f, 11.7314f, 24.8512f, 17.5045f, + 6.8143f, -14.7678f, -42.8682f, -16.1166f, -13.7942f, -20.4421f, + 1.4928f, 29.4512f, 13.1269f, -26.8534f, -7.1498f, 6.9288f, + 12.0685f, 25.8088f, 13.8913f, 37.8771f, 77.3020f, 41.3878f, + -31.3089f, -16.5767f, 72.2701f, 101.6937f, 66.1076f, 29.3520f, + 33.0047f, 43.3667f, 18.6451f, -26.2905f, -83.9726f, -67.8400f, + 103.2615f, 89.8720f, 41.6101f, 14.5203f, 4.9658f, -6.6327f +}; + +const float lsf_cdk_wb_gc_stg3[] = +{ + -41.3186f, -87.9369f, -117.0141f, -113.4593f, -76.4138f, -35.5126f, -13.8432f, -7.5581f, -3.0880f, 2.3802f, + -19.0684f, -32.7726f, -38.9479f, -44.5597f, -48.0524f, -54.3931f, -59.1547f, -53.0509f, -42.1806f, -24.7633f, + 27.3501f, -3.4361f, -42.3300f, -83.6244f, -126.2025f, -139.2743f, -121.0968f, -84.5803f, -46.8967f, -18.1514f, + -0.8794f, 7.8351f, 13.7504f, 10.5629f, -2.3365f, -27.6351f, -53.8406f, -67.9140f, -63.0094f, -41.9336f, + 9.4961f, -11.0357f, -24.5415f, -6.6821f, 20.3012f, 24.1832f, 9.4935f, -5.4294f, -16.9057f, -12.2235f, + -53.4765f, -68.3201f, -39.2295f, -10.3152f, -3.0430f, -6.2765f, -10.5345f, -10.9752f, -8.2812f, -5.0682f, + 52.0481f, 94.0614f, 84.0495f, 48.7509f, 4.2751f, -40.3696f, -69.1195f, -63.3772f, -42.9216f, -24.6160f, + 10.0049f, 13.7676f, 17.2697f, 29.3297f, 46.7856f, 60.3615f, 66.0947f, 59.6799f, 45.2938f, 27.9216f, + 3.2564f, -15.2692f, -47.6037f, -66.2845f, -62.6754f, -33.3695f, 8.7487f, 22.9938f, 23.4655f, 15.0233f, + -23.6148f, 4.1981f, 21.0969f, 4.2267f, -12.9805f, -17.4187f, -2.7787f, 14.0826f, 22.1174f, 12.4585f, + 44.7733f, 31.5401f, -0.1129f, -26.8177f, -43.6473f, -45.9941f, -38.3653f, -26.4489f, -17.8081f, -11.4307f, + -21.6468f, 9.0710f, 56.6256f, 68.0223f, 58.5665f, 37.6095f, 13.9228f, -1.0286f, -7.3812f, -7.6752f, + 45.1285f, 52.2192f, 35.8172f, 24.0812f, 18.9679f, 16.9917f, 14.5014f, 8.4539f, -0.8742f, -3.9224f, + -36.6106f, -54.0904f, -50.6995f, -17.6751f, 24.5062f, 61.1192f, 77.2085f, 68.1297f, 51.1173f, 30.6627f, + 45.4659f, 77.8448f, 86.8785f, 84.8886f, 78.1169f, 70.7257f, 58.9888f, 47.0442f, 34.4050f, 19.2233f, + -40.9082f, -17.6764f, 44.9914f, 99.5556f, 123.8320f, 129.2527f, 119.7749f, 99.9787f, 72.9475f, 42.1147f +}; + +const float lsf_cdk_wb_vc_stg1[] = +{ + -28.5460f, -28.7607f, -132.3446f, -253.0434f, -312.8796f, -342.8824f, -300.5386f, -244.2990f, -209.7251f, -159.5373f, -112.6287f, -67.3791f, -48.8219f, -29.0922f, -22.2704f, -4.3572f, + -46.5981f, -22.9649f, -50.9384f, -55.9409f, -47.4823f, -67.2740f, -93.7612f, -98.1688f, -103.5437f, -102.1144f, -101.9471f, -86.9149f, -76.1870f, -53.2461f, -51.2004f, -39.3148f, + 12.7666f, 41.7683f, -13.1290f, -96.2977f, -149.3018f, -210.6122f, -234.0799f, -215.3711f, -220.5745f, -210.7746f, -191.5374f, -156.6170f, -137.7840f, -109.8098f, -92.2552f, -56.2013f, + -45.2993f, -13.6438f, -31.2795f, 0.5585f, 26.1751f, 13.9611f, 18.6252f, 28.1510f, 20.3802f, 26.9694f, 32.9577f, 42.5006f, 29.2892f, 25.1029f, 1.3317f, -5.8774f, + -65.7100f, -62.1535f, -124.6012f, -161.3454f, -151.1323f, -164.9561f, -165.1614f, -150.4622f, -139.8421f, -109.2422f, -83.0457f, -55.1891f, -45.0696f, -29.5104f, -29.5390f, -21.1071f, + -75.2456f, -87.4543f, -164.3682f, -176.4217f, -83.4371f, -28.9912f, -6.9410f, 7.5825f, -2.7413f, 1.1408f, 4.1258f, 6.3013f, -0.6780f, -0.2756f, -18.0540f, -14.7263f, + 109.2056f, 132.5509f, 37.4910f, -93.8923f, -199.5966f, -323.5385f, -370.8597f, -259.1066f, -144.1366f, -52.9207f, -7.3753f, 8.7209f, 4.6669f, 18.2182f, 35.3204f, 18.9218f, + 34.9292f, 54.1737f, -19.4212f, -84.9971f, -62.3420f, -22.1402f, -18.0859f, -54.5195f, -107.3912f, -147.4533f, -198.2396f, -216.4862f, -199.3848f, -152.0050f, -94.9586f, -38.9081f, + -43.7524f, -65.5612f, -209.2403f, -339.0183f, -315.2712f, -219.0569f, -129.2175f, -68.7060f, -44.3255f, -17.2217f, 5.9129f, 29.8303f, 18.2167f, 13.0068f, -3.9593f, 4.1232f, + -20.9014f, 30.0658f, 17.8576f, -24.7442f, -27.5837f, -29.5508f, -45.9995f, -42.7483f, -54.9773f, -59.2762f, -57.4101f, -42.5711f, -43.9485f, -38.1621f, -41.1044f, -32.5227f, + -0.5370f, 38.0716f, 14.4030f, -41.8046f, -67.6856f, -96.6404f, -122.3561f, -123.7498f, -138.9439f, -138.4913f, -136.8318f, -124.9522f, -118.9503f, -96.3028f, -81.0357f, -58.1597f, + -19.4244f, 61.2237f, 71.3972f, 25.6367f, 35.9458f, 21.4457f, -1.7383f, 3.2413f, -12.2673f, -20.9311f, -19.4463f, -5.0683f, -9.0711f, -11.3618f, -25.0494f, -19.2853f, + -30.0686f, 7.6179f, -29.1133f, -90.4660f, -97.3464f, -101.9661f, -79.7809f, -41.4927f, -30.2058f, -14.9387f, -1.3463f, 14.7957f, 5.7342f, -1.8387f, -13.7457f, -15.5035f, + -60.0474f, -62.2162f, -94.9658f, -16.5692f, 137.3642f, 195.2581f, 171.5869f, 140.1564f, 102.9256f, 81.4529f, 62.9621f, 57.0500f, 25.7595f, 5.7185f, -17.0122f, -18.2020f, + 186.4318f, 224.6768f, 114.4757f, -1.7200f, -54.2938f, -162.2942f, -260.9445f, -305.8334f, -275.9291f, -196.7974f, -106.2413f, -38.2122f, -9.9698f, -0.0348f, -3.2806f, -1.0904f, + 131.8525f, 182.9257f, 129.5468f, 39.5803f, -1.4035f, -45.6323f, -49.7229f, -34.2829f, -46.2254f, -45.3785f, -41.8506f, -32.6587f, -52.7586f, -51.1091f, -48.4846f, -48.8108f, + -7.2430f, 5.5232f, -74.0471f, -159.3008f, -202.7316f, -252.2241f, -289.9449f, -278.4816f, -262.2343f, -234.1872f, -194.1267f, -147.2734f, -119.3163f, -94.6419f, -70.6759f, -32.5601f, + -22.3081f, -6.0222f, -71.4069f, -57.5585f, 87.3579f, 111.3674f, 19.2319f, -62.1519f, -140.4286f, -175.0389f, -160.2987f, -104.7539f, -80.1002f, -50.0734f, -23.5490f, 1.6408f, + 23.3797f, 81.2481f, 31.3892f, -52.3576f, -81.9250f, -125.5061f, -125.9686f, -77.3511f, -70.4429f, -55.1778f, -44.3888f, -25.9966f, -26.5913f, -23.2118f, -31.8502f, -31.7050f, + -27.1231f, 37.7616f, 25.1095f, 15.1436f, 46.6224f, 72.7080f, 91.0447f, 118.4813f, 115.1246f, 132.4240f, 135.0095f, 145.7460f, 121.1771f, 93.8520f, 46.9298f, 19.6713f, + -19.2617f, 10.4880f, -44.5537f, -114.3566f, -130.3973f, -156.7718f, -173.2891f, -165.3661f, -167.0274f, -147.1746f, -129.2874f, -104.7640f, -95.4641f, -77.5872f, -69.6100f, -49.0499f, + -3.7184f, 35.4165f, -28.7033f, -86.2246f, -61.2082f, -15.9498f, 31.1702f, 56.3138f, 49.9412f, 77.3057f, 94.0143f, 94.3239f, 78.8126f, 62.9187f, 30.4449f, 9.8069f, + 55.4567f, 100.2570f, 28.4890f, -59.9100f, -114.0757f, -166.5609f, -236.0665f, -274.6304f, -256.7512f, -58.8984f, 6.9854f, 2.1456f, 44.3655f, 27.4061f, -65.0542f, -69.1642f, + 95.5202f, 139.3445f, 117.4449f, 81.4589f, 34.9276f, -44.4909f, -90.4718f, -127.2388f, -175.4005f, -220.3445f, -288.6741f, -303.4144f, -260.5738f, -126.2845f, -58.1968f, -29.1673f, + 3.0556f, 18.3576f, -71.4110f, -183.6864f, -237.4567f, -273.2383f, -199.6331f, -69.6698f, -37.7715f, -22.6972f, -8.8733f, 16.1036f, 11.3358f, -3.2045f, -17.9569f, -20.6306f, + 39.1896f, 96.2913f, 80.5943f, 18.4912f, -3.4620f, -34.5205f, -64.0148f, -77.2972f, -99.9022f, -107.3139f, -104.8068f, -92.0120f, -86.4257f, -73.8585f, -70.7371f, -53.2077f, + 81.1530f, 122.0539f, 53.2063f, -53.6774f, -106.3376f, -163.4776f, -180.9786f, -175.0377f, -183.3532f, -183.5190f, -169.4248f, -137.3097f, -123.3554f, -101.5521f, -94.1512f, -61.8612f, + 47.0309f, 137.9525f, 111.1768f, 67.6681f, 63.8415f, 52.4017f, 35.8194f, 35.6828f, 19.7444f, 10.1125f, 6.1064f, 10.9675f, 5.0407f, -0.1812f, -16.8272f, -19.3810f, + 42.6721f, 92.5038f, 31.4316f, -5.1224f, -6.0796f, -41.9120f, -30.0922f, 1.7396f, 15.4681f, 21.9765f, 36.6015f, 47.1275f, 37.4374f, 28.9853f, 9.1342f, 2.7556f, + -25.6593f, 22.2684f, 98.1230f, 166.4577f, 187.4970f, 165.0274f, 123.8612f, 113.1471f, 79.0653f, 48.7839f, 25.8742f, 32.9158f, 10.3013f, 1.0495f, -15.4120f, -15.0391f, + 304.7019f, 354.4388f, 217.4228f, 65.5482f, 65.3717f, 25.9965f, -93.4052f, -188.0092f, -255.0247f, -224.5901f, -158.7919f, -116.2751f, -72.5203f, -57.4171f, -28.9851f, -1.9506f, + 179.5714f, 241.9845f, 193.4582f, 112.7762f, 108.6980f, 80.4323f, 56.9618f, 58.6676f, 36.2938f, 12.8297f, 4.7285f, 10.9217f, 12.0551f, 12.0937f, 1.6504f, -14.7259f +}; + +const float lsf_cdk_wb_vc_stg2[] = +{ + -4.8704f, -25.4945f, -63.8565f, -65.1017f, -4.5396f, 12.9750f, + -51.6246f, -71.2351f, -70.8930f, -49.5365f, -41.5492f, -21.1764f, + -4.1941f, -21.5321f, -43.7546f, -75.1360f, -101.6917f, -51.6149f, + 39.1412f, 15.8593f, -34.7315f, -30.9497f, 5.4101f, -22.1983f, + -27.3812f, -44.2900f, -51.8477f, 17.0318f, 63.3214f, 33.3719f, + -42.1936f, -38.7776f, 26.9794f, 58.3819f, 22.3255f, 7.3631f, + -17.3453f, 32.8013f, 16.4392f, -4.8961f, 34.6309f, 3.7975f, + 20.9889f, 11.0332f, 21.2790f, 43.6082f, 11.3288f, -4.0437f, + -30.7619f, -28.1362f, -7.6918f, -26.0495f, -20.5254f, 20.4943f, + -5.8695f, -15.0159f, -12.0884f, 4.0124f, -37.3326f, -57.6803f, + 31.1085f, 51.7290f, 46.8635f, -11.1193f, -84.1480f, -75.2940f, + 31.7638f, 33.3860f, -2.0831f, -68.1944f, -69.2055f, 16.6054f, + 26.8476f, 11.7277f, -21.2873f, -16.1653f, 77.7471f, 74.9747f, + -11.9492f, -11.8103f, 39.7377f, 110.8560f, 91.1983f, 51.6182f, + -16.9337f, 34.0576f, 97.5442f, 55.3237f, 6.0911f, -14.5976f, + 63.2733f, 65.6975f, 59.3910f, 57.9345f, 46.9389f, 25.4049f +}; + +const float lsf_cdk_wb_vc_stg3[] = +{ + -32.9020f, -78.5896f, -107.4534f, -95.7731f, -74.7222f, -53.0220f, -21.3706f, -6.3135f, 4.4667f, 8.3786f, + -55.7273f, -51.1982f, -23.4921f, -31.8303f, -40.9730f, -44.0985f, -32.5056f, -19.4304f, -11.2363f, -6.8031f, + -1.3625f, -17.5965f, -40.9966f, -56.5415f, -66.9172f, -82.2625f, -98.8410f, -92.9959f, -64.2789f, -34.2565f, + -0.1831f, 28.9371f, 27.3975f, 6.7646f, -26.2844f, -55.3561f, -55.5887f, -25.6472f, 4.2175f, 6.7426f, + -0.1042f, -22.5234f, -18.6769f, 9.5775f, 20.8908f, 1.7399f, -25.4612f, -48.9497f, -58.9339f, -45.8070f, + -59.3842f, -92.5268f, -67.7156f, -8.1650f, 22.6518f, 30.8838f, 30.1565f, 24.4312f, 17.5083f, 9.4537f, + 61.2263f, 100.3160f, 74.2819f, 32.8490f, -21.2300f, -80.0984f, -138.8597f, -144.8649f, -102.7813f, -51.4501f, + 20.9615f, 14.5464f, 12.7374f, 42.2801f, 62.5685f, 59.3555f, 43.2439f, 37.0487f, 22.3288f, 14.0209f, + 6.4664f, -20.5406f, -67.1147f, -81.1455f, -18.3522f, 38.5675f, 31.4978f, 9.2431f, -5.5141f, -0.9299f, + -14.7299f, -8.8186f, -2.0488f, -3.6924f, -11.6375f, -3.0631f, 38.0648f, 50.4570f, 46.9399f, 28.7229f, + 34.6418f, 11.8422f, -31.9716f, -72.1947f, -102.4017f, -89.6780f, -33.2158f, 7.5030f, 18.7080f, 14.6731f, + -62.1236f, -44.3324f, 53.6090f, 72.1405f, 58.0429f, 57.2172f, 43.2329f, 33.7172f, 19.9635f, 6.9351f, + 73.8739f, 68.1656f, 32.4182f, 5.6585f, -7.7073f, 3.9480f, 12.5407f, 12.3801f, -2.4527f, -5.8024f, + -21.3075f, -24.8496f, -17.5965f, 2.9303f, 59.0699f, 104.4524f, 127.5622f, 113.8932f, 89.2660f, 52.1358f, + 4.2469f, 56.7592f, 88.2184f, 81.0948f, 49.2982f, 15.3523f, -8.4240f, -22.2333f, -30.5271f, -24.1128f, + 46.4076f, 80.4091f, 88.4039f, 96.0474f, 97.7032f, 96.0620f, 87.9680f, 71.7615f, 52.3257f, 28.0991f +}; + +const float *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 int lsf_numbits[TCXLPC_NUMSTAGES] = { 5, 4, 4 }; + +const int lsf_dims[TCXLPC_NUMSTAGES] = { 16, 6, 10 }; +const int lsf_offs[TCXLPC_NUMSTAGES] = { 0, 0, 6 }; + +const float lsf_ind_cdk_nb_gc_stg4[] = +{ + -33.5099f, -17.2439f, + 1.9585f, 6.4210f, + -21.9240f, 24.8014f, + 23.6604f, 49.3421f +}; + +const float lsf_ind_cdk_nb_vc_stg4[] = +{ + -33.5292f, -23.3982f, + 15.6149f, 34.3889f, + -9.2455f, 6.1721f, + 60.7325f, 78.8354f +}; + +const float lsf_ind_cdk_wb_gc_stg4[] = +{ + -31.4516f, -19.9820f, + 9.1071f, 6.9160f, + -17.3554f, 28.1193f, + 31.7476f, 59.9379f +}; + +const float lsf_ind_cdk_wb_vc_stg4[] = +{ + -25.6665f, -20.7100f, + 17.1565f, 9.9963f, + -13.7601f, 37.4813f, + 55.4374f, 66.3001f +}; + +const float *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 int lsf_ind_numbits[TCXLPC_IND_NUMSTAGES] = { 2 }; + +const int lsf_ind_dims[TCXLPC_IND_NUMSTAGES] = { 2 }; +const int 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 } +}; + +const float lsf_q_diff_cb_8b_rf[256*16] = +{ + -49.142456f, 13.490689f, -21.704788f, 63.851589f, 17.341200f, 49.889275f, 4.535705f, -49.377617f, 12.881550f, 3.317029f, -45.874687f, -91.048477f, -159.075317f, -244.532806f, -208.950378f, -60.136238f, + -71.911499f, -50.432014f, -131.216339f, -25.763540f, -90.432335f, -140.176178f, -31.643175f, -46.414715f, -23.065298f, -42.936611f, -38.403904f, 15.094532f, -0.061476f, -28.153961f, -21.246065f, 10.218022f, + -134.834076f, -120.343132f, 98.120338f, 51.493057f, -18.822592f, 5.707322f, -93.194328f, 48.820892f, 38.169155f, 22.535019f, 17.952980f, -59.919395f, -154.178802f, -66.216209f, -30.895947f, -30.548832f, + -41.079960f, -11.862259f, -32.120766f, -35.889202f, -28.737438f, 26.212168f, -37.682671f, -117.789268f, -206.368179f, -150.378693f, -26.382723f, -33.924740f, 14.733324f, -7.089695f, 8.373900f, 41.311722f, + -44.370823f, -21.727020f, -164.064880f, 39.315842f, 14.170435f, 2.276680f, -43.158184f, -105.471977f, 46.076225f, -35.652943f, -72.096603f, -88.481071f, -121.452873f, -86.098267f, -92.925804f, -58.238682f, + -62.593822f, -14.669445f, -39.062012f, -12.045748f, -53.345932f, -70.633652f, -100.257874f, -63.507019f, 57.782543f, 62.015087f, 67.188080f, 65.260689f, -49.929119f, -162.794342f, -204.251465f, -104.609535f, + -66.932289f, -18.313484f, -68.981606f, -25.012476f, -94.210236f, 1.026957f, -67.785004f, -35.943043f, -53.149406f, -87.719955f, -112.206566f, -113.875397f, 111.780113f, 102.159576f, 1.001174f, -50.978374f, + -101.098640f, -70.354515f, -151.534393f, -91.954025f, 3.666550f, 78.893501f, 42.150974f, -57.122208f, -56.242603f, -97.829124f, -66.723511f, 11.967057f, 16.204992f, -23.608727f, -19.899971f, 28.121500f, + 10.450438f, 45.892262f, -54.131168f, -16.160269f, -64.032661f, -176.495041f, -5.962820f, -72.027107f, -150.201141f, -32.517159f, 61.674686f, 44.256657f, 46.283817f, -5.180211f, -141.241837f, -167.211639f, + -173.577682f, -92.975533f, -112.498154f, -101.956200f, -66.556870f, -79.061409f, -139.621201f, -1.422741f, -10.495166f, 71.210350f, 49.869511f, -2.298943f, -35.104397f, 24.463161f, -11.476251f, -46.980118f, + -37.676750f, 24.794701f, -40.237633f, 33.943848f, -51.101398f, 166.382629f, 110.829704f, 23.702038f, 23.627102f, -6.121801f, 0.773019f, -142.445435f, -263.982605f, -14.189220f, -131.928268f, -155.050293f, + -30.214348f, -9.421390f, -102.936676f, 83.361900f, -24.453602f, -180.015442f, 92.876984f, -79.562981f, -9.609303f, -34.706200f, -120.354073f, -29.731850f, -81.171555f, 36.295174f, 61.845047f, 47.662693f, + -110.844032f, 83.765533f, -123.206459f, -51.540508f, -51.287010f, -48.821514f, -29.502964f, -6.343169f, 23.775656f, -0.353102f, -23.523582f, -94.919563f, -133.085464f, -118.824188f, -53.901115f, -52.530910f, + -55.833942f, -37.825222f, 21.633268f, -2.833855f, -172.300034f, 74.660912f, -62.712250f, -77.443947f, 114.319824f, 49.023743f, 36.734745f, 53.222221f, -31.211931f, -15.118987f, -37.109795f, -50.964909f, + -2.209181f, 103.944717f, 186.623413f, -64.544991f, -32.391006f, -40.504578f, -24.400692f, 23.758614f, -28.194080f, -40.393677f, -41.950493f, -90.601120f, -169.530365f, -181.697540f, -67.184174f, -66.990860f, + -24.511374f, 34.831326f, 36.412617f, 49.172550f, -16.029377f, -109.529999f, 4.142260f, -20.617449f, -56.997406f, 30.342079f, -83.989975f, 1.144082f, 161.687592f, 61.147705f, -86.482475f, -92.777733f, + -88.158249f, -53.647205f, -131.604202f, 18.409283f, -8.442244f, -74.841873f, -30.877779f, 73.223831f, 26.580759f, -20.676722f, -31.395731f, -93.706764f, -88.946129f, -60.194122f, -118.809082f, -83.768547f, + -27.869957f, -5.078736f, -133.762909f, -274.870483f, 25.990072f, 21.509178f, 36.674843f, -3.828471f, -37.908432f, 2.206993f, -2.133470f, 15.392393f, -76.964806f, -123.400665f, -55.604580f, 13.984759f, + -39.818924f, -24.414286f, -78.231728f, 114.239975f, 68.886200f, 49.643444f, 61.244785f, 24.158489f, -11.322248f, -82.068733f, -152.400940f, -144.792816f, -89.084679f, -107.811325f, -15.021494f, 27.688988f, + -26.188799f, 13.887177f, -74.969177f, 125.939407f, 54.065468f, -29.856068f, 6.488181f, -63.185188f, -96.026291f, -188.663879f, -165.438187f, 203.997070f, 43.201817f, 21.809793f, -74.018494f, -76.644218f, + 14.730933f, 52.225765f, -133.046051f, 73.062096f, -12.101256f, -61.917290f, -85.989738f, -25.391121f, 61.084568f, -56.463966f, 192.920975f, 44.298870f, -151.724915f, 91.825546f, 4.643712f, -14.348310f, + -83.082611f, -43.735950f, -57.932819f, -63.816303f, -127.738678f, -96.165390f, 27.380922f, 106.262009f, 117.074669f, 97.982422f, 63.797035f, 48.936672f, -12.647917f, -65.618805f, -84.200691f, -93.463432f, + -79.058868f, -82.570656f, -23.950100f, -42.977753f, 35.295464f, -60.833336f, -54.265438f, -1.680498f, -73.608223f, -41.047230f, -32.325935f, -36.250416f, -2.680869f, 24.178974f, 12.027203f, 4.833654f, + -70.078651f, -40.907417f, -113.092224f, 27.616556f, -46.329929f, 104.583298f, 82.129387f, 0.280690f, -27.957493f, -79.316704f, 111.977844f, 50.056763f, -19.403173f, 25.433884f, 70.602043f, 28.069981f, + -1.787399f, 19.136635f, -48.166355f, 5.009412f, -62.536564f, 75.527115f, -47.088139f, -11.585875f, -65.448433f, -92.899475f, 107.363365f, -32.311649f, -203.382462f, -152.693619f, -50.552776f, 31.944372f, + 8.727448f, 163.701584f, -151.617279f, -120.834221f, -140.449585f, -168.542450f, -161.597626f, -134.148041f, -44.436928f, 23.024485f, 88.100662f, 153.087036f, 171.657425f, 142.269592f, 72.176025f, 34.152279f, + 24.626226f, 141.228775f, 68.035118f, 32.383106f, 29.076723f, -23.316879f, -11.166278f, 28.757330f, -105.244186f, -168.721451f, 15.529101f, -45.646198f, -99.508888f, 12.179071f, 41.687931f, -6.929618f, + -32.293335f, -15.942890f, 0.017796f, 227.668884f, 35.207336f, -33.792694f, 82.114479f, 15.197913f, -26.902617f, 65.209732f, 1.587932f, -56.761986f, -22.348925f, -26.869337f, 19.428514f, 27.321255f, + -102.949432f, -25.011555f, -147.959137f, -87.200294f, 47.153675f, 18.530943f, -0.166834f, 19.560911f, 89.191528f, 52.157402f, 2.918095f, -61.719532f, -94.293381f, -51.465199f, -1.655222f, -17.656567f, + -38.911335f, 6.948825f, -39.729725f, -51.301937f, -53.620224f, -108.789536f, 155.468872f, 63.620651f, 35.850296f, 70.581047f, 42.754013f, 127.703674f, 66.715858f, -130.426041f, -146.462341f, 74.622078f, + -1.029140f, 54.317455f, 8.387774f, 41.543407f, -10.573199f, 24.244738f, 30.842634f, -26.604139f, -33.421272f, -9.906475f, -31.059523f, 10.844967f, 30.019199f, -202.162201f, -258.204132f, 91.369331f, + -153.889771f, 115.453377f, 72.695793f, -18.096334f, 20.942005f, -35.160381f, -38.443104f, -34.397667f, -48.781742f, -1.410000f, 62.099541f, 79.766754f, 142.615189f, 135.960159f, 96.626495f, 58.906452f, + -79.472115f, -49.353893f, -49.954609f, -155.367615f, -116.776726f, 15.010523f, 18.099497f, -55.247025f, 16.403715f, 87.059982f, -23.132126f, -173.747818f, -144.933502f, -28.767344f, -32.596806f, -0.380802f, + -15.925756f, -5.412324f, -105.707176f, -130.356949f, -98.465538f, -47.166088f, -87.599068f, 42.630928f, -62.413151f, -107.954193f, 158.527435f, 98.763542f, -3.586527f, -6.147307f, -13.222188f, -23.993233f, + -24.975382f, 56.402035f, 52.029133f, -3.636582f, -18.978687f, -30.510057f, -20.777334f, 0.297320f, -75.612679f, -166.890121f, -182.792877f, -17.244802f, 17.907167f, -95.983925f, -107.016418f, 6.600997f, + 13.935800f, 124.014893f, -78.200630f, -86.667000f, 27.445192f, -62.815701f, -53.436100f, -106.422089f, -98.502609f, -122.057808f, -94.039665f, 79.832077f, 85.983383f, 86.996208f, 71.870331f, 101.132660f, + -51.503838f, -34.840988f, -93.907707f, 54.647934f, 85.969376f, -35.794395f, -36.596844f, -102.254219f, -196.495346f, 34.254475f, -15.691520f, -81.330208f, -7.808877f, -105.690956f, -96.873695f, 28.378246f, + 79.900681f, 76.900246f, 101.535088f, 103.327919f, 76.696190f, 36.222244f, -87.911812f, -186.179047f, 47.998817f, 180.776077f, 27.586971f, 68.147926f, 8.632617f, -127.173943f, -218.839523f, -269.181305f, + -51.884178f, -23.658228f, -7.389097f, 51.481766f, -16.066425f, -70.871017f, -193.338547f, 194.566742f, 115.566246f, -35.451885f, -78.933662f, 8.663171f, 16.445974f, -68.275475f, -91.542229f, 1.517690f, + -39.556801f, 39.785755f, -76.877228f, -215.618423f, 126.814384f, 37.883842f, 26.489124f, -32.631229f, -79.764656f, -5.413741f, -44.822353f, -38.384186f, 145.878082f, 205.717392f, 96.100632f, 80.714775f, + -36.383427f, 1.122570f, 179.888214f, -48.044216f, -121.014236f, -85.808846f, -125.241035f, -79.817886f, -0.247583f, 50.953720f, 13.693697f, -5.582759f, -50.636333f, -46.192039f, -66.636848f, -36.257576f, + -122.950089f, -101.489883f, -260.444885f, -20.923767f, -57.475227f, 15.233345f, -42.816353f, -43.372814f, 58.668098f, 2.198759f, -2.974080f, 16.032595f, 93.305153f, 50.504028f, -14.432660f, -50.193291f, + -16.826427f, 8.873464f, -87.595573f, 23.091625f, -3.794562f, 38.739624f, 159.341888f, 57.302864f, 10.663289f, -44.891232f, -143.189377f, -141.278580f, 34.162834f, 67.916397f, -11.724302f, 82.864563f, + 8.689659f, 79.660339f, -106.648331f, -40.056900f, -61.659725f, -89.878143f, 30.882858f, -96.414940f, -87.919632f, 71.567696f, -13.048811f, -99.413971f, 158.306488f, 148.612640f, 101.164139f, 44.707798f, + 51.876743f, 173.028961f, -7.548154f, 42.151535f, -0.306372f, -63.804768f, -65.823441f, -61.424610f, -3.614527f, -0.266337f, -28.529921f, -42.772068f, -92.503525f, -24.051035f, -29.639515f, -52.302032f, + -21.027899f, 32.422092f, -19.221569f, -81.996292f, 170.400146f, 147.834946f, 78.837563f, 54.455120f, -4.170513f, -14.816674f, 66.761642f, 29.512554f, 1.267826f, -7.617690f, -74.421074f, -86.431335f, + -19.333296f, 100.725983f, 62.089886f, 80.720032f, -11.293929f, -156.758041f, 130.283081f, 64.092621f, 10.666490f, 23.035032f, 9.748004f, -82.614822f, -134.818069f, -117.491508f, -98.273796f, 27.608231f, + 3.230417f, 41.808163f, 13.598584f, 214.913864f, 110.737106f, 36.832939f, -14.412317f, -27.091141f, -72.668190f, 5.492285f, 219.188553f, 157.024200f, 139.305466f, 42.584637f, -89.405518f, -147.115540f, + 5.685055f, 57.183292f, -12.697913f, 68.282562f, -33.609550f, -33.049332f, 87.031670f, -39.772167f, -127.605225f, -30.905075f, -129.695374f, -167.423813f, 14.979711f, -80.101776f, -175.781570f, -120.638008f, + -26.057411f, -22.450294f, -86.065346f, -174.294159f, -236.409439f, 106.705414f, 94.844818f, -24.300186f, -47.618366f, -4.900061f, -8.250068f, 26.776390f, 23.026890f, -0.663881f, -8.460385f, 52.523418f, + -239.938965f, -188.228012f, -72.794617f, -24.974373f, 64.134842f, 47.954140f, 37.109238f, 56.990929f, 19.013355f, 2.195176f, -39.343456f, -65.541855f, -48.117985f, 33.679371f, 1.032876f, -8.904166f, + 1.318133f, 23.793682f, -11.594374f, 208.226288f, 86.628777f, -41.451736f, -85.691925f, -59.617199f, -144.367111f, -168.655807f, 108.856461f, 32.739384f, -66.105087f, -32.850475f, 68.247009f, 136.522278f, + 46.231567f, 61.993446f, -37.963066f, 71.883453f, 4.955863f, 90.692329f, -55.423782f, -173.421982f, 91.392097f, 4.265558f, -86.143791f, 11.978693f, -147.210098f, -173.357559f, 47.334595f, 132.379639f, + -8.091352f, 36.792015f, 42.705544f, 0.830618f, -22.491022f, -42.331161f, -6.163970f, 83.671753f, -37.618378f, -48.777485f, 136.386185f, 88.433350f, 121.425102f, 78.104286f, -118.565308f, -236.474899f, + -34.999004f, 35.648041f, 104.321472f, -80.549561f, 88.479385f, 4.159388f, -68.049988f, -110.190895f, -59.762150f, -34.927917f, -42.892593f, -50.185341f, -31.525537f, 28.561077f, 30.799391f, 32.589943f, + -19.395960f, 10.917861f, -33.211983f, 59.916050f, 17.923265f, 69.628220f, -59.527351f, -0.360134f, 20.055620f, -76.225594f, 59.490189f, 219.202728f, 44.065163f, -105.835022f, 149.316025f, 103.121368f, + -26.811831f, 4.917114f, -50.918606f, -51.282066f, -44.665630f, -34.671989f, 54.816383f, -53.930695f, -122.650787f, 9.736618f, -86.848312f, -33.875164f, 28.787636f, -128.559616f, -13.832273f, 240.435959f, + -127.768944f, -120.395676f, -224.640091f, -106.371384f, -110.915848f, -119.944382f, -64.704178f, -86.686111f, 57.449604f, 91.349197f, 96.250694f, 156.740128f, 176.836166f, 127.207031f, 51.964844f, 14.125758f, + -47.998665f, 17.796474f, 29.304367f, 75.164230f, 58.860054f, 113.970734f, 70.417877f, 23.055088f, -25.342611f, -99.771896f, 5.999279f, 51.847668f, -60.419800f, -163.240036f, -99.791527f, -66.431305f, + -0.302659f, 17.211594f, -98.700340f, 53.635334f, -28.992607f, -89.555244f, 112.895592f, -32.920498f, -109.022964f, 150.316772f, 124.435059f, 47.075050f, 111.757408f, 77.910065f, -34.123623f, 33.374477f, + -8.188879f, 23.113052f, -14.419042f, 58.259747f, -4.053533f, 3.542868f, 101.208923f, 41.556973f, 65.754631f, 15.887958f, -6.614230f, -95.157341f, -213.709061f, 82.959053f, 10.967265f, 42.520882f, + -12.848677f, 33.983711f, 26.826427f, 55.942802f, 17.707258f, 59.918518f, 15.309278f, 207.269272f, 99.491982f, 42.829330f, 116.586906f, 97.039436f, -36.674652f, -119.304512f, 74.699173f, 64.565712f, + -127.629143f, 210.633652f, 90.269417f, -15.052937f, 10.047224f, -44.578220f, -32.594685f, -24.894297f, -32.681622f, 36.690662f, 60.424084f, 6.454986f, 7.198017f, 25.681587f, -4.052445f, -25.874166f, + -13.218253f, 25.233515f, -43.822559f, 14.608809f, 50.092663f, 29.797066f, 122.838074f, 60.946331f, -15.227234f, 70.429047f, 49.234367f, 22.393675f, 241.398132f, 68.944763f, -19.084089f, 15.646838f, + -61.749660f, 22.046791f, -33.557991f, -16.016773f, -39.896496f, -65.069405f, -73.831696f, -54.138386f, -41.472534f, -59.811478f, -96.109680f, -119.990692f, -91.886162f, -31.355206f, -9.082160f, -39.052567f, + -27.257662f, 71.028709f, -136.328506f, -98.025055f, -21.314344f, -16.991056f, -34.343781f, -70.373230f, -55.339901f, -30.724577f, -8.068395f, -12.537150f, 6.994465f, -2.531820f, -19.959831f, -32.511631f, + -189.575684f, -170.668686f, 159.468323f, 69.316818f, 9.541554f, -35.932343f, -76.965225f, -73.569916f, -80.277435f, -52.695671f, 36.840542f, 4.612717f, -5.781191f, 68.836777f, 46.053165f, 5.477945f, + 23.076845f, 56.007298f, 58.995125f, 73.648643f, -23.558571f, 31.706146f, 6.650000f, -81.954597f, -43.828186f, -91.444901f, -136.752670f, 3.109934f, -61.638336f, 161.845291f, 158.234512f, 75.812927f, + -29.586615f, 8.254013f, -12.131930f, 42.161793f, -20.277391f, -118.423508f, -194.639008f, -196.011337f, 38.792351f, 37.828663f, -2.185939f, 11.298992f, -6.172924f, -4.559058f, -65.562843f, -27.597832f, + -47.978813f, 22.640007f, -58.066402f, 58.001053f, -47.134541f, 8.486321f, -6.111372f, -31.006121f, 51.575218f, 5.865514f, 17.294910f, -41.168453f, 73.907234f, 13.599236f, -307.273499f, -197.696899f, + -44.109650f, 49.449520f, 84.357780f, -161.258835f, -95.109154f, -44.129417f, -5.148076f, -26.549320f, -4.192320f, -31.172485f, -35.216717f, 42.882584f, 4.978696f, 0.798938f, 44.287029f, 7.057617f, + -44.323925f, -3.754397f, -20.289011f, 35.057964f, 30.896481f, 47.822914f, 57.432564f, -18.862158f, -58.972874f, -40.730820f, -53.210159f, 151.582123f, 189.086823f, -47.681084f, -160.354431f, 18.183973f, + -24.190926f, -8.054521f, -60.337772f, 17.447094f, 52.011765f, 64.135529f, -12.559262f, -64.698524f, -145.641434f, -49.002659f, 27.998568f, 54.442074f, 31.638771f, -105.428864f, -187.366058f, -170.395126f, + -52.519932f, -45.655670f, -54.255409f, 18.195887f, -47.736511f, -25.311331f, -74.233253f, -139.686768f, -7.455135f, 30.180883f, 16.468306f, 73.234703f, 89.610466f, 86.974052f, 38.241241f, -12.159492f, + 27.982965f, 58.867645f, 9.410244f, -37.832794f, -107.431290f, 148.510559f, 114.846024f, 37.929848f, -49.612717f, -97.690834f, -11.054573f, -58.132690f, -120.672997f, -0.656331f, 67.064285f, -17.834682f, + -38.582962f, 4.200229f, -16.068153f, 16.516636f, -13.899181f, 5.986161f, -2.004643f, 12.832077f, -44.597519f, -86.681267f, -38.071716f, -52.322094f, 61.482838f, 23.035675f, 222.921036f, 209.259064f, + -53.377850f, 219.871765f, 18.681116f, -49.476475f, -66.432587f, -11.111042f, 8.136900f, 38.469578f, 83.534767f, 23.165945f, -66.981857f, -119.944641f, -90.701843f, -5.017766f, 13.544878f, 7.416979f, + -26.158424f, 21.733870f, 8.429042f, -7.359868f, -81.261559f, -0.384979f, 107.991409f, -33.468559f, 163.344254f, 171.295059f, 21.148136f, -44.234226f, -50.298836f, -2.045869f, -46.947075f, -69.817322f, + 54.305538f, 77.911476f, 98.722816f, -46.229565f, -143.810577f, -1.355024f, 61.036888f, -13.015687f, -3.865948f, 88.857635f, 7.053370f, 11.180832f, -46.409653f, -90.435066f, -105.360260f, -147.441849f, + 75.489372f, 105.739868f, 60.188259f, 33.809502f, -21.277689f, -21.943260f, -50.937679f, -75.105469f, 43.895504f, -42.176373f, -73.326416f, 343.493774f, 168.802673f, 63.476738f, 36.762135f, 96.509972f, + -43.959518f, -13.900088f, -83.791946f, -2.585726f, -89.923798f, -318.138428f, 56.854568f, 72.487968f, -32.397919f, 28.099873f, -17.146538f, -96.395309f, 0.466646f, -28.547890f, -71.721748f, -40.413429f, + -91.491898f, -100.288185f, -158.042801f, -94.347038f, 41.776943f, 56.555912f, 18.842609f, 21.550163f, -8.122741f, 83.330833f, 83.349388f, 56.535236f, 6.853065f, -16.367655f, 6.860499f, 12.135324f, + -122.978020f, 41.508400f, -57.019398f, 119.866692f, 169.921616f, 82.577713f, 6.609851f, 29.209021f, -35.676617f, -95.016159f, -42.960949f, -61.483852f, -28.365889f, 44.539429f, 11.786313f, -39.760418f, + -35.204288f, -3.827494f, 1.364895f, 53.625450f, 67.540977f, 12.539343f, -62.200562f, -131.499298f, -190.222824f, 97.861145f, 145.009247f, 116.742218f, 39.964626f, 5.113988f, -49.972206f, -22.433067f, + -21.844286f, -3.302132f, -103.041687f, 72.974442f, 0.991044f, 31.884541f, -68.314651f, 15.106439f, 38.181488f, -142.549530f, -177.428543f, 26.987268f, -65.951744f, -49.118980f, 100.179466f, 67.782463f, + -68.886017f, -50.878456f, -101.627640f, 94.751526f, 63.353767f, -35.431698f, 88.086647f, 85.405006f, 1.274280f, -8.066319f, 108.974724f, 81.340332f, 19.295490f, -5.680541f, -76.852966f, -93.998848f, + 0.026969f, 0.110805f, -0.074311f, 0.076925f, 0.017105f, 0.036573f, -0.118072f, 0.068798f, 0.056649f, 0.036456f, 0.063553f, 0.071463f, 0.000525f, -0.019787f, -0.046544f, 0.021337f, + -17.799213f, 17.198961f, -23.454958f, -48.785267f, 32.178555f, 142.656906f, 87.394043f, -46.504601f, -91.326263f, -128.089188f, 168.745255f, 12.046860f, -75.234085f, 321.776276f, 84.140045f, 147.402191f, + -7.771455f, 13.708800f, -83.826019f, -18.597784f, -45.941696f, -97.131195f, 73.443825f, 13.631736f, -35.554703f, 154.701080f, 86.402138f, 6.515917f, -68.449318f, -152.233841f, -30.240294f, -16.017389f, + -55.553074f, -10.045274f, -82.091660f, -104.274841f, -102.906937f, -76.238228f, -59.226723f, -42.700069f, 16.344666f, 35.539070f, 49.328686f, 56.921478f, 131.003021f, 165.738358f, 186.387207f, 144.321213f, + 24.576750f, 51.924622f, 2.034293f, 189.503342f, 148.765106f, 101.905212f, 63.054604f, -22.561197f, -112.342194f, 8.821053f, 33.745621f, -43.875877f, -58.067898f, -146.850281f, -17.419054f, 72.366890f, + -30.276649f, -31.782654f, -80.339973f, 100.106911f, 93.313034f, 4.726528f, -48.094799f, -115.030556f, -191.082672f, 102.985733f, 88.130089f, 19.376783f, 42.609215f, 50.674198f, 152.159012f, 114.587776f, + -137.391373f, 14.609784f, -65.256355f, 1.609928f, 37.473400f, 26.934027f, 24.673132f, 119.508095f, 88.831779f, 43.605965f, 27.401138f, -7.082619f, -78.587341f, -76.090195f, -60.487331f, -49.042698f, + -3.795852f, 48.615219f, -32.316784f, 47.219639f, -71.672012f, -177.180862f, 227.674683f, 121.423073f, 55.595085f, 89.844704f, 18.789379f, 72.883820f, -30.959936f, -1.702511f, 69.411217f, 21.385332f, + -31.896704f, 58.013481f, 15.825336f, 21.007841f, 73.693138f, 2.008733f, 47.849987f, 22.561638f, -56.861252f, -96.624382f, 116.512817f, 122.175636f, 14.970264f, -131.112076f, -137.480362f, 145.503159f, + 3.666602f, 60.865307f, 190.182358f, 42.435371f, -21.053213f, -17.096897f, -76.084404f, -13.743227f, 117.478218f, 140.799774f, 154.908340f, 88.790558f, 92.327370f, 121.949478f, 69.189064f, 33.268280f, + -24.028364f, -0.568868f, -10.598723f, 23.224901f, -10.145369f, 23.696190f, -80.020584f, 133.288193f, 78.874382f, -28.811146f, -74.702332f, -142.888794f, -177.398254f, -126.189499f, -64.583435f, -4.795106f, + -42.301235f, 1.254746f, -92.263153f, -67.414131f, -68.581459f, -105.596657f, -95.386429f, -140.669708f, -167.874496f, -26.571861f, 58.823044f, 95.171120f, 164.426514f, 117.247391f, 67.970955f, 67.381973f, + 12.281957f, 57.241734f, 145.007370f, 102.782562f, 6.108451f, 23.661549f, -109.679001f, 79.513168f, 54.415848f, -107.359993f, -127.692383f, -2.818198f, -116.707993f, 22.176086f, -1.896818f, 13.089568f, + 42.066715f, 109.299110f, 22.366495f, -16.778564f, 21.774530f, -4.182106f, -18.286386f, -52.603218f, -118.524780f, -89.037674f, 118.551682f, 115.277679f, 89.577263f, 130.519241f, 158.623138f, 169.276016f, + -127.461502f, -97.991295f, -154.912262f, 156.017349f, 83.816185f, -40.645927f, -30.617186f, -97.806175f, -64.010101f, 50.553226f, 32.767338f, -3.065530f, 46.381119f, 52.668839f, 32.740833f, -18.864176f, + -35.447090f, 10.117445f, -29.844646f, 121.351227f, 83.683456f, 57.303402f, 15.328587f, 44.133987f, 67.000153f, 104.188065f, 10.872536f, -10.320432f, 63.163109f, -83.689003f, -200.906555f, -56.971607f, + -73.476898f, -50.613533f, 157.811996f, -36.126892f, -3.998129f, -33.125019f, -40.811184f, 75.547150f, -26.170004f, 16.685923f, 89.786247f, -2.189539f, -13.579331f, 56.560184f, 54.771152f, 26.603344f, + -50.784908f, -37.853783f, -22.237158f, -10.529336f, -75.668167f, 170.388672f, 64.201385f, 9.919388f, -25.087654f, -97.517700f, -38.260277f, 51.479713f, 98.044075f, 224.824921f, 125.035980f, 68.006523f, + -13.163634f, 49.532330f, 22.343836f, 23.637941f, -71.608704f, -200.313492f, 22.972029f, -65.936508f, -139.879044f, 109.168282f, 73.714027f, 8.318653f, -33.382645f, -57.808838f, -26.988724f, 70.492950f, + -57.241489f, -35.265514f, -140.595444f, 85.484810f, 13.172671f, -44.652134f, -64.718590f, 80.219849f, 113.279419f, 8.199357f, 46.910881f, 1.842971f, 6.611537f, 108.265114f, 84.200981f, -15.673004f, + -54.020992f, -40.065796f, 68.741219f, 89.963760f, -22.845310f, 156.119400f, 40.349724f, 13.827300f, 99.219742f, -10.468677f, -69.469467f, -91.899101f, -28.343006f, -18.399660f, -48.014648f, 18.084986f, + 39.514809f, 117.259254f, 84.999840f, 3.152317f, -89.788651f, -15.256340f, 128.664642f, 16.396799f, -2.824860f, -2.224188f, -108.113235f, -104.294632f, 285.672485f, 258.659821f, 131.015823f, 46.896381f, + 35.400707f, 199.269470f, -50.829807f, -59.871765f, -112.504417f, -87.914078f, -74.663177f, -14.457950f, 3.730728f, 8.424652f, 34.759491f, 5.061568f, 49.715153f, 29.911200f, -4.833649f, -7.921039f, + 79.273865f, 68.455246f, 143.235184f, 29.923138f, -61.068966f, 27.401043f, -93.697815f, 39.637844f, 278.054901f, 207.706467f, 114.287697f, 191.970261f, 28.365456f, -67.643982f, -126.002037f, -324.593506f, + -38.810867f, 77.219002f, 226.800339f, 84.473801f, -40.547543f, -21.564167f, 131.517456f, 93.058868f, 25.796638f, 24.364828f, -21.709984f, 0.377355f, -100.328873f, -63.233959f, 39.949356f, -20.796144f, + -49.434875f, 13.246425f, 235.871155f, 150.979660f, 94.417747f, 49.695023f, 9.298592f, 42.695667f, 12.962906f, 29.078457f, 141.417770f, 131.790558f, 139.121719f, 102.666374f, 34.500813f, -11.908920f, + -2.108662f, 13.590509f, -38.806015f, -50.421722f, -148.383850f, -9.163120f, 221.518173f, 91.873947f, -57.944500f, 7.884820f, -23.169016f, -6.481791f, 39.176830f, -30.829500f, -216.452530f, -132.310471f, + -60.222321f, -37.813641f, -144.648758f, -74.471680f, -53.668755f, -36.867607f, 163.549622f, 118.314560f, 9.347286f, -64.045303f, 54.008766f, 6.278257f, -3.053545f, 65.511765f, 31.613440f, 28.923603f, + -68.111702f, -58.754192f, -20.550688f, -9.141284f, 178.296661f, 46.222195f, 85.088615f, 25.129522f, 3.565898f, 73.297729f, 22.594685f, -30.790440f, -60.898556f, -59.714981f, -25.799683f, -26.515989f, + 79.872566f, 27.157415f, -193.357193f, 172.950409f, 131.502487f, -2.173946f, -11.273206f, 11.559188f, -135.590240f, -117.606354f, 162.157654f, 74.852615f, 84.181198f, 42.567123f, 72.688606f, 30.169746f, + -22.176310f, 8.126409f, -98.820702f, 162.383163f, 130.916565f, 39.752148f, -32.870506f, -173.600403f, 116.578125f, 45.067692f, -27.598148f, 8.555970f, -3.395607f, -42.335846f, -20.110458f, -40.589352f, + 31.181765f, 77.636864f, 60.341606f, 90.832474f, -9.832494f, -111.538925f, 111.043030f, 140.765152f, 80.575752f, 24.432682f, 81.943199f, 20.720406f, 1.215079f, 4.115319f, -68.575241f, -91.525787f, + -84.731537f, -0.527349f, 25.745188f, 36.190254f, -62.206528f, -86.327141f, -27.536991f, -15.557912f, 32.424694f, 13.717608f, 11.215924f, 22.781013f, 9.574938f, 61.158257f, 61.121010f, 32.403088f, + -18.375742f, 10.047339f, -50.339001f, -6.936292f, 12.167328f, 150.529266f, 222.465683f, 183.672455f, 58.230515f, 30.788654f, -22.198248f, 57.085861f, 28.043667f, -36.177765f, 171.042053f, 134.737167f, + 0.297151f, 95.241844f, 51.197784f, 41.369175f, 33.568478f, 7.960698f, 55.897408f, 15.283177f, 29.098846f, 91.276161f, 20.340677f, -60.202499f, -171.769867f, -193.836426f, 13.407167f, 121.289520f, + -77.249527f, -31.146763f, -86.916313f, 13.008453f, -21.325594f, -35.007175f, -0.394985f, 39.783211f, 158.601135f, 162.017731f, 166.716888f, 164.855255f, 145.650070f, 87.215416f, 13.765621f, -16.071383f, + -11.922022f, 69.904465f, 145.530533f, 137.786896f, 42.237782f, 75.689651f, 121.502434f, 26.309196f, 0.019661f, -62.185799f, -152.175339f, 86.949432f, 41.679405f, 18.519968f, 34.415928f, 25.165304f, + -9.927750f, 11.307752f, -64.252609f, 131.465469f, 47.641304f, 22.456234f, 36.158360f, -40.804043f, -91.170403f, 86.573074f, -47.294422f, 15.884171f, 222.589951f, 158.826157f, 154.847031f, 224.892197f, + 34.394650f, 50.068573f, -4.612890f, 39.353638f, -13.351929f, 82.855324f, -34.119553f, -198.830780f, 169.354126f, 20.893297f, 2.412445f, -82.652008f, -123.564072f, 148.278564f, 67.057632f, 86.445847f, + 8.496761f, 55.847862f, 9.401371f, -12.230957f, -48.765945f, 339.392365f, 127.588539f, -17.772644f, 73.892937f, -37.477283f, 39.123516f, 58.133339f, -42.253559f, -161.082916f, 77.454605f, 125.429886f, + 43.473793f, 173.585449f, 85.007156f, 42.041813f, -61.597820f, 51.345463f, 44.502201f, -8.306359f, -2.903240f, -41.573891f, 114.340172f, 93.989349f, -18.752844f, 33.966118f, 85.911499f, -5.925835f, + 69.373337f, 94.525620f, 55.872551f, -12.796402f, -57.766541f, 205.378647f, 150.999893f, -34.033718f, 46.349552f, 51.589359f, -9.740956f, 165.190857f, 245.511856f, 140.620789f, 33.383125f, -80.622025f, + -24.897663f, 9.583753f, 62.261280f, -111.380074f, -93.574211f, 37.958935f, 11.259578f, -85.749733f, -185.118637f, 15.325944f, -47.716419f, -70.300369f, -64.094902f, -120.984238f, -115.879242f, -5.316128f, + -43.105038f, -38.260498f, -69.155273f, -106.188942f, -215.693817f, -116.750755f, -22.012207f, -17.229620f, 2.833113f, 47.987717f, 6.774336f, -11.583231f, 16.325312f, 30.872992f, 21.988634f, 21.333845f, + -40.281574f, -19.919075f, 83.175934f, 145.520676f, 74.963409f, -17.649036f, -97.185730f, -32.826363f, -53.159214f, -13.556940f, -30.614326f, -68.210266f, -70.881149f, -25.398729f, -57.834473f, -78.295006f, + -54.354683f, -53.242130f, -151.652374f, 75.184731f, -12.681744f, -62.721302f, 39.976120f, -84.622726f, -164.732422f, -81.025864f, -59.992664f, 18.575914f, 59.433632f, 91.230606f, 74.121452f, 15.667545f, + -56.008598f, -36.547680f, -74.135963f, 60.449661f, -43.171642f, 20.404333f, -94.677895f, -134.441208f, -21.513660f, -79.943031f, -11.399878f, -26.450451f, -51.884460f, 13.872990f, -10.700389f, 13.693831f, + -54.557514f, 14.214915f, -109.558357f, -39.927799f, -80.414780f, -21.436823f, -29.838932f, -133.094101f, 41.575626f, 119.561104f, 108.865402f, 113.994164f, 70.534935f, -74.075966f, -153.541779f, 13.645255f, + -19.660948f, 72.645828f, 57.090542f, 10.197439f, -82.249893f, -86.073334f, -65.963997f, 26.606983f, 62.380840f, -79.725609f, -67.844391f, -100.735214f, 103.173157f, 41.282562f, -14.417590f, 97.527374f, + -15.501063f, 10.106770f, 19.181379f, -48.813862f, -54.115250f, 235.424240f, 13.094974f, -96.655479f, -53.639637f, 13.621657f, 1.518511f, 44.934509f, 57.590019f, -41.299301f, -105.937149f, 5.567881f, + -26.978188f, 39.920815f, 39.867668f, -30.284748f, -137.471680f, -12.073587f, -11.821868f, -56.056862f, -109.460243f, -95.643143f, 71.884705f, 3.678432f, -69.469994f, 46.625034f, 21.143269f, -12.124670f, + -235.238770f, -189.902191f, -98.019753f, 1.308181f, 6.093620f, -51.336655f, -74.336411f, -58.007866f, -34.142288f, -23.622774f, 21.920612f, 54.356789f, 118.404907f, 98.866112f, 78.824142f, 48.048695f, + 38.583252f, 140.003342f, 104.366905f, 59.575905f, 16.539742f, 143.487717f, 46.418877f, 67.189468f, -16.257248f, -14.486803f, -37.126595f, -97.505363f, -80.173981f, -94.221985f, -115.390350f, -118.126472f, + 14.582953f, 70.503632f, -14.045506f, -19.149410f, -112.971611f, -166.393768f, 175.770172f, 72.728432f, -123.819260f, -84.734123f, -79.798332f, 15.522896f, 9.189954f, 45.245491f, 67.264786f, 21.392374f, + -30.288527f, 176.278839f, -42.118710f, -113.833649f, 18.178839f, -98.263985f, -5.378097f, -36.394852f, 56.751965f, 34.232403f, -15.896103f, -21.939495f, -36.014275f, -97.239891f, -44.097141f, -21.397247f, + -57.630421f, -14.344311f, -48.722851f, 4.000876f, -85.091949f, 134.974442f, 96.790924f, 44.602585f, 116.120537f, 108.384445f, 134.965012f, 62.810093f, -51.505104f, -66.570000f, 0.324640f, -61.159451f, + 46.961773f, 91.328773f, 255.896439f, 266.543579f, 55.914829f, 1.617108f, 3.187201f, -8.799063f, 27.105843f, 96.940453f, -6.333913f, -40.912540f, -123.896332f, -219.183456f, -147.103104f, -82.445755f, + 4.730723f, 14.597744f, -4.770158f, 50.178673f, -46.408352f, 46.296600f, 159.859604f, 44.269157f, 25.871405f, 18.163599f, -69.356171f, 99.161255f, 145.530502f, 110.339287f, -78.356651f, -249.688126f, + -4.995772f, 7.796484f, -231.294037f, 72.029633f, 33.000286f, -63.268135f, 113.155357f, -3.829946f, -48.667412f, 20.674379f, -19.940260f, -66.963058f, -30.490475f, 1.557967f, -21.697649f, -25.190910f, + -68.609848f, -42.050915f, -81.286026f, -171.873383f, 5.826807f, -37.863060f, 65.958603f, 64.783348f, 16.320978f, 7.862601f, -63.484844f, -35.056782f, 36.112469f, 25.719179f, -27.790937f, -49.815948f, + -52.712395f, 5.407033f, -50.664661f, -57.217823f, 93.290443f, 86.227432f, 47.213612f, 8.067347f, -70.909805f, -102.342758f, -81.671745f, -96.333832f, -76.863091f, -17.267122f, 0.470240f, 11.259017f, + 45.857506f, 61.279209f, -16.262930f, 65.889984f, 39.496490f, 31.019928f, 10.330289f, -12.880993f, -158.328720f, -214.299026f, 136.159515f, 34.651714f, 58.886429f, 52.877373f, 18.637857f, -97.587326f, + -83.695442f, -46.231495f, -126.655914f, 84.273537f, 24.091738f, -77.565994f, -121.072006f, -65.358688f, 13.704159f, 17.912792f, 129.792953f, 45.167286f, -76.637970f, -90.235817f, 29.498278f, 22.527498f, + -38.629421f, -13.281903f, 19.966961f, 21.830301f, -71.014816f, -56.646057f, -183.160706f, 153.295105f, 121.722061f, 122.379555f, 191.160324f, 94.983765f, -38.069660f, -13.902174f, -28.430313f, -3.660168f, + -61.012142f, -16.898062f, -122.156700f, 40.265934f, -4.676280f, 89.712509f, 77.850525f, -22.210423f, 54.780842f, -9.432448f, -77.245964f, 33.276836f, 8.500788f, 24.147732f, -37.488598f, -50.028263f, + -13.981007f, -3.172497f, 12.233177f, -3.165506f, -42.713432f, 159.373047f, 120.601517f, 61.609337f, -95.282997f, 154.044556f, 146.461670f, 105.883102f, 35.354893f, -32.637356f, 13.527010f, 52.834805f, + -59.811607f, 31.116199f, -44.788532f, -25.192825f, 11.671334f, -60.872108f, 94.383209f, 44.916836f, -91.212807f, -106.707802f, -36.229931f, -17.900185f, -138.207123f, -165.818100f, 56.715836f, 45.974777f, + -7.959111f, 85.271294f, 17.490253f, -50.336193f, -56.605679f, -100.320343f, -152.276581f, -135.327911f, 88.408737f, 129.427505f, 125.965462f, 98.592941f, 27.923223f, 7.087426f, 27.595392f, 42.971786f, + -25.500626f, 121.667168f, 83.573936f, 3.791471f, -23.845556f, 49.105648f, 81.526443f, 160.776093f, 22.598379f, -98.819115f, -47.420437f, -16.478176f, 46.472534f, -122.984657f, 0.608375f, 57.243511f, + -12.015658f, -0.135543f, -139.000534f, 151.549393f, 71.025963f, -20.232512f, 95.418777f, -70.840523f, 52.608326f, 22.649012f, -56.357464f, 137.754135f, 50.294880f, -87.514961f, 20.277452f, 193.218811f, + -111.404922f, -69.059303f, -107.005531f, 53.955250f, 56.233429f, 68.297432f, 9.512801f, -94.675659f, 125.887329f, 141.677551f, 37.625774f, -55.039444f, -107.942078f, -106.586906f, -103.690109f, -31.521854f, + -7.459867f, 80.387726f, -22.849117f, -7.418187f, -31.289583f, -58.895996f, 121.585495f, 71.303520f, 69.327995f, 33.343830f, -42.588058f, 246.521713f, 44.359360f, -30.136723f, 45.514824f, 33.970772f, + 13.146280f, 37.437431f, 11.781944f, 221.298462f, 64.525116f, -28.227280f, -2.765812f, -60.692303f, -105.971016f, 145.109314f, 29.132435f, -9.364019f, 92.389153f, -40.417786f, -167.946228f, 91.506371f, + 20.380590f, 124.691406f, -34.959442f, -32.687466f, -68.501457f, -12.932295f, 8.627584f, -95.438469f, 34.264408f, 157.920456f, 94.634033f, 154.451233f, 203.167297f, 140.269073f, 62.590698f, -14.471005f, + -23.798073f, 20.029366f, -28.207727f, -42.335686f, -94.120468f, -119.036964f, -160.177826f, 13.003415f, -10.760310f, -23.243717f, 23.871334f, -25.554195f, -70.506531f, -62.087463f, 52.588543f, 91.934219f, + -45.170189f, -10.087015f, -66.042885f, -262.296326f, 71.659988f, 42.020767f, -0.749665f, 30.568419f, -84.345169f, -88.957222f, 62.976131f, 17.781088f, 35.814819f, 41.151264f, 100.832329f, 51.108604f, + -55.090458f, 141.549744f, 45.250282f, 126.572884f, 51.766277f, -4.223619f, -20.867323f, -46.912258f, 12.903956f, -24.562819f, -59.262470f, -34.927166f, -24.950871f, 4.246840f, 14.226479f, -12.156185f, + -18.676003f, 56.782200f, 24.631006f, 31.817165f, -57.425724f, -164.249939f, -100.221893f, -51.068310f, -151.775375f, -103.694389f, 51.353741f, -14.789831f, 103.796227f, 121.169785f, 67.449203f, 45.746460f, + -9.249492f, -0.717516f, -95.589256f, -58.979927f, 183.596542f, 82.821739f, -44.961880f, -113.124100f, -73.027855f, 24.111319f, -9.787043f, -20.309830f, -9.503817f, -25.950542f, -63.329922f, -49.288395f, + -39.281731f, -8.520073f, 12.045630f, 113.941223f, 56.889790f, 11.705962f, -25.992363f, -25.818201f, 41.962906f, 136.173462f, 158.992706f, 71.041000f, -94.766388f, -115.894958f, -100.844521f, -76.998589f, + -8.995197f, 14.692396f, 10.648182f, 46.508247f, -46.040749f, -30.752420f, -101.055634f, 157.707993f, 120.625099f, -34.914780f, -60.452560f, -125.891411f, -64.873436f, 115.602501f, 134.647278f, 88.401085f, + -16.291512f, 25.577784f, -57.797333f, -93.257050f, 204.563004f, 23.844887f, 18.521849f, -48.872440f, -34.910671f, 52.242157f, 90.209885f, 155.241089f, 122.966759f, 97.500565f, 51.306534f, 61.434639f, + 5.888782f, 91.756126f, 55.121063f, 59.742477f, -13.308426f, -24.613007f, -59.364792f, -131.265594f, -87.939194f, -56.433189f, -38.294590f, 21.820187f, 22.980511f, -26.082766f, -9.050174f, -5.993128f, + -109.033333f, -70.663361f, -105.171837f, -29.390360f, 23.201317f, -1.143196f, -0.591588f, -62.349960f, 177.791931f, 64.124794f, 18.023848f, 85.805557f, 57.960117f, -10.079674f, -10.009348f, -11.720422f, + -1.513953f, 39.937832f, 25.296638f, 52.355652f, 31.179762f, 169.450806f, 131.414230f, 42.987076f, 48.422070f, -2.570796f, -102.850693f, -184.716797f, 126.997742f, 120.658882f, 70.227798f, 51.911579f, + 14.841161f, 42.875328f, -31.856815f, -61.852024f, -95.273911f, -33.013256f, 70.492905f, -26.551783f, -11.850163f, 50.677963f, -74.369408f, 121.694061f, 184.952850f, 83.381836f, 119.151489f, 86.071533f, + -76.190552f, 217.282104f, -47.804283f, 21.103445f, 63.081154f, 35.664818f, 9.597631f, -78.337799f, 33.574825f, 9.579362f, 11.619099f, -66.239075f, -93.457573f, -67.129135f, -28.104412f, -48.758240f, + -32.987583f, 55.155075f, -19.071968f, 25.848909f, 147.531418f, 161.891159f, 100.338860f, 122.278191f, 117.346077f, 121.715561f, 59.932480f, -5.041065f, -11.882968f, 25.816359f, 5.152595f, -6.028398f, + -50.602802f, 47.969971f, 109.523300f, -18.894117f, 104.845932f, 3.333271f, 81.642517f, 48.507870f, 18.322062f, 13.163134f, -27.716911f, -78.545464f, -60.946442f, -21.241007f, -43.533047f, -54.892029f, + 23.136389f, 29.755871f, 115.663109f, 366.295105f, 92.912613f, -56.490879f, -23.877293f, -67.456276f, -41.077976f, 176.197632f, 112.048927f, 87.809334f, 124.036644f, 73.674416f, 55.857883f, -59.281975f, + 36.171646f, 81.249886f, 0.990727f, 62.659752f, -6.243932f, -32.411499f, 103.505295f, -8.062663f, -11.415750f, -33.329777f, -157.624710f, 108.892738f, -52.815735f, -116.408310f, -114.794746f, -108.042885f, + -53.235435f, -53.853008f, -22.214457f, -62.809551f, -184.508316f, 55.657627f, 60.393047f, 8.903349f, 119.629532f, 99.485672f, 93.179787f, 12.529486f, -36.033150f, 91.600227f, 120.306450f, 101.186569f, + -266.389862f, -40.268497f, 58.560471f, -15.688929f, 15.476221f, 40.140427f, 70.106178f, 33.398193f, -55.307781f, -54.812614f, 9.501314f, -32.842312f, 1.404359f, 72.411819f, 48.677658f, 19.896832f, + -30.625458f, -22.088581f, 23.690083f, 147.814285f, 106.761505f, 32.618851f, -56.217175f, -56.086750f, -39.910542f, -27.860449f, 41.870930f, 33.237003f, 14.673645f, 133.780670f, 65.161377f, 29.900471f, + 52.106541f, 97.515167f, -46.684582f, 28.368923f, 50.509525f, -14.864295f, 9.164424f, -87.343681f, -53.357895f, -14.466661f, -124.789276f, 139.007889f, 57.820137f, -198.630005f, 89.412651f, 73.174347f, + -11.813260f, 28.477610f, 43.814209f, 53.005009f, -31.552076f, 12.509279f, -45.665352f, 0.665018f, 89.380127f, 35.962025f, 56.310169f, 231.104538f, 77.507759f, -6.636252f, -114.024948f, -103.220619f, + 3.209964f, 92.323235f, 134.360977f, 72.508331f, -71.873093f, -24.684990f, -70.873833f, -80.898567f, 36.660206f, 107.964767f, 56.888454f, -41.093380f, -94.986824f, 5.479705f, 85.588272f, 86.314072f, + 2.358892f, 19.563696f, -40.146599f, 106.779350f, 84.014519f, 66.932846f, 7.030437f, -25.116844f, 113.391785f, 69.206184f, -40.131550f, 153.922714f, 143.482407f, 34.324108f, 313.322266f, 143.053925f, + -22.836403f, 14.444014f, -49.938580f, -50.887901f, -139.897385f, 96.043907f, 97.666435f, -49.784187f, 51.330086f, 49.973110f, 36.349068f, 19.132963f, -131.961868f, -176.490204f, 84.266121f, 168.514481f, + -37.196350f, -31.474470f, -145.770355f, 73.739777f, -13.749185f, -36.067165f, -73.649986f, 69.205238f, 57.424969f, -29.286839f, 50.821659f, 151.341400f, 196.208405f, 145.900299f, 73.740807f, 59.942463f, + -48.483910f, 109.854485f, 175.905731f, 107.550728f, 182.661041f, 127.042297f, 56.932144f, -4.789718f, -40.474155f, -4.276073f, 15.682971f, -20.523733f, -2.600147f, 47.862274f, 10.863128f, -28.360899f, + -38.357815f, 12.670331f, -18.138870f, 42.676201f, 92.674187f, 36.742359f, 52.514660f, -5.668614f, -115.172440f, 43.835323f, 63.331287f, 56.027485f, 115.062248f, 3.782463f, -26.444477f, 273.927704f, + -70.262749f, -8.360212f, 4.471777f, 3.338549f, 59.435081f, 178.305817f, 71.276756f, -18.074911f, 8.591813f, 75.633720f, 25.886395f, -77.867401f, -98.552505f, 23.158539f, 89.771393f, 55.317135f, + -43.166435f, -20.516071f, -21.639067f, 58.366417f, -37.861000f, 87.507889f, 228.670868f, 168.987442f, 151.971222f, 95.947609f, 62.651642f, 55.564648f, -1.630664f, -52.394417f, -111.610962f, 110.578148f, + -3.820340f, 128.265320f, 241.518845f, 81.778282f, 29.058863f, -34.290600f, -72.192398f, -76.477760f, -66.605965f, -11.854634f, 31.504972f, 41.623680f, 49.260410f, 46.350578f, 25.015730f, 0.466101f, + -74.436829f, -21.117008f, 50.415005f, 41.561440f, 24.320005f, 3.089626f, 84.041313f, 176.202164f, 134.057922f, 109.030365f, 39.151558f, 51.717243f, 205.704620f, 150.353210f, 111.243019f, 26.017376f, + -0.922336f, 8.721625f, 49.901936f, 20.303036f, -45.592381f, -38.354324f, 58.650257f, -53.023918f, -56.784760f, -43.466248f, -124.796875f, -123.479370f, -110.273987f, -34.595661f, -16.564945f, 34.111702f, + -30.525043f, -2.907169f, -178.401764f, -44.677608f, -17.348223f, -31.677353f, -14.556618f, -31.867868f, 20.035357f, 2.716418f, -2.513957f, -41.058819f, -52.201744f, 41.795589f, 65.134628f, 38.667267f, + -92.711220f, -81.188332f, 165.320053f, 146.599762f, 22.146481f, -21.278519f, -40.179806f, -68.613281f, 115.899551f, 67.407913f, 2.306747f, 0.489086f, -1.279717f, 7.199631f, -40.551086f, -8.905237f, + -56.852066f, -32.516693f, -15.849322f, 68.052765f, 92.856277f, 97.140533f, 38.923428f, -64.162766f, -101.875473f, -63.277794f, -78.587120f, -32.074039f, 106.572845f, 95.851845f, 38.376095f, 15.852232f, + -53.858379f, -20.356443f, -84.059586f, -105.614822f, -51.119640f, -2.018013f, -77.954140f, -175.482086f, 79.777809f, 19.744781f, -53.635326f, -51.991280f, -49.052460f, -20.029406f, 16.108711f, 24.346910f, + 65.308319f, 24.882250f, -53.676472f, 35.191555f, -75.052139f, -100.669830f, 139.646332f, 26.502867f, -87.489288f, 144.371918f, 85.639999f, -5.127411f, 49.956379f, -68.622177f, -194.561584f, -257.525238f, + -72.071564f, 88.947922f, 181.188904f, -141.172180f, 21.858112f, 21.690336f, 80.976372f, 74.222694f, 14.965449f, 4.836141f, -13.533607f, 12.946756f, 80.034424f, 18.799646f, -1.797944f, -11.852658f, + -55.483604f, -28.792759f, -51.127789f, -27.386141f, -3.054134f, 270.684784f, 127.849197f, -7.843138f, -46.675968f, -2.273780f, -41.244320f, 107.264915f, 109.052605f, -57.428146f, -94.478180f, 201.012741f, + 58.417904f, 129.794479f, 88.032875f, -43.482414f, 1.503281f, 18.233082f, -4.274224f, -9.935395f, -90.743645f, -138.744934f, 13.047572f, 99.424622f, 79.562485f, -10.939718f, -128.585876f, -119.279457f, + -106.237129f, -91.740143f, 68.612770f, 19.771488f, -23.333853f, 6.881060f, -114.409279f, 37.293667f, 27.547070f, -21.962831f, 62.975277f, 126.174873f, 137.661591f, 88.351982f, 21.489727f, 36.082073f, + 49.864040f, 101.988388f, 41.740952f, -2.001927f, -83.519859f, 222.208069f, 203.213120f, 27.999317f, -8.565958f, -46.465588f, -117.948517f, -54.232327f, 28.665607f, -23.274929f, -55.554726f, -66.254654f, + -52.622940f, -27.317537f, -61.638550f, 130.447021f, 38.187801f, -83.578110f, 91.015823f, 65.975807f, -29.551769f, -55.780457f, -169.249374f, 136.943573f, 43.613983f, 85.860855f, 145.805145f, 83.847832f, + 15.936594f, 90.094734f, -129.895950f, 8.163410f, -8.877759f, -0.308240f, -33.896103f, 62.208805f, 103.766220f, 66.179008f, 27.826544f, -68.158470f, -111.605835f, -60.367783f, -34.454868f, -50.271614f, + -51.554886f, -21.024059f, -18.746723f, 92.973503f, -20.544609f, -4.456210f, 41.285404f, -2.806954f, 202.912384f, 180.625198f, 93.686058f, 105.542542f, -40.283619f, -22.137281f, 28.882605f, 86.878098f, + 166.593475f, 204.373047f, 175.392639f, 6.547530f, -67.728508f, -1.995924f, 104.944130f, 25.587944f, -76.602921f, 2.406351f, -37.560753f, -66.060905f, 82.223129f, -5.690928f, -80.786980f, -192.349823f, + 5.629341f, 24.807444f, 33.959263f, 139.666183f, 67.254204f, 113.142754f, 5.735409f, -36.896606f, 102.640205f, 13.071086f, -75.008644f, 135.153275f, 112.622955f, 93.684708f, 55.722095f, 17.380138f, + -78.392647f, 67.183548f, 41.397549f, 47.879723f, -95.470726f, -223.305008f, 34.429707f, 203.257339f, 81.951591f, 24.905951f, -102.131676f, -172.571976f, 80.404175f, -3.289175f, -63.539902f, -178.667999f, + -8.287517f, 28.750130f, 2.918398f, -190.230972f, 30.998074f, -24.621058f, 57.173183f, 67.070824f, -30.796249f, 125.394531f, 129.483154f, 69.056030f, 61.479782f, 5.587425f, -26.427807f, -42.299709f, + -53.579803f, 3.932101f, 19.298172f, 60.866375f, 203.507217f, 92.185112f, 4.952492f, 26.875463f, 58.186695f, 23.599648f, -55.879227f, -95.170883f, -128.408905f, -56.559254f, -13.179881f, -6.339478f, + 32.887764f, 110.878929f, 47.881824f, 61.743668f, 32.366764f, -43.335995f, 132.176224f, 23.456560f, -170.514435f, 21.666937f, -6.332648f, 200.979141f, 36.371750f, 69.918137f, 54.659019f, -24.744967f, + -48.200562f, -14.369913f, -109.873573f, 132.716415f, 33.534492f, 21.027716f, 29.168337f, -6.307217f, 29.464451f, -16.280748f, -5.903169f, -33.134434f, -163.021179f, -114.629570f, 242.579056f, 153.244400f, + -245.076645f, -119.108864f, 30.076363f, 46.303539f, 62.514118f, -1.635351f, 60.051456f, 85.906593f, 63.114086f, 96.103294f, 94.438263f, 60.414326f, 27.037113f, 46.420849f, 23.188837f, -4.991467f, + 48.128830f, 147.061111f, -19.109028f, -62.073257f, 73.974655f, 35.121407f, 48.858604f, 17.476908f, -27.161577f, -26.075205f, -23.080959f, -22.997204f, 22.060139f, 18.945644f, 12.078902f, 26.152502f, + -11.399143f, 35.660534f, 7.735845f, 28.895029f, 11.763469f, 67.383682f, 32.067547f, 172.807663f, 41.212330f, -64.892891f, 202.612274f, 66.128975f, 24.998840f, 129.758621f, 97.607491f, 64.079475f, + 16.849846f, -8.063315f, -96.246849f, -42.776253f, -61.709106f, 8.576951f, 41.636856f, 4.893633f, -184.455124f, 90.305283f, 214.893326f, 77.557159f, -52.231232f, -59.771557f, 115.499374f, 10.271899f, + -52.432972f, -10.506747f, 32.671928f, 30.160530f, -30.343365f, -108.296562f, -124.741348f, -114.153496f, 22.689064f, 53.387943f, 152.464798f, 195.884613f, 223.508789f, 180.783310f, 88.327431f, 24.891722f, + 44.069721f, 128.580154f, 87.081917f, 97.057877f, 80.764305f, 71.377975f, 76.201828f, 19.052254f, -86.244247f, -55.772846f, -78.071259f, 59.358582f, -18.004076f, -97.394165f, 203.970825f, 128.282730f, + -29.760933f, -17.373451f, -26.997627f, 298.461884f, 135.359589f, -5.173777f, 50.398880f, 16.654043f, -28.228046f, 127.954193f, 88.721756f, 31.046473f, 72.834770f, 51.219566f, 124.174194f, 179.024460f, + -71.473610f, -8.079115f, -80.057495f, 73.607849f, -11.565989f, 6.495467f, 75.740349f, 69.178413f, 172.751343f, 50.800892f, -29.929661f, -55.132294f, -39.521492f, -34.578106f, 29.018955f, 18.790855f, + 4.944071f, 58.298073f, 72.167747f, -20.213915f, -49.029274f, -5.245622f, 135.798645f, 114.233170f, 48.812248f, 154.565750f, 91.869995f, 9.594048f, 29.263868f, 29.942837f, 60.248390f, 56.068134f, + 20.676535f, 129.442535f, 114.557922f, 65.585472f, 9.776167f, 76.209824f, 142.460770f, 65.045479f, 31.220121f, 68.550804f, 85.770195f, 65.380852f, 33.190002f, -80.774033f, -170.538605f, 61.262844f, + -23.503824f, 198.854172f, 14.658221f, 54.346264f, 29.317448f, -15.893962f, 6.081978f, 50.519886f, 129.337723f, 125.421761f, 131.127838f, 197.853912f, 207.257065f, 154.032959f, 90.113098f, 66.989784f, + -62.626553f, 0.772200f, -28.967108f, -85.223953f, -146.385803f, 82.958099f, -24.949381f, 93.786552f, 94.234512f, -39.738564f, -74.894165f, -36.566628f, -39.978264f, 3.580493f, -15.366054f, -32.318130f, + -54.913471f, 12.737958f, -117.342049f, -59.757664f, -14.541400f, -24.570677f, -20.895752f, -18.573147f, -31.541250f, 3.822062f, 63.816460f, 68.993881f, 96.323494f, 113.108215f, 60.914867f, 38.452541f, + -74.699921f, -33.957706f, 274.636505f, 42.985191f, -13.963601f, 35.379383f, 27.960144f, -9.738332f, 15.494253f, -5.034236f, -48.640007f, -28.968740f, -24.268768f, 34.582504f, 11.429268f, 13.275120f, + 32.094368f, 53.997974f, 58.552933f, 60.038021f, 15.307313f, -14.686091f, -79.145950f, -92.266304f, 6.606106f, -31.398434f, 1.153621f, 61.459366f, 211.102783f, 199.088348f, 139.181458f, 90.360237f, + 13.961225f, 107.374969f, -42.851105f, 111.353691f, 85.895554f, -10.314037f, -36.885490f, -48.654755f, -86.748146f, -13.811635f, -28.521486f, -133.376526f, 66.836365f, 63.232780f, 50.980137f, 33.082199f, + 0.719331f, 59.833492f, 52.997120f, 109.368217f, 78.191238f, 181.871460f, 110.776367f, 41.572018f, 32.371555f, 59.911247f, 100.121117f, 147.708542f, 67.625221f, -90.737854f, -184.544220f, -95.008667f, + 17.476965f, 51.444233f, 130.136398f, 86.703789f, -21.260557f, -68.970932f, -246.970169f, 111.624298f, 106.618408f, -70.539291f, -17.852840f, 74.588875f, 22.676432f, 82.200706f, 75.469940f, 86.911079f, + -21.763515f, 88.468819f, 69.462051f, 28.234957f, 137.905060f, 97.628418f, 100.231453f, 71.048729f, -26.023251f, 18.455929f, 100.078911f, 91.618004f, 129.572266f, 162.295929f, 117.883362f, 73.251602f, + 20.503130f, 123.177406f, 98.707054f, -61.945675f, -133.366302f, -42.585499f, 17.451960f, -85.110466f, -109.559792f, 57.105164f, 49.939404f, 71.494247f, 106.595436f, -5.332850f, -10.096909f, 95.286079f, + -98.944687f, -70.735931f, -91.238235f, 77.213318f, 43.834396f, 103.931374f, 14.455284f, -18.546854f, 60.298130f, 69.783432f, 81.150307f, 75.219597f, 117.014557f, 133.318222f, 45.655605f, 44.907104f, + -17.773401f, 16.685305f, 35.210880f, 58.453514f, -39.141315f, 154.492096f, 160.108368f, 54.245167f, 143.091782f, 18.370985f, -46.498653f, 30.260704f, -32.253002f, 114.865051f, 94.643227f, 42.126125f, + 8.305405f, 73.466248f, 71.895737f, 7.841229f, -21.096027f, -83.805069f, 142.372986f, 32.864574f, -67.817047f, 0.273488f, -20.763456f, -39.558540f, 45.929173f, 245.427109f, 63.606354f, -33.662392f, + -9.818366f, 215.528351f, -34.979908f, -46.600666f, -52.985126f, -36.442551f, -23.177917f, 89.040405f, 115.907364f, 85.734955f, 85.459145f, 53.537971f, 38.606289f, 35.117779f, -9.532898f, -46.531116f, + 70.627678f, 109.927406f, 130.617371f, 127.965912f, 68.237038f, 175.485825f, 141.335297f, 101.838699f, 85.440056f, 100.211769f, -9.782224f, -34.040447f, -36.362839f, -103.141747f, -183.433182f, -281.405945f, + 13.631050f, 103.082298f, 153.487061f, 95.539291f, 80.014320f, 47.319462f, -47.897068f, 144.786728f, 150.994034f, 33.507248f, 38.446999f, -11.836577f, -52.710697f, -5.434279f, -6.585646f, -43.525864f, + -46.841568f, -36.090340f, 91.028366f, 223.865204f, 162.487579f, 161.622040f, 92.281693f, 72.600441f, 62.700375f, 116.998756f, 104.000122f, 56.268940f, 3.313947f, 39.044933f, 12.683829f, -66.421524f, + -53.988426f, -4.046704f, -43.765293f, -58.490433f, -61.409744f, 68.780487f, 180.177185f, 130.743820f, 59.566154f, 41.610359f, -29.455439f, -47.845570f, -53.330845f, -194.252975f, -99.193802f, -28.624321f, + -40.226192f, 19.173496f, -102.776230f, -115.559639f, -2.041245f, 17.804632f, 54.120743f, 35.981876f, 107.003677f, 67.225113f, 6.590813f, 31.162287f, 75.625832f, 94.116089f, 68.273361f, 19.100948f, + -81.027779f, -47.543785f, -81.577866f, 147.072006f, 140.771072f, 98.894592f, 98.462875f, 120.500710f, 69.188560f, -27.267778f, -26.730125f, 19.004963f, 28.982193f, 18.988167f, 15.679336f, 0.912693f, + 60.063290f, 68.444176f, -38.306652f, 274.795166f, 81.706596f, 1.653586f, 59.518078f, 81.843979f, 45.452694f, -98.132660f, 99.485909f, 72.635452f, 59.011009f, 43.986206f, 68.393044f, 153.643753f, + -54.196396f, 105.024605f, -46.588734f, 29.173431f, 46.003738f, 53.556526f, -1.795008f, -94.732422f, 74.060417f, 37.018723f, 57.519180f, 40.312252f, 4.980567f, 1.190214f, 65.139198f, 16.854973f, + 83.697479f, 124.012848f, 136.707169f, 105.191093f, 50.574764f, 7.427887f, 165.615936f, 120.431198f, 35.935490f, 146.632690f, 107.372086f, 101.817780f, 178.695389f, 32.956997f, -43.566265f, -170.662201f, + -45.706387f, 22.193432f, 48.583588f, 7.809529f, 108.639076f, 20.145479f, -8.151466f, 16.626425f, 45.076824f, 100.699867f, 56.172535f, 31.245377f, 41.698193f, 43.700226f, 33.969212f, 13.647820f, + 30.930534f, 96.241432f, 20.796177f, 20.642069f, -30.030577f, 105.024353f, 182.286652f, 51.891121f, -23.670610f, 19.259420f, -25.995207f, 144.711807f, 151.061661f, 39.095882f, 216.597061f, 151.033951f, + 55.972961f, 165.229263f, 42.423416f, -9.421596f, 9.304959f, -24.490530f, 65.337448f, 0.772096f, 34.500309f, 28.041000f, 164.460770f, 148.005341f, -44.788933f, -131.866653f, 118.602074f, 174.952545f, + -36.805115f, 2.389628f, -160.064590f, -74.493019f, -34.030777f, -37.621536f, 21.365028f, 11.060207f, 72.113487f, 151.263977f, 203.227783f, 232.426346f, 240.348846f, 198.561386f, 130.545105f, 79.279305f, + -5.590322f, 28.170464f, 31.049704f, 123.245987f, 143.256638f, 251.395782f, 35.744690f, -42.437420f, -26.080673f, 16.841845f, 18.203182f, 83.183998f, 68.937943f, -68.034676f, 4.653465f, 101.861214f, + 75.410370f, 146.164398f, 101.675415f, 188.854752f, 65.271072f, -0.098294f, 44.761238f, -45.286770f, -80.445572f, 95.316223f, -28.573139f, 1.249410f, 194.675003f, 77.615021f, 9.229208f, 122.592499f, + -53.932175f, 216.979111f, -2.220833f, 63.310429f, 91.275101f, 57.843071f, 70.857147f, 42.466930f, 77.749489f, 57.652969f, 21.516739f, -1.124474f, -30.274309f, -13.056955f, 15.011532f, -30.375456f, + 67.425507f, 84.229256f, 101.499359f, 28.049738f, -35.614960f, 320.076202f, 252.214386f, 152.618103f, 138.893570f, 99.840240f, 27.951473f, 49.207226f, 65.402916f, 7.603233f, -14.404366f, -35.147362f, + -19.139826f, 222.586807f, 160.578033f, 15.308187f, 37.928532f, 2.810670f, 89.260468f, 73.903893f, -14.074634f, 9.220748f, 52.358765f, 29.237804f, 68.572754f, 74.369972f, 135.163269f, 53.634529f, + 27.498774f, 55.932766f, 90.594849f, 106.451241f, 66.339134f, 276.491119f, 112.921783f, 68.186401f, 34.717724f, 217.367447f, 183.300674f, 171.332642f, 233.111526f, 113.635857f, -94.105415f, 101.164040f +}; + +/*----------------------------------------------------------------------------------* + * LSF quantization - Scaling factors + *----------------------------------------------------------------------------------*/ + +/* stable ISP vector */ +const float stable_ISP[M] = +{ + 0.9808f, 0.9239f, 0.8315f, 0.7071f, 0.5556f, 0.3827f, 0.1951f, 0.0f, -0.195f, -0.3826f, -0.5555f, -0.7071f, -0.8314f, -0.9238f, -0.9808f, 0.045f +}; + +/* stable ISF vector */ +const float stable_ISF[M] = +{ + 399.846527f, 799.890991f, 1199.888550f, 1600.019531f, 1999.927002f, 2399.963379f, 2799.979736f, 3200.0f, 3599.812256f, 3999.815918f, 4399.827637f, 4799.980469f, 5199.744629f, 5599.576660f, 6000.153320f, 1554.147827f +}; + +/* stable LSP vector (corresponds to GEWB_Ave[]) */ +const float stable_LSP[M] = +{ + 0.9899f, 0.9667f, 0.8998f, 0.7837f, 0.6581f, 0.5009f, 0.3307f, 0.1643f, -0.0224f, -0.1955f, -0.3658f, -0.5200f, -0.6730f, -0.8040f, -0.9057f,-0.9700f +}; + + +/*----------------------------------------------------------------------------------* + * LSF quantization - Mean LSF vectors + *----------------------------------------------------------------------------------*/ +/* These are not used anywhere */ +/* A 16-by-1 matrix */ +const float means_wb_cleanspeech_lsf16k0[16] = {355.08f, 696.48f, 1260.55f, 1735.55f, 2220.70f, 2676.17f, 3123.44f, 3560.94f, 3989.45f, 4399.61f, 4869.14f, 5372.66f, 5894.53f, 6364.45f, 6883.20f, 7302.73f}; +/* A 16-by-1 matrix */ +const float means_swb_cleanspeech_lsf25k6[16] = {614.44f, 1437.24f, 2259.37f, 2994.68f, 3732.57f, 4420.10f, 5187.93f, 5985.97f, 6790.66f, 7523.16f, 8283.87f, 9010.86f, 9757.03f, 10458.90f, 11209.84f, 11888.64f}; +/* A 16-by-1 matrix */ +const float means_swb_cleanspeech_lsf32k0[16] = {739.65f, 1811.71f, 2794.79f, 3708.53f, 4594.87f, 5528.75f, 6583.99f, 7512.05f, 8455.51f, 9352.67f, 10266.73f, 11133.74f, 12067.91f, 12958.21f, 13940.67f, 14794.15f}; + +/* An 16-by-1 matrix */ +const float SVWB2_Ave[16] = +{ + 389.8438f, 581.2500f, 1047.6563f, 1493.3594f, 1985.9375f, 2462.8906f, 2923.8281f, 3392.9688f, 3851.9531f, 4298.4375f, 4819.9219f, 5337.5000f, 5893.7500f, 6378.9063f, 6899.6094f, 7325.7813f +}; +/* An 16-by-1 matrix */ +const float IANB_Ave[16] = +{ + 283.5938f, 559.7656f, 973.8281f, 1331.2500f, 1695.3125f, 2037.1094f, 2383.9844f, 2713.6719f, 3035.9375f, 3334.3750f, 3614.0625f, 3910.9375f, 4261.3281f, 4854.2969f, 5467.5781f, 5934.7656f +}; +/* An 16-by-1 matrix */ +const float IAWB_Ave[16] = +{ + 225.3906f, 527.3438f, 986.7188f, 1380.8594f, 1773.0469f, 2150.0000f, 2537.8906f, 2914.0625f, 3298.8281f, 3670.3125f, 4051.1719f, 4421.4844f, 4807.4219f, 5182.8125f, 5566.0156f, 5940.2344f +}; +/* An 16-by-1 matrix */ +const float IAWB2_Ave[16] = +{ + 285.5469f, 694.1406f, 1247.6563f, 1713.2813f, 2198.8281f, 2658.5938f, 3129.6875f, 3579.6875f, 4034.7656f, 4480.0781f, 4973.0469f, 5483.2031f, 5986.7188f, 6460.1563f, 6953.5156f, 7393.3594f +}; +/* An 16-by-1 matrix */ +const float UVNB_Ave[16] = +{ + 397.6563f, 689.0625f, 1115.6250f, 1465.2344f, 1801.1719f, 2113.2813f, 2434.7656f, 2719.1406f, 3001.9531f, 3243.7500f, 3460.5469f, 3642.5781f, 3897.2656f, 4586.3281f, 5351.1719f, 5888.2813f +}; +/* An 16-by-1 matrix */ +const float UVWB_Ave[16] = +{ + 350.7813f, 742.1875f, 1239.0625f, 1636.7188f, 2023.8281f, 2406.6406f, 2786.7188f, 3150.7813f, 3513.6719f, 3862.5000f, 4212.5000f, 4545.3125f, 4893.3594f, 5232.8125f, 5586.3281f, 5930.8594f +}; +/* An 16-by-1 matrix */ +const float SVNB_Ave[16] = +{ + 347.6563f, 495.3125f, 753.9063f, 1133.5938f, 1538.2813f, 1883.9844f, 2278.1250f, 2595.3125f, 2924.6094f, 3203.9063f, 3478.9063f, 3728.5156f, 4214.0625f, 4908.2031f, 5452.7344f, 5930.8594f +}; +/* An 16-by-1 matrix */ +const float SVWB_Ave[16] = +{ + 325.0000f, 487.5000f, 761.3281f, 1204.2969f, 1613.6719f, 1998.8281f, 2413.6719f, 2760.5469f, 3128.1250f, 3485.1563f, 3857.4219f, 4195.7031f, 4603.5156f, 5023.4375f, 5456.2500f, 5878.1250f +}; +/* An 16-by-1 matrix */ +const float GEWB_Ave[16] = +{ + 289.8438f, 527.3438f, 919.5313f, 1365.2344f, 1736.7188f, 2131.2500f, 2513.2813f, 2863.6719f, 3245.7031f, 3600.7813f, 3962.8906f, 4314.0625f, 4703.9063f, 5102.7344f, 5508.2031f, 5899.6094f +}; +/* An 16-by-1 matrix */ +const float GEWB2_Ave[16] = +{ + 355.0781f, 696.4844f, 1260.5469f, 1735.5469f, 2220.7031f, 2676.1719f, 3123.4375f, 3560.9375f, 3989.4531f, 4399.6094f, 4869.1406f, 5372.6563f, 5894.5313f, 6364.4531f, 6883.2031f, 7302.7344f +}; +/* An 16-by-1 matrix */ +const float GENB_Ave[16] = +{ + 326.5625f, 525.0000f, 881.6406f, 1274.6094f, 1630.0781f, 1965.2344f, 2324.2188f, 2619.9219f, 2935.1563f, 3216.4063f, 3469.1406f, 3687.1094f, 4059.7656f, 4775.7813f, 5412.1094f, 5912.1094f +}; +/* An 16-by-1 matrix */ +const float TRNB_Ave[16] = +{ + 358.9844f, 521.4844f, 822.6563f, 1227.3438f, 1598.4375f, 1928.9063f, 2306.6406f, 2605.4688f, 2925.7813f, 3202.7344f, 3464.0625f, 3689.0625f, 4118.7500f, 4837.1094f, 5429.6875f, 5920.3125f +}; +/* An 16-by-1 matrix */ +const float TRWB_Ave[16] = +{ + 325.7813f, 517.9688f, 840.2344f, 1305.0781f, 1681.6406f, 2069.9219f, 2467.9688f, 2811.7188f, 3190.2344f, 3543.3594f, 3906.6406f, 4244.9219f, 4637.1094f, 5043.7500f, 5463.2813f, 5877.3438f +}; +/* An 16-by-1 matrix */ +const float TRWB2_Ave[16] = +{ + 369.1406f, 603.9063f, 1119.5313f, 1621.0938f, 2086.7188f, 2565.6250f, 2992.1875f, 3441.0156f, 3864.8438f, 4271.0938f, 4753.9063f, 5303.5156f, 5851.9531f, 6359.3750f, 6880.4688f, 7335.1563f +}; +/* An 16-by-1 matrix */ +const float AUNB_Ave[16] = +{ + 346.4844f, 563.6719f, 920.3125f, 1247.6563f, 1603.5156f, 1933.2031f, 2281.6406f, 2591.7969f, 2905.0781f, 3195.7031f, 3463.6719f, 3702.3438f, 4056.6406f, 4758.5938f, 5413.2813f, 5910.5469f +}; +/* An 16-by-1 matrix */ +const float AUWB_Ave[16] = +{ + 316.4063f, 573.4375f, 967.1875f, 1334.7656f, 1717.1875f, 2086.7188f, 2465.2344f, 2818.3594f, 3191.7969f, 3546.0938f, 3917.9688f, 4284.7656f, 4692.9688f, 5107.4219f, 5525.7813f, 5911.3281f +}; +/* An 16-by-1 matrix */ +const float AUWB2_Ave[16] = +{ + 364.4531f, 681.6406f, 1187.5000f, 1623.8281f, 2101.1719f, 2535.1563f, 2986.7188f, 3408.2031f, 3848.4375f, 4269.5313f, 4771.0938f, 5330.8594f, 5883.5938f, 6366.0156f, 6889.0625f, 7331.2500f +}; +/* An 16-by-1 matrix */ +const float Predictor0[16] = +{ + 0.83499f, 0.83499f, 0.83499f, 0.82999f, 0.82999f, 0.82999f, 0.80499f, 0.80750f, 0.79999f, 0.79300f, 0.80750f, 0.80750f, 0.79300f, 0.78500f, 0.78500f, 0.75500f +}; +/* An 16-by-1 matrix */ +const float Predictor1[16] = +{ + 0.82501f, 0.82501f, 0.82501f, 0.81299f, 0.80301f, 0.81299f, 0.81299f, 0.79749f, 0.79999f, 0.79999f, 0.80750f, 0.82001f, 0.82001f, 0.81500f, 0.82501f, 0.81299f +}; +/* An 16-by-1 matrix */ +const float Predictor2[16] = +{ + 0.73999f, 0.72000f, 0.74799f, 0.73999f, 0.74799f, 0.73300f, 0.73300f, 0.72501f, 0.72501f, 0.73300f, 0.73999f, 0.73999f, 0.72000f, 0.70499f, 0.72000f, 0.70499f +}; +/* An 16-by-1 matrix */ +const float Predictor3[16] = +{ + 0.73999f, 0.73999f, 0.75500f, 0.73999f, 0.74799f, 0.72501f, 0.71500f, 0.70499f, 0.69000f, 0.70499f, 0.72000f, 0.75500f, 0.76300f, 0.75500f, 0.76300f, 0.75800f +}; +/* An 16-by-1 matrix */ +const float Predictor4[16] = +{ + 0.57999f, 0.56000f, 0.58801f, 0.57999f, 0.58801f, 0.57300f, 0.57300f, 0.56500f, 0.56500f, 0.57300f, 0.57999f, 0.57999f, 0.56000f, 0.54501f, 0.54001f, 0.52499f +}; +/* An 16-by-1 matrix */ +const float Predictor5[16] = +{ + 0.72751f, 0.72000f, 0.72000f, 0.72751f, 0.72751f, 0.72000f, 0.72000f, 0.72000f, 0.72751f, 0.73499f, 0.74301f, 0.75000f, 0.75000f, 0.71301f, 0.71301f, 0.71301f +}; +/* An 16-by-1 matrix */ +const float Predictor6[16] = +{ + 0.73499f, 0.72751f, 0.73499f, 0.72000f, 0.72000f, 0.70001f, 0.68301f, 0.66501f, 0.64499f, 0.67001f, 0.68301f, 0.74301f, 0.75000f, 0.72000f, 0.75000f, 0.74301f +}; +/* An 16-by-1 matrix */ +const float Predictor7[16] = +{ + 0.74301f, 0.73499f, 0.74301f, 0.74301f, 0.74301f, 0.73499f, 0.74301f, 0.75000f, 0.75000f, 0.75500f, 0.76501f, 0.74301f, 0.73499f, 0.72751f, 0.71301f, 0.75500f +}; +/* An 16-by-1 matrix */ +const float Predictor8[16] = +{ + 0.75500f, 0.75500f, 0.75500f, 0.75000f, 0.75000f, 0.75000f, 0.73499f, 0.72751f, 0.72000f, 0.71301f, 0.72751f, 0.72751f, 0.71301f, 0.70499f, 0.70499f, 0.67499f +}; +/* An 16-by-16 matrix */ +const float UVD_MA1[256] = +{ + -117.5781f, -196.4844f, -166.4063f, -73.0469f, -51.1719f, -25.0000f, -17.5781f, -7.8125f, 4.2969f, 21.8750f, 24.6094f, 35.1563f, 42.9688f, 68.3594f, 37.8906f, 12.8906f, + 62.8906f, 137.8906f, 185.1563f, 196.0938f, 276.9531f, 305.4688f, 310.1563f, 298.8281f, 246.8750f, 207.8125f, 158.5938f, 111.3281f, 89.8438f, 56.6406f, 37.8906f, 20.3125f, + -14.4531f, -1.9531f, 80.0781f, 126.1719f, 160.9375f, 136.3281f, 86.3281f, 35.5469f, -2.3438f, -23.0469f, -33.5938f, -43.7500f, -12.5000f, 81.6406f, 28.5156f, 8.9844f, + -106.6406f, -240.2344f, -320.3125f, -310.1563f, -325.7813f, -327.3438f, -321.0938f, -319.9219f, -293.3594f, -273.8281f, -250.3906f, -219.5313f, -152.7344f, -105.8594f, -71.8750f, -24.6094f, + 102.3438f, 65.6250f, 40.6250f, -3.5156f, -30.4688f, -63.6719f, -55.0781f, -77.7344f, -74.6094f, -97.2656f, -95.7031f, -123.8281f, -65.6250f, 208.9844f, 42.5781f, 12.8906f, + -160.1563f, -263.6719f, -266.0156f, -238.6719f, -195.3125f, -154.6875f, -106.6406f, -71.4844f, -18.3594f, 23.4375f, 75.7813f, 139.4531f, 407.8125f, 421.8750f, 130.8594f, 54.6875f, + 60.1563f, 72.2656f, 100.0000f, 92.9688f, 79.2969f, 92.9688f, 109.3750f, 101.5625f, 117.1875f, 104.2969f, 100.7813f, 76.5625f, 47.2656f, -241.4063f, -102.7344f, -23.4375f, + 134.7656f, 275.3906f, 335.5469f, 307.0313f, 290.2344f, 228.1250f, 166.0156f, 104.2969f, 65.6250f, 41.0156f, 28.9063f, 10.9375f, 46.4844f, 104.2969f, 41.0156f, 15.2344f, + -15.2344f, -64.8438f, -89.8438f, -76.5625f, -99.6094f, -107.8125f, -124.2188f, -136.3281f, -151.1719f, -171.0938f, -210.5469f, -239.4531f, -293.7500f, -373.4375f, -528.5156f, -635.9375f, + 194.5313f, 187.1094f, 161.7188f, 90.2344f, 38.2813f, 1.9531f, -7.0313f, -16.0156f, -23.4375f, -30.4688f, -35.5469f, -37.5000f, -31.6406f, 28.1250f, 11.7188f, -3.1250f, + 16.0156f, 46.8750f, 25.3906f, 55.0781f, 45.7031f, 72.6563f, 97.2656f, 116.7969f, 163.2813f, 203.1250f, 221.0938f, 241.4063f, 270.3125f, 226.1719f, 125.3906f, 64.8438f, + -92.1875f, -108.5938f, -26.9531f, 5.0781f, 44.1406f, 141.4063f, 173.8281f, 210.5469f, 196.4844f, 151.1719f, 105.0781f, 67.1875f, 46.8750f, -8.2031f, 0.3906f, 1.5625f, + -40.2344f, -17.9688f, -53.5156f, -51.5625f, -42.1875f, -37.8906f, -26.1719f, -14.4531f, -3.1250f, 16.0156f, 32.0313f, 41.7969f, 16.7969f, -236.3281f, -73.8281f, -21.8750f, + -85.9375f, -123.0469f, -188.2813f, -201.5625f, -191.0156f, -173.8281f, -162.1094f, -141.4063f, -118.7500f, -80.0781f, -53.1250f, -26.5625f, -2.7344f, 51.1719f, 27.3438f, 9.7656f, + -3.9063f, -47.2656f, -82.0313f, -92.5781f, -87.5000f, -117.9688f, -96.0938f, -121.0938f, -105.8594f, -133.9844f, -111.3281f, -142.1875f, 10.9375f, 274.6094f, 52.7344f, 21.0938f, + 46.0938f, 19.5313f, -26.1719f, -64.8438f, -136.3281f, -162.5000f, -172.6563f, -174.2188f, -171.4844f, -164.0625f, -149.2188f, -124.6094f, -95.7031f, -81.6406f, -54.6875f, -32.0313f +}; +/* An 16-by-16 matrix */ +const float UVD_MA2[256] = +{ + -29.2969f, -25.0000f, -58.5938f, -90.2344f, -106.2500f, -108.5938f, -96.8750f, -75.7813f, -60.9375f, -41.7969f, -28.9063f, -16.7969f, -35.9375f, -8.2031f, 3.5156f, 1.9531f, + 153.5156f, 107.4219f, -4.6875f, -60.9375f, -81.2500f, -83.9844f, -63.2813f, -51.5625f, -44.9219f, -42.5781f, -36.7188f, -33.2031f, -40.6250f, -3.9063f, 1.9531f, -0.3906f, + -116.0156f, -151.9531f, -38.6719f, -30.4688f, -25.7813f, -7.4219f, -4.6875f, 3.1250f, 0.0000f, -1.1719f, -5.8594f, -8.5938f, -44.1406f, -32.0313f, -6.2500f, 0.7813f, + 23.0469f, -4.2969f, 1.9531f, -12.8906f, -4.2969f, -23.8281f, -27.3438f, -54.2969f, -55.8594f, -93.3594f, -80.8594f, -87.1094f, 277.7344f, 273.8281f, 55.8594f, 26.5625f, + -76.1719f, 158.5938f, 86.7188f, 19.1406f, -2.3438f, -8.9844f, -2.3438f, 3.5156f, 0.0000f, 5.0781f, 10.1563f, 19.1406f, -17.1875f, -50.3906f, -7.0313f, -2.7344f, + 8.9844f, -11.7188f, -55.0781f, 30.8594f, -7.0313f, -29.6875f, -21.4844f, -5.4688f, 17.1875f, 38.2813f, 34.3750f, 33.5938f, -37.5000f, -137.1094f, -43.7500f, -15.2344f, + 148.4375f, 128.5156f, 91.7969f, 67.5781f, 55.0781f, 28.1250f, 9.7656f, -1.5625f, -2.3438f, -7.4219f, -8.2031f, -12.8906f, -21.4844f, -8.9844f, 1.1719f, -0.3906f, + -31.6406f, -82.0313f, -110.9375f, 61.7188f, 154.6875f, 113.2813f, 63.6719f, 23.0469f, -9.7656f, -8.5938f, -3.9063f, -2.3438f, -17.9688f, -12.5000f, 3.5156f, 1.9531f, + 3.5156f, 13.2813f, -5.8594f, 1.9531f, 8.9844f, -18.7500f, -49.6094f, -94.9219f, -135.5469f, -164.4531f, -177.7344f, -185.5469f, -193.3594f, -175.3906f, -114.8438f, -63.6719f, + -5.0781f, -66.7969f, -162.5000f, -161.7188f, -95.7031f, -9.7656f, 26.9531f, 39.8438f, 40.6250f, 32.8125f, 19.5313f, 12.8906f, -14.8438f, -1.5625f, 0.0000f, 1.9531f, + 19.5313f, 46.0938f, 26.5625f, 14.4531f, 57.4219f, 124.6094f, 144.9219f, 138.6719f, 113.6719f, 79.6875f, 50.7813f, 31.6406f, 8.2031f, 17.9688f, 14.0625f, 8.5938f, + -37.1094f, -42.1875f, 121.4844f, 83.5938f, -10.9375f, -59.7656f, -88.2813f, -75.0000f, -50.3906f, -26.9531f, -16.4063f, -4.2969f, -18.7500f, -6.6406f, 5.0781f, 0.7813f, + -72.2656f, -87.1094f, -40.6250f, 10.1563f, 20.7031f, 34.7656f, 51.5625f, 70.7031f, 100.7813f, 135.1563f, 155.0781f, 173.8281f, 153.1250f, 94.1406f, 48.8281f, 22.6563f, + 32.4219f, 12.8906f, -3.5156f, -31.6406f, 15.6250f, 38.6719f, 21.8750f, 3.1250f, -19.9219f, -33.2031f, -41.4063f, -48.4375f, -76.5625f, 1.9531f, 1.9531f, 0.0000f, + 55.8594f, 57.8125f, 7.4219f, -47.2656f, -96.4844f, -82.4219f, -26.1719f, 32.4219f, 77.3438f, 104.6875f, 113.2813f, 117.1875f, 93.7500f, 64.0625f, 33.5938f, 14.4531f, + -77.3438f, -53.1250f, 144.5313f, 145.3125f, 117.1875f, 93.7500f, 60.9375f, 44.1406f, 30.8594f, 23.4375f, 17.1875f, 11.3281f, -13.6719f, -14.8438f, 2.3438f, 2.7344f +}; +/* An 16-by-16 matrix */ +const float UVWB_MA3[256] = +{ + -10.1563f, 8.9844f, 2.7344f, -2.3438f, -0.3906f, 1.1719f, 15.6250f, 13.6719f, -16.7969f, -9.3750f, 21.8750f, 61.3281f, 103.5156f, 165.2344f, 149.2188f, 101.5625f, + 23.8281f, -117.1875f, -50.7813f, -39.4531f, -3.1250f, 41.4063f, 42.1875f, 44.5313f, 34.3750f, 16.7969f, -0.7813f, -12.8906f, -21.8750f, 26.1719f, 11.3281f, 5.0781f, + -12.1094f, 18.3594f, 17.5781f, -47.2656f, 17.9688f, 8.5938f, 43.3594f, 91.0156f, -100.0000f, -98.4375f, -48.0469f, -27.7344f, -12.1094f, 21.0938f, 21.8750f, 12.8906f, + 7.8125f, -60.1563f, 26.1719f, 77.3438f, -90.6250f, -65.2344f, -33.5938f, -4.6875f, 30.8594f, 45.3125f, 34.3750f, 30.4688f, 17.1875f, 29.2969f, 10.5469f, -2.7344f, + -5.4688f, 59.7656f, -64.8438f, 8.2031f, 41.7969f, 25.0000f, 91.0156f, -87.1094f, -57.4219f, -10.5469f, -0.3906f, 16.7969f, 23.8281f, 27.3438f, 19.5313f, 7.0313f, + 1.1719f, -44.9219f, -3.1250f, 55.8594f, 75.0000f, 75.3906f, -48.4375f, -76.1719f, -77.3438f, -63.2813f, -29.2969f, 5.4688f, 17.5781f, 32.4219f, 30.8594f, 19.1406f, + 4.6875f, -22.2656f, 9.7656f, -11.3281f, -4.2969f, 4.6875f, -2.7344f, -5.0781f, -4.6875f, 12.1094f, 28.9063f, 38.6719f, -3.9063f, -164.4531f, -81.6406f, -43.3594f, + -9.7656f, 44.9219f, 46.4844f, -7.4219f, -45.7031f, -64.0625f, -79.2969f, -92.5781f, -80.4688f, -66.0156f, -42.9688f, -16.0156f, -4.2969f, 5.8594f, 0.3906f, -2.7344f, + -5.0781f, 66.4063f, -55.8594f, -50.0000f, -87.5000f, -36.7188f, 0.3906f, 37.5000f, 56.2500f, 39.8438f, 11.3281f, 0.7813f, -14.4531f, 17.9688f, 2.7344f, -4.6875f, + -4.2969f, 3.9063f, -13.2813f, 14.8438f, 9.3750f, 33.5938f, 58.2031f, 82.4219f, 93.7500f, 108.9844f, 96.4844f, 85.1563f, 60.1563f, 62.8906f, 28.9063f, 5.8594f, + -9.3750f, 25.0000f, 42.9688f, 48.8281f, -9.3750f, 48.0469f, 62.8906f, 64.8438f, 69.1406f, 7.0313f, -43.7500f, -45.3125f, -55.0781f, -45.7031f, -44.1406f, -35.5469f, + -1.5625f, -7.8125f, -6.6406f, -4.2969f, -10.5469f, 5.0781f, -5.8594f, -15.6250f, -22.6563f, -61.3281f, -98.4375f, -110.5469f, -112.5000f, -72.6563f, -63.2813f, -43.7500f, + -7.8125f, 0.7813f, 12.5000f, 17.1875f, -12.1094f, -19.1406f, 3.1250f, 5.0781f, 21.4844f, -23.0469f, -63.2813f, -82.8125f, -23.8281f, 150.0000f, 44.9219f, 14.0625f, + -1.5625f, 16.4063f, -29.2969f, 35.9375f, 104.6875f, -79.2969f, -48.8281f, 3.9063f, 20.3125f, 47.2656f, 28.1250f, -16.7969f, -42.5781f, -18.3594f, -25.7813f, -29.6875f, + -15.2344f, 29.6875f, 104.6875f, -99.2188f, -10.9375f, 33.9844f, 0.7813f, 35.5469f, 33.2031f, 26.5625f, 34.7656f, 37.5000f, 16.4063f, 35.1563f, 15.2344f, 1.5625f, + 0.7813f, 0.7813f, -21.8750f, 2.7344f, 26.1719f, -12.1094f, -85.5469f, -75.0000f, -9.3750f, 57.0313f, 97.2656f, 105.0781f, 81.6406f, 77.7344f, 41.4063f, 12.1094f +}; +/* An 16-by-16 matrix */ +const float SVNB_SN1[256] = +{ + 52.7344f, 42.5781f, 52.7344f, -59.7656f, -214.4531f, 83.5938f, 162.5000f, 76.1719f, 113.6719f, 96.4844f, 39.0625f, -49.6094f, -226.1719f, -62.5000f, -25.7813f, -12.5000f, + -41.7969f, -58.5938f, -107.0313f, -58.2031f, 250.7813f, 232.0313f, 132.0313f, 71.4844f, 31.6406f, -12.1094f, -5.4688f, -58.5938f, -151.1719f, -15.6250f, -17.1875f, -7.0313f, + 28.5156f, 16.4063f, 66.7969f, 132.4219f, 83.2031f, 16.4063f, -53.5156f, -108.2031f, -148.0469f, -172.2656f, -171.8750f, -186.7188f, 105.4688f, 49.2188f, -1.5625f, 2.3438f, + -119.9219f, -187.1094f, -248.4375f, -232.8125f, -39.0625f, 32.4219f, 65.2344f, 78.1250f, 101.5625f, 146.8750f, 204.2969f, 410.5469f, 446.0938f, 191.4063f, 97.2656f, 42.1875f, + -57.8125f, -83.9844f, -126.5625f, -222.6563f, -358.2031f, -267.5781f, -81.2500f, 49.6094f, 111.3281f, 137.8906f, 172.2656f, 367.1875f, 429.6875f, 178.9063f, 89.4531f, 39.0625f, + 166.7969f, 168.7500f, 214.0625f, 166.4063f, 51.9531f, 5.0781f, -3.5156f, -55.0781f, -42.1875f, -56.2500f, -76.1719f, -163.6719f, -286.3281f, -56.2500f, -42.5781f, -17.5781f, + -44.9219f, -85.9375f, -75.7813f, 258.2031f, 350.0000f, 268.7500f, 191.0156f, 137.1094f, 82.4219f, 100.7813f, 57.4219f, 11.7188f, -291.4063f, -306.2500f, -60.9375f, -37.1094f, + 6.2500f, -18.7500f, -34.3750f, -167.9688f, -311.7188f, 14.0625f, 79.6875f, 26.5625f, 67.9688f, 63.2813f, 7.8125f, 23.8281f, 244.9219f, 103.9063f, 39.8438f, 18.7500f, + -98.4375f, -144.5313f, -246.0938f, -239.8438f, 265.6250f, 400.0000f, 339.4531f, 233.5938f, 163.6719f, 101.1719f, 75.3906f, 10.5469f, 35.1563f, 60.9375f, 20.7031f, 10.5469f, + -18.7500f, 12.8906f, 10.1563f, -88.6719f, -217.1875f, -299.2188f, -152.7344f, 90.2344f, 161.3281f, 110.1563f, 88.2813f, 34.7656f, 75.7813f, 73.0469f, 17.1875f, 11.7188f, + -79.6875f, -113.6719f, -134.7656f, -51.1719f, 48.8281f, 28.1250f, 6.2500f, -11.3281f, -41.4063f, -19.1406f, -10.5469f, 71.4844f, 278.9063f, 108.2031f, 44.5313f, 19.1406f, + -4.2969f, 80.0781f, 111.3281f, 26.9531f, -22.6563f, -80.8594f, -117.5781f, -62.5000f, -11.7188f, -0.7813f, 4.6875f, -38.6719f, -226.5625f, -69.5313f, -31.2500f, -16.0156f, + 46.8750f, 73.8281f, 109.7656f, 166.7969f, 91.4063f, 53.9063f, 48.4375f, 49.2188f, 19.5313f, 80.0781f, 47.2656f, 29.6875f, -311.3281f, -470.3125f, -91.7969f, -51.9531f, + 24.6094f, -7.0313f, 57.0313f, 260.1563f, 187.5000f, 92.1875f, 52.3438f, -15.2344f, -37.8906f, -50.7813f, -68.3594f, -147.6563f, -291.4063f, -62.1094f, -41.4063f, -17.9688f, + 150.7813f, 155.8594f, 162.1094f, 61.3281f, -68.3594f, -110.1563f, -123.0469f, -124.2188f, -86.7188f, -87.8906f, -104.2969f, -133.5938f, 123.8281f, 59.3750f, 5.8594f, 5.4688f, + 15.2344f, 21.8750f, 27.7344f, -37.1094f, -151.1719f, -198.8281f, -232.4219f, -182.0313f, -154.2969f, -72.6563f, -9.3750f, 164.4531f, 317.9688f, 114.0625f, 49.6094f, 20.3125f +}; +/* An 16-by-16 matrix */ +const float SVNB_SN2[256] = +{ + -6.2500f, 43.3594f, 43.3594f, -34.7656f, -44.9219f, -157.8125f, -200.7813f, 63.2813f, 108.2031f, 16.0156f, -36.7188f, -34.7656f, 5.8594f, 12.1094f, 0.7813f, 0.7813f, + -32.0313f, -38.6719f, -9.7656f, -112.1094f, -181.2500f, 79.6875f, 7.0313f, -48.0469f, -14.8438f, 21.8750f, 42.5781f, 77.3438f, 62.5000f, 37.5000f, 16.0156f, 7.4219f, + -37.1094f, -24.2188f, -94.5313f, -162.1094f, 124.2188f, 46.0938f, -47.2656f, 17.1875f, 28.9063f, 15.6250f, 33.2031f, 44.5313f, 20.3125f, 14.0625f, 8.2031f, 3.1250f, + 11.3281f, 15.6250f, 16.7969f, 8.9844f, -78.9063f, -58.2031f, 112.5000f, 58.2031f, -7.8125f, -42.5781f, -72.6563f, -107.4219f, -49.6094f, 7.0313f, -9.7656f, -2.3438f, + 7.8125f, 14.0625f, -37.8906f, -89.0625f, 220.7031f, 198.4375f, 52.3438f, 16.4063f, -27.3438f, -92.5781f, -100.7813f, -101.1719f, -48.0469f, -3.5156f, -11.3281f, -3.9063f, + -28.1250f, -66.0156f, 192.1875f, 180.8594f, 75.3906f, 79.6875f, -5.0781f, -29.2969f, -32.0313f, -48.8281f, -70.7031f, -89.8438f, -70.7031f, -3.9063f, -15.6250f, -4.6875f, + -42.1875f, -86.3281f, -89.4531f, 253.1250f, 224.6094f, 112.5000f, 57.0313f, 0.3906f, -5.4688f, -1.5625f, -19.9219f, -46.8750f, -31.6406f, -5.4688f, -6.6406f, -1.9531f, + -77.7344f, -103.1250f, -120.7031f, 81.6406f, 3.1250f, -50.0000f, 9.3750f, -18.3594f, 33.9844f, 100.3906f, 93.7500f, 72.2656f, 36.3281f, 27.3438f, 13.2813f, 6.2500f, + 9.7656f, 32.0313f, -23.4375f, -60.5469f, -158.9844f, -240.2344f, 11.3281f, 39.0625f, -44.1406f, 12.5000f, 80.8594f, 100.7813f, 79.2969f, 43.3594f, 19.1406f, 8.2031f, + 14.4531f, 49.6094f, 37.1094f, 1.5625f, 43.7500f, -17.5781f, -84.7656f, -61.7188f, -108.2031f, -158.9844f, -118.7500f, -59.3750f, 28.1250f, 20.3125f, -2.3438f, 0.0000f, + -11.7188f, -31.6406f, -45.3125f, -162.5000f, -85.5469f, 264.4531f, 210.1563f, 128.1250f, 83.2031f, 23.4375f, -23.4375f, -42.5781f, -30.4688f, 0.0000f, -1.9531f, 0.0000f, + 3.5156f, -5.8594f, 10.1563f, 29.2969f, -68.3594f, -131.2500f, -262.8906f, -228.9063f, 92.9688f, 121.0938f, 77.3438f, 73.8281f, 82.8125f, 49.2188f, 18.7500f, 9.3750f, + -7.0313f, -1.5625f, -31.2500f, 39.8438f, 50.7813f, -45.3125f, -104.6875f, -183.9844f, -221.4844f, -40.6250f, 80.0781f, 86.3281f, 55.8594f, 31.6406f, 11.3281f, 4.6875f, + 1.5625f, 15.2344f, 25.3906f, 44.9219f, 34.3750f, 73.8281f, 53.1250f, 48.4375f, 19.1406f, 41.4063f, 14.4531f, 34.7656f, -146.4844f, -244.5313f, -44.5313f, -28.5156f, + 210.9375f, 205.0781f, 184.3750f, 86.3281f, 46.0938f, -12.1094f, 5.8594f, 2.7344f, -27.7344f, -54.2969f, -42.1875f, -36.3281f, -5.0781f, -1.5625f, -5.0781f, -3.1250f, + -17.1875f, -17.1875f, -55.8594f, -106.2500f, -205.0781f, -142.5781f, 187.1094f, 196.0938f, 121.8750f, 87.8906f, 62.8906f, 28.1250f, 10.9375f, 16.4063f, 10.1563f, 4.6875f +}; +/* An 16-by-16 matrix */ +const float SVWB_SN1[256] = +{ + -27.7344f, -23.8281f, -66.4063f, -219.9219f, -375.7813f, -330.0781f, 72.6563f, 164.4531f, 110.1563f, 134.3750f, 101.5625f, 60.5469f, 72.6563f, 20.3125f, -7.0313f, -4.2969f, + -41.7969f, -54.2969f, -112.8906f, -105.4688f, 307.8125f, 240.2344f, 97.2656f, 67.9688f, -0.3906f, -9.3750f, 62.1094f, 41.4063f, -17.9688f, -71.4844f, -73.0469f, -41.7969f, + -56.2500f, -86.3281f, -83.9844f, 140.2344f, 75.0000f, -13.2813f, -72.6563f, -127.3438f, -100.0000f, -48.4375f, -19.1406f, 32.8125f, 83.5938f, 92.5781f, 72.6563f, 35.5469f, + 85.1563f, 129.6875f, 130.8594f, 16.0156f, -74.6094f, -153.9063f, -239.8438f, -212.1094f, -162.1094f, -148.0469f, -111.3281f, -59.7656f, -33.5938f, -39.4531f, -26.9531f, -5.0781f, + 229.2969f, 240.6250f, 285.9375f, 163.6719f, 105.4688f, 98.4375f, 39.8438f, 15.6250f, 20.7031f, -13.6719f, -22.2656f, -13.2813f, 7.4219f, -5.4688f, -5.8594f, -46.8750f, + -29.6875f, -86.7188f, -49.6094f, 475.0000f, 464.0625f, 318.3594f, 207.8125f, 125.0000f, 121.4844f, 89.0625f, 13.2813f, -23.0469f, -37.5000f, -33.5938f, -17.1875f, -14.8438f, + -68.7500f, -110.1563f, -198.0469f, -177.7344f, 438.2813f, 530.8594f, 376.9531f, 289.8438f, 238.2813f, 175.0000f, 185.1563f, 160.9375f, 72.2656f, 49.6094f, 49.6094f, -9.3750f, + -60.9375f, -87.8906f, 6.2500f, 178.9063f, 165.2344f, 171.0938f, 153.5156f, 156.2500f, 205.0781f, 257.0313f, 266.4063f, 266.0156f, 239.0625f, 171.0938f, 104.2969f, 26.5625f, + 34.7656f, 46.8750f, 67.1875f, 138.6719f, 76.1719f, -3.1250f, -8.5938f, -26.1719f, -42.9688f, -15.6250f, -36.3281f, -63.6719f, -149.2188f, -267.5781f, -361.7188f, -182.8125f, + -88.6719f, -141.4063f, -176.5625f, -225.3906f, -83.2031f, -8.5938f, 21.8750f, 32.0313f, 51.5625f, 84.3750f, 135.9375f, 164.0625f, 139.8438f, 116.7969f, 100.3906f, 55.8594f, + 14.8438f, -30.0781f, 45.7031f, 334.3750f, 189.8438f, 110.1563f, 6.2500f, -60.1563f, -50.7813f, -123.0469f, -241.4063f, -305.8594f, -348.4375f, -212.8906f, -34.3750f, 23.0469f, + 85.1563f, 126.5625f, 90.6250f, -63.2813f, -227.7344f, -215.6250f, 49.2188f, 24.2188f, -15.6250f, -10.5469f, -88.6719f, -135.9375f, -130.4688f, -126.5625f, -92.9688f, -25.3906f, + 32.0313f, 6.2500f, -7.8125f, -210.5469f, -307.4219f, 235.9375f, 132.8125f, 101.1719f, 101.5625f, -20.7031f, -98.0469f, -82.4219f, -4.6875f, 49.6094f, 66.7969f, 38.6719f, + -9.3750f, 65.6250f, 78.9063f, -55.4688f, -87.1094f, -175.0000f, -110.1563f, 47.6563f, 57.8125f, 60.5469f, 141.7969f, 148.4375f, 135.5469f, 102.7344f, 48.4375f, -26.5625f, + 64.4531f, 58.5938f, 88.2813f, 37.1094f, -67.1875f, -100.3906f, -161.3281f, -199.2188f, -208.2031f, -286.7188f, -396.0938f, -471.0938f, -325.7813f, -63.2813f, 2.3438f, 37.8906f, + -30.4688f, -28.1250f, -31.6406f, -125.7813f, -236.3281f, -285.5469f, -289.0625f, -220.3125f, -139.0625f, -85.5469f, -58.9844f, 4.2969f, 78.1250f, 92.5781f, 82.8125f, 66.4063f +}; +/* An 16-by-16 matrix */ +const float SVWB_SN2[256] = +{ + -49.2188f, -59.3750f, -133.5938f, -165.2344f, 121.4844f, 37.1094f, 1.1719f, 11.3281f, -36.3281f, 1.5625f, 88.6719f, 75.3906f, 55.4688f, 46.8750f, 36.3281f, 24.2188f, + 74.2188f, 100.7813f, 149.2188f, 121.0938f, 64.8438f, -4.2969f, -30.0781f, -26.1719f, -84.7656f, -127.7344f, -128.9063f, -147.6563f, -180.0781f, -120.7031f, -55.4688f, -18.3594f, + -6.2500f, -22.6563f, -30.0781f, -132.4219f, -208.5938f, 183.2031f, 155.8594f, 92.5781f, 113.2813f, 52.7344f, 13.2813f, 33.5938f, -5.4688f, -30.0781f, -11.7188f, 3.9063f, + 5.0781f, -1.5625f, 251.5625f, 223.4375f, 160.9375f, 171.0938f, 106.2500f, 111.7188f, 91.4063f, 69.1406f, 46.0938f, 57.4219f, 51.1719f, 53.9063f, 49.6094f, 14.8438f, + -28.5156f, -34.3750f, -43.7500f, 16.4063f, 14.0625f, 55.0781f, 165.6250f, 150.7813f, 196.8750f, 225.0000f, 204.2969f, 188.6719f, 168.3594f, 128.1250f, 91.0156f, 23.0469f, + -46.8750f, -66.0156f, -105.4688f, -173.8281f, -231.6406f, -104.6875f, -51.9531f, -53.9063f, -4.2969f, 21.8750f, 51.9531f, 82.0313f, 64.8438f, 45.3125f, 47.6563f, 53.5156f, + 110.1563f, 144.5313f, 99.6094f, 29.6875f, -34.7656f, -74.6094f, 54.2969f, 31.2500f, 4.6875f, 68.7500f, 72.2656f, 56.6406f, 95.3125f, 98.8281f, 67.5781f, -7.0313f, + 5.0781f, 5.4688f, -16.7969f, 28.5156f, -23.0469f, -105.4688f, -175.0000f, -242.9688f, -23.0469f, 146.0938f, 137.8906f, 114.4531f, 73.8281f, -21.0938f, -77.7344f, -47.6563f, + -29.2969f, -41.4063f, -109.7656f, -121.8750f, 228.5156f, 158.2031f, 72.2656f, 24.2188f, -68.7500f, -124.6094f, -128.9063f, -156.2500f, -163.2813f, -63.2813f, -1.5625f, 30.4688f, + -12.1094f, -4.2969f, -30.8594f, -32.4219f, -34.3750f, -107.0313f, -133.9844f, -168.3594f, -243.3594f, -202.3438f, -57.8125f, -4.2969f, -6.6406f, -8.2031f, 8.2031f, 35.1563f, + -39.4531f, -67.5781f, -93.7500f, 173.4375f, 118.3594f, 47.2656f, 40.6250f, -14.4531f, 72.2656f, 52.3438f, -17.5781f, -53.1250f, -64.0625f, 1.5625f, 59.7656f, 44.5313f, + -3.1250f, 15.6250f, 41.7969f, -29.6875f, -99.2188f, -215.2344f, -262.8906f, 112.5000f, 124.2188f, 9.7656f, 5.4688f, -24.2188f, -37.8906f, -0.7813f, 5.0781f, -7.8125f, + 33.9844f, 49.6094f, 31.2500f, 84.3750f, 131.2500f, 57.4219f, 73.4375f, 64.4531f, -3.9063f, 48.8281f, 75.3906f, 33.9844f, -49.2188f, -154.6875f, -287.5000f, -261.3281f, + 0.7813f, 1.5625f, 37.5000f, 72.2656f, 2.3438f, 24.2188f, -14.4531f, -53.1250f, -69.1406f, -97.6563f, -88.6719f, 78.5156f, 290.6250f, 254.2969f, 137.1094f, 28.9063f, + -6.2500f, -15.2344f, -32.0313f, -69.1406f, -148.4375f, -71.4844f, -9.3750f, -42.5781f, -75.7813f, -158.9844f, -250.3906f, -240.2344f, -61.3281f, 57.0313f, 74.6094f, 65.2344f, + -8.2031f, -4.6875f, -15.2344f, -24.6094f, -62.1094f, -50.0000f, 7.8125f, 2.3438f, 6.2500f, 15.2344f, -23.4375f, -94.9219f, -232.0313f, -286.3281f, -142.1875f, 17.9688f +}; +/* An 16-by-32 matrix */ +const float GEWB_MA1[512] = +{ + 105.0781f, 104.6875f, 162.5000f, 112.1094f, 61.3281f, 2.7344f, -51.5625f, -107.8125f, -188.2813f, -273.8281f, -400.3906f, -527.3438f, -641.4063f, -383.5938f, -125.3906f, -19.1406f, + 92.5781f, 370.7031f, 536.7188f, 479.6875f, 522.2656f, 476.1719f, 438.6719f, 396.8750f, 332.8125f, 293.7500f, 259.3750f, 218.3594f, 175.0000f, 119.5313f, 75.7813f, 32.4219f, + -2.3438f, -68.7500f, -145.7031f, -43.3594f, -86.3281f, -151.1719f, -188.6719f, -249.6094f, -294.1406f, -307.0313f, -302.3438f, -255.8594f, -128.1250f, -44.5313f, -9.7656f, 10.5469f, + 52.7344f, 64.0625f, -1.5625f, -70.7031f, -142.1875f, -206.2500f, -181.2500f, -165.6250f, -153.5156f, -122.6563f, -94.5313f, -72.2656f, -40.6250f, -23.8281f, -12.5000f, -14.4531f, + 5.8594f, -85.1563f, -125.7813f, 260.9375f, 233.2031f, 133.9844f, 76.5625f, -1.9531f, -17.9688f, -62.1094f, -140.2344f, -204.6875f, -245.7031f, -214.0625f, -120.3125f, -37.1094f, + 94.5313f, 180.8594f, 299.6094f, 258.2031f, 217.9688f, 157.4219f, 104.6875f, 74.6094f, 27.7344f, -1.5625f, -19.9219f, -40.2344f, -55.0781f, -68.7500f, -62.8906f, -55.4688f, + -69.9219f, -57.4219f, 279.2969f, 337.8906f, 378.9063f, 364.0625f, 321.0938f, 298.0469f, 235.1563f, 200.7813f, 170.3125f, 144.5313f, 111.3281f, 73.8281f, 41.4063f, 14.0625f, + -19.1406f, -88.6719f, -230.0781f, -364.4531f, -457.8125f, -273.4375f, -96.8750f, -68.3594f, -51.5625f, -51.5625f, -48.8281f, -40.2344f, -18.3594f, -19.1406f, -4.6875f, 23.4375f, + -2.7344f, -88.6719f, -157.8125f, 106.2500f, 32.4219f, -19.5313f, -64.4531f, -124.6094f, -133.9844f, -195.7031f, -285.5469f, -366.7969f, -395.7031f, -237.1094f, -78.9063f, -0.7813f, + -29.6875f, -105.8594f, -258.2031f, -227.3438f, 115.6250f, 33.5938f, -23.4375f, -64.8438f, -130.8594f, -122.6563f, -83.2031f, -111.3281f, -126.5625f, -109.3750f, -64.0625f, -15.2344f, + -103.1250f, -176.5625f, -43.3594f, 66.7969f, 89.4531f, 139.4531f, 138.6719f, 180.0781f, 198.8281f, 201.9531f, 191.0156f, 172.2656f, 135.5469f, 96.0938f, 61.7188f, 29.2969f, + 26.1719f, -19.1406f, -132.8125f, -213.2813f, -296.0938f, -358.9844f, -342.1875f, -283.9844f, -257.0313f, -221.4844f, -192.1875f, -156.2500f, -91.4063f, -54.6875f, -24.6094f, 14.0625f, + -55.4688f, 36.7188f, 200.7813f, 156.2500f, 158.5938f, 151.9531f, 148.0469f, 161.3281f, 152.7344f, 147.2656f, 138.2813f, 122.6563f, 95.7031f, 60.9375f, 36.7188f, 13.2813f, + 37.8906f, -18.3594f, -123.4375f, -242.1875f, -341.4063f, -69.9219f, -80.4688f, -113.2813f, -118.7500f, -200.7813f, -269.5313f, -282.4219f, -196.4844f, -98.4375f, -28.5156f, 15.2344f, + 189.4531f, 263.2813f, 207.8125f, 76.1719f, 14.8438f, -23.4375f, 6.6406f, 20.3125f, 24.6094f, 28.9063f, 33.2031f, 24.2188f, 13.6719f, -3.9063f, -8.5938f, -19.9219f, + -41.0156f, -8.9844f, 112.1094f, 153.9063f, 183.2031f, 237.8906f, 275.7813f, 335.9375f, 364.4531f, 364.4531f, 341.4063f, 308.2031f, 249.2188f, 181.6406f, 116.0156f, 57.8125f, + -87.1094f, -194.9219f, -326.9531f, -317.5781f, -152.7344f, -90.2344f, -69.5313f, -71.0938f, -31.6406f, 0.7813f, 32.8125f, 44.1406f, 51.1719f, 55.4688f, 49.6094f, 41.7969f, + -25.0000f, 105.0781f, 343.3594f, 331.6406f, 395.7031f, 451.9531f, 488.2813f, 522.2656f, 493.3594f, 459.3750f, 409.3750f, 351.5625f, 274.6094f, 196.0938f, 124.2188f, 64.4531f, + 23.8281f, 0.3906f, -77.3438f, -81.6406f, -134.7656f, -162.8906f, -109.3750f, -109.3750f, -119.9219f, -106.2500f, -133.2031f, -163.2813f, -235.9375f, -288.2813f, -346.4844f, -153.9063f, + 17.5781f, 30.0781f, 48.4375f, 59.3750f, 38.6719f, 16.7969f, 7.8125f, -1.5625f, -35.5469f, -33.2031f, -75.0000f, -109.3750f, -212.5000f, -294.5313f, -459.3750f, -506.2500f, + 67.5781f, 26.9531f, -19.1406f, -88.2813f, -134.3750f, -187.1094f, -191.0156f, -241.4063f, -283.9844f, -355.0781f, -438.2813f, -564.8438f, -504.6875f, -192.1875f, -80.0781f, 3.9063f, + -31.2500f, -31.2500f, 132.0313f, 111.3281f, 48.0469f, 18.7500f, -29.6875f, -31.2500f, -41.0156f, -46.0938f, -42.1875f, -31.2500f, -22.6563f, -10.9375f, -3.5156f, -3.1250f, + 28.9063f, -30.8594f, -114.0625f, -241.4063f, -295.3125f, 134.7656f, 84.3750f, 70.3125f, 55.8594f, -28.5156f, -72.6563f, -87.1094f, -78.1250f, -55.8594f, -20.3125f, -8.2031f, + -98.8281f, -202.7344f, -225.7813f, -73.4375f, -37.5000f, -13.6719f, -2.7344f, 10.5469f, 51.9531f, 85.1563f, 100.7813f, 100.7813f, 90.2344f, 70.3125f, 46.8750f, 27.3438f, + 106.6406f, 289.0625f, 371.0938f, 287.5000f, 273.8281f, 248.0469f, 238.6719f, 235.1563f, 221.0938f, 208.2031f, 192.9688f, 174.6094f, 136.7188f, 89.8438f, 51.1719f, 16.4063f, + -39.0625f, -134.7656f, -274.2188f, -137.5000f, 276.9531f, 266.4063f, 189.4531f, 126.5625f, 62.8906f, 43.7500f, 57.8125f, 9.7656f, -34.3750f, -41.4063f, -33.5938f, -39.4531f, + 119.9219f, 103.5156f, 98.8281f, 25.3906f, -24.6094f, -29.2969f, -66.0156f, -110.1563f, -152.3438f, -195.7031f, -214.8438f, -207.8125f, -158.5938f, -115.6250f, -72.6563f, -51.5625f, + -10.1563f, 27.3438f, 19.5313f, -32.8125f, -34.7656f, 10.9375f, 41.4063f, 77.7344f, 119.1406f, 152.7344f, 175.7813f, 183.2031f, 163.6719f, 117.5781f, 74.6094f, 31.2500f, + 8.5938f, 15.2344f, -60.1563f, -166.4063f, -233.2031f, -194.1406f, -62.1094f, -26.9531f, 16.0156f, 37.1094f, 44.5313f, 44.5313f, 38.6719f, 12.8906f, -2.7344f, -15.6250f, + -63.2813f, -139.0625f, -199.6094f, -180.0781f, -185.5469f, -200.3906f, -186.3281f, -189.4531f, -154.2969f, -97.2656f, -53.1250f, -27.7344f, -1.5625f, 12.8906f, 21.0938f, 25.0000f, + -32.0313f, -115.2344f, -219.5313f, 94.1406f, 25.3906f, -63.6719f, -88.6719f, -150.0000f, -92.5781f, -89.4531f, -103.9063f, -87.1094f, -36.7188f, 3.9063f, 16.0156f, 12.1094f, + -40.6250f, -126.1719f, -117.9688f, 286.3281f, 252.3438f, 163.2813f, 105.8594f, 58.2031f, 60.5469f, 60.1563f, 46.4844f, 38.6719f, 34.7656f, 24.6094f, 5.0781f, -6.2500f +}; +/* An 16-by-32 matrix */ +const float GETRNB_SN1[512] = +{ + -46.4844f, -105.8594f, -166.7969f, 174.6094f, 125.3906f, 22.6563f, 14.4531f, -41.0156f, -25.3906f, 38.6719f, 41.4063f, 8.2031f, -108.2031f, 20.7031f, 3.5156f, -2.3438f, + -36.3281f, -94.1406f, -169.1406f, -322.6563f, -401.5625f, 6.6406f, 70.3125f, 53.9063f, 125.0000f, 91.4063f, 59.3750f, 91.7969f, 380.0781f, 232.0313f, 77.7344f, 37.5000f, + -117.1875f, -185.1563f, -216.0156f, -194.1406f, -146.0938f, -90.2344f, -87.5000f, -66.4063f, -56.6406f, 19.9219f, 60.1563f, 278.9063f, 522.6563f, 269.5313f, 105.8594f, 46.0938f, + -44.9219f, -89.0625f, -96.8750f, 3.5156f, -10.5469f, -76.5625f, -93.7500f, -105.0781f, -114.4531f, -121.0938f, -107.8125f, -99.2188f, 300.3906f, 187.8906f, 45.7031f, 23.0469f, + 67.1875f, 22.6563f, 183.2031f, 228.5156f, 200.0000f, 131.2500f, 56.6406f, -20.3125f, -65.2344f, -134.3750f, -148.0469f, -190.2344f, 111.3281f, 147.2656f, 10.5469f, 10.5469f, + 31.6406f, 13.2813f, 224.2188f, 335.5469f, 319.5313f, 274.2188f, 203.5156f, 134.3750f, 69.1406f, 8.9844f, -45.3125f, -107.0313f, -238.6719f, -30.4688f, -23.8281f, -13.6719f, + 29.6875f, 7.4219f, -40.6250f, -151.5625f, -268.3594f, 21.0938f, 108.9844f, 56.2500f, 92.5781f, 87.1094f, 42.9688f, 3.5156f, -130.8594f, 1.5625f, 1.1719f, -3.9063f, + 44.9219f, 148.4375f, 189.8438f, 174.2188f, 151.9531f, 123.4375f, 93.3594f, 97.2656f, 76.9531f, 80.8594f, 63.2813f, 55.0781f, -169.9219f, -592.1875f, -159.7656f, -53.1250f, + -57.0313f, -135.9375f, -166.0156f, 251.9531f, 389.8438f, 308.5938f, 237.8906f, 182.8125f, 110.1563f, 112.1094f, 59.7656f, 33.9844f, -180.0781f, -231.2500f, -34.3750f, -25.0000f, + -97.2656f, -183.9844f, -326.1719f, -250.7813f, 230.0781f, 375.0000f, 346.4844f, 248.8281f, 172.6563f, 111.7188f, 94.5313f, 51.5625f, 55.4688f, 116.7969f, 38.6719f, 17.1875f, + 50.0000f, 14.4531f, -46.8750f, -122.6563f, -223.0469f, -285.1563f, -339.0625f, -217.9688f, -101.1719f, -42.5781f, 3.1250f, 161.3281f, 447.2656f, 231.6406f, 82.0313f, 35.9375f, + 58.9844f, 129.2969f, 104.2969f, 50.7813f, -9.3750f, -34.7656f, -51.9531f, -16.7969f, -29.2969f, 22.2656f, 7.4219f, 36.7188f, -183.2031f, -310.9375f, -48.4375f, -35.1563f, + -132.4219f, -182.8125f, -114.0625f, -13.2813f, 29.6875f, 69.9219f, 90.2344f, 105.0781f, 101.1719f, 109.7656f, 107.4219f, 79.6875f, -36.3281f, 61.3281f, 20.7031f, 6.2500f, + 12.8906f, 68.7500f, 9.7656f, -78.5156f, -121.4844f, -194.1406f, -198.8281f, -94.5313f, -18.3594f, 2.3438f, 33.5938f, 18.7500f, -64.4531f, 68.7500f, 9.3750f, 3.1250f, + 10.5469f, 87.1094f, 180.0781f, 195.3125f, 187.1094f, 185.5469f, 191.0156f, 218.7500f, 248.0469f, 289.4531f, 360.9375f, 526.1719f, 603.9063f, 314.8438f, 108.2031f, 21.0938f, + 199.2188f, 181.2500f, 157.0313f, 44.5313f, -31.2500f, -111.3281f, -113.2813f, -125.3906f, -110.5469f, -143.7500f, -126.9531f, -165.6250f, 151.5625f, 157.0313f, 20.3125f, 14.8438f, + 203.5156f, 239.8438f, 285.9375f, 214.4531f, 167.1875f, 108.5938f, 70.3125f, 31.6406f, 5.4688f, -42.9688f, -79.6875f, -138.6719f, -253.5156f, -12.5000f, -21.8750f, -14.0625f, + 28.1250f, 10.1563f, 102.3438f, 102.7344f, 62.1094f, 44.1406f, 23.4375f, -3.9063f, -28.5156f, -47.2656f, -78.5156f, -128.5156f, -300.0000f, -23.8281f, -23.4375f, -15.2344f, + 33.2031f, 22.2656f, 45.3125f, -15.6250f, -30.4688f, -62.1094f, -60.1563f, -96.4844f, -85.9375f, -142.9688f, -129.2969f, -207.8125f, -13.6719f, 134.3750f, 0.0000f, 9.7656f, + 205.8594f, 358.9844f, 523.0469f, 478.5156f, 464.8438f, 399.6094f, 302.3438f, 225.3906f, 153.5156f, 62.5000f, -1.5625f, -71.8750f, -109.7656f, 11.3281f, -8.2031f, -4.6875f, + -89.8438f, -110.5469f, -132.0313f, -148.0469f, -122.2656f, -114.4531f, -63.6719f, -47.6563f, 5.8594f, 37.8906f, 94.9219f, 65.6250f, 141.0156f, 175.3906f, 39.8438f, 23.8281f, + 147.6563f, 144.1406f, 144.1406f, 53.1250f, 16.4063f, -28.1250f, -28.5156f, -60.1563f, -60.5469f, -101.5625f, -105.4688f, -173.4375f, -219.5313f, 67.5781f, -14.0625f, -3.5156f, + 65.6250f, 42.1875f, -14.0625f, -135.5469f, -218.3594f, -170.3125f, -99.2188f, -102.7344f, -92.1875f, -88.6719f, -96.4844f, -92.9688f, 310.9375f, 190.6250f, 48.0469f, 24.2188f, + -58.9844f, -46.0938f, 63.6719f, 176.5625f, 167.9688f, 189.0625f, 178.1250f, 163.2813f, 147.2656f, 141.7969f, 100.0000f, 71.4844f, -157.4219f, -558.2031f, -149.2188f, -49.2188f, + -79.6875f, -142.9688f, -254.6875f, -200.0000f, 167.1875f, 137.8906f, 71.0938f, 34.3750f, -3.9063f, -36.7188f, -21.0938f, -4.2969f, 312.8906f, 205.8594f, 58.9844f, 29.6875f, + 23.4375f, 30.8594f, -66.0156f, -181.6406f, -308.2031f, -329.6875f, -21.4844f, 70.7031f, 81.6406f, 67.1875f, 82.0313f, 41.7969f, 101.5625f, 155.8594f, 35.5469f, 20.3125f, + -26.9531f, -80.0781f, -147.2656f, -64.0625f, 252.7344f, 228.1250f, 117.9688f, 58.9844f, 12.5000f, -52.7344f, -53.1250f, -87.1094f, -105.0781f, 66.4063f, 1.5625f, 1.9531f, + 14.8438f, 163.2813f, 345.7031f, 382.4219f, 386.7188f, 401.1719f, 339.8438f, 314.0625f, 261.3281f, 209.7656f, 140.6250f, 94.1406f, -131.2500f, -500.3906f, -132.0313f, -43.3594f, + -164.0625f, -273.4375f, -356.2500f, -242.9688f, -131.6406f, -19.9219f, 26.1719f, 67.5781f, 127.3438f, 216.4063f, 299.2188f, 544.9219f, 646.8750f, 349.2188f, 152.3438f, 69.5313f, + -55.0781f, -98.4375f, -198.0469f, -321.0938f, -423.4375f, -330.0781f, -109.3750f, 7.8125f, 58.2031f, 94.5313f, 153.5156f, 371.4844f, 557.8125f, 289.0625f, 118.3594f, 52.7344f, + -46.8750f, -14.4531f, 12.1094f, 41.0156f, 28.1250f, 38.6719f, 20.7031f, 45.7031f, 23.0469f, 66.7969f, 46.8750f, 69.1406f, -161.7188f, -387.8906f, -62.5000f, -38.2813f, + -149.2188f, -239.0625f, -246.4844f, -65.2344f, 1.5625f, 40.6250f, 50.7813f, 55.0781f, 94.5313f, 126.9531f, 135.9375f, 167.9688f, 409.3750f, 254.2969f, 86.7188f, 42.5781f +}; +/* An 16-by-16 matrix */ +const float GETRNB_SN2[256] = +{ + -10.5469f, 27.7344f, 17.5781f, -1.5625f, 10.9375f, 26.9531f, 9.7656f, 36.7188f, 17.5781f, 35.1563f, 17.5781f, 33.9844f, -69.1406f, -221.4844f, -45.3125f, -23.0469f, + -81.2500f, -57.4219f, 207.4219f, 155.8594f, 77.7344f, 44.1406f, -8.2031f, -10.9375f, -13.2813f, -14.8438f, -18.7500f, -17.9688f, -18.3594f, 7.0313f, -0.3906f, -0.3906f, + 26.9531f, -7.8125f, -44.9219f, -138.6719f, -148.4375f, 151.5625f, 148.0469f, 75.3906f, 52.3438f, 14.4531f, -16.4063f, -23.4375f, -13.6719f, 11.3281f, 2.3438f, 1.9531f, + 41.7969f, 34.7656f, -38.2813f, -73.8281f, 148.0469f, 112.8906f, 26.5625f, 8.5938f, -27.7344f, -69.9219f, -73.0469f, -75.0000f, -53.5156f, 1.5625f, -6.6406f, -2.7344f, + -17.1875f, -31.6406f, -144.9219f, -175.0000f, 88.2813f, 29.2969f, -20.3125f, 16.7969f, 15.6250f, 14.0625f, 30.8594f, 46.8750f, 50.7813f, 29.6875f, 14.0625f, 5.8594f, + 51.1719f, 44.9219f, 75.0000f, 69.1406f, 9.7656f, -2.7344f, -8.9844f, -37.1094f, -51.5625f, -71.8750f, -80.4688f, -95.7031f, -78.1250f, -4.6875f, -11.3281f, -4.2969f, + 17.5781f, -9.7656f, -97.2656f, 19.5313f, -73.8281f, -139.8438f, 98.8281f, 56.6406f, -15.2344f, 10.5469f, 13.2813f, -7.8125f, -20.3125f, 5.0781f, 0.3906f, 0.7813f, + -99.2188f, -60.5469f, 8.9844f, -34.7656f, -11.7188f, 8.9844f, -8.9844f, -8.2031f, -17.5781f, -33.5938f, -35.9375f, -42.5781f, -18.7500f, 20.3125f, 1.1719f, 1.1719f, + -96.8750f, -91.0156f, 54.2969f, 83.2031f, 90.6250f, 141.0156f, 136.3281f, 156.6406f, 145.7031f, 117.5781f, 89.8438f, 80.8594f, 79.6875f, 39.4531f, 12.5000f, 5.4688f, + 191.7969f, 213.2813f, 159.7656f, 57.4219f, 13.2813f, -7.0313f, 20.3125f, 23.0469f, 18.7500f, 10.5469f, 5.4688f, 2.7344f, -0.3906f, -14.4531f, -6.2500f, -3.5156f, + 14.0625f, 16.0156f, 0.0000f, -8.2031f, -11.3281f, -25.0000f, -80.8594f, -135.1563f, -201.5625f, -138.6719f, -25.0000f, 28.5156f, 60.9375f, 36.7188f, 11.7188f, 4.2969f, + -10.9375f, -67.5781f, -108.5938f, 197.6563f, 166.7969f, 64.0625f, 43.3594f, 8.2031f, -12.8906f, -23.8281f, -30.4688f, -35.1563f, -12.5000f, 15.2344f, 1.5625f, 1.5625f, + -17.1875f, -23.4375f, -83.9844f, -145.7031f, -189.4531f, -105.4688f, 4.6875f, 58.9844f, 105.8594f, 103.5156f, 83.9844f, 69.5313f, 59.7656f, 27.7344f, 12.5000f, 6.6406f, + 42.9688f, 60.5469f, -11.3281f, -101.1719f, -85.1563f, -71.4844f, -68.3594f, -51.5625f, -33.2031f, -38.2813f, -33.9844f, -36.3281f, -30.0781f, 0.0000f, -3.5156f, -1.5625f, + -45.3125f, -5.4688f, 91.7969f, 0.3906f, -92.9688f, -155.4688f, -163.6719f, -21.4844f, 42.5781f, 30.0781f, 24.2188f, 28.9063f, 28.5156f, 18.3594f, 6.2500f, 3.1250f, + -7.8125f, -42.1875f, -85.5469f, 96.0938f, 7.8125f, -71.8750f, -128.1250f, -175.3906f, -26.1719f, 55.4688f, 48.8281f, 42.9688f, 35.5469f, 28.9063f, 10.9375f, 5.0781f +}; +/* An 16-by-32 matrix */ +const float GETRWB_SN1[512] = +{ + -90.6250f, -74.6094f, 110.1563f, 96.8750f, 134.3750f, 152.3438f, 167.1875f, 191.4063f, 210.1563f, 231.2500f, 242.1875f, 237.1094f, 208.2031f, 145.3125f, 101.9531f, 53.1250f, + -23.0469f, -88.6719f, -163.2813f, -112.5000f, -96.4844f, -175.0000f, -195.7031f, -251.5625f, -296.8750f, -360.1563f, -434.3750f, -470.3125f, -204.2969f, -50.7813f, 4.6875f, 51.1719f, + 54.2969f, 327.3438f, 547.6563f, 518.3594f, 572.2656f, 543.3594f, 535.5469f, 524.2188f, 476.5625f, 448.0469f, 406.6406f, 355.4688f, 286.3281f, 202.3438f, 130.8594f, 70.7031f, + 82.4219f, 57.8125f, -36.7188f, -107.4219f, -189.0625f, -228.9063f, -211.3281f, -247.6563f, -227.7344f, -199.6094f, -165.6250f, -125.7813f, -111.3281f, -116.7969f, -75.7813f, -33.9844f, + 160.1563f, 141.4063f, 131.6406f, 28.5156f, -14.0625f, -44.1406f, -70.3125f, -107.0313f, -145.7031f, -192.5781f, -195.7031f, -184.7656f, -153.5156f, -141.0156f, -105.8594f, -98.0469f, + -33.2031f, -142.9688f, -319.9219f, -207.8125f, 294.1406f, 268.7500f, 161.7188f, 79.2969f, 9.3750f, -16.7969f, 50.3906f, 23.4375f, -39.0625f, -48.0469f, -37.8906f, -44.5313f, + 1.5625f, 14.4531f, 189.0625f, 200.7813f, 132.8125f, 87.8906f, 34.7656f, 23.0469f, 15.6250f, 1.1719f, -1.9531f, -0.3906f, -4.2969f, -19.1406f, -16.7969f, -18.7500f, + -87.1094f, -183.9844f, -258.2031f, -221.4844f, -193.7500f, -202.7344f, -181.2500f, -211.7188f, -189.0625f, -133.9844f, -107.8125f, -72.2656f, -16.7969f, 6.6406f, 32.8125f, 51.9531f, + -41.4063f, -121.8750f, -260.9375f, -289.4531f, 150.3906f, 128.5156f, 47.2656f, -61.3281f, -165.2344f, -277.3438f, -373.8281f, -500.0000f, -446.4844f, -128.9063f, -7.8125f, 51.1719f, + 97.6563f, 61.3281f, 27.7344f, -121.0938f, -215.6250f, -289.0625f, -291.0156f, -303.9063f, -323.0469f, -415.6250f, -521.8750f, -636.3281f, -307.8125f, -76.1719f, -17.1875f, 51.1719f, + 54.6875f, 247.2656f, 378.9063f, 337.5000f, 338.6719f, 297.2656f, 266.7969f, 253.1250f, 223.4375f, 212.5000f, 201.5625f, 183.2031f, 149.6094f, 92.9688f, 55.8594f, 21.4844f, + 45.3125f, 55.8594f, 89.4531f, 52.3438f, -9.7656f, -46.8750f, -90.6250f, -130.0781f, -208.9844f, -250.7813f, -384.7656f, -491.7969f, -731.6406f, -674.6094f, -128.9063f, -3.9063f, + -25.0000f, -32.0313f, -24.2188f, -90.6250f, -120.3125f, -135.1563f, -115.6250f, -106.2500f, -59.7656f, -10.1563f, 42.1875f, 80.0781f, 90.6250f, 61.7188f, 50.3906f, 20.7031f, + 32.0313f, -35.9375f, -120.7031f, -308.9844f, -440.6250f, -101.1719f, -94.9219f, -158.2031f, -143.3594f, -248.8281f, -352.7344f, -423.4375f, -263.6719f, -77.7344f, 6.6406f, 57.0313f, + -96.4844f, -222.2656f, -346.0938f, -296.0938f, -130.4688f, -80.4688f, -61.7188f, -58.5938f, -25.0000f, 22.2656f, 74.2188f, 98.4375f, 101.9531f, 82.0313f, 63.6719f, 50.3906f, + -8.9844f, -124.6094f, -178.9063f, 308.9844f, 280.4688f, 156.2500f, 91.0156f, -31.6406f, -67.9688f, -156.2500f, -296.0938f, -409.3750f, -522.6563f, -405.4688f, -112.5000f, -2.3438f, + 19.5313f, 180.4688f, 118.3594f, -18.3594f, -47.6563f, -52.3438f, 5.8594f, 53.5156f, 69.9219f, 86.7188f, 103.9063f, 97.2656f, 85.5469f, 48.0469f, 31.2500f, 11.7188f, + -45.3125f, -129.6875f, -253.9063f, -431.2500f, -533.9844f, -269.9219f, -146.8750f, -115.2344f, -69.5313f, -77.7344f, -66.4063f, -9.3750f, 48.8281f, 37.1094f, 48.8281f, 65.6250f, + -25.7813f, -122.6563f, -205.4688f, 126.9531f, 60.9375f, -21.8750f, -44.5313f, -112.1094f, -49.2188f, -72.2656f, -114.0625f, -116.4063f, -73.8281f, -31.6406f, 0.3906f, 8.9844f, + 57.4219f, -11.7188f, -113.6719f, -301.1719f, -366.7969f, 102.3438f, 71.0938f, 49.2188f, 49.6094f, -39.0625f, -63.6719f, -52.3438f, -35.5469f, -37.1094f, -20.3125f, -7.4219f, + -87.8906f, -193.7500f, -175.3906f, -23.8281f, 17.9688f, 52.7344f, 71.0938f, 96.4844f, 126.5625f, 157.8125f, 178.5156f, 181.2500f, 164.0625f, 119.1406f, 81.6406f, 41.4063f, + 163.2813f, 121.8750f, 162.1094f, 28.9063f, -60.9375f, -134.7656f, -156.2500f, -247.6563f, -300.3906f, -412.8906f, -532.0313f, -719.1406f, -721.8750f, -183.9844f, -57.4219f, 33.9844f, + 14.8438f, 7.4219f, -90.6250f, -215.6250f, -272.6563f, -367.5781f, -188.6719f, 46.4844f, 21.0938f, -13.2813f, 27.3438f, -26.5625f, -56.2500f, -75.0000f, -98.8281f, -92.1875f, + 31.2500f, -11.7188f, -83.5938f, -61.3281f, -114.0625f, -121.8750f, -110.5469f, -135.5469f, -150.0000f, -145.3125f, -190.2344f, -196.4844f, -291.4063f, -371.0938f, -535.9375f, -251.5625f, + 17.1875f, 21.4844f, 48.4375f, 70.7031f, 48.8281f, 42.5781f, 23.8281f, 11.3281f, -28.5156f, -21.0938f, -80.4688f, -108.5938f, -249.2188f, -362.8906f, -610.5469f, -680.4688f, + 313.2813f, 321.4844f, 283.5938f, 137.8906f, 106.2500f, 47.6563f, 45.7031f, 36.7188f, 31.2500f, 15.6250f, 26.5625f, 18.3594f, 16.4063f, -7.4219f, -10.1563f, -26.9531f, + 19.5313f, -37.8906f, -119.5313f, -260.1563f, -358.5938f, -433.2031f, -439.0625f, -303.1250f, -277.3438f, -284.3750f, -263.6719f, -189.8438f, -58.5938f, -1.1719f, 36.3281f, 62.5000f, + 31.6406f, -56.2500f, -51.1719f, 124.6094f, 88.6719f, -37.5000f, -92.1875f, -201.9531f, -277.7344f, -370.7031f, -480.8594f, -642.1875f, -634.7656f, -173.4375f, -45.7031f, 33.5938f, + -89.8438f, -92.5781f, 228.9063f, 312.1094f, 363.6719f, 399.6094f, 420.7031f, 460.5469f, 442.5781f, 430.0781f, 401.1719f, 355.0781f, 285.5469f, 201.1719f, 128.9063f, 66.7969f, + 175.0000f, 246.8750f, 408.9844f, 305.4688f, 246.4844f, 152.3438f, 60.5469f, -32.0313f, -133.5938f, -267.5781f, -430.8594f, -593.7500f, -694.9219f, -363.6719f, -83.5938f, 13.2813f, + -30.0781f, -137.5000f, -137.8906f, 307.4219f, 366.4063f, 264.4531f, 200.3906f, 137.5000f, 110.9375f, 108.5938f, 96.4844f, 70.7031f, 55.0781f, 28.5156f, 3.1250f, -15.2344f, + 21.0938f, 16.4063f, -26.1719f, -116.4063f, -181.6406f, -231.6406f, -208.2031f, -213.6719f, -244.5313f, -289.4531f, -381.6406f, -514.4531f, -650.3906f, -239.4531f, -46.4844f, 31.2500f +}; +/* An 16-by-16 matrix */ +const float GETRWB_SN2[256] = +{ + -78.9063f, -96.0938f, -139.0625f, -139.0625f, -90.6250f, -64.0625f, -30.8594f, 1.5625f, 30.4688f, 50.7813f, 59.3750f, 64.4531f, 66.4063f, 55.0781f, 35.1563f, 27.3438f, + 14.8438f, 30.4688f, -28.1250f, -72.2656f, -174.2188f, -215.6250f, 105.0781f, 115.2344f, 40.6250f, 30.0781f, -21.0938f, -71.8750f, -65.6250f, -28.1250f, -12.5000f, -0.7813f, + 26.9531f, 36.3281f, 15.2344f, 45.3125f, 39.0625f, 17.9688f, 19.5313f, -0.3906f, -0.7813f, 24.2188f, 3.1250f, -41.0156f, -157.8125f, -256.2500f, -192.9688f, -87.5000f, + -111.3281f, -119.1406f, 102.7344f, 37.8906f, 11.3281f, 12.8906f, -9.3750f, 21.0938f, 13.6719f, 9.7656f, -1.5625f, -2.3438f, -11.7188f, 5.0781f, 7.8125f, 8.2031f, + -10.9375f, -27.3438f, -62.5000f, 13.2813f, 1.9531f, -56.6406f, -103.1250f, -166.0156f, -210.5469f, -128.5156f, -7.4219f, 89.0625f, 160.5469f, 109.3750f, 55.0781f, 19.9219f, + 95.3125f, 95.7031f, 7.4219f, -124.6094f, -180.0781f, -71.8750f, -3.9063f, 18.3594f, 85.9375f, 114.4531f, 120.7031f, 128.9063f, 109.7656f, 54.6875f, 27.7344f, 4.6875f, + -50.0000f, -98.0469f, -146.0938f, 165.6250f, 108.9844f, 26.5625f, 13.6719f, -26.5625f, 5.0781f, 17.5781f, -2.3438f, -16.0156f, -28.5156f, -6.6406f, 3.1250f, 10.5469f, + -21.4844f, -2.7344f, 171.0938f, 195.3125f, 192.5781f, 172.6563f, 111.7188f, 82.4219f, 26.5625f, -15.2344f, -45.7031f, -65.2344f, -70.3125f, -51.1719f, -29.2969f, -24.6094f, + 11.7188f, 12.1094f, 26.9531f, 44.5313f, -67.1875f, -158.9844f, -232.8125f, -152.7344f, 39.8438f, 66.0156f, 61.7188f, 51.1719f, 17.9688f, 1.5625f, -2.3438f, -1.1719f, + 26.9531f, 29.6875f, 12.8906f, 92.9688f, 64.0625f, 46.4844f, 62.5000f, 64.4531f, 106.6406f, 133.5938f, 149.6094f, 163.6719f, 178.1250f, 147.6563f, 102.3438f, 37.5000f, + -21.4844f, 16.7969f, -23.0469f, -106.6406f, -78.1250f, -111.7188f, -112.1094f, -86.3281f, -96.4844f, -95.7031f, -75.7813f, -62.5000f, -50.3906f, -14.0625f, -12.1094f, 1.1719f, + -13.6719f, -17.9688f, -106.2500f, -139.4531f, 189.0625f, 96.0938f, -4.2969f, 8.2031f, -48.0469f, -76.9531f, -39.8438f, -36.7188f, -37.5000f, -8.5938f, 2.3438f, 2.3438f, + -45.7031f, -73.4375f, -98.4375f, -88.6719f, 0.0000f, 179.6875f, 197.6563f, 205.4688f, 195.7031f, 151.9531f, 97.6563f, 51.1719f, -10.9375f, -12.5000f, 9.3750f, 6.6406f, + 155.8594f, 199.6094f, 152.3438f, 57.0313f, 31.2500f, -32.8125f, -31.6406f, -22.2656f, -48.0469f, -53.9063f, -37.1094f, -32.0313f, -19.9219f, -12.8906f, -5.4688f, -17.5781f, + -3.5156f, 4.6875f, 117.1875f, 118.7500f, 71.0938f, 10.5469f, -76.9531f, -100.7813f, -134.3750f, -153.5156f, -150.0000f, -124.2188f, -54.6875f, -1.9531f, -2.3438f, 2.3438f, + 25.0000f, 9.7656f, -2.7344f, -100.0000f, -119.5313f, 148.8281f, 94.9219f, 37.5000f, -6.6406f, -74.2188f, -111.3281f, -96.0938f, -25.3906f, 18.7500f, 14.4531f, 11.3281f +}; +/* An 16-by-16 matrix */ +const float TRWB2_SN1[256] = +{ + -28.9063f, -150.0000f, -298.4375f, -376.5625f, -438.2813f, -356.2500f, -319.9219f, -289.0625f, -284.3750f, -223.4375f, -148.0469f, -123.8281f, -97.6563f, -19.9219f, -26.1719f, 33.2031f, + -121.4844f, -241.4063f, -171.4844f, -42.1875f, 60.9375f, 100.3906f, 157.8125f, 212.1094f, 251.1719f, 284.7656f, 285.9375f, 223.4375f, 174.2188f, 128.5156f, 92.1875f, 64.0625f, + 204.2969f, 605.0781f, 608.2031f, 576.5625f, 536.7188f, 465.6250f, 417.1875f, 360.5469f, 351.9531f, 307.8125f, 280.0781f, 156.6406f, 102.3438f, 2.3438f, -39.0625f, -143.7500f, + -5.0781f, -31.2500f, -73.8281f, -150.7813f, -189.8438f, -139.4531f, -84.3750f, -24.6094f, 25.3906f, 73.8281f, 96.8750f, 75.7813f, 85.1563f, 85.5469f, 80.0781f, 66.0156f, + -40.6250f, -202.7344f, -301.5625f, 192.1875f, 87.5000f, 7.0313f, -79.2969f, -95.3125f, -49.2188f, -85.9375f, -141.4063f, -162.8906f, -105.8594f, -27.7344f, -13.2813f, -19.5313f, + -78.9063f, 48.4375f, 316.7969f, 380.8594f, 517.9688f, 573.4375f, 630.0781f, 596.4844f, 575.7813f, 533.5938f, 476.5625f, 353.9063f, 273.4375f, 198.8281f, 137.1094f, 80.8594f, + -22.2656f, -76.5625f, -92.9688f, -109.7656f, -104.2969f, -93.3594f, -74.2188f, -53.5156f, -10.5469f, 1.5625f, 30.0781f, -69.5313f, -100.0000f, -216.0156f, -261.3281f, -431.6406f, + -71.4844f, -82.4219f, 314.0625f, 308.2031f, 267.5781f, 206.6406f, 187.1094f, 157.4219f, 144.9219f, 122.2656f, 108.9844f, 19.1406f, -7.4219f, -60.9375f, -69.9219f, -130.8594f, + 296.0938f, 331.2500f, 237.5000f, 122.2656f, 105.8594f, 68.7500f, 69.1406f, 28.5156f, 41.4063f, 23.8281f, 23.0469f, -62.1094f, -79.2969f, -112.1094f, -104.6875f, -133.9844f, + 77.7344f, 27.3438f, 37.1094f, -11.3281f, -95.7031f, -160.5469f, -291.0156f, -394.1406f, -575.3906f, -750.3906f, -1028.5156f, -643.7500f, -209.7656f, -110.9375f, -33.9844f, 80.8594f, + 32.0313f, -84.7656f, -179.6875f, -252.3438f, -280.4688f, -320.7031f, -383.9844f, -500.7813f, -617.1875f, -823.4375f, -727.7344f, -237.8906f, -158.9844f, -47.6563f, -19.5313f, 94.9219f, + -51.5625f, 142.1875f, 142.1875f, 132.8125f, 191.0156f, 193.7500f, 232.8125f, 236.7188f, 275.0000f, 295.3125f, 303.5156f, 240.6250f, 203.5156f, 159.7656f, 119.1406f, 82.4219f, + 48.0469f, -73.8281f, -35.5469f, -119.5313f, -124.6094f, -158.9844f, -234.3750f, -265.2344f, -355.8594f, -333.9844f, -221.0938f, -97.2656f, -25.3906f, -0.3906f, -25.3906f, -9.7656f, + 30.8594f, -22.6563f, -40.2344f, -58.5938f, -104.6875f, -103.5156f, -166.4063f, -187.1094f, -239.8438f, -262.1094f, -392.5781f, -538.2813f, -791.7969f, -604.2969f, -221.8750f, -20.3125f, + -107.4219f, -261.3281f, -417.9688f, -428.5156f, -268.7500f, -169.1406f, -132.8125f, -57.8125f, -10.5469f, 75.7813f, 120.7031f, 108.2031f, 89.4531f, 73.4375f, 32.0313f, 49.6094f, + 155.0781f, 524.6094f, 578.9063f, 675.3906f, 772.6563f, 785.9375f, 769.1406f, 723.4375f, 675.3906f, 614.8438f, 549.6094f, 424.6094f, 331.2500f, 248.4375f, 168.3594f, 108.5938f +}; +/* An 16-by-16 matrix */ +const float TRWB2_SN2[256] = +{ + 19.5313f, -25.7813f, -189.8438f, -332.0313f, 196.8750f, 134.7656f, 101.9531f, 3.9063f, -80.8594f, -85.1563f, -67.9688f, -7.0313f, 28.1250f, 26.9531f, 1.1719f, 9.3750f, + -66.7969f, -171.4844f, -246.8750f, 152.3438f, 55.8594f, -34.7656f, -114.0625f, -122.6563f, -88.6719f, -61.3281f, 12.8906f, 70.7031f, 72.2656f, 79.6875f, 50.0000f, 65.2344f, + 178.9063f, 179.2969f, 30.4688f, -97.6563f, -142.5781f, -148.8281f, -137.8906f, -149.2188f, -127.7344f, -110.9375f, -74.6094f, -7.0313f, 1.1719f, 14.4531f, 11.3281f, 37.1094f, + -66.0156f, -88.6719f, -165.2344f, -175.0000f, -189.4531f, -166.4063f, -142.1875f, -110.9375f, -92.9688f, -71.8750f, -89.0625f, -74.2188f, -56.6406f, 6.6406f, 25.3906f, 56.6406f, + -1.5625f, -46.8750f, -66.4063f, -130.0781f, -264.4531f, -305.4688f, -280.8594f, -152.7344f, -43.7500f, 90.6250f, 181.2500f, 153.1250f, 107.4219f, 83.9844f, 47.2656f, 54.2969f, + -36.7188f, -50.7813f, 176.9531f, 115.2344f, -17.5781f, -111.7188f, -173.4375f, -184.7656f, -202.7344f, -167.1875f, -104.6875f, -15.6250f, -4.6875f, 17.9688f, 15.2344f, 46.0938f, + -73.8281f, -95.7031f, 314.4531f, 318.3594f, 202.3438f, 114.4531f, 63.2813f, 42.9688f, -26.1719f, -61.7188f, -87.1094f, -46.8750f, -14.0625f, 5.8594f, 10.1563f, 23.4375f, + 8.9844f, 50.7813f, 41.7969f, 0.0000f, -12.1094f, -25.7813f, 12.8906f, 8.5938f, 39.4531f, -3.9063f, -12.5000f, -90.6250f, -109.7656f, -230.4688f, -262.5000f, -425.3906f, + 19.9219f, 41.4063f, 61.3281f, 51.5625f, 15.6250f, 4.2969f, -28.5156f, -25.7813f, -64.4531f, -114.8438f, -219.1406f, -300.7813f, -289.8438f, -191.0156f, -78.9063f, 1.5625f, + 9.7656f, 89.8438f, 111.7188f, 69.9219f, 29.2969f, 7.0313f, 5.8594f, 9.3750f, 42.5781f, 73.0469f, 121.0938f, 130.4688f, 128.1250f, 113.6719f, 92.5781f, 82.8125f, + -92.9688f, -192.1875f, -214.8438f, 219.9219f, 298.4375f, 238.2813f, 211.7188f, 166.7969f, 145.7031f, 101.9531f, 64.8438f, 66.7969f, 47.6563f, 13.2813f, -8.2031f, -35.9375f, + -140.2344f, -180.4688f, -3.9063f, 8.5938f, -16.4063f, -0.7813f, 30.4688f, 65.2344f, 60.1563f, 60.5469f, 28.9063f, 28.5156f, 25.7813f, 36.7188f, 34.7656f, 49.2188f, + -1.9531f, -42.9688f, -146.0938f, -213.2813f, -150.7813f, -53.1250f, 37.1094f, 119.1406f, 170.7031f, 222.6563f, 240.2344f, 217.9688f, 180.8594f, 130.8594f, 81.6406f, 58.9844f, + 8.9844f, 146.8750f, 114.0625f, 91.7969f, 189.4531f, 202.7344f, 256.6406f, 214.4531f, 186.7188f, 132.0313f, 72.6563f, 2.7344f, -10.9375f, -60.5469f, -37.1094f, -73.4375f, + 64.8438f, 54.2969f, -108.2031f, -279.6875f, -321.0938f, 91.4063f, 124.6094f, 127.3438f, 91.4063f, 14.0625f, -60.5469f, -123.8281f, -96.4844f, -31.2500f, 19.1406f, 45.7031f, + 168.3594f, 333.2031f, 291.0156f, 200.0000f, 126.9531f, 54.2969f, 32.4219f, -12.1094f, -9.7656f, -18.3594f, -6.6406f, -4.6875f, -9.3750f, -16.7969f, -1.9531f, 5.0781f +}; +/* An 16-by-32 matrix */ +const float GEWB2_MA1[512] = +{ + 257.4219f, 661.7188f, 638.2813f, 591.0156f, 509.7656f, 428.9063f, 364.4531f, 314.4531f, 286.3281f, 243.7500f, 205.0781f, 132.4219f, 93.3594f, 19.5313f, -13.6719f, -83.9844f, + 2.3438f, 25.3906f, 48.8281f, 21.4844f, -33.2031f, -49.2188f, -106.2500f, -123.4375f, -198.0469f, -228.9063f, -394.5313f, -499.2188f, -758.2031f, -746.0938f, -166.4063f, 30.4688f, + 109.7656f, 123.0469f, 92.1875f, -1.5625f, -39.8438f, -66.7969f, -90.6250f, -130.8594f, -141.4063f, -166.0156f, -190.6250f, -235.5469f, -261.3281f, -287.5000f, -253.1250f, -231.6406f, + 11.3281f, -98.0469f, -227.3438f, -340.2344f, -378.5156f, -350.3906f, -387.1094f, -420.7031f, -498.0469f, -578.1250f, -389.8438f, -153.5156f, -96.4844f, -3.5156f, 10.9375f, 105.8594f, + -23.4375f, -141.0156f, 156.6406f, 215.6250f, 92.1875f, 13.6719f, -76.5625f, -83.9844f, -193.7500f, -266.7969f, -355.8594f, -320.3125f, -225.0000f, -116.7969f, -93.7500f, -55.0781f, + 162.5000f, 224.2188f, 258.5938f, 136.7188f, 51.9531f, -62.5000f, -168.3594f, -305.0781f, -468.7500f, -645.3125f, -794.9219f, -426.5625f, -175.3906f, -75.0000f, -4.2969f, 102.7344f, + -80.4688f, -237.8906f, -363.6719f, 10.9375f, -89.4531f, -139.8438f, -212.1094f, -180.4688f, -147.2656f, -140.6250f, -131.2500f, -98.0469f, -41.0156f, 13.6719f, 10.1563f, 31.2500f, + 144.1406f, 490.6250f, 539.0625f, 613.6719f, 674.2188f, 674.6094f, 642.1875f, 594.1406f, 527.3438f, 451.5625f, 384.3750f, 292.1875f, 226.5625f, 154.2969f, 99.2188f, 42.1875f, + -57.4219f, -187.1094f, -128.9063f, -28.5156f, -106.2500f, -172.2656f, -267.5781f, -326.9531f, -444.9219f, -569.5313f, -535.1563f, -161.7188f, -81.2500f, -4.6875f, 5.4688f, 83.2031f, + -19.5313f, 39.0625f, -32.0313f, -98.8281f, -2.7344f, 46.4844f, 114.8438f, 153.1250f, 192.9688f, 225.7813f, 230.0781f, 204.2969f, 180.4688f, 149.6094f, 117.1875f, 97.2656f, + -36.7188f, -141.4063f, -224.6094f, -300.7813f, -385.5469f, -390.2344f, -360.1563f, -272.2656f, -227.3438f, -119.1406f, -52.7344f, -12.1094f, -3.1250f, 8.9844f, -12.8906f, 24.2188f, + 11.3281f, -25.0000f, -1.5625f, -48.0469f, -134.3750f, -161.7188f, -265.2344f, -299.6094f, -450.0000f, -547.2656f, -822.2656f, -744.1406f, -227.3438f, -117.1875f, -25.0000f, 87.1094f, + 167.1875f, 386.7188f, 398.0469f, 316.0156f, 266.0156f, 183.5938f, 142.9688f, 69.9219f, 49.2188f, -10.1563f, -55.0781f, -141.7969f, -165.2344f, -209.3750f, -170.7031f, -212.8906f, + -51.9531f, -139.4531f, 142.1875f, 94.1406f, -15.2344f, -88.6719f, -130.4688f, -119.1406f, -166.4063f, -114.0625f, -39.8438f, 33.9844f, 62.1094f, 71.0938f, 62.5000f, 74.2188f, + 218.7500f, 298.4375f, 207.4219f, 60.9375f, 8.5938f, -7.0313f, 8.9844f, -7.8125f, 7.4219f, 0.0000f, 5.0781f, -23.8281f, -13.6719f, -17.1875f, -4.6875f, -18.7500f, + 12.8906f, -91.7969f, -247.6563f, -426.9531f, 53.1250f, -12.1094f, -26.5625f, -111.3281f, -206.6406f, -208.9844f, -180.4688f, -97.2656f, -37.1094f, -20.7031f, -45.3125f, -23.8281f, + -73.4375f, -245.3125f, -349.2188f, 274.2188f, 273.4375f, 145.7031f, 76.5625f, 19.9219f, 37.1094f, -21.8750f, -74.6094f, -70.7031f, -67.5781f, -51.5625f, -45.3125f, -85.1563f, + 14.4531f, -73.4375f, -258.2031f, -424.6094f, -516.4063f, -100.7813f, -72.6563f, -70.7031f, -92.9688f, -145.3125f, -163.2813f, -198.4375f, -169.1406f, -76.9531f, -28.5156f, 10.9375f, + -90.2344f, -86.7188f, 355.8594f, 341.7969f, 261.3281f, 171.8750f, 141.7969f, 117.5781f, 100.3906f, 75.0000f, 57.4219f, 26.5625f, 30.0781f, 16.7969f, 22.2656f, 6.6406f, + -1.5625f, -73.0469f, -139.0625f, -160.1563f, -222.2656f, -194.9219f, -228.1250f, -221.8750f, -257.8125f, -274.6094f, -376.9531f, -469.1406f, -601.5625f, -276.5625f, -98.4375f, 33.9844f, + 85.9375f, 25.0000f, -26.1719f, -139.4531f, -223.4375f, -290.6250f, -356.6406f, -459.3750f, -562.1094f, -739.8438f, -840.6250f, -297.6563f, -163.6719f, -57.0313f, -3.9063f, 109.7656f, + -98.8281f, -244.9219f, -419.9219f, -471.0938f, -281.6406f, -155.4688f, -131.6406f, -73.4375f, -46.0938f, 19.5313f, 48.8281f, 77.3438f, 78.1250f, 74.2188f, 37.5000f, 64.0625f, + -135.9375f, -289.4531f, -333.5938f, -139.4531f, -63.6719f, -40.2344f, -10.1563f, 55.8594f, 90.2344f, 124.2188f, 130.8594f, 126.9531f, 107.0313f, 91.0156f, 65.2344f, 74.2188f, + -55.8594f, -100.0000f, -74.6094f, -109.3750f, -97.6563f, -74.6094f, -32.0313f, 14.4531f, 49.2188f, 39.8438f, 26.1719f, -50.7813f, -78.9063f, -167.9688f, -193.3594f, -316.4063f, + 90.6250f, 41.7969f, -8.5938f, -133.2031f, -194.1406f, -204.2969f, -237.1094f, -252.3438f, -291.4063f, -269.5313f, -186.7188f, -115.2344f, -62.5000f, -30.0781f, -20.7031f, -2.7344f, + -12.8906f, -38.2813f, -100.7813f, -195.7031f, -230.0781f, -171.0938f, -123.4375f, -65.6250f, -22.6563f, 32.0313f, 68.3594f, 85.5469f, 97.2656f, 101.1719f, 92.5781f, 88.2813f, + -153.5156f, -259.7656f, -7.4219f, 72.2656f, 97.2656f, 103.9063f, 147.6563f, 182.8125f, 194.9219f, 198.4375f, 181.2500f, 151.5625f, 121.0938f, 92.9688f, 72.6563f, 56.6406f, + -93.7500f, -38.6719f, 159.3750f, 187.5000f, 270.7031f, 297.2656f, 369.5313f, 368.3594f, 371.4844f, 348.8281f, 305.4688f, 239.4531f, 188.2813f, 137.1094f, 101.5625f, 63.6719f, + -8.9844f, 204.2969f, 345.7031f, 352.7344f, 457.8125f, 502.7344f, 578.9063f, 582.4219f, 576.5625f, 547.6563f, 484.3750f, 392.5781f, 307.4219f, 235.9375f, 169.1406f, 114.0625f, + 102.3438f, 385.9375f, 353.1250f, 285.9375f, 286.7188f, 259.7656f, 279.2969f, 256.2500f, 262.8906f, 240.2344f, 211.3281f, 145.3125f, 110.9375f, 54.2969f, 26.5625f, -32.8125f, + -46.4844f, 174.2188f, 436.7188f, 474.6094f, 535.9375f, 500.0000f, 471.8750f, 386.3281f, 344.1406f, 263.6719f, 217.5781f, 124.6094f, 88.6719f, 8.9844f, -15.2344f, -100.0000f, + -39.8438f, 69.5313f, 148.0469f, 98.4375f, 142.5781f, 124.6094f, 177.7344f, 147.2656f, 161.3281f, 108.5938f, 87.8906f, -14.0625f, -26.1719f, -137.1094f, -146.4844f, -301.5625f +}; +/* An 16-by-16 matrix */ +const float AUNB_SN1[256] = +{ + -70.3125f, -30.8594f, -19.9219f, 15.2344f, 25.7813f, 38.6719f, 18.7500f, 42.1875f, 21.8750f, 49.6094f, 13.2813f, 17.9688f, -183.5938f, -330.0781f, -55.0781f, -35.1563f, + -82.8125f, 32.0313f, 110.9375f, 164.8438f, 162.5000f, 162.5000f, 122.2656f, 112.8906f, 91.0156f, 82.0313f, 42.1875f, 21.4844f, -171.4844f, -516.7969f, -131.2500f, -48.0469f, + -3.5156f, 158.2031f, 207.8125f, 257.4219f, 277.3438f, 311.7188f, 329.6875f, 379.2969f, 418.7500f, 461.3281f, 571.8750f, 747.2656f, 792.1875f, 481.2500f, 214.4531f, 103.5156f, + 29.2969f, 19.1406f, 128.9063f, 192.5781f, 175.0000f, 128.5156f, 79.6875f, 26.1719f, -7.0313f, -52.3438f, -91.7969f, -156.2500f, -236.3281f, -11.7188f, -26.1719f, -14.0625f, + -3.5156f, -2.7344f, -37.1094f, -86.7188f, -125.7813f, -164.4531f, -125.3906f, -91.0156f, -42.9688f, -33.5938f, 26.1719f, -7.4219f, 1.1719f, 134.7656f, 16.0156f, 11.7188f, + 59.7656f, 13.2813f, -67.1875f, -150.7813f, -195.3125f, -214.0625f, -196.4844f, -164.0625f, -123.8281f, -80.8594f, -44.5313f, 71.4844f, 428.1250f, 258.2031f, 77.3438f, 36.7188f, + 240.6250f, 195.7031f, 183.9844f, 85.9375f, 61.3281f, 21.4844f, 1.5625f, -62.8906f, -69.5313f, -122.6563f, -104.2969f, -151.9531f, 84.3750f, 167.5781f, 17.9688f, 14.8438f, + -218.3594f, -333.5938f, -308.2031f, -144.1406f, -59.7656f, 25.0000f, 57.0313f, 115.6250f, 151.5625f, 203.1250f, 224.2188f, 374.2188f, 578.5156f, 350.7813f, 132.8125f, 64.0625f, + 51.1719f, 53.5156f, 45.3125f, 22.2656f, 25.0000f, -8.2031f, -14.8438f, -43.7500f, -48.0469f, -77.7344f, -83.5938f, -148.0469f, -250.3906f, 32.4219f, -20.7031f, -8.2031f, + -39.4531f, -126.5625f, -253.1250f, -312.8906f, -326.1719f, -287.8906f, -195.7031f, -115.6250f, -33.5938f, 56.2500f, 156.2500f, 400.3906f, 586.3281f, 336.3281f, 125.7813f, 58.9844f, + -90.2344f, -155.0781f, -200.0000f, -197.6563f, -120.3125f, -78.1250f, -49.6094f, -35.5469f, -7.0313f, 6.6406f, 36.7188f, 44.5313f, 311.7188f, 244.1406f, 62.8906f, 34.3750f, + -202.3438f, -241.0156f, -78.5156f, 40.2344f, 100.7813f, 108.9844f, 106.6406f, 104.2969f, 109.7656f, 98.0469f, 83.5938f, 44.5313f, 22.6563f, 105.4688f, 27.3438f, 12.1094f, + 6.6406f, -33.5938f, -30.4688f, -32.0313f, -8.5938f, -28.5156f, -66.7969f, -116.7969f, -130.4688f, -168.3594f, -164.8438f, -205.4688f, 201.9531f, 199.6094f, 27.7344f, 20.7031f, + 107.8125f, 71.0938f, -15.6250f, -131.2500f, -180.0781f, -36.3281f, 133.5938f, 104.2969f, 64.8438f, 7.0313f, -16.7969f, -76.5625f, -57.0313f, 92.1875f, 7.0313f, 5.4688f, + 88.6719f, 132.0313f, 87.5000f, 73.4375f, 41.7969f, 31.2500f, 22.2656f, 35.9375f, 13.2813f, 31.2500f, -1.9531f, -1.5625f, -201.1719f, -362.1094f, -67.9688f, -39.0625f, + 285.5469f, 290.6250f, 311.3281f, 263.6719f, 230.4688f, 171.0938f, 128.1250f, 83.9844f, 56.2500f, 9.3750f, -37.5000f, -93.3594f, -189.8438f, -68.3594f, -25.3906f, -16.0156f +}; +/* An 16-by-16 matrix */ +const float AUWB_SN1[256] = +{ + 128.1250f, 53.5156f, 139.8438f, 128.9063f, 71.8750f, 56.6406f, -23.4375f, -114.8438f, -216.7969f, -306.2500f, -369.1406f, -340.6250f, -234.7656f, -131.6406f, -60.5469f, -12.8906f, + 12.5000f, -82.8125f, -190.6250f, -254.2969f, -293.7500f, -342.5781f, -348.4375f, -346.0938f, -333.2031f, -310.5469f, -275.3906f, -214.4531f, -128.9063f, -87.5000f, -49.6094f, -3.5156f, + 145.3125f, 127.7344f, 76.9531f, 12.8906f, 5.0781f, -21.4844f, -33.9844f, -48.4375f, -48.8281f, -57.8125f, -56.2500f, -65.6250f, -68.3594f, -71.8750f, -49.6094f, -48.8281f, + 293.7500f, 283.9844f, 243.3594f, 202.7344f, 175.3906f, 136.7188f, 120.7031f, 112.8906f, 106.2500f, 98.4375f, 72.2656f, 48.4375f, 46.0938f, 13.6719f, 8.5938f, -7.8125f, + 5.4688f, 56.2500f, 115.6250f, 168.7500f, 162.5000f, 126.9531f, 69.1406f, 64.8438f, 58.9844f, 48.0469f, 42.5781f, 40.6250f, 18.3594f, -8.5938f, -17.5781f, -19.1406f, + 121.0938f, 43.7500f, -55.0781f, -206.6406f, -255.4688f, -20.7031f, 63.2813f, -12.8906f, -116.0156f, -215.2344f, -301.5625f, -319.1406f, -210.9375f, -112.1094f, -37.1094f, -2.7344f, + -61.7188f, 94.1406f, 173.0469f, 212.1094f, 218.3594f, 226.1719f, 221.0938f, 236.7188f, 238.2813f, 242.9688f, 235.1563f, 225.7813f, 189.4531f, 129.2969f, 76.9531f, 40.6250f, + -183.9844f, -207.0313f, 14.4531f, 106.2500f, 155.0781f, 172.6563f, 182.0313f, 204.2969f, 219.1406f, 231.2500f, 237.5000f, 225.0000f, 189.4531f, 135.9375f, 86.7188f, 51.9531f, + 63.2813f, 0.0000f, -33.9844f, -33.2031f, -58.9844f, -129.2969f, -160.1563f, -235.5469f, -299.6094f, -402.3438f, -526.5625f, -707.8125f, -677.7344f, -264.8438f, -110.9375f, -2.3438f, + -60.9375f, 14.0625f, 5.8594f, 10.1563f, 16.0156f, 46.0938f, 78.5156f, 103.5156f, 132.4219f, 149.2188f, 164.0625f, 169.9219f, 147.2656f, 103.1250f, 62.1094f, 32.8125f, + -26.9531f, -107.0313f, -160.5469f, -61.7188f, 23.4375f, -21.8750f, -74.2188f, -119.1406f, -144.9219f, -151.9531f, -160.5469f, -158.9844f, -132.0313f, -107.8125f, -67.5781f, -38.6719f, + 0.0000f, -10.1563f, -76.5625f, -148.0469f, -144.1406f, -127.7344f, -75.3906f, -57.8125f, -30.0781f, -3.9063f, 24.6094f, 38.2813f, 38.2813f, 19.1406f, 15.6250f, -1.9531f, + -58.2031f, -168.7500f, -284.7656f, -360.5469f, -362.1094f, -299.2188f, -221.8750f, -177.7344f, -130.0781f, -85.5469f, -47.6563f, -11.3281f, 4.2969f, 3.5156f, 7.8125f, 21.0938f, + 69.1406f, 25.0000f, -23.4375f, -90.6250f, -160.5469f, -215.6250f, -217.5781f, -214.8438f, -198.8281f, -181.2500f, -148.4375f, -129.2969f, -116.0156f, -112.5000f, -83.9844f, -66.4063f, + -6.2500f, 171.4844f, 379.2969f, 431.2500f, 472.2656f, 516.7969f, 523.0469f, 536.7188f, 514.4531f, 477.7344f, 432.4219f, 383.9844f, 305.0781f, 208.9844f, 123.0469f, 58.9844f, + -168.7500f, -283.9844f, -267.9688f, -132.8125f, -60.9375f, -15.6250f, 7.0313f, 39.8438f, 66.0156f, 100.3906f, 119.5313f, 130.8594f, 115.6250f, 83.2031f, 53.5156f, 37.8906f +}; +/* An 16-by-16 matrix */ +const float AUWB2_SN1[256] = +{ + -41.7969f, -174.2188f, -326.1719f, -406.6406f, -450.0000f, -453.5156f, -447.6563f, -378.5156f, -323.4375f, -208.2031f, -98.0469f, -94.5313f, -54.2969f, 67.1875f, 37.1094f, 182.0313f, + 410.9375f, 393.7500f, 410.9375f, 341.7969f, 337.5000f, 292.1875f, 305.8594f, 269.5313f, 294.5313f, 279.2969f, 268.7500f, 133.5938f, 76.1719f, -12.5000f, -98.0469f, -198.8281f, + -121.4844f, -66.4063f, 142.9688f, 246.8750f, 292.1875f, 337.1094f, 383.9844f, 407.0313f, 436.7188f, 464.0625f, 442.5781f, 349.6094f, 284.3750f, 242.5781f, 179.6875f, 163.2813f, + 237.5000f, 205.0781f, 125.7813f, 11.7188f, -92.5781f, -188.6719f, -336.7188f, -460.1563f, -644.9219f, -853.1250f, -1082.0313f, -526.9531f, -167.9688f, -10.9375f, 50.0000f, 219.5313f, + 115.6250f, 66.7969f, -75.0000f, -167.5781f, -190.6250f, -183.5938f, -192.1875f, -184.7656f, -175.0000f, -137.5000f, -94.5313f, -120.7031f, -131.6406f, -82.0313f, -103.5156f, -71.0938f, + 324.6094f, 274.6094f, 178.1250f, 84.7656f, 64.4531f, 25.3906f, 6.6406f, -20.7031f, -26.1719f, -30.4688f, -14.8438f, -86.7188f, -132.8125f, -128.5156f, -136.3281f, -152.7344f, + 63.2813f, -5.0781f, -61.7188f, -130.8594f, -205.4688f, -275.3906f, -385.1563f, -486.3281f, -640.6250f, -839.4531f, -1075.7813f, -525.0000f, -145.3125f, -4.6875f, 52.3438f, 220.3125f, + -30.8594f, -151.9531f, -222.2656f, -273.0469f, -316.7969f, -367.1875f, -413.2813f, -507.4219f, -599.2188f, -811.3281f, -762.8906f, -198.0469f, -84.3750f, 55.8594f, 74.6094f, 237.1094f, + -41.4063f, -45.3125f, -82.0313f, -87.8906f, -126.1719f, -128.9063f, -192.9688f, -191.7969f, -273.4375f, -295.7031f, -412.8906f, -556.2500f, -867.9688f, -589.4531f, -101.1719f, 135.9375f, + -142.9688f, -292.1875f, -459.7656f, -475.0000f, -397.2656f, -272.6563f, -173.4375f, -60.1563f, 3.9063f, 111.3281f, 141.0156f, 110.9375f, 99.6094f, 140.2344f, 73.0469f, 142.5781f, + 30.0781f, 174.6094f, 163.2813f, 185.5469f, 176.9531f, 179.2969f, 185.5469f, 201.1719f, 219.5313f, 253.1250f, 257.0313f, 176.5625f, 143.3594f, 130.4688f, 95.3125f, 79.6875f, + 3.9063f, 76.9531f, 66.4063f, 64.8438f, 56.2500f, 23.4375f, 20.3125f, -0.7813f, -7.8125f, -15.6250f, 7.0313f, -92.9688f, -108.9844f, -169.5313f, -176.1719f, -315.2344f, + -179.6875f, -278.5156f, -213.6719f, -59.7656f, 25.0000f, 94.9219f, 150.7813f, 192.1875f, 242.1875f, 293.7500f, 296.4844f, 209.3750f, 173.8281f, 126.5625f, 58.9844f, -12.5000f, + -96.0938f, -154.6875f, -161.3281f, -144.9219f, -138.2813f, -123.8281f, -119.9219f, -89.0625f, -76.1719f, -39.4531f, -14.0625f, -67.9688f, -76.9531f, -63.2813f, -101.9531f, -136.3281f, + -128.5156f, -93.7500f, 127.3438f, 180.4688f, 167.1875f, 134.3750f, 158.2031f, 146.0938f, 171.4844f, 169.5313f, 182.4219f, 49.6094f, 33.2031f, -60.1563f, -96.8750f, -266.7969f, + -4.6875f, 5.8594f, -86.7188f, -88.6719f, -12.1094f, 48.4375f, 78.1250f, 114.8438f, 139.4531f, 211.3281f, 237.1094f, 179.2969f, 146.8750f, 137.5000f, 110.1563f, 110.5469f +}; +/* An 16-by-16 matrix */ +const float CNG_SN1[256] = +{ + 234.3750f, 640.6250f, 1187.1094f, 1662.8906f, 2153.1250f, 2632.8125f, 3120.7031f, 3581.6406f, 4059.7656f, 4535.9375f, 5031.2500f, 5507.8125f, 6007.0313f, 6466.4063f, 6959.3750f, 7389.8438f, + 464.0625f, 971.4844f, 1463.2813f, 1915.2344f, 2383.9844f, 2836.3281f, 3295.7031f, 3744.9219f, 4209.3750f, 4669.5313f, 5145.3125f, 5607.4219f, 6079.6875f, 6528.1250f, 6997.2656f, 7426.5625f, + 135.1563f, 312.1094f, 882.4219f, 1388.6719f, 1904.6875f, 2412.1094f, 2935.9375f, 3438.6719f, 3934.7656f, 4423.0469f, 4933.9844f, 5444.5313f, 5969.5313f, 6466.0156f, 6959.7656f, 7437.1094f, + 171.4844f, 631.2500f, 1346.0938f, 1852.7344f, 2372.2656f, 2846.8750f, 3341.0156f, 3799.2188f, 4276.1719f, 4728.9063f, 5200.0000f, 5653.9063f, 6113.2813f, 6551.9531f, 6989.8438f, 7412.8906f, + 359.7656f, 703.1250f, 1162.5000f, 1565.2344f, 1994.1406f, 2397.2656f, 2803.9063f, 3183.5938f, 3537.8906f, 3872.6563f, 4300.3906f, 4900.3906f, 5340.2344f, 6055.4688f, 6807.8125f, 7393.3594f, + 350.0000f, 741.7969f, 1185.5469f, 1612.5000f, 2070.7031f, 2511.3281f, 2970.3125f, 3405.8594f, 3861.7188f, 4319.9219f, 4850.3906f, 5320.7031f, 5844.5313f, 6302.7344f, 6826.1719f, 7210.9375f, + 282.0313f, 588.6719f, 991.0156f, 1342.5781f, 1690.6250f, 2027.3438f, 2350.7813f, 2672.2656f, 2963.6719f, 3258.9844f, 3486.3281f, 3715.2344f, 3874.6094f, 4326.1719f, 5317.5781f, 5867.5781f, + 123.0469f, 239.0625f, 652.7344f, 1136.7188f, 1558.5938f, 1985.5469f, 2390.6250f, 2800.7813f, 3198.4375f, 3583.2031f, 3964.0625f, 4369.5313f, 4785.1563f, 5180.4688f, 5582.0313f, 5970.3125f, + 345.7031f, 753.1250f, 1175.7813f, 1551.9531f, 1934.3750f, 2304.6875f, 2675.0000f, 3034.7656f, 3398.8281f, 3753.5156f, 4133.2031f, 4507.8125f, 4885.9375f, 5253.9063f, 5629.6875f, 5995.7031f, + 132.0313f, 398.4375f, 1037.8906f, 1459.3750f, 1890.2344f, 2262.1094f, 2658.5938f, 3031.2500f, 3413.2813f, 3773.0469f, 4151.1719f, 4518.3594f, 4896.0938f, 5260.9375f, 5631.2500f, 5989.8438f, + 439.8438f, 767.1875f, 1171.4844f, 1505.8594f, 1860.9375f, 2190.6250f, 2532.0313f, 2846.0938f, 3167.5781f, 3448.0469f, 3738.2813f, 4159.7656f, 4687.1094f, 5126.9531f, 5555.8594f, 5957.8125f, + 150.3906f, 318.3594f, 781.2500f, 1148.0469f, 1525.7813f, 1905.8594f, 2262.8906f, 2630.4688f, 2992.5781f, 3330.4688f, 3636.3281f, 3963.2813f, 4530.0781f, 5060.5469f, 5510.1563f, 5953.5156f, + 247.2656f, 564.4531f, 937.5000f, 1286.3281f, 1654.2969f, 2019.9219f, 2399.6094f, 2767.1875f, 3147.2656f, 3507.8125f, 3876.5625f, 4267.1875f, 4682.4219f, 5077.3438f, 5475.0000f, 5882.0313f, + 228.1250f, 487.5000f, 878.9063f, 1223.0469f, 1582.0313f, 1921.8750f, 2269.9219f, 2598.4375f, 2918.3594f, 3220.3125f, 3481.6406f, 3703.1250f, 3979.6875f, 4775.3906f, 5418.3594f, 5907.4219f, + 451.9531f, 710.9375f, 1072.2656f, 1369.1406f, 1700.7813f, 1991.0156f, 2317.1875f, 2596.8750f, 2893.7500f, 3138.2813f, 3373.0469f, 3548.0469f, 3897.2656f, 4776.5625f, 5398.0469f, 5901.5625f, + 223.4375f, 547.2656f, 982.0313f, 1367.5781f, 1758.9844f, 2134.7656f, 2526.9531f, 2904.2969f, 3287.5000f, 3643.7500f, 4025.7813f, 4417.5781f, 4815.6250f, 5196.4844f, 5588.2813f, 5961.3281f +}; +/* An 16-by-32 matrix */ +const float IAA_MA1[512] = +{ + -68.3594f, -191.4063f, -203.1250f, -246.4844f, -251.9531f, -239.8438f, -238.2813f, -214.0625f, -196.4844f, -168.7500f, -137.8906f, -117.5781f, -92.9688f, -55.0781f, -26.1719f, 10.1563f, + 117.5781f, 158.9844f, 88.6719f, 37.5000f, -4.6875f, -7.0313f, -5.0781f, 0.7813f, 15.2344f, 41.7969f, 48.4375f, 35.9375f, 32.4219f, 39.0625f, 24.2188f, 28.1250f, + -109.3750f, -287.8906f, -222.2656f, -64.0625f, -3.5156f, 39.0625f, 55.0781f, 82.4219f, 98.4375f, 109.7656f, 107.0313f, 84.7656f, 80.4688f, 85.5469f, 45.7031f, 41.4063f, + -103.9063f, -294.1406f, -328.5156f, -229.2969f, -190.2344f, -134.7656f, -102.7344f, -65.2344f, -44.5313f, -11.7188f, 3.1250f, 12.5000f, 13.2813f, 23.8281f, 21.4844f, 40.6250f, + -35.5469f, -53.5156f, -114.4531f, -136.3281f, -137.5000f, -127.3438f, -104.6875f, -96.4844f, -69.5313f, -50.3906f, -21.8750f, -37.5000f, -4.2969f, 85.5469f, 19.1406f, 21.8750f, + -7.0313f, 0.3906f, -12.8906f, -5.4688f, -7.4219f, -1.9531f, -8.5938f, -5.4688f, -16.7969f, -14.4531f, -40.6250f, -55.8594f, -146.4844f, -300.7813f, -74.2188f, -39.0625f, + 28.1250f, -8.5938f, -47.2656f, -85.9375f, -125.0000f, -147.6563f, -195.3125f, -229.2969f, -284.7656f, -310.5469f, -412.5000f, -509.7656f, -660.5469f, -425.7813f, -176.5625f, -23.4375f, + 7.4219f, -108.9844f, -176.9531f, -226.5625f, -229.6875f, -288.6719f, -335.1563f, -407.8125f, -500.3906f, -630.4688f, -359.7656f, -146.8750f, -106.6406f, -32.8125f, -0.7813f, 73.0469f, + 333.2031f, 296.4844f, 230.8594f, 146.8750f, 101.5625f, 47.6563f, 15.2344f, -27.7344f, -51.9531f, -71.8750f, -81.6406f, -116.0156f, -116.7969f, -66.7969f, -48.4375f, -32.4219f, + 103.9063f, 13.2813f, -71.0938f, -143.3594f, -201.5625f, -267.9688f, -344.1406f, -437.8906f, -552.3438f, -716.4063f, -824.2188f, -389.4531f, -202.7344f, -107.0313f, -42.5781f, 53.5156f, + -0.7813f, -3.1250f, 16.4063f, 35.5469f, 67.1875f, 82.4219f, 116.4063f, 131.2500f, 169.1406f, 159.7656f, 213.2813f, 407.4219f, 585.5469f, 405.4688f, 160.1563f, 73.8281f, + 33.5938f, 99.2188f, 101.1719f, 99.2188f, 96.0938f, 85.5469f, 71.8750f, 47.6563f, 30.8594f, 4.2969f, -21.4844f, -66.4063f, -141.7969f, -364.8438f, -144.9219f, -73.4375f, + 65.6250f, 65.2344f, -47.6563f, -95.3125f, -126.9531f, -132.8125f, -140.2344f, -133.9844f, -129.2969f, -113.6719f, -108.5938f, -105.4688f, -106.2500f, -63.2813f, -39.4531f, -17.9688f, + -95.3125f, -179.2969f, -143.3594f, -132.8125f, -115.2344f, -85.9375f, -67.5781f, -41.7969f, -8.5938f, 20.7031f, 40.2344f, 114.4531f, 423.4375f, 315.2344f, 101.5625f, 45.7031f, + -124.6094f, -253.9063f, -267.5781f, -166.7969f, -113.2813f, -41.0156f, 9.7656f, 62.8906f, 118.3594f, 163.2813f, 229.2969f, 419.5313f, 610.5469f, 423.8281f, 156.2500f, 66.4063f, + 57.0313f, 100.3906f, 110.1563f, 115.2344f, 118.3594f, 114.8438f, 116.0156f, 102.3438f, 92.5781f, 75.3906f, 35.9375f, 133.2031f, 476.5625f, 345.3125f, 123.0469f, 56.2500f, + -113.6719f, -217.9688f, 57.4219f, 78.5156f, 110.1563f, 109.3750f, 121.0938f, 117.9688f, 122.2656f, 119.5313f, 114.0625f, 93.3594f, 77.3438f, 73.4375f, 41.4063f, 36.7188f, + -4.2969f, -3.1250f, -60.9375f, -79.6875f, -90.2344f, -97.6563f, -103.5156f, -112.8906f, -105.0781f, -123.4375f, -125.7813f, -175.7813f, -190.6250f, -264.0625f, -303.9063f, -380.0781f, + -45.7031f, -10.5469f, 1.5625f, 37.5000f, 67.9688f, 89.4531f, 105.8594f, 121.0938f, 134.3750f, 141.4063f, 134.3750f, 106.6406f, 81.6406f, 70.3125f, 42.5781f, 41.4063f, + -101.5625f, -113.2813f, 58.9844f, 105.0781f, 158.5938f, 172.6563f, 215.2344f, 230.4688f, 265.2344f, 266.0156f, 351.5625f, 505.0781f, 637.1094f, 442.1875f, 186.3281f, 86.3281f, + -14.4531f, 146.0938f, 153.9063f, 161.7188f, 163.6719f, 154.2969f, 134.7656f, 122.2656f, 110.1563f, 99.6094f, 82.4219f, 49.2188f, 32.8125f, 19.9219f, -3.9063f, -20.7031f, + 157.8125f, 127.7344f, 67.9688f, 10.9375f, -48.4375f, -113.2813f, -191.4063f, -271.4844f, -394.9219f, -433.9844f, -206.6406f, -112.5000f, -71.4844f, -26.9531f, -2.7344f, 55.4688f, + 219.9219f, 293.7500f, 228.5156f, 216.7969f, 200.0000f, 186.7188f, 165.6250f, 154.6875f, 146.8750f, 133.9844f, 117.1875f, 75.7813f, 75.3906f, 63.2813f, 30.4688f, 17.9688f, + -23.0469f, -51.1719f, -13.6719f, 19.1406f, 21.0938f, -4.6875f, -35.9375f, -72.2656f, -94.9219f, -112.8906f, -112.5000f, -134.3750f, -127.3438f, 0.0000f, -14.8438f, 2.3438f, + 193.7500f, 227.3438f, 220.3125f, 200.7813f, 203.5156f, 191.4063f, 189.8438f, 170.3125f, 168.7500f, 125.0000f, 178.1250f, 414.0625f, 594.9219f, 413.2813f, 163.6719f, 75.7813f, + 67.9688f, 30.0781f, 7.0313f, -34.7656f, -43.7500f, -76.5625f, -64.4531f, -96.4844f, -86.7188f, -127.3438f, -129.6875f, -192.9688f, 194.9219f, 241.0156f, 47.2656f, 23.4375f, + 123.0469f, 116.7969f, 89.4531f, 53.5156f, 30.4688f, -1.1719f, -15.6250f, -53.9063f, -77.3438f, -119.9219f, -146.4844f, -196.0938f, -201.1719f, -9.7656f, -34.3750f, -19.1406f, + -90.6250f, -11.3281f, 137.8906f, 155.8594f, 189.4531f, 190.2344f, 204.2969f, 205.4688f, 217.1875f, 218.3594f, 203.1250f, 162.1094f, 128.1250f, 110.5469f, 73.0469f, 64.8438f, + 71.0938f, 150.3906f, 157.4219f, 176.9531f, 201.1719f, 223.4375f, 248.0469f, 269.9219f, 307.4219f, 332.8125f, 450.7813f, 579.2969f, 694.9219f, 480.8594f, 204.6875f, 96.0938f, + -106.6406f, -192.1875f, -72.2656f, -37.8906f, -20.3125f, -19.9219f, -6.6406f, -10.5469f, 5.0781f, 7.8125f, 17.5781f, -7.8125f, 20.3125f, 95.3125f, 22.6563f, 21.8750f, + 7.8125f, -1.1719f, -94.1406f, -104.2969f, -75.7813f, -33.5938f, 1.5625f, 29.2969f, 54.6875f, 74.6094f, 78.1250f, 60.1563f, 53.5156f, 57.0313f, 33.2031f, 30.0781f, + 35.9375f, 245.3125f, 238.6719f, 276.5625f, 275.7813f, 279.6875f, 262.5000f, 271.0938f, 255.8594f, 241.7969f, 214.8438f, 168.7500f, 138.2813f, 110.9375f, 79.6875f, 67.1875f +}; +/* An 16-by-8 matrix */ +const float GESVNB_AR1[128] = +{ + -9.7656f, -25.0000f, -54.6875f, -46.0938f, 105.4688f, 93.7500f, 49.6094f, 27.3438f, 7.8125f, -15.6250f, -21.8750f, -43.3594f, -32.0313f, 25.0000f, 0.7813f, 1.9531f, + 31.6406f, 40.6250f, 27.7344f, 27.3438f, 0.0000f, -19.1406f, -21.0938f, -28.5156f, -23.0469f, -35.9375f, -39.8438f, -78.5156f, -157.8125f, -20.3125f, -15.6250f, -5.8594f, + -43.7500f, -84.7656f, -98.0469f, -78.9063f, -13.2813f, 22.2656f, 22.6563f, 24.2188f, 30.8594f, 49.6094f, 69.1406f, 119.5313f, 204.6875f, 123.0469f, 43.7500f, 20.7031f, + 6.6406f, -2.3438f, 13.2813f, 25.7813f, 5.4688f, -10.1563f, -67.9688f, -76.5625f, -55.4688f, -51.1719f, -39.8438f, -37.8906f, 70.3125f, 60.1563f, 11.3281f, 6.6406f, + 1.9531f, -10.5469f, -41.7969f, -76.9531f, -133.9844f, -130.0781f, -71.0938f, -55.8594f, -35.5469f, -6.6406f, 16.7969f, 46.8750f, 149.6094f, 104.2969f, 32.4219f, 15.6250f, + -0.3906f, -5.8594f, -13.6719f, -21.8750f, -66.0156f, -56.6406f, 33.5938f, 39.4531f, 30.0781f, 18.7500f, 11.3281f, 30.4688f, -3.5156f, 26.5625f, 5.8594f, 3.5156f, + 1.1719f, 3.5156f, 125.0000f, 175.7813f, 150.3906f, 135.9375f, 83.9844f, 60.5469f, 41.0156f, 17.5781f, -5.0781f, -29.2969f, -106.2500f, -50.3906f, -20.3125f, -8.9844f, + 1.5625f, 19.1406f, 21.0938f, 35.1563f, 35.9375f, 39.4531f, 23.0469f, 26.9531f, 7.8125f, 27.3438f, 8.9844f, 16.7969f, -109.3750f, -243.7500f, -44.5313f, -21.4844f +}; +/* An 16-by-8 matrix */ +const float GESVNB_AR2[128] = +{ + -8.5938f, -13.6719f, -12.1094f, -64.8438f, -64.0625f, 84.7656f, 82.8125f, 60.5469f, 64.8438f, 48.0469f, 26.1719f, 12.8906f, -8.2031f, -16.0156f, -1.1719f, -0.3906f, + -5.4688f, -7.8125f, -6.2500f, -27.3438f, -30.0781f, -20.7031f, 8.9844f, -2.7344f, -38.2813f, -48.0469f, -38.6719f, -19.1406f, 139.4531f, 44.5313f, 14.0625f, 7.4219f, + -22.2656f, -46.4844f, -118.3594f, -83.9844f, -12.8906f, -40.2344f, -37.8906f, -45.7031f, -41.0156f, -39.8438f, -26.1719f, -52.3438f, -68.7500f, 44.1406f, 6.2500f, 3.1250f, + -4.6875f, 5.4688f, 11.7188f, -14.4531f, -43.7500f, -88.2813f, -80.4688f, -9.7656f, 48.8281f, 52.3438f, 38.6719f, 32.4219f, 21.4844f, -1.5625f, 3.5156f, 1.5625f, + -7.4219f, 8.9844f, 66.7969f, 22.2656f, 5.0781f, -5.8594f, -10.1563f, -16.4063f, -25.3906f, -26.9531f, -30.0781f, -66.0156f, -137.1094f, -41.0156f, -19.1406f, -8.2031f, + -5.4688f, -3.9063f, 3.1250f, 13.6719f, 62.8906f, 40.6250f, -28.9063f, -39.8438f, -52.7344f, -18.3594f, 17.5781f, 103.1250f, 20.3125f, -26.9531f, -0.3906f, -1.9531f, + 83.2031f, 110.9375f, 89.8438f, 47.2656f, 19.5313f, 4.6875f, 16.7969f, 18.7500f, 10.5469f, -2.7344f, -9.3750f, -15.2344f, 29.2969f, 0.3906f, -3.5156f, -1.1719f, + -29.2969f, -53.5156f, -34.7656f, 107.4219f, 64.0625f, 25.3906f, 48.8281f, 35.5469f, 33.5938f, 35.5469f, 21.8750f, 3.9063f, 3.5156f, -3.9063f, 0.0000f, 0.0000f +}; +/* An 16-by-8 matrix */ +const float GESVWB_AR1[128] = +{ + -1.1719f, -6.2500f, -12.1094f, 0.7813f, -31.6406f, -48.0469f, -88.2813f, -101.5625f, -76.5625f, -47.6563f, -7.8125f, 30.4688f, 69.5313f, 56.6406f, 32.8125f, 17.9688f, + 21.4844f, 16.4063f, 5.8594f, 12.5000f, -18.7500f, -31.6406f, -42.5781f, -53.5156f, -73.0469f, -103.1250f, -128.9063f, -151.1719f, -141.7969f, -68.7500f, -14.8438f, 14.4531f, + -12.5000f, -27.3438f, -56.2500f, -105.0781f, -131.6406f, -71.4844f, 23.0469f, 22.6563f, 17.1875f, 19.1406f, 16.4063f, 19.9219f, 28.1250f, 19.5313f, 10.1563f, 14.8438f, + -7.0313f, -22.6563f, -30.8594f, 48.8281f, 137.5000f, 113.6719f, 70.3125f, 46.0938f, 28.1250f, 9.7656f, -8.9844f, -32.0313f, -72.2656f, -65.2344f, -12.8906f, 2.3438f, + -3.9063f, 52.7344f, 212.5000f, 201.9531f, 201.9531f, 219.1406f, 201.1719f, 206.2500f, 195.3125f, 184.3750f, 161.3281f, 149.6094f, 124.2188f, 85.5469f, 46.0938f, 22.2656f, + -21.0938f, -109.3750f, -239.8438f, -214.0625f, -203.5156f, -203.9063f, -175.0000f, -187.1094f, -178.5156f, -171.0938f, -147.2656f, -138.6719f, -124.2188f, -105.8594f, -86.7188f, -34.7656f, + -24.2188f, -37.5000f, -33.5938f, -3.9063f, 40.6250f, 60.5469f, 46.8750f, 43.7500f, 74.2188f, 103.1250f, 113.6719f, 106.2500f, 90.6250f, 64.8438f, 37.1094f, 10.5469f, + 12.8906f, 23.8281f, 60.5469f, 47.2656f, 3.5156f, -10.9375f, 2.3438f, 40.2344f, 25.0000f, 6.6406f, 1.5625f, -0.7813f, -12.1094f, -34.3750f, -81.6406f, -80.4688f +}; +/* An 16-by-8 matrix */ +const float GESVWB_AR2[128] = +{ + -57.4219f, -127.3438f, -164.4531f, -35.5469f, -8.5938f, -9.7656f, -5.4688f, -8.2031f, 12.5000f, 29.6875f, 40.6250f, 39.8438f, 25.3906f, 18.3594f, 19.5313f, 16.0156f, + -15.2344f, -6.2500f, 23.8281f, -5.0781f, -14.8438f, -21.8750f, 18.3594f, 59.7656f, 76.1719f, 83.2031f, 82.8125f, 85.9375f, 95.7031f, 95.7031f, 81.6406f, 33.5938f, + -13.2813f, -28.5156f, 32.0313f, 151.1719f, 77.7344f, 27.7344f, 21.8750f, -7.0313f, -12.8906f, -21.8750f, -34.3750f, -30.8594f, -1.9531f, 23.0469f, 21.4844f, 11.3281f, + -2.7344f, -8.2031f, -8.2031f, -61.7188f, -48.0469f, 118.7500f, 88.2813f, 65.6250f, 48.4375f, 3.1250f, -29.2969f, -35.5469f, -21.0938f, -1.9531f, 14.4531f, 11.7188f, + -10.1563f, -8.5938f, -26.1719f, -87.8906f, 41.7969f, 14.8438f, -32.0313f, -44.1406f, -83.2031f, -80.0781f, -24.2188f, 10.9375f, 34.7656f, 37.1094f, 20.3125f, 6.6406f, + 88.6719f, 157.8125f, 126.9531f, 52.3438f, 17.5781f, -6.2500f, 1.1719f, -5.8594f, -21.4844f, -25.3906f, -21.4844f, -21.0938f, -7.0313f, -3.1250f, 0.3906f, -5.4688f, + 7.4219f, 11.7188f, 4.6875f, 10.9375f, 18.7500f, 5.0781f, 0.7813f, -18.3594f, -14.8438f, 16.0156f, 11.3281f, -3.1250f, -60.1563f, -123.0469f, -160.5469f, -94.5313f, + 3.1250f, 9.3750f, 11.3281f, -23.8281f, -83.9844f, -128.5156f, -92.5781f, -41.4063f, -4.6875f, -4.6875f, -25.0000f, -46.0938f, -65.2344f, -46.4844f, 3.1250f, 20.3125f +}; +/* An 16-by-32 matrix */ +const float AUWB2_MA1[512] = +{ + 152.7344f, 116.4063f, 69.9219f, -14.4531f, -87.8906f, -151.1719f, -244.9219f, -337.5000f, -475.0000f, -642.1875f, -823.4375f, -314.0625f, -108.2031f, -1.9531f, 47.2656f, 182.8125f, + 137.1094f, 83.2031f, 55.0781f, -29.2969f, -50.7813f, -64.0625f, -129.6875f, -160.1563f, -204.6875f, -223.8281f, -224.6094f, -185.1563f, -129.2969f, -40.2344f, -8.5938f, 78.5156f, + 31.6406f, 341.4063f, 444.1406f, 477.7344f, 485.1563f, 492.9688f, 483.5938f, 462.8906f, 445.7031f, 423.8281f, 387.8906f, 286.3281f, 222.6563f, 165.6250f, 100.0000f, 56.6406f, + -2.3438f, -9.7656f, -41.0156f, -57.4219f, -127.7344f, -133.5938f, -229.2969f, -242.1875f, -372.6563f, -446.4844f, -733.5938f, -804.2969f, -139.0625f, -39.0625f, 52.3438f, 186.3281f, + -76.9531f, -197.2656f, -322.6563f, -407.4219f, -337.1094f, -189.4531f, -115.6250f, -40.2344f, -2.3438f, 69.5313f, 105.0781f, 95.7031f, 90.2344f, 125.0000f, 94.9219f, 161.3281f, + -202.3438f, -236.3281f, 110.1563f, 167.9688f, 207.8125f, 232.8125f, 264.0625f, 292.1875f, 315.6250f, 336.3281f, 325.7813f, 266.0156f, 208.5938f, 194.5313f, 114.4531f, 131.6406f, + -95.3125f, -219.9219f, -281.2500f, -233.9844f, -195.3125f, -192.9688f, -244.9219f, -288.6719f, -401.5625f, -476.1719f, -116.0156f, 3.5156f, 27.7344f, 106.2500f, 111.3281f, 219.9219f, + -175.0000f, -333.5938f, -357.8125f, -202.3438f, -112.1094f, -20.3125f, 21.8750f, 95.7031f, 135.5469f, 204.6875f, 217.5781f, 194.1406f, 162.5000f, 176.5625f, 125.3906f, 170.7031f, + 58.5938f, 44.1406f, 10.9375f, -10.1563f, 0.3906f, -31.2500f, -69.1406f, -88.2813f, -75.3906f, -60.9375f, -24.2188f, -88.6719f, -93.7500f, -149.6094f, -208.9844f, -316.0156f, + -93.7500f, -96.0938f, -67.9688f, -25.7813f, 31.2500f, 58.2031f, 95.3125f, 110.9375f, 161.3281f, 169.5313f, 184.7656f, 61.7188f, 21.8750f, -65.2344f, -127.3438f, -282.4219f, + 51.1719f, -4.2969f, 55.0781f, 12.5000f, 9.3750f, -47.6563f, -155.0781f, -238.2813f, -346.8750f, -317.1875f, 11.7188f, 90.6250f, 119.5313f, 144.9219f, 133.2031f, 174.2188f, + -61.7188f, -212.8906f, -206.6406f, 58.9844f, 55.4688f, -39.4531f, -166.4063f, -279.6875f, -402.7344f, -577.7344f, -605.4688f, -137.5000f, -51.5625f, 56.6406f, 73.0469f, 201.9531f, + 57.8125f, -40.6250f, -173.8281f, -328.5156f, -12.1094f, 71.4844f, -33.5938f, -123.4375f, -240.2344f, -257.8125f, -90.2344f, 32.8125f, 75.0000f, 107.4219f, 78.5156f, 121.4844f, + -71.4844f, -85.9375f, -94.9219f, -71.0938f, -92.5781f, -68.7500f, -103.9063f, -91.0156f, -131.2500f, -132.4219f, -253.9063f, -398.0469f, -645.3125f, -330.4688f, -20.3125f, 151.1719f, + -40.6250f, -45.7031f, -99.2188f, -129.6875f, -74.6094f, 0.3906f, 25.0000f, 71.0938f, 123.8281f, 193.3594f, 244.5313f, 224.2188f, 202.7344f, 198.4375f, 178.1250f, 197.2656f, + -58.9844f, -92.5781f, 192.1875f, 187.1094f, 106.6406f, 54.2969f, 14.0625f, -23.4375f, -46.4844f, 28.9063f, 67.9688f, 73.4375f, 116.4063f, 142.9688f, 135.5469f, 186.7188f, + 61.7188f, 8.9844f, -82.0313f, -175.7813f, -262.8906f, -248.8281f, -165.2344f, -129.2969f, -51.9531f, 5.4688f, 50.0000f, 26.9531f, 24.2188f, 55.8594f, 66.7969f, 122.2656f, + 195.7031f, 153.9063f, 14.4531f, -22.2656f, 26.1719f, 27.3438f, 17.9688f, 13.6719f, 35.9375f, 46.8750f, 131.6406f, 100.7813f, 107.8125f, 110.5469f, 143.7500f, 195.3125f, + 16.4063f, -61.3281f, -155.4688f, -234.3750f, -289.8438f, -304.6875f, -305.0781f, -382.8125f, -455.4688f, -636.3281f, -378.1250f, -58.2031f, -38.6719f, 73.4375f, 81.6406f, 206.6406f, + -93.7500f, 74.2188f, 181.6406f, 212.1094f, 224.6094f, 220.7031f, 236.3281f, 232.8125f, 255.0781f, 233.9844f, 227.7344f, 108.9844f, 79.2969f, -19.9219f, -72.6563f, -230.0781f, + 123.4375f, 144.9219f, 162.8906f, 145.3125f, 114.4531f, 73.8281f, 89.8438f, 60.1563f, 71.8750f, 35.5469f, 36.7188f, -68.3594f, -77.3438f, -139.8438f, -177.3438f, -287.5000f, + 28.1250f, -62.1094f, -141.4063f, -194.9219f, -247.2656f, -269.5313f, -310.1563f, -288.6719f, -258.5938f, -178.1250f, -140.6250f, -132.0313f, -98.0469f, -2.3438f, 19.5313f, 135.1563f, + -78.9063f, -129.6875f, -167.1875f, -180.4688f, -198.4375f, -171.8750f, -215.6250f, -252.7344f, -345.7031f, -475.3906f, -676.9531f, -241.7969f, -63.2813f, 37.1094f, 78.9063f, 199.2188f, + -35.5469f, -152.7344f, -276.9531f, -345.3125f, -395.3125f, -391.0156f, -365.6250f, -278.9063f, -198.8281f, -77.3438f, 16.4063f, 38.6719f, 46.4844f, 101.9531f, 92.9688f, 193.7500f, + -144.5313f, 35.9375f, 185.9375f, 235.9375f, 266.0156f, 297.6563f, 322.6563f, 348.8281f, 364.8438f, 391.0156f, 372.6563f, 305.8594f, 245.7031f, 230.4688f, 160.9375f, 182.4219f, + -75.3906f, -8.5938f, -10.9375f, 17.9688f, 83.5938f, 151.1719f, 196.0938f, 251.1719f, 284.3750f, 337.5000f, 335.5469f, 282.4219f, 226.9531f, 222.2656f, 169.9219f, 188.6719f, + 87.1094f, 113.6719f, 247.2656f, 198.4375f, 136.7188f, 55.0781f, -60.9375f, -185.9375f, -363.2813f, -553.5156f, -706.6406f, -298.4375f, -80.4688f, 30.0781f, 74.6094f, 201.1719f, + -185.5469f, -308.9844f, -162.8906f, 29.2969f, 78.5156f, 133.9844f, 159.3750f, 214.4531f, 239.0625f, 276.1719f, 267.9688f, 223.4375f, 180.8594f, 178.5156f, 125.3906f, 145.7031f, + 328.9063f, 279.6875f, 261.3281f, 231.6406f, 163.6719f, 165.2344f, 145.7031f, 125.3906f, 106.6406f, 109.3750f, 138.2813f, 84.7656f, 75.3906f, 90.6250f, 68.3594f, 114.8438f, + 45.3125f, -23.4375f, -56.2500f, -116.7969f, -164.4531f, -215.2344f, -285.9375f, -371.8750f, -469.9219f, -649.2188f, -779.6875f, -209.7656f, -93.7500f, 21.4844f, 53.9063f, 189.8438f, + -126.1719f, -259.7656f, -267.9688f, -83.5938f, -78.5156f, -101.5625f, -145.7031f, -128.5156f, -130.0781f, -64.4531f, 25.7813f, 37.5000f, 68.3594f, 121.0938f, 113.6719f, 189.8438f, + -7.4219f, 16.7969f, 13.6719f, 15.6250f, 16.4063f, 21.4844f, 24.6094f, 39.4531f, 51.9531f, 75.7813f, 86.7188f, 59.3750f, 45.7031f, 56.6406f, 51.9531f, 83.2031f +}; + +/*----------------------------------------------------------------------------------* + * LSF quantization - LSF mode/codebook selection tables + *----------------------------------------------------------------------------------*/ +const short CB_lsf[] = +{ + -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 short CB_p_lsf[] = +{ + 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 float *const ModeMeans[] = {IANB_Ave, UVNB_Ave, SVNB_Ave, GENB_Ave, TRNB_Ave, AUNB_Ave, IAWB_Ave, UVWB_Ave, + SVWB_Ave, GEWB_Ave, TRWB_Ave, AUWB_Ave, IAWB2_Ave, NULL, SVWB2_Ave, GEWB2_Ave, TRWB2_Ave, AUWB2_Ave + }; +const float * const Predictors[] = {Predictor6, NULL, Predictor1, Predictor3, NULL, Predictor6,Predictor5, NULL, Predictor0, + Predictor2, NULL, Predictor5, Predictor7, NULL, Predictor8, Predictor4, NULL, Predictor7 + }; +const float means_nb_31bits_ma_lsf[16] = {336.3281f , 531.2500f , 886.7188f , 1266.7969f , 1629.2969f , 1973.4375f , 2348.4375f , 2646.8750f , 2998.4375f , 3292.1875f , 3591.4062f , 3806.2500f , 4132.8125f , 4652.7344f , 5250.0000f , 5883.2031f}; +const float means_wb_31bits_ma_lsf[16] = {319.5312f , 548.0469f , 934.3750f , 1353.5156f , 1730.0781f , 2120.3125f , 2505.4688f , 2860.5469f , 3243.7500f , 3601.9531f , 3969.5312f , 4332.4219f , 4736.3281f , 5137.8906f , 5562.8906f , 5963.2812f}; + + +const short CBsizes[] = +{ + 1,2,4,8,16,32,64 +}; + + +const short CBbits[] = +{ + -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 short CBbits_p[] = +{ + 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 short BitsVQ[]= +{ + -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 short BitsVQ_p[]= +{ + 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 short 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,1} /* should check how is the cb for audio mode at 13.2*/ +}; + +const float *const Quantizers[] = {SVNB_SN1, SVNB_SN2, GETRNB_SN1, GETRNB_SN2, AUNB_SN1,SVWB_SN1, SVWB_SN2, GETRWB_SN1, + GETRWB_SN2, AUWB_SN1,TRWB2_SN1, TRWB2_SN2, AUWB2_SN1, CNG_SN1 + }; +const float *const Quantizers_p[] = {IAA_MA1, UVD_MA1, UVD_MA2, UVWB_MA3, GESVNB_AR1, GESVNB_AR2, GESVWB_AR1, GESVWB_AR2, + GEWB2_MA1,GEWB_MA1, AUWB2_MA1 + }; + +const float vals[NO_LEADERS][MAX_NO_VALS]= +{ + {1.0f, 0.0f, 0.0f, 0.0f}, + {0.5f, 0.0f, 0.0f, 0.0f}, + {1.0f, 0.0f, 0.0f, 0.0f}, + {2.0f, 0.0f, 0.0f, 0.0f}, + {1.5f, 0.5f, 0.0f, 0.0f}, + {1.0f, 0.0f, 0.0f, 0.0f}, + {2.0f, 1.0f, 0.0f, 0.0f}, + {1.5f, 0.5f, 0.0f, 0.0f}, + {1.0f, 0.0f, 0.0f, 0.0f}, + {2.0f, 1.0f, 0.0f, 0.0f}, + {2.0f, 0.0f, 0.0f, 0.0f}, + {1.5f, 0.5f, 0.0f, 0.0f}, + {2.5f, 0.5f, 0.0f, 0.0f}, + {2.0f, 1.0f, 0.0f, 0.0f}, + {2.0f, 1.0f, 0.0f, 0.0f}, + {3.0f, 1.0f, 0.0f, 0.0f}, + {1.5f, 0.5f, 0.0f, 0.0f}, + {2.5f, 1.5f, 0.5f, 0.0f}, + {2.0f, 1.0f, 0.0f, 0.0f}, + {2.0f, 0.0f, 0.0f, 0.0f}, + {3.0f, 1.0f, 0.0f, 0.0f}, + {1.5f, 0.5f, 0.0f, 0.0f}, + {2.5f, 1.5f, 0.5f, 0.0f}, + {2.0f, 1.0f, 0.0f, 0.0f}, + {2.0f, 1.0f, 0.0f, 0.0f}, + {3.0f, 1.0f, 0.0f, 0.0f}, + {3.0f, 2.0f, 1.0f, 0.0f}, + {1.5f, 0.5f, 0.0f, 0.0f}, + {2.5f, 1.5f, 0.5f, 0.0f}, + {2.5f, 0.5f, 0.0f, 0.0f}, + {3.5f, 0.5f, 0.0f, 0.0f}, + {2.0f, 1.0f, 0.0f, 0.0f}, + {2.0f, 0.0f, 0.0f, 0.0f}, + {3.0f, 1.0f, 0.0f, 0.0f}, + {3.0f, 2.0f, 1.0f, 0.0f}, + {4.0f, 0.0f, 0.0f, 0.0f}, + {1.5f, 0.5f, 0.0f, 0.0f}, + {2.5f, 1.5f, 0.5f, 0.0f}, + {2.5f, 1.5f, 0.5f, 0.0f}, + {3.5f, 1.5f, 0.5f, 0.0f}, + {2.0f, 1.0f, 0.0f, 0.0f}, + {3.0f, 2.0f, 1.0f, 0.0f}, + {3.0f, 2.0f, 1.0f, 0.0f}, + {3.0f, 0.0f, 0.0f, 0.0f}, + {4.0f, 1.0f, 0.0f, 0.0f}, + {1.5f, 0.0f, 0.0f, 0.0f}, + {2.5f, 1.5f, 0.5f, 0.0f}, + {2.5f, 1.5f, 0.5f, 0.0f}, + {3.5f, 1.5f, 0.5f, 0.0f} +}; + +const int no_vals[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 int no_vals_ind[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 int C_VQ[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 unsigned int table_no_cv[] = { 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 + }; + +const int pi0[] = {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 float pl_HQ[] = /* vectors in first layers */ +{ + 1, 1, 0, 0, 0, 0, 0, 0, /* 112, 4, 28 */ + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, /* 128, 128, 1 */ + 1, 1, 1, 1, 0, 0, 0, 0, /* 1120, 16, 70 */ + 2, 0, 0, 0, 0, 0, 0, 0, /* 16 , 2, 8 */ + 1.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, /* 5 */ /* 1024,128, 8 */ + 1, 1, 1, 1, 1, 1, 0, 0, /* 1792, 64, 28 */ + 2, 1, 1, 0, 0, 0, 0, 0, /* 1344, 8, 168 */ + 1.5, 1.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, /* 3584, 128, 28*/ + 1, 1, 1, 1, 1, 1, 1, 1, /*256, 256, 1*/ + 2, 1, 1, 1, 1, 0, 0, 0, /* 10 */ /* 8960, 32, 280 */ + 2, 2, 0, 0, 0, 0, 0, 0, /* 112, 4, 28 */ + 1.5, 1.5, 1.5, 0.5, 0.5, 0.5, 0.5, 0.5, /* 7168, 128, 56 */ + 2.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, /* 1024, 128, 8*/ + 2, 1, 1, 1, 1, 1, 1, 0, /* 7168, 128, 56*/ + 2, 2, 1, 1, 0, 0, 0, 0, /* 15 */ /* 6720, 16, 420 */ + 3, 1, 0, 0, 0, 0, 0, 0, /* 224, 4, 56 */ + 1.5, 1.5, 1.5, 1.5, 0.5, 0.5, 0.5, 0.5, /* 8960, 128, 70 */ + 2.5, 1.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, /* 7168, 128, 56*/ + 2.0, 2.0, 1.0, 1.0, 1.0, 1.0, 0, 0, /* 26880, 64, 420 */ + 2, 2, 2, 0, 0, 0, 0, 0, /*20 */ /* 448, 8, 56 */ + 3, 1, 1, 1, 0, 0, 0, 0, /* 4480, 16, 280 */ + 1.5, 1.5, 1.5, 1.5, 1.5, 0.5, 0.5, 0.5, /* 7168, 128, 56 */ + 2.5, 1.5, 1.5, 0.5, 0.5, 0.5, 0.5, 0.5, /* 21504, 128, 168 */ + 2.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, /* 7168, 256, 28 */ + 2.0, 2.0, 2.0, 1.0, 1.0, 0, 0, 0, /* 25 */ /* 17920, 32, 560 */ + 3.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0, 0, /* 10752, 64, 168 */ + 3.0, 2.0, 1.0, 0, 0, 0, 0, 0, /* 2688, 8, 336 */ + 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 0.5, 0.5, /* 3584, 128, 28 */ + 2.5, 1.5, 1.5, 1.5, 0.5, 0.5, 0.5, 0.5, /* 35840,128,280*/ + 2.5, 2.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, /*30 */ /* 3584, 128, 28*/ + 3.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, /* 1024,128, 8 */ + 2.0, 2.0, 2.0, 1.0, 1.0, 1.0, 1.0, 0, + 2.0f, 2.0f, 2.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 3.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, + 3.0f, 2.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, + 4.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 0.5f, + 2.5f, 1.5f, 1.5f, 1.5f, 1.5f, 0.5f, 0.5f, 0.5f, + 2.5f, 2.5f, 1.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, + 3.5f, 1.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, + 2.0f, 2.0f, 2.0f, 2.0f, 1.0f, 1.0f, 0.0f, 0.0f, + 3.0f, 2.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, + 3.0f, 2.0f, 2.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 3.0f, 3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 4.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, + 2.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 0.5f, 0.5f, + 2.5f, 2.5f, 1.5f, 1.5f, 0.5f, 0.5f, 0.5f, 0.5f, + 3.5f, 1.5f, 1.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f +}; + +/*----------------------------------------------------------------------------------* + * LSF quantization for CNG + *----------------------------------------------------------------------------------*/ + +const short cng_sort[] = {/*5f */1,1,0,1,0,0, /* 4f */0,1,0,1,0,0,1,1,1,1}; + +const short perm_MSLVQ[][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} +}; + +const int pl_par[] = /* 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 float scales[][MAX_NO_SCALES*2]= /* 2 subvectors */ +{ + {1.528f, 0.000f, 0.000f, 1.532f, 0.000f, 0.000f, }, /* 14 */ + {1.605f, 0.000f, 0.000f, 1.532f, 0.000f, 0.000f, }, /* 15 */ + {1.275f, 2.458f, 0.000f, 1.532f, 0.000f, 0.000f, }, /* 18 */ + {1.275f, 2.458f, 0.000f, 1.631f, 0.000f, 0.000f, }, /* 19 */ + {1.057f, 1.794f, 2.896f, 1.154f, 1.860f, 3.067f, }, /* 25 */ + {0.927f, 1.458f, 2.317f, 1.033f, 1.791f, 3.440f, }, /* 28*/ /* mode 0 UV WB*/ + {1.284f, 2.676f, 0.000f, 1.451f, 0.000f, 0.000f, }, + {1.368f, 0.000f, 0.000f, 1.401f, 2.477f, 0.000f, }, /* 19 */ + {0.861f, 1.243f, 1.818f, 1.228f, 2.226f, 10.307f, }, /* 24 */ + {1.072f, 1.934f, 3.633f, 1.221f, 2.938f, 10.723f, }, /* 25 */ + {0.899f, 1.417f, 0.677f, 1.033f, 1.837f, 10.893f, }, /* 29 */ + {0.830f, 1.323f, 0.629f, 0.911f, 1.585f, 10.088f, }, /* 32 */ /* mode 1 UV NB*/ + {1.573f, 0.000f, 0.000f, 1.656f, 0.000f, 0.000f, }, /* 17 */ + {1.239f, 2.404f, 0.000f, 1.556f, 0.000f, 0.000f, }, /* 18 */ + {1.055f, 1.700f, 4.439f, 1.656f, 0.000f, 0.000f, }, /* 21 */ + {1.250f, 2.404f, 4.132f, 1.355f, 2.361f, 0.000f, }, /* 22 */ + {1.056f, 1.785f, 4.523f, 1.318f, 2.586f, 0.000f, }, /* 25 */ + {0.996f, 1.505f, 3.355f, 1.185f, 1.776f, 2.728f, }, + {0.929f, 1.387f, 3.357f, 1.080f, 1.701f, 2.885f, }, + {0.922f, 1.493f, 3.369f, 1.080f, 1.701f, 2.885f, }, + {0.922f, 1.493f, 3.369f, 1.066f, 1.694f, 3.135f, }, + {0.922f, 1.493f, 3.369f, 0.962f, 1.550f, 3.946f, }, /* 30 */ + {0.746f, 1.108f, 2.869f, 0.959f, 1.481f, 3.907f, }, /* 32 */ + {0.770f, 1.194f, 2.823f, 0.907f, 1.402f, 2.116f, }, + {0.748f, 1.103f, 2.866f, 1.182f, 0.811f, 3.332f, },/* 34*/ + {0.677f, 0.963f, 2.127f, 0.726f, 1.082f, 2.204f, }, /* 37*/ /* mode 2 V WB*/ + {1.639f, 0.000f, 0.000f, 1.218f, 2.161f, 0.000f, }, /* 17 */ + {1.286f, 2.446f, 0.000f, 1.410f, 0.000f, 0.000f, }, /* 18 */ + {1.086f, 1.728f, 3.758f, 1.218f, 2.161f, 0.000f, }, /* 22 */ + {1.035f, 1.575f, 4.815f, 1.218f, 2.161f, 0.000f, }, /* 23 */ + {0.964f, 1.533f, 4.942f, 1.218f, 2.161f, 0.000f, }, /* 24 */ + {0.841f, 1.198f, 1.982f, 1.218f, 2.161f, 0.000f, }, /* 25 */ + {0.898f, 1.298f, 2.184f, 1.216f, 2.664f, 0.000f, }, /* 27 */ + {0.841f, 1.237f, 2.237f, 0.995f, 1.657f, 2.836f, }, /* 29 */ + {0.697f, 0.981f, 2.043f, 0.935f, 1.505f, 0.659f, }, /* 34 */ + {0.669f, 0.909f, 1.328f, 0.985f, 0.654f, 1.911f, }, /* 37 */ /* mode 3 V NB*/ + {1.212f, 1.897f, 0.000f, 0.000f, 0.000f, 0.000f, }, /* 12 (11.883) */ + {1.634f, 0.000f, 0.000f, 1.669f, 0.000f, 0.000f, }, /* 16 (15.826) */ + {1.288f, 2.423f, 0.000f, 1.669f, 0.000f, 0.000f, }, /* 19 (18.572) */ + {1.212f, 1.897f, 0.000f, 1.669f, 0.000f, 0.000f, }, /* 20 (19.796) */ + {1.083f, 1.766f, 3.175f, 1.669f, 0.000f, 0.000f, }, /* 21 (20.910) */ + {1.037f, 1.609f, 4.228f, 1.669f, 0.000f, 0.000f, }, /* 22 (21.776) */ + {1.095f, 1.659f, 2.716f, 1.315f, 2.506f, 0.000f, }, /* 23 (22.959) */ + {0.941f, 1.386f, 2.221f, 1.315f, 2.506f, 0.000f, }, /* 25 (24.992) */ + {0.908f, 1.306f, 1.901f, 1.320f, 2.623f, 0.000f, }, /* 26 (25.904) */ + {1.075f, 1.767f, 0.790f, 1.320f, 2.623f, 0.000f, }, /* 27 (26.829) */ + {1.022f, 1.531f, 0.759f, 1.110f, 1.755f, 2.594f, }, /* 28 (27.989) */ + {1.075f, 1.767f, 0.790f, 1.093f, 1.902f, 3.014f, }, /* 29 (28.984) */ + {0.893f, 1.472f, 0.675f, 1.103f, 1.770f, 2.842f, }, /* 30 (29.980) */ + {0.910f, 1.548f, 0.685f, 1.032f, 1.651f, 2.513f, }, /* 31 (30.966) */ + {0.826f, 1.256f, 0.632f, 0.981f, 1.542f, 2.217f, }, /* 32 (31.995) */ /* G WB*/ + {1.184f, 1.810f, 2.761f, 0.000f, 0.000f, 0.000f, }, /* 12 (11.925) */ + {1.611f, 0.000f, 0.000f, 1.618f, 0.000f, 0.000f, }, /* 16 (15.826) */ + {1.184f, 1.810f, 2.761f, 1.550f, 0.000f, 0.000f, }, /* 19 (18.745) */ + {1.184f, 1.810f, 2.761f, 1.618f, 0.000f, 0.000f, }, /* 20 (19.838) */ + {1.063f, 1.737f, 2.985f, 1.618f, 0.000f, 0.000f, }, /* 21 (20.910) */ + {1.078f, 1.825f, 3.162f, 1.469f, 2.249f, 0.000f, }, /* 22 (21.985) */ + {1.375f, 0.915f, 2.082f, 1.469f, 2.249f, 0.000f, }, /* 23 (22.815) */ + {0.960f, 1.423f, 0.700f, 1.310f, 2.132f, 0.000f, }, /* 25 (24.996) */ + {1.124f, 0.794f, 1.902f, 1.283f, 2.302f, 0.000f, }, /* 26 (25.993) */ + {1.077f, 1.727f, 0.767f, 1.250f, 1.951f, 2.981f, }, /* 27 (26.954) */ + {0.933f, 1.471f, 0.685f, 1.250f, 1.951f, 2.981f, }, /* 28 (27.992) */ + {0.927f, 1.600f, 0.674f, 1.154f, 1.776f, 2.854f, }, /* 29 (28.996) */ + {1.047f, 0.722f, 1.785f, 1.056f, 1.642f, 2.701f, }, /* 30 (29.988) */ + {0.971f, 0.688f, 1.509f, 1.043f, 1.730f, 2.931f, }, /* 31 (30.962) */ + {0.919f, 0.662f, 1.367f, 1.057f, 1.808f, 3.069f, }, /* 32 (31.987) */ /* G NB*/ + + {1.617f, 0.000f, 0.000f, 1.657f, 0.000f, 0.000f, }, /* 17 */ + {1.275f, 2.298f, 0.000f, 1.563f, 0.000f, 0.000f, }, /* 18 */ + {1.308f, 2.354f, 0.000f, 1.387f, 0.000f, 0.000f, }, /* 21 */ + {1.291f, 2.418f, 0.000f, 1.355f, 2.443f, 0.000f, }, /* 22 */ + {1.079f, 1.769f, 3.012f, 1.387f, 0.000f, 0.000f, }, /* 24 */ + {1.079f, 1.769f, 3.012f, 1.325f, 2.555f, 0.000f, }, /* 25 */ + {0.897f, 1.340f, 2.604f, 1.070f, 1.689f, 2.527f, }, /* 28 */ + {0.897f, 1.340f, 2.604f, 0.939f, 1.454f, 2.083f, }, /* 30 */ + {0.905f, 1.327f, 2.599f, 1.109f, 0.777f, 1.705f, }, + {0.762f, 1.101f, 2.359f, 0.939f, 1.454f, 2.083f, }, + {0.794f, 1.226f, 3.180f, 1.109f, 0.777f, 1.705f, }, /* 33 */ /* mode 6 T WB */ + {1.629f, 0.000f, 0.000f, 1.191f, 2.211f, 0.000f, }, /* 17 */ + {1.277f, 2.557f, 0.000f, 1.367f, 0.000f, 0.000f, }, /* 18 */ + {1.082f, 1.761f, 3.929f, 1.191f, 2.211f, 0.000f, }, /* 22 */ + {1.018f, 1.535f, 2.808f, 1.191f, 2.211f, 0.000f, }, /* 23 */ + {0.944f, 1.477f, 2.763f, 1.191f, 2.211f, 0.000f, }, /* 24 */ + {0.910f, 1.744f, 3.317f, 1.191f, 2.211f, 0.000f, }, /* 25 */ + {0.920f, 1.648f, 3.068f, 0.969f, 1.683f, 3.953f, }, /* 28 */ + {0.739f, 1.111f, 2.694f, 0.879f, 1.411f, 2.305f, }, /* 31 */ + {0.709f, 1.032f, 2.717f, 0.810f, 1.245f, 1.824f, }, /* 32*/ /* mode 7 T NB*/ + {0.758f, 1.116f, 1.964f, 2.021f, 0.798f, 1.219f, }, /* 31 */ + {0.699f, 1.034f, 1.978f, 2.021f, 0.798f, 1.219f, }, /* 32 */ /* mode 8 G 16k */ + {0.726f, 1.050f, 1.845f, 1.355f, 0.860f, 2.205f, }, /* 32 (31.998) */ + {0.677f, 0.997f, 1.669f, 1.355f, 0.860f, 2.205f, }, /* 33 (32.983) */ + {1.646f, 0.000f, 0.000f, 1.254f, 2.459f, 0.000f, }, /* 17 */ + {1.073f, 1.863f, 3.231f, 1.678f, 0.000f, 0.000f, }, /* 21 */ + {1.073f, 1.863f, 3.231f, 1.254f, 2.459f, 0.000f, }, /* 22 */ + {0.951f, 1.492f, 2.496f, 1.255f, 2.971f, 0.000f, }, /* 25 */ + {1.148f, 1.841f, 0.813f, 1.255f, 2.971f, 0.000f, }, /* 26 */ + {0.602f, 0.869f, 1.418f, 1.264f, 0.764f, 2.218f}, /* 36 */ /* mode 10 AUDIO_WB LVQ bitrate 15-36 + 4 + 1*/ + {0.853f, 1.769f, 4.425f, 1.000f, 1.000f, 1.000f}, /* 17 */ + {1.011f, 1.663f, 4.403f, 1.578f, 0.000f, 0.000f}, /* 21 */ + {1.011f, 1.663f, 4.403f, 1.202f, 2.424f, 0.000f}, /* 22 */ + {0.881f, 1.618f, 4.136f, 1.202f, 2.424f, 0.000f}, /* 25 */ + {0.847f, 1.791f, 4.466f, 1.202f, 2.424f, 0.000f}, /* 26 */ + {0.670f, 1.112f, 2.389f, 1.202f, 2.424f, 0.000f}, /* 28 */ /* mode 11 AUDIO_NB */ + {1.131f, 1.815f, 0.796f, 1.265f, 2.794f, 0.000f, }, /* 26 */ + {0.570f, 0.804f, 1.197f, 1.162f, 1.949f, 0.728f, }, /* 36*/ /* mode 12 AUDIO_WB 16k bitrate 15-36 + 4 + 1*/ + {1.045f, 1.586f, 3.754f, 1.669f, 0.000f, 0.000f, }, /* 22 (21.776) */ + {0.880f, 1.280f, 2.824f, 1.099f, 1.735f, 0.000f, }, /* 28 (27.994) */ + {0.831f, 1.215f, 2.927f, 1.089f, 1.708f, 2.479f, }, /* 29 (28.996) */ + {0.870f, 1.327f, 2.906f, 1.066f, 1.719f, 2.676f, }, /* 30 (29.991) */ + {0.772f, 1.122f, 2.351f, 1.446f, 0.944f, 2.072f, }, /* 32 (31.992) */ + {0.701f, 0.977f, 1.738f, 0.947f, 1.453f, 2.082f, }, /* 33 (32.993) */ + {0.719f, 1.021f, 1.701f, 1.119f, 0.794f, 1.696f, }, /* 34 (33.968) */ + {0.640f, 0.884f, 1.732f, 0.755f, 1.090f, 1.548f, }, /* 37 (36.995) */ /* VOICED 16k */ + /* 5sf */ + {1.218f, 0.796f, 2.283f, 1.290f, 3.325f, 0.000f, }, /* 25 (24.980) */ + {1.590f, 0.835f, 4.436f, 1.097f, 3.070f, 0.000f, }, /* 25 (24.974) */ + {0.994f, 2.617f, 0.000f, 1.091f, 2.233f, 3.457f, }, /* 25 (24.852) */ + {0.887f, 1.573f, 3.543f, 1.088f, 1.827f, 3.067f, }, /* 25 (24.994) */ + {0.837f, 1.238f, 1.903f, 1.298f, 2.797f, 0.000f, }, /* 25 (24.996) */ + {1.138f, 2.826f, 0.000f, 1.106f, 2.796f, 4.391f, }, /* 25 (24.671) */ + + /* 4sf */ + {0.941f, 1.931f, 4.473f, 0.681f, 1.266f, 2.328f, }, /* 25 (24.936) */ + {1.352f, 4.332f, 0.000f, 0.820f, 1.545f, 4.175f, }, /* 25 (24.955) */ + {1.343f, 3.607f, 0.000f, 0.859f, 1.453f, 2.590f, }, /* 25 (24.853) */ + {1.208f, 2.740f, 0.000f, 0.759f, 1.240f, 2.182f, }, /* 25 (24.881) */ + {1.123f, 2.736f, 0.000f, 0.874f, 1.498f, 2.586f, }, /* 25 (24.939) */ + {0.919f, 2.471f, 0.000f, 0.615f, 1.072f, 2.096f, }, /* 25 (24.996) */ + {1.548f, 4.508f, 0.000f, 0.825f, 2.178f, 4.305f, }, /* 25 (24.310) */ + {1.217f, 2.898f, 0.000f, 0.737f, 1.217f, 1.930f, }, /* 25 (24.955) */ + {0.976f, 2.190f, 5.716f, 1.506f, 0.642f, 4.211f, }, /* 25 (24.984) */ + {1.107f, 2.595f, 0.000f, 1.302f, 0.604f, 0.880f, }, /* 25 (24.866) */ +}; + +const float scales_p[][MAX_NO_SCALES*2]= /* 2 subvectors 20 modes */ +{ + {1.464f, 2.374f, 0.000f, 0.000f, 0.000f, 0.000f, }, /* 9 (8.464) */ + {1.265f, 2.564f, 0.000f, 1.638f, 0.000f, 0.000f, }, /* 19 (18.572) */ + {1.063f, 1.703f, 2.805f, 1.294f, 2.353f, 0.000f, }, /* 23 (22.959) */ + {1.063f, 1.917f, 3.063f, 1.365f, 0.000f, 0.000f, }, /* 24 (23.949) */ + {0.914f, 1.412f, 2.223f, 1.294f, 2.353f, 0.000f, }, /* 25 (24.992) */ + {0.882f, 1.401f, 2.402f, 1.313f, 2.441f, 0.000f, }, /* 27 (26.902) */ + {1.356f, 0.867f, 2.377f, 1.070f, 1.686f, 2.546f, }, /* 28 (27.996) */ + {0.846f, 1.348f, 2.546f, 1.076f, 1.742f, 2.658f, }, /* 29 (28.937) */ + {0.845f, 1.379f, 2.566f, 1.019f, 1.577f, 2.443f, }, /* 30 (29.954) */ + {0.756f, 1.189f, 2.799f, 1.084f, 1.804f, 2.758f, }, /* 31 (30.978) */ + {0.755f, 1.218f, 2.821f, 0.944f, 1.433f, 1.973f, }, /* 32 (31.978) */ + {0.724f, 1.235f, 2.942f, 1.255f, 0.848f, 2.000f, }, /* 34 (33.975) */ + {0.687f, 1.113f, 2.338f, 0.853f, 1.328f, 1.944f, }, /* 35 (34.975) */ + {0.648f, 1.029f, 1.836f, 0.854f, 1.356f, 1.961f, }, /* 36 (35.889) */ + {0.648f, 1.029f, 1.836f, 0.687f, 1.058f, 1.900f, }, /* 39 (38.488) */ /* V WB*/ + {1.613f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, }, /* 8 (7.913) */ + {1.267f, 2.475f, 0.000f, 1.619f, 0.000f, 0.000f, }, /* 19 (18.572) */ + {1.014f, 1.630f, 2.464f, 1.285f, 2.151f, 0.000f, }, /* 23 (22.773) */ + {0.893f, 1.390f, 2.314f, 1.465f, 2.299f, 0.000f, }, /* 24 (23.999) */ + {0.930f, 1.401f, 2.150f, 1.280f, 2.254f, 0.000f, }, /* 25 (24.992) */ + {0.893f, 1.390f, 2.314f, 1.276f, 2.206f, 2.984f, }, /* 27 (26.962) */ + {0.893f, 1.390f, 2.314f, 1.036f, 1.646f, 2.471f, }, /* 28 (27.835) */ + {0.857f, 1.337f, 2.464f, 1.043f, 1.730f, 2.625f, }, /* 29 (28.937) */ + {0.765f, 1.219f, 1.553f, 1.036f, 1.646f, 2.471f, }, /* 30 (29.969) */ + {0.789f, 1.328f, 1.652f, 1.052f, 1.784f, 2.706f, }, /* 31 (30.952) */ + {0.764f, 1.224f, 1.555f, 0.920f, 1.443f, 2.035f, }, /* 32 (31.978) */ + {0.663f, 1.061f, 1.238f, 1.379f, 0.898f, 1.951f, }, /* 34 (33.992) */ + {0.673f, 1.104f, 1.306f, 1.259f, 0.828f, 1.954f, }, /* 35 (35.000) */ + {0.666f, 1.071f, 1.249f, 0.803f, 1.241f, 1.729f, }, /* 36 (35.980) */ + {0.658f, 1.039f, 1.214f, 0.950f, 0.651f, 1.429f, }, /* 39 (38.512) */ /* V NB*/ + + {1.600f, 0.000f, 0.000f, 1.553f, 0.000f, 0.000f, }, /* 15 (14.733) */ + {1.134f, 1.986f, 3.295f, 1.553f, 0.000f, 0.000f, }, /* 19 (18.745) */ + {0.987f, 1.788f, 2.659f, 1.647f, 0.000f, 0.000f, }, /* 22 (21.776) */ + {0.899f, 1.602f, 2.579f, 1.647f, 0.000f, 0.000f, }, /* 23 (22.791) */ + {0.797f, 1.294f, 2.140f, 1.647f, 0.000f, 0.000f, }, /* 24 (23.999) */ + {0.797f, 1.294f, 2.140f, 1.335f, 2.225f, 0.000f, }, /* 25 (24.996) */ + {0.741f, 1.151f, 1.816f, 1.335f, 2.225f, 0.000f, }, /* 26 (25.934) */ + {0.797f, 1.294f, 2.140f, 1.186f, 1.932f, 0.000f, }, /* 28 (27.969) */ + {0.741f, 1.151f, 1.816f, 1.164f, 1.823f, 2.769f, }, /* 29 (28.996) */ + {0.708f, 1.126f, 1.953f, 1.076f, 1.730f, 2.777f, }, /* 30 (29.988) */ + {0.660f, 1.049f, 1.571f, 1.076f, 1.730f, 2.777f, }, /* 31 (30.931) */ + {0.662f, 1.026f, 1.554f, 1.074f, 1.913f, 3.022f, }, /* 32 (31.987) */ + {0.660f, 1.049f, 1.571f, 1.439f, 0.926f, 2.131f, }, /* 33 (32.982) */ + {0.630f, 0.966f, 1.522f, 1.312f, 0.881f, 2.207f, }, /* 34 (33.967) */ + {0.617f, 0.921f, 1.447f, 1.032f, 1.549f, 0.756f, }, /* 35 (34.994) */ /* G WB*/ + + {1.595f, 0.000f, 0.000f, 1.502f, 0.000f, 0.000f, }, /* 15 (14.733) */ + {1.123f, 1.946f, 3.732f, 1.502f, 0.000f, 0.000f, }, /* 19 (18.792) */ + {1.033f, 2.075f, 4.339f, 1.419f, 2.446f, 0.000f, }, /* 22 (21.985) */ + {0.985f, 1.793f, 5.965f, 1.281f, 2.324f, 0.000f, }, /* 23 (22.773) */ + {0.881f, 1.606f, 6.995f, 1.419f, 2.446f, 0.000f, }, /* 24 (23.932) */ + {0.844f, 1.582f, 7.020f, 1.281f, 2.324f, 0.000f, }, /* 25 (24.955) */ + {0.789f, 1.520f, 7.203f, 1.281f, 2.324f, 0.000f, }, /* 26 (25.991) */ + {0.869f, 1.547f, 6.995f, 1.030f, 1.754f, 3.102f, }, /* 28 (27.979) */ + {0.817f, 1.492f, 7.120f, 1.030f, 1.754f, 3.102f, }, /* 29 (28.878) */ + {0.755f, 1.382f, 7.133f, 1.030f, 1.754f, 3.102f, }, /* 30 (29.954) */ + {0.706f, 1.315f, 7.225f, 1.030f, 1.754f, 3.102f, }, /* 31 (30.893) */ + {0.689f, 1.296f, 7.290f, 1.016f, 1.875f, 3.239f, }, /* 32 (31.963) */ + {0.698f, 1.275f, 7.209f, 0.914f, 1.548f, 2.433f, }, /* 33 (32.997) */ + {0.679f, 1.315f, 7.290f, 1.229f, 1.845f, 0.813f, }, /* 34 (33.986) */ + {0.679f, 1.315f, 7.290f, 1.188f, 0.772f, 1.955f, }, /* 35 (34.952) */ /* G NB*/ + + + {1.011f, 1.777f, 2.760f, 1.614f, 0.000f, 0.000f, }, /* 21 */ + {0.853f, 1.382f, 2.066f, 1.245f, 2.679f, 0.000f, }, /* 25 */ + { 1.207f, 0.778f, 2.208f, 1.245f, 2.679f, 0.000f, }, /* 26 */ + { 1.207f, 0.778f, 2.208f, 1.013f, 1.832f, 3.053f, }, /* 29 */ + {1.207f, 0.778f, 2.208f, 1.420f, 0.872f, 2.330f, }, /* 30 */ + {0.525f, 0.770f, 1.073f, 0.815f, 1.237f, 0.567f,}, /* 40 */ /* mode 7 AUDIO_WB 19-40 + 0 + 1 */ + {1.070f, 1.791f, 3.903f, 1.599f, 0.000f, 0.000f}, /* 21 */ + {0.820f, 1.217f, 2.089f, 1.255f, 2.290f, 0.000f}, /* 25 */ + {0.780f, 1.169f, 2.495f, 1.255f, 2.290f, 0.000f}, /* 26 */ + {1.075f, 0.723f, 2.361f, 1.110f, 1.961f, 3.491f}, /* 30 */ + {0.691f, 1.029f, 2.337f, 1.034f, 1.791f, 4.004f}, /* 31 */ + {0.671f, 1.076f, 2.606f, 0.955f, 1.547f, 2.514f}, /* 32 */ /*mode 8 AUDIO_NB */ + {1.184f, 0.776f, 2.117f, 1.057f, 1.670f, 0.674f,}, /* 30 */ + {0.521f, 0.747f, 1.033f, 0.796f, 1.333f, 0.542f,}, /* 40 */ /* mode 9 AUDIO_WB 16k 19-40+ 0 + 1*/ + {1.679f, 0.000f, 0.000f, 1.282f, 2.471f, 0.000f, }, /* 17 (16.823) */ + {1.088f, 1.849f, 3.195f, 1.687f, 0.000f, 0.000f, }, /* 21 (20.910) */ + {1.088f, 1.849f, 3.195f, 1.282f, 2.471f, 0.000f, }, /* 22 (21.907) */ + {1.126f, 1.689f, 0.790f, 1.282f, 2.471f, 0.000f, }, /* 25 (24.863) */ + {0.930f, 1.382f, 0.682f, 1.282f, 2.471f, 0.000f, }, /* 26 (25.921) */ + {1.115f, 0.794f, 1.852f, 1.281f, 3.033f, 0.000f, }, /* 27 (26.837) */ + {0.840f, 1.376f, 0.623f, 0.800f, 1.416f, 4.260f, }, /* 36 (35.998) */ /* INACTIVE NB */ + + {0.801f, 1.148f, 1.802f, 0.000f, 0.000f, 0.000f, }, /* 17 (16.932) */ + {1.089f, 1.812f, 3.172f, 1.677f, 0.000f, 0.000f, }, /* 21 (20.910) */ + {1.089f, 1.904f, 3.221f, 1.521f, 2.635f, 0.000f, }, /* 22 (21.985) */ + {0.845f, 1.212f, 1.934f, 1.313f, 2.419f, 0.000f, }, /* 25 (24.845) */ + {0.779f, 1.095f, 1.700f, 1.313f, 2.419f, 0.000f, }, /* 26 (25.999) */ + {0.723f, 1.015f, 1.664f, 1.313f, 2.419f, 0.000f, }, /* 27 (26.981) */ + {0.893f, 0.652f, 1.438f, 1.076f, 0.720f, 1.794f, }, /* 36 (35.929) */ /* INACTIVE WB*/ + + {1.359f, 2.306f, 0.000f, 1.669f, 0.000f, 0.000f, }, /* 17 (16.823) */ + {1.077f, 1.927f, 3.546f, 1.669f, 0.000f, 0.000f, }, /* 21 (20.910) */ + {1.077f, 2.032f, 3.578f, 1.429f, 2.711f, 0.000f, }, /* 22 (21.985) */ + {0.833f, 1.253f, 2.105f, 1.283f, 2.556f, 0.000f, }, /* 25 (24.845) */ + {0.776f, 1.152f, 1.858f, 1.283f, 2.556f, 0.000f, }, /* 26 (25.934) */ + {0.719f, 1.066f, 1.732f, 1.283f, 2.556f, 0.000f, }, /* 27 (26.914) */ + {0.941f, 0.651f, 1.565f, 0.722f, 1.190f, 1.940f, }, /* 36 (35.915) */ /* INACTIVE 16k*/ + + {1.292f, 2.479f, 0.000f, 1.541f, 0.000f, 0.000f, }, /* 18 (17.479) */ + {1.202f, 1.903f, 0.000f, 1.541f, 0.000f, 0.000f, }, /* 19 (18.703) */ + {1.028f, 1.641f, 2.455f, 1.648f, 0.000f, 0.000f, }, /* 22 (21.776) */ + {1.247f, 0.878f, 2.329f, 1.648f, 0.000f, 0.000f, }, /* 23 (22.791) */ + {0.863f, 1.358f, 2.522f, 1.648f, 0.000f, 0.000f, }, /* 24 (23.999) */ + {0.817f, 1.222f, 2.010f, 1.074f, 1.785f, 2.733f, }, /* 29 (28.966) */ + {0.815f, 0.612f, 1.281f, 1.055f, 1.724f, 2.952f, }, /* 32 (31.990) */ /* UNVOICED NB */ + {1.545f, 0.000f, 0.000f, 1.548f, 0.000f, 0.000f, }, /* 14 (13.640) */ + {1.640f, 0.000f, 0.000f, 1.548f, 0.000f, 0.000f, }, /* 15 (14.733) */ + {1.287f, 2.749f, 0.000f, 1.548f, 0.000f, 0.000f, }, /* 18 (17.479) */ + {1.287f, 2.749f, 0.000f, 1.654f, 0.000f, 0.000f, }, /* 19 (18.572) */ + {1.190f, 2.026f, 0.000f, 1.654f, 0.000f, 0.000f, }, /* 20 (19.796) */ + {0.931f, 1.458f, 2.450f, 1.294f, 2.742f, 0.000f, }, /* 25 (24.992) */ + {0.877f, 1.396f, 2.737f, 1.081f, 1.816f, 3.360f, }, /* 28 (27.996) */ /* UNVOICED WB*/ + + {1.131f, 1.636f, 0.000f, 1.371f, 0.000f, 0.000f, }, /* 24 (23.818) */ + {0.934f, 1.277f, 0.728f,1.157f, 1.697f, 0.000f, }, /* 30 (29.992) */ + {0.833f, 1.162f, 0.658f,1.151f, 1.687f, 0.000f, }, /* 31 (30.998) */ + {0.751f, 1.032f, 0.598f,1.151f, 1.687f, 0.000f, }, /* 32 (31.987) */ + {0.709f, 1.005f, 0.570f, 1.060f, 1.772f, 2.719f, }, /* 34 (33.994) */ + {0.746f, 1.001f, 0.601f,1.004f, 1.803f, 2.892f, }, /* 35 (35.000) */ + {0.743f, 1.000f, 0.599f,0.936f, 1.861f, 2.874f, }, /* 36 (35.994) */ + {0.775f, 0.614f, 1.037f, 0.796f, 1.304f, 1.905f, }, /* 39 (38.301) */ /* VOICED 16k */ + {0.894f, 1.339f, 2.549f, 1.308f, 2.601f, 0.000f, }, /* 26 (25.917) */ + {0.720f, 1.012f, 1.598f, 1.512f, 0.926f, 2.137f, }, /* 32 (31.980) */ + {0.681f, 0.973f, 1.649f, 1.381f, 0.876f, 2.129f, }, /* 33 (32.990) */ + {0.684f, 0.964f, 1.640f, 1.168f, 1.776f, 0.787f, }, /* 34 (33.974) */ + {0.668f, 0.935f, 1.551f, 1.016f, 1.518f, 0.712f, }, /* 35 (34.989) */ + {0.659f, 0.911f, 1.425f, 1.337f, 0.889f, 0.642f, }, /* 36 (35.988) */ + {0.659f, 0.911f, 1.425f, 0.839f, 1.287f, 0.607f, }, /* 37 (36.989) */ /* GENERIC 16k*/ + {1.633f, 0.000f, 0.000f, 1.687f, 0.000f, 0.000f, }, /* 16 (15.826) */ + {1.076f, 1.790f, 2.942f, 1.687f, 0.000f, 0.000f, }, /* 21 (20.910) */ + {0.834f, 1.229f, 1.890f, 1.687f, 0.000f, 0.000f, }, /* 24 (23.999) */ + {0.938f, 1.404f, 2.153f, 1.306f, 2.630f, 0.000f, }, /* 25 (24.992) */ + {1.340f, 0.886f, 2.320f, 1.306f, 2.630f, 0.000f, }, /* 26 (25.917) */ + {0.833f, 1.250f, 1.908f, 1.306f, 2.630f, 0.000f, }, /* 27 (26.883) */ + {0.833f, 1.213f, 1.873f, 1.125f, 1.839f, 2.819f, }, /* 28 (27.901) */ + {0.765f, 1.162f, 1.690f, 1.024f, 1.738f, 2.838f, }, /* 30 (29.916) */ + {0.725f, 1.050f, 1.791f, 1.480f, 0.922f, 3.104f, }, /* 31 (30.993) */ + {0.712f, 1.012f, 1.549f, 1.494f, 0.903f, 3.364f, }, /* 32 (31.980) */ + {0.659f, 0.927f, 1.357f, 1.494f, 0.903f, 3.364f, }, /* 33 (32.958) */ + {0.822f, 0.614f, 1.288f, 0.910f, 1.509f, 2.255f, }, /* 34 (33.987) */ + {0.841f, 0.624f, 1.278f, 1.161f, 0.762f, 1.808f, }, /* 35 (34.994) */ + {0.838f, 0.622f, 1.266f, 1.080f, 0.711f, 1.710f, }, /* 36 (35.968) */ + {0.832f, 0.619f, 1.275f, 0.938f, 1.430f, 0.644f, }, /* 37 (36.971) */ /* GENERIC 12.8k MA*/ + + {0.884f, 1.349f, 2.570f, 1.314f, 2.609f, 0.000f, }, /* 26 (25.917) */ + {0.711f, 1.018f, 1.615f, 1.482f, 0.921f, 3.431f, }, /* 32 (31.980) */ + {0.679f, 0.974f, 1.659f, 0.948f, 1.549f, 3.448f, }, /* 33 (32.995) */ + {0.831f, 0.618f, 1.481f, 0.933f, 1.514f, 2.310f, }, /* 34 (33.993) */ + {0.816f, 0.610f, 1.402f, 1.426f, 0.877f, 2.265f, }, /* 35 (34.992) */ + {0.787f, 1.257f, 0.596f, 0.859f, 1.447f, 2.431f, }, /* 36 (35.997) */ + {0.787f, 1.257f, 0.596f, 1.106f, 0.735f, 1.659f, }, /* 37 (36.961) */ /* AUDIO 16k */ +}; + +/* An 16-by-34 matrix in Scale = 20.48f */ +const float sigma_MSLVQ[][16] = +{ + { 1.0f }, /* IA NB */ + { 1.0f }, /* UV NB */ + {41.8457031f, 43.9453125f, 62.5976563f, 72.3632813f, 78.7597656f, 82.4707031f, 85.4492188f, 86.5722656f, 86.6210938f, 84.9121094f, 85.2050781f, 105.5664063f, 127.8320313f, 68.6523438f, 25.7324219f, 16.9433594f }, /* V NB */ + {48.9257813f, 50.5859375f, 71.0449219f, 72.4609375f, 74.5117188f, 77.8808594f, 79.5898438f, 80.8105469f, 79.9804688f, 74.5117188f, 70.0683594f, 88.7207031f, 119.1406250f, 102.0019531f, 37.1093750f, 25.0976563f }, /* G NB */ + {48.2421875f, 48.0468750f, 68.7500000f, 76.9531250f, 80.9570313f, 85.1562500f, 89.0625000f, 91.8457031f, 90.4296875f, 85.2050781f, 81.5917969f, 106.2988281f, 133.6425781f, 84.3750000f, 34.7656250f, 26.6113281f }, /* T NB */ + {85.5957031f, 82.9101563f, 99.5605469f, 105.9570313f, 106.6406250f, 106.8847656f, 101.6601563f, 99.5605469f, 97.7050781f, 97.0703125f, 97.1191406f, 117.8710938f, 128.1738281f, 153.9550781f, 33.1542969f, 14.5996094f },/* AU NB*/ + { 1.0f }, + { 1.0f }, /* UV WB*/ + {44.2382813f, 52.1972656f, 85.7910156f, 98.6816406f, 101.7089844f, 107.2753906f, 106.9824219f, 112.0605469f, 118.8476563f, 126.3183594f, 125.4882813f, 126.8554688f, 136.3281250f, 136.7675781f, 146.9726563f, 129.7851563f }, /* V WB */ + {61.8164063f, 69.8730469f, 94.6289063f, 97.0214844f, 96.0449219f, 101.3671875f, 100.5371094f, 104.3945313f, 108.5937500f, 106.9824219f, 107.9101563f, 112.8417969f, 120.7519531f, 120.6542969f, 122.0214844f, 119.6289063f }, /* G WB */ + {56.8847656f, 56.9335938f, 86.7187500f, 100.1953125f, 101.9042969f, 108.5449219f, 113.4765625f, 117.9199219f, 124.1699219f, 122.1679688f, 126.3183594f, 137.4023438f, 153.9550781f, 158.8867188f, 161.9140625f, 155.9570313f }, /* T WB */ + {84.8632813f, 88.6230469f, 112.0605469f, 118.3593750f, 123.3886719f, 121.0937500f, 115.4785156f, 118.7011719f, 118.5058594f, 119.0429688f, 123.9257813f, 127.6855469f, 138.5742188f, 125.2441406f, 118.9941406f, 109.0332031f },/* AU WB */ + { 1.0f }, + { 1.0f }, + {75.2441406f, 84.3261719f, 110.6933594f, 125.0000000f, 134.0332031f, 140.3808594f, 146.6308594f, 159.5214844f, 161.3281250f, 173.9746094f, 186.9628906f, 190.9667969f, 196.2402344f, 181.9335938f, 177.9785156f, 187.2070313f }, /* VO 16k */ + {89.6972656f, 92.9687500f, 122.0703125f, 129.0527344f, 130.4687500f, 128.3691406f, 132.5683594f, 139.2578125f, 137.9882813f, 139.9902344f, 152.8320313f, 157.3730469f, 172.4121094f, 179.4433594f, 147.9980469f, 194.1894531f }, /* G 16k */ + {90.3320313f, 108.3496094f, 118.7500000f, 125.7324219f, 135.7421875f, 137.9882813f, 143.0175781f, 145.1660156f, 145.8007813f, 155.1757813f, 171.2402344f, 176.1230469f, 165.4785156f, 161.3769531f, 148.6816406f, 174.4140625f }, /* T 16k */ + {103.1250000f, 112.3046875f, 142.3339844f, 150.6347656f, 150.0488281f, 145.8496094f, 149.3164063f, 145.8496094f, 153.5156250f, 157.3242188f, 175.0000000f, 170.9960938f, 157.4707031f, 168.1152344f, 156.5917969f, 229.0527344f },/* AU 16k */ + {87.5488281f, 116.4062500f, 102.3925781f, 103.1738281f, 100.8789063f, 95.2636719f, 101.7578125f, 110.5468750f, 122.2167969f, 115.2343750f, 107.2753906f, 108.8378906f, 101.7089844f, 111.5722656f, 111.6699219f, 155.9570313f }, + {160.5957031f, 122.6074219f, 117.4804688f, 129.7363281f, 130.9570313f, 133.8378906f, 139.1601563f, 159.9121094f, 168.0664063f, 161.3281250f, 141.9433594f, 142.1386719f, 132.0312500f, 129.8828125f, 122.9980469f, 160.9863281f }, + {53.2226563f, 105.1757813f, 133.9355469f, 143.3593750f, 158.2031250f, 168.1640625f, 160.5957031f, 164.4042969f, 173.4863281f, 182.0800781f, 170.0683594f, 165.3320313f, 128.1738281f, 96.5332031f, 91.9433594f, 93.7988281f }, + {69.5312500f, 169.0429688f, 118.9453125f, 104.6875000f, 100.7812500f, 98.3398438f, 98.8281250f, 95.9472656f, 97.8027344f, 97.6562500f, 95.8496094f, 99.8046875f, 94.3847656f, 106.5917969f, 117.1386719f, 144.7265625f }, + {136.1816406f, 130.5175781f, 130.9082031f, 133.3007813f, 131.3476563f, 129.1992188f, 133.8867188f, 166.1621094f, 197.0703125f, 281.9824219f, 305.7617188f, 255.8105469f, 392.7734375f, 336.6699219f, 135.2050781f, 96.7773438f }, + {123.0957031f, 119.6777344f, 126.3183594f, 119.5800781f, 117.3339844f, 108.4472656f, 107.9101563f, 112.2070313f, 148.2910156f, 153.9550781f, 127.6367188f, 129.9316406f, 132.5683594f, 149.3164063f, 144.6777344f, 244.6289063f }, + {92.3339844f, 97.5097656f, 94.0917969f, 90.2832031f, 94.1894531f, 95.8007813f, 92.8710938f, 86.4746094f, 83.8867188f, 74.1699219f, 70.8984375f, 69.3847656f, 71.5332031f, 167.2851563f, 71.8750000f, 21.5820313f }, + {44.0429688f, 73.9257813f, 140.6738281f, 121.8750000f, 129.5410156f, 127.3437500f, 115.7226563f, 104.8339844f, 106.2500000f, 110.0097656f, 125.0000000f, 107.5195313f, 85.6445313f, 79.2968750f, 69.9218750f, 55.9570313f }, + {106.4453125f, 99.4140625f, 95.6542969f, 92.7246094f, 94.3359375f, 92.0898438f, 83.6914063f, 84.7167969f, 87.1582031f, 101.6113281f, 91.1621094f, 75.3417969f, 73.0957031f, 71.5332031f, 68.0175781f, 63.7207031f }, + {43.3105469f, 125.5371094f, 107.4707031f, 85.4003906f, 83.1542969f, 80.7617188f, 78.8574219f, 80.0781250f, 80.1269531f, 88.0859375f, 93.2128906f, 81.3964844f, 74.8535156f, 73.0957031f, 65.8203125f, 59.3750000f }, + {149.6093750f, 127.3925781f, 117.1875000f, 111.9628906f, 113.4277344f, 113.8671875f, 107.8125000f, 97.9492188f, 100.7324219f, 113.5253906f, 167.9687500f, 203.4667969f, 154.9804688f, 119.1894531f, 107.1289063f, 104.8828125f }, + {59.5214844f, 86.2792969f, 106.0058594f, 113.7207031f, 134.4726563f, 120.9960938f, 120.4589844f, 100.4882813f, 98.5839844f, 100.0488281f, 132.3730469f, 191.8457031f, 194.7753906f, 77.8320313f, 70.0195313f, 41.9433594f }, + {88.2812500f, 92.3828125f, 92.1386719f, 93.5546875f, 97.6074219f, 92.7734375f, 89.0625000f, 87.2070313f, 88.8671875f, 94.1406250f, 121.5820313f, 121.9238281f, 116.7968750f, 122.1191406f, 164.5996094f, 140.4296875f }, + {86.2792969f, 92.8710938f, 83.5937500f, 86.0839844f, 95.8984375f, 95.2148438f, 90.5273438f, 86.5234375f, 82.1289063f, 81.3964844f, 77.9785156f, 89.4042969f, 143.7011719f, 168.3593750f, 41.5039063f, 27.6855469f }, + {97.1679688f, 101.0253906f, 104.3945313f, 110.4003906f, 108.7890625f, 107.4707031f, 97.8515625f, 92.6757813f, 79.1503906f, 81.6406250f, 77.1972656f, 108.8867188f, 212.2070313f, 198.8281250f, 47.4609375f, 35.3515625f }, + {74.8535156f, 97.3632813f, 100.1464844f, 91.6992188f, 90.3808594f, 89.6484375f, 83.2031250f, 84.0820313f, 81.9335938f, 96.4355469f, 110.9863281f, 92.6757813f, 83.4960938f, 82.1289063f, 77.8808594f, 70.8984375f} +}; + +/* An 16-by-34 matrix in Scale = 20.48f */ +const float inv_sigma_MSLVQ[][16] = +{ + {1.0f }, /* IA NB */ + {1.0f }, /* UV NB */ + {0.0238973f, 0.0227556f, 0.0159750f, 0.0138192f, 0.0126968f, 0.0121255f, 0.0117029f, 0.0115510f, 0.0115445f, 0.0117769f, 0.0117364f, 0.0094727f, 0.0078228f, 0.0145661f, 0.0388615f, 0.0590202f }, /* V NB */ + {0.0204391f, 0.0197683f, 0.0140756f, 0.0138005f, 0.0134207f, 0.0128401f, 0.0125644f, 0.0123746f, 0.0125031f, 0.0134207f, 0.0142718f, 0.0112713f, 0.0083934f, 0.0098037f, 0.0269474f, 0.0398444f }, /* G NB */ + {0.0207287f, 0.0208130f, 0.0145455f, 0.0129949f, 0.0123522f, 0.0117431f, 0.0112281f, 0.0108878f, 0.0110583f, 0.0117364f, 0.0122561f, 0.0094074f, 0.0074826f, 0.0118519f, 0.0287640f, 0.0375780f }, /* T NB */ + {0.0116828f, 0.0120612f, 0.0100441f, 0.0094378f, 0.0093773f, 0.0093559f, 0.0098367f, 0.0100441f, 0.0102349f, 0.0103018f, 0.0102966f, 0.0084838f, 0.0078019f, 0.0064954f, 0.0301620f, 0.0684950f }, /* AU NB */ + {1.0f }, + {1.0f }, /* UV WB */ + {0.0226049f, 0.0191581f, 0.0116562f, 0.0101336f, 0.0098320f, 0.0093218f, 0.0093473f, 0.0089237f, 0.0084141f, 0.0079165f, 0.0079689f, 0.0078830f, 0.0073352f, 0.0073117f, 0.0068040f, 0.0077050f }, /* V WB */ + {0.0161769f, 0.0143117f, 0.0105676f, 0.0103070f, 0.0104118f, 0.0098651f, 0.0099466f, 0.0095790f, 0.0092086f, 0.0093473f, 0.0092670f, 0.0088620f, 0.0082814f, 0.0082881f, 0.0081953f, 0.0083592f }, /* G WB */ + {0.0175794f, 0.0175643f, 0.0115315f, 0.0099805f, 0.0098131f, 0.0092128f, 0.0088124f, 0.0084803f, 0.0080535f, 0.0081855f, 0.0079165f, 0.0072779f, 0.0064954f, 0.0062938f, 0.0061761f, 0.0064120f }, /* T WB */ + {0.0117837f, 0.0112837f, 0.0089237f, 0.0084488f, 0.0081045f, 0.0082581f, 0.0086596f, 0.0084245f, 0.0084384f, 0.0084003f, 0.0080693f, 0.0078317f, 0.0072163f, 0.0079844f, 0.0084038f, 0.0091715f }, /* AU WB */ + {1.0f }, + {1.0f }, + {0.0132901f, 0.0118587f, 0.0090340f, 0.0080000f, 0.0074608f, 0.0071235f, 0.0068198f, 0.0062687f, 0.0061985f, 0.0057480f, 0.0053487f, 0.0052365f, 0.0050958f, 0.0054965f, 0.0056187f, 0.0053417f }, /* V 16k */ + {0.0111486f, 0.0107563f, 0.0081920f, 0.0077488f, 0.0076647f, 0.0077900f, 0.0075433f, 0.0071809f, 0.0072470f, 0.0071434f, 0.0065431f, 0.0063543f, 0.0058001f, 0.0055728f, 0.0067568f, 0.0051496f }, /* G 16k */ + {0.0110703f, 0.0092294f, 0.0084211f, 0.0079534f, 0.0073669f, 0.0072470f, 0.0069921f, 0.0068887f, 0.0068587f, 0.0064443f, 0.0058397f, 0.0056778f, 0.0060431f, 0.0061967f, 0.0067258f, 0.0057335f }, /* T 16k */ + {0.0096970f, 0.0089043f, 0.0070257f, 0.0066386f, 0.0066645f, 0.0068564f, 0.0066972f, 0.0068564f, 0.0065140f, 0.0063563f, 0.0057143f, 0.0058481f, 0.0063504f, 0.0059483f, 0.0063860f, 0.0043658f }, /* AU 16k */ + {0.0114222f, 0.0085906f, 0.0097663f, 0.0096924f, 0.0099129f, 0.0104972f, 0.0098273f, 0.0090459f, 0.0081822f, 0.0086780f, 0.0093218f, 0.0091880f, 0.0098320f, 0.0089628f, 0.0089550f, 0.0064120f }, + {0.0062268f, 0.0081561f, 0.0085121f, 0.0077079f, 0.0076361f, 0.0074717f, 0.0071860f, 0.0062534f, 0.0059500f, 0.0061985f, 0.0070451f, 0.0070354f, 0.0075740f, 0.0076992f, 0.0081302f, 0.0062117f }, + {0.0187890f, 0.0095079f, 0.0074663f, 0.0069755f, 0.0063210f, 0.0059466f, 0.0062268f, 0.0060826f, 0.0057641f, 0.0054921f, 0.0058800f, 0.0060484f, 0.0078019f, 0.0103591f, 0.0108763f, 0.0106611f }, + {0.0143820f, 0.0059157f, 0.0084072f, 0.0095522f, 0.0099225f, 0.0101688f, 0.0101186f, 0.0104224f, 0.0102247f, 0.0102400f, 0.0104330f, 0.0100196f, 0.0105949f, 0.0093816f, 0.0085369f, 0.0069096f }, + {0.0073431f, 0.0076618f, 0.0076389f, 0.0075018f, 0.0076134f, 0.0077400f, 0.0074690f, 0.0060182f, 0.0050743f, 0.0035463f, 0.0032705f, 0.0039091f, 0.0025460f, 0.0029703f, 0.0073962f, 0.0103330f }, + {0.0081238f, 0.0083558f, 0.0079165f, 0.0083626f, 0.0085227f, 0.0092211f, 0.0092670f, 0.0089121f, 0.0067435f, 0.0064954f, 0.0078347f, 0.0076964f, 0.0075433f, 0.0066972f, 0.0069119f, 0.0040878f }, + {0.0108302f, 0.0102554f, 0.0106279f, 0.0110763f, 0.0106169f, 0.0104383f, 0.0107676f, 0.0115641f, 0.0119208f, 0.0134826f, 0.0141047f, 0.0144124f, 0.0139795f, 0.0059778f, 0.0139130f, 0.0463348f }, + {0.0227051f, 0.0135271f, 0.0071086f, 0.0082051f, 0.0077196f, 0.0078528f, 0.0086414f, 0.0095389f, 0.0094118f, 0.0090901f, 0.0080000f, 0.0093006f, 0.0116762f, 0.0126108f, 0.0143017f, 0.0178709f }, + {0.0093945f, 0.0100589f, 0.0104543f, 0.0107846f, 0.0106004f, 0.0108590f, 0.0119487f, 0.0118040f, 0.0114734f, 0.0098414f, 0.0109695f, 0.0132728f, 0.0136807f, 0.0139795f, 0.0147021f, 0.0156935f }, + {0.0230891f, 0.0079658f, 0.0093049f, 0.0117095f, 0.0120258f, 0.0123821f, 0.0126811f, 0.0124878f, 0.0124802f, 0.0113525f, 0.0107281f, 0.0122855f, 0.0133594f, 0.0136807f, 0.0151929f, 0.0168421f }, + {0.0066841f, 0.0078498f, 0.0085333f, 0.0089315f, 0.0088162f, 0.0087822f, 0.0092754f, 0.0102094f, 0.0099273f, 0.0088086f, 0.0059535f, 0.0049148f, 0.0064524f, 0.0083900f, 0.0093345f, 0.0095345f }, + {0.0168007f, 0.0115903f, 0.0094334f, 0.0087935f, 0.0074365f, 0.0082647f, 0.0083016f, 0.0099514f, 0.0101436f, 0.0099951f, 0.0075544f, 0.0052125f, 0.0051341f, 0.0128482f, 0.0142817f, 0.0238417f }, + {0.0113274f, 0.0108245f, 0.0108532f, 0.0106889f, 0.0102451f, 0.0107789f, 0.0112281f, 0.0114670f, 0.0112527f, 0.0106224f, 0.0082249f, 0.0082018f, 0.0085619f, 0.0081887f, 0.0060753f, 0.0071210f }, + {0.0115903f, 0.0107676f, 0.0119626f, 0.0116166f, 0.0104277f, 0.0105026f, 0.0110464f, 0.0115576f, 0.0121760f, 0.0122855f, 0.0128240f, 0.0111851f, 0.0069589f, 0.0059397f, 0.0240941f, 0.0361199f }, + {0.0102915f, 0.0098985f, 0.0095790f, 0.0090579f, 0.0091921f, 0.0093049f, 0.0102196f, 0.0107903f, 0.0126342f, 0.0122488f, 0.0129538f, 0.0091839f, 0.0047124f, 0.0050295f, 0.0210700f, 0.0282873f }, + {0.0133594f, 0.0102708f, 0.0099854f, 0.0109052f, 0.0110643f, 0.0111547f, 0.0120188f, 0.0118931f, 0.0122050f, 0.0103696f, 0.0090101f, 0.0107903f, 0.0119766f, 0.0121760f, 0.0128401f, 0.0141047f} +}; + +/* An 16-by-19 matrix in Scale = 20.48f */ +const float sigma_p[][16] = +{ + {59.3261719f, 63.9160156f, 69.7753906f, 66.3574219f, 67.3339844f, 68.5546875f, 66.6015625f, 66.0156250f, 66.0156250f, 67.9687500f, 68.2617188f, 84.3261719f, 96.5820313f, 118.6523438f, 44.0917969f, 43.1152344f }, /* IA NB */ + {51.2207031f, 66.6015625f, 69.3847656f, 68.6035156f, 67.9199219f, 69.6289063f, 69.6777344f, 69.5800781f, 52.5878906f, 64.9902344f, 65.3808594f, 68.7500000f, 71.4355469f, 77.0507813f, 77.9296875f, 80.3222656f }, /* U NB */ + {32.7148438f, 34.9121094f, 47.0703125f, 55.6152344f, 60.1562500f, 68.3105469f, 71.8261719f, 72.7539063f, 73.8281250f, 70.8984375f, 69.4335938f, 77.1972656f, 95.8007813f, 74.3164063f, 20.8984375f, 10.9375000f }, /* V NB */ + {53.8085938f, 61.3281250f, 78.1738281f, 75.8789063f, 73.7792969f, 81.3964844f, 80.7128906f, 80.5664063f, 83.6914063f, 77.0996094f, 72.5097656f, 86.6210938f, 121.6796875f, 117.7734375f, 40.0390625f, 16.8945313f },/* G NB */ + {1.0f }, /* T NB */ + {57.0312500f, 64.5996094f, 71.4355469f, 75.8789063f, 77.0507813f, 79.0039063f, 74.5117188f, 74.2187500f, 72.9492188f, 72.8515625f, 66.9433594f, 73.9257813f, 109.6191406f, 121.5332031f, 23.7792969f, 13.3789063f }, /* AU NB */ + {55.4687500f, 65.6738281f, 71.8261719f, 71.6308594f, 73.0468750f, 74.3164063f, 73.0957031f, 73.4863281f, 73.8769531f, 75.2441406f, 78.0761719f, 82.6171875f, 90.1367188f, 95.8496094f, 66.0644531f, 68.9941406f }, /* IA WB */ + {67.9687500f, 64.0625000f, 65.8203125f, 76.9531250f, 117.1875000f, 145.5078125f, 77.6855469f, 23.2421875f, 81.0546875f, 81.1035156f, 81.4453125f, 85.0585938f, 90.0878906f, 95.8984375f, 92.3828125f, 90.7226563f }, /* U WB */ + {35.6933594f, 39.4042969f, 57.3242188f, 64.6484375f, 68.0175781f, 76.2695313f, 80.7128906f, 82.0800781f, 85.1562500f, 89.6484375f, 89.9414063f, 95.3613281f, 104.7363281f, 106.0546875f, 105.2734375f, 97.8515625f }, /* V WB */ + {61.4257813f, 75.1464844f, 88.4277344f, 82.1777344f, 82.4218750f, 89.1601563f, 89.2578125f, 94.1894531f, 95.5566406f, 95.9472656f, 97.0703125f, 102.6367188f, 107.2265625f, 107.3730469f, 105.4199219f, 98.1933594f },/* G WB */ + {1.0f },/* T WB */ + {51.1230469f, 62.5976563f, 71.5820313f, 75.5371094f, 78.9550781f, 79.9804688f, 79.4433594f, 82.9101563f, 82.6171875f, 83.1054688f, 84.8632813f, 86.1328125f, 89.5996094f, 83.6914063f, 79.3945313f, 78.2226563f }, /* AU WB */ + {72.9980469f, 86.2792969f, 90.0878906f, 89.5996094f, 92.4316406f, 90.5273438f, 90.5273438f, 92.1386719f, 97.3632813f, 101.3671875f, 111.7675781f, 110.8398438f, 97.5585938f, 93.1640625f, 92.8710938f, 115.7226563f },/* IA 16k */ + {1.0f },/* U 16k */ + {54.4921875f, 67.4804688f, 94.1406250f, 125.0000000f, 122.8027344f, 123.0957031f, 118.5546875f, 115.0878906f, 128.5644531f, 140.3808594f, 144.2382813f, 139.4042969f, 151.4160156f, 138.1347656f, 140.3808594f, 154.7851563f }, /* V 16k */ + {96.8261719f, 117.3339844f, 132.5683594f, 134.4726563f, 140.7226563f, 136.8652344f, 141.6992188f, 141.1132813f, 143.8964844f, 152.6367188f, 168.5058594f, 169.1406250f, 158.4960938f, 156.1523438f, 147.4609375f, 182.4707031f },/* G 16k */ + {1.0f },/* T 16k */ + {55.1269531f, 70.3613281f, 83.1054688f, 87.2070313f, 90.5273438f, 91.4550781f, 94.7265625f, 93.6035156f, 97.6074219f, 98.7304688f, 104.6875000f, 99.6582031f, 95.6054688f, 91.6503906f, 88.4765625f, 78.2226563f, },/* NOT USED ! AU 16k */ + {69.5312500f, 80.1757813f, 101.3183594f, 100.9277344f, 106.4941406f, 111.1816406f, 107.6171875f, 112.9882813f, 116.6992188f, 117.1875000f, 120.9472656f, 125.0976563f, 130.7617188f, 128.7109375f, 123.3886719f, 104.9316406f} /* G WB for MA*/ +}; +/* An 16-by-19 matrix in Scale = 20.48f */ +const float inv_sigma_p[][16] = +{ + {0.0168560f, 0.0156455f, 0.0143317f, 0.0150699f, 0.0148513f, 0.0145869f, 0.0150147f, 0.0151479f, 0.0151479f, 0.0147126f, 0.0146495f, 0.0118587f, 0.0103539f, 0.0084280f, 0.0226800f, 0.0231937f }, /* IA NB */ + {0.0195234f, 0.0150147f, 0.0144124f, 0.0145765f, 0.0147232f, 0.0143619f, 0.0143518f, 0.0143719f, 0.0190158f, 0.0153869f, 0.0152950f, 0.0145455f, 0.0139986f, 0.0129785f, 0.0128321f, 0.0124498f }, /* U NB */ + {0.0305672f, 0.0286434f, 0.0212448f, 0.0179807f, 0.0166234f, 0.0146390f, 0.0139225f, 0.0137450f, 0.0135450f, 0.0141047f, 0.0144023f, 0.0129538f, 0.0104383f, 0.0134560f, 0.0478505f, 0.0914286f }, /* V NB */ + {0.0185844f, 0.0163057f, 0.0127920f, 0.0131789f, 0.0135539f, 0.0122855f, 0.0123896f, 0.0124121f, 0.0119487f, 0.0129702f, 0.0137912f, 0.0115445f, 0.0082183f, 0.0084909f, 0.0249756f, 0.0591908f }, /* G NB */ + {1.0f }, /* T NB */ + {0.0175342f, 0.0154800f, 0.0139986f, 0.0131789f, 0.0129785f, 0.0126576f, 0.0134207f, 0.0134737f, 0.0137082f, 0.0137265f, 0.0149380f, 0.0135271f, 0.0091225f, 0.0082282f, 0.0420534f, 0.0747445f }, /* AU NB */ + {0.0180282f, 0.0152268f, 0.0139225f, 0.0139605f, 0.0136898f, 0.0134560f, 0.0136807f, 0.0136080f, 0.0135360f, 0.0132901f, 0.0128080f, 0.0121040f, 0.0110943f, 0.0104330f, 0.0151367f, 0.0144940f }, /* IA WB */ + {0.0147126f, 0.0156098f, 0.0151929f, 0.0129949f, 0.0085333f, 0.0068725f, 0.0128724f, 0.0430252f, 0.0123373f, 0.0123299f, 0.0122782f, 0.0117566f, 0.0111003f, 0.0104277f, 0.0108245f, 0.0110226f }, /* U WB */ + {0.0280164f, 0.0253779f, 0.0174446f, 0.0154683f, 0.0147021f, 0.0131114f, 0.0123896f, 0.0121832f, 0.0117431f, 0.0111547f, 0.0111183f, 0.0104864f, 0.0095478f, 0.0094291f, 0.0094991f, 0.0102196f }, /* V WB */ + {0.0162798f, 0.0133073f, 0.0113087f, 0.0121687f, 0.0121327f, 0.0112158f, 0.0112035f, 0.0106169f, 0.0104650f, 0.0104224f, 0.0103018f, 0.0097431f, 0.0093260f, 0.0093133f, 0.0094859f, 0.0101840f }, /* G WB */ + {1.0f }, /* T WB */ + {0.0195606f, 0.0159750f, 0.0139700f, 0.0132385f, 0.0126654f, 0.0125031f, 0.0125876f, 0.0120612f, 0.0121040f, 0.0120329f, 0.0117837f, 0.0116100f, 0.0111608f, 0.0119487f, 0.0125953f, 0.0127840f }, /* AU WB */ + {0.0136990f, 0.0115903f, 0.0111003f, 0.0111608f, 0.0108188f, 0.0110464f, 0.0110464f, 0.0108532f, 0.0102708f, 0.0098651f, 0.0089471f, 0.0090220f, 0.0102503f, 0.0107338f, 0.0107676f, 0.0086414f }, /* IA 16k*/ + {1.0f }, /* U 16k */ + {0.0183513f, 0.0148191f, 0.0106224f, 0.0080000f, 0.0081431f, 0.0081238f, 0.0084349f, 0.0086890f, 0.0077782f, 0.0071235f, 0.0069330f, 0.0071734f, 0.0066043f, 0.0072393f, 0.0071235f, 0.0064606f }, /* V 16k */ + {0.0103278f, 0.0085227f, 0.0075433f, 0.0074365f, 0.0071062f, 0.0073065f, 0.0070572f, 0.0070865f, 0.0069494f, 0.0065515f, 0.0059345f, 0.0059122f, 0.0063093f, 0.0064040f, 0.0067815f, 0.0054803f }, /* G 16k */ + {1.0f }, /* T 16k */ + {0.0181399f, 0.0142124f, 0.0120329f, 0.0114670f, 0.0110464f, 0.0109343f, 0.0105567f, 0.0106834f, 0.0102451f, 0.0101286f, 0.0095522f, 0.0100343f, 0.0104597f, 0.0109110f, 0.0113024f, 0.0127840f },/* NOT USED ! AU 16k */ + {0.0143820f, 0.0124726f, 0.0098699f, 0.0099081f, 0.0093902f, 0.0089943f, 0.0092922f, 0.0088505f, 0.0085690f, 0.0085333f, 0.0082681f, 0.0079938f, 0.0076475f, 0.0077693f, 0.0081045f, 0.0095300f} /* G WB for MA*/ +}; +const int no_lead[][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 0 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 1 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 2 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 3 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 6 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 7 T NB */ + { 18, 18, 11, 9, 6, 5, }, /* 31 */ + { 24, 23, 13, 9, 6, 5, }, /* 32 */ /* mode 8 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 */ /* mode 10 AUDIO_WB*/ + { 48, 48, 34, 13, 11, 9 }, /* 36 */ /* mode 10 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 */ + { 39, 30, 12, 2, 2, 0 }, /* 28 */ /* AUDIO_NB */ + { 11, 9, 8, 4, 2, 0, }, /* 26 */ + { 48, 48, 48, 13, 9, 8, }, /* 36 */ /* mode 12 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 actually not used */ + { 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 int no_lead_p[][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 */ + { 8, 8, 5, 4, 2, 0, }, /* 25 */ + { 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 */ + { 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 */ + + { 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*/ + + { 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*/ + { 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 */ + + { 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) */ + { 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*/ + + { 2, 0, 0, 2, 0, 0, }, /* 16 (15.826) */ + { 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*/ + + + { 11, 10, 5, 4, 2, 0, }, /* 26 (25.917) */ + { 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 short min_lat_bits_SN[] = {-1, -1, 17, 12, 17, 17, -1, -1, 17, 12, 17, 17, -1, -1, 22, -1, 32, 26 + }; + +const short min_lat_bits_pred[] = {17, 18, 9, 15, -1, 21, 17, 14, 9, 15, -1, 21, 17, -1, -1, 26, -1, 26, 16}; + + + +const short offset_in_lvq_mode_SN[][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 short offset_in_lvq_mode_pred[][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 short offset_lvq_modes_SN[] = {-1,-1,26,51,77,96,-1,-1,12,36,66,90,-1,-1,105,-1,88,102, + 112 + }; /* CNG */ + +const short offset_lvq_modes_pred[] = {74, 95, 15, 45, -1, 66, 81, 102, 0, 30, -1, 60, 88, -1, 109, 117, -1, 139, 124}; + + +/*-----------------------------------------------------------------* + * BC-TCVQ frame-end quantization tables (BC-TCVQ is used in Voiced mode for 16kHz isf) + *-----------------------------------------------------------------*/ +const int 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 int 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 short BC_TCVQ_BIT_ALLOC_40B[M/2+4] = {1, 4, 5,5,4,4, 2,2,2,2, 5,4 }; /*1+39bit*/ + +const short 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 */ +}; + +/* Intra-Prediction */ +const float AR_IntraCoeff[N_STAGE_VQ-1][2][2] = +{ + {{-0.292479f, 0.676331f}, {-0.422648f, 0.217490f}}, + {{ 0.048957f, 0.500476f}, { 0.087301f, 0.287286f}}, + {{ 0.199481f, 0.502784f}, { 0.106762f, 0.420907f}}, + {{ 0.240459f, 0.440504f}, { 0.214255f, 0.396496f}}, + {{ 0.193161f, 0.494850f}, { 0.158690f, 0.306771f}}, + {{ 0.093435f, 0.370662f}, { 0.065526f, 0.148231f}}, + {{ 0.037417f, 0.336906f}, {-0.024246f, 0.187298f}} +}; + +const float SN_IntraCoeff[N_STAGE_VQ-1][2][2] = +{ + {{-0.452324f, 0.808759f}, {-0.524298f, 0.305544f}}, + {{ 0.009663f, 0.606028f}, {-0.013208f, 0.421115f}}, + {{ 0.144877f, 0.673495f}, { 0.080963f, 0.580317f}}, + {{ 0.208225f, 0.633144f}, { 0.215958f, 0.584520f}}, + {{ 0.050822f, 0.767842f}, { 0.076879f, 0.416693f}}, + {{ 0.005058f, 0.550614f}, {-0.006786f, 0.296984f}}, + {{-0.023860f, 0.611144f}, {-0.162706f, 0.576228f}} +}; + +const float scale_ARSN[M] = {1.8307f, 1.8404f, 1.8009f, 1.7416f, 1.7240f, 1.7467f, 1.6106f, 1.6497f, 1.5702f, 1.5548f, 1.5745f, 1.6199f, 1.5633f, 1.5239f, 1.5796f, 1.5615f}; +const float scale_inv_ARSN[M] = {0.5462f, 0.5434f, 0.5553f, 0.5742f, 0.5800f, 0.5725f, 0.6209f, 0.6062f, 0.6369f, 0.6432f, 0.6351f, 0.6173f, 0.6397f, 0.6562f, 0.6331f, 0.6404f}; + +/* TCVQ Codebook */ +const float AR_TCVQ_CB_SUB1[2][128][2] = +{ + { + {-170.0561F,-169.3847F,},{-90.97870F,48.531700F,},{-148.6968F,17.218300F,},{-107.0229F,-34.21990F,},{-129.8378F,-87.31650F,},{-220.1001F,-234.4751F,},{-129.6736F,52.471700F,},{20.510900F,-288.6602F,}, + {-221.5495F,-0.070200F,},{58.214300F,123.37490F,},{-74.50640F,211.33990F,},{-48.14920F,123.86970F,},{-192.6126F,-247.4666F,},{-206.1983F,104.78470F,},{-125.3893F,-150.7979F,},{-168.7912F,-86.03110F,}, + {-95.16320F,-89.65400F,},{-12.70900F,177.33540F,},{-73.43770F,-250.7212F,},{-51.23060F,-84.00830F,},{-264.2502F,102.67830F,},{-184.2570F,-157.5882F,},{-121.9781F,-62.24850F,},{-132.6231F,115.89740F,}, + {-47.38870F,-84.58990F,},{-2.521300F,94.296500F,},{-79.13010F,-82.28630F,},{-49.25610F,-5.992200F,},{-286.7041F,-146.2168F,},{-178.7492F,-2.262600F,},{-115.8487F,-10.64920F,},{-119.9947F,-216.1283F,}, + {-69.10170F,1.3002000F,},{-68.48210F,-106.6926F,},{24.572700F,141.84890F,},{51.813600F,206.02520F,},{-51.84400F,-72.25850F,},{-175.4067F,-470.9963F,},{-112.2572F,-109.9498F,},{-51.26580F,339.48830F,}, + {-38.93840F,-40.88940F,},{-29.20570F,-69.73790F,},{-55.22180F,51.015500F,},{-12.33040F,42.160700F,},{-31.81780F,63.017700F,},{-174.1785F,-89.95120F,},{-110.4181F,-345.4240F,},{-49.84300F,-64.35890F,}, + {-59.63520F,-175.9810F,},{-69.02910F,-44.58650F,},{-43.97120F,-49.59230F,},{-87.25920F,-138.5465F,},{-96.25540F,-174.5186F,},{-154.7553F,-275.2756F,},{-109.5143F,128.62810F,},{-14.54350F,-25.04360F,}, + {-46.05230F,81.366800F,},{-32.03440F,24.870900F,},{-132.5154F,-143.2318F,},{-22.59640F,-51.55940F,},{-178.7877F,251.71930F,},{-148.7196F,-212.2087F,},{-106.1241F,217.56180F,},{24.099800F,29.423900F,}, + {-119.7589F,-323.8735F,},{121.21500F,173.78130F,},{28.604700F,-10.13160F,},{37.177600F,85.584900F,},{87.071500F,238.62500F,},{109.09800F,76.070100F,},{167.92980F,224.78890F,},{165.46650F,86.241500F,}, + {-9.919200F,0.5865000F,},{126.17610F,92.028000F,},{-38.94060F,-121.2069F,},{4.4071000F,-13.64760F,},{32.528700F,-1.269700F,},{109.85480F,288.47620F,},{193.40720F,153.42400F,},{34.912700F,501.59090F,}, + {12.630000F,53.019400F,},{11.431500F,13.336900F,},{191.94830F,224.70850F,},{40.979900F,-73.55240F,},{5.8897000F,-171.8742F,},{111.18560F,4.0700000F,},{201.66060F,-41.15440F,},{122.30070F,274.89960F,}, + {-2.425900F,-107.2105F,},{-24.07350F,-25.13440F,},{-4.758000F,-49.75210F,},{66.313900F,932.60360F,},{63.427900F,76.575200F,},{131.07660F,161.35400F,},{211.93280F,81.864800F,},{90.057500F,-27.39110F,}, + {-0.656200F,269.81920F,},{38.372300F,52.479100F,},{9.8096000F,55.003200F,},{101.87250F,118.98060F,},{121.92950F,-125.7858F,},{131.37830F,88.916800F,},{218.95100F,305.25590F,},{299.20050F,200.64100F,}, + {-5.459000F,-45.76330F,},{64.972100F,353.45030F,},{-19.39350F,0.4459000F,},{183.81020F,144.04150F,},{134.69810F,96.639400F,},{135.54900F,-149.4564F,},{219.02860F,440.63140F,},{200.41160F,402.24270F,}, + {39.254000F,-5.942300F,},{72.189700F,27.428900F,},{65.129100F,51.010200F,},{47.723500F,14.090300F,},{219.06510F,290.25100F,},{156.45050F,43.423900F,},{232.59480F,-226.2346F,},{263.13970F,83.869400F,}, + {74.758000F,73.874300F,},{14.975400F,-30.59550F,},{167.16620F,0.0965000F,},{101.95820F,53.053900F,},{-11.37910F,-38.59220F,},{158.02420F,120.38810F,},{239.72370F,224.38630F,},{657.07030F,665.65960F,}, + }, + + { + {-368.0999F,-65.52540F,},{-102.2718F,-140.9826F,},{-20.59040F,-66.70470F,},{-95.79090F,184.47330F,},{-837.7641F,-904.4130F,},{-510.6703F,492.69680F,},{-339.6600F,-757.9813F,},{-254.7818F,-220.3240F,}, + {-195.1893F,174.78510F,},{-225.8519F,-77.48110F,},{-216.3949F,43.255000F,},{-38.17870F,-32.99880F,},{-513.7912F,0.1722000F,},{-480.2339F,-631.9721F,},{-338.9732F,89.728000F,},{-150.2896F,414.33830F,}, + {-299.8150F,-389.7000F,},{-78.78780F,-23.51500F,},{-110.4856F,-76.99170F,},{-55.54460F,-127.1259F,},{-217.9132F,295.10380F,},{-475.2952F,178.16700F,},{-313.6053F,299.37920F,},{-383.7671F,290.27470F,}, + {-162.0853F,-139.3168F,},{-10.81860F,411.75810F,},{44.425800F,-95.93580F,},{31.498700F,285.88550F,},{-313.9570F,-197.7654F,},{-439.8449F,-43.63990F,},{-311.4479F,-51.44460F,},{-112.9209F,-79.77700F,}, + {-135.4290F,-11.18290F,},{-14.37020F,-101.2914F,},{-55.36790F,-170.9950F,},{-97.12010F,33.922700F,},{-341.4857F,133.28130F,},{-419.5535F,-1029.264F,},{-261.0493F,-606.2968F,},{-445.1823F,-298.5443F,}, + {-95.70290F,-200.4782F,},{-18.66770F,205.38260F,},{5.2869000F,154.20340F,},{-176.5040F,-252.4035F,},{-172.0901F,-378.6187F,},{-372.2359F,-501.4665F,},{-252.0296F,-151.3651F,},{-287.6742F,43.301600F,}, + {-63.75070F,119.02160F,},{-136.2005F,87.531000F,},{-87.96100F,287.68010F,},{36.839700F,-33.04480F,},{-118.0163F,-214.5814F,},{-365.9238F,-348.5409F,},{-236.4188F,-425.5134F,},{-25.16220F,-39.63130F,}, + {-63.00320F,-82.32200F,},{-152.9630F,-507.2372F,},{-57.66390F,48.660600F,},{5.3785000F,51.097300F,},{-168.7345F,-49.50600F,},{-359.4378F,-199.1688F,},{-233.7651F,-285.0083F,},{33.347500F,60.305100F,}, + {9.5961000F,-60.67060F,},{-22.43980F,93.048400F,},{184.09080F,107.94670F,},{164.32090F,265.57780F,},{-67.49340F,123.30580F,},{233.22030F,704.96710F,},{353.99250F,-262.9922F,},{210.06920F,175.77800F,}, + {-104.2510F,-314.3242F,},{0.9024000F,-7.495400F,},{86.823700F,85.372000F,},{72.376700F,137.49970F,},{-13.00090F,-69.46920F,},{236.74980F,46.279600F,},{374.54780F,-27.20110F,},{136.88650F,-35.73790F,}, + {-34.16180F,16.487600F,},{283.87900F,353.51860F,},{21.261500F,12.921800F,},{123.46920F,17.014100F,},{98.105500F,5.7719000F,},{238.18290F,-47.81850F,},{386.73840F,560.96730F,},{32.152700F,578.18980F,}, + {70.706200F,208.99530F,},{69.254100F,50.614900F,},{273.61320F,220.89670F,},{244.46280F,129.16830F,},{108.85950F,215.41490F,},{265.47770F,276.31920F,},{395.46140F,283.90850F,},{412.94530F,299.13520F,}, + {-5.075000F,-154.7571F,},{142.09250F,160.91980F,},{172.66840F,-70.68220F,},{79.050300F,-150.7248F,},{220.80900F,545.83980F,},{289.05480F,1023.7731F,},{421.94000F,140.86480F,},{436.59640F,74.580500F,}, + {31.476700F,103.73850F,},{84.791000F,-50.67070F,},{136.49490F,394.28200F,},{264.97310F,-186.0375F,},{531.67460F,343.03590F,},{310.71060F,184.35030F,},{494.98260F,403.81940F,},{406.31780F,490.15840F,}, + {137.11870F,78.459100F,},{-26.93550F,-247.3193F,},{-13.90060F,-408.4927F,},{315.74950F,11.906200F,},{507.81160F,-77.48790F,},{313.84650F,400.68920F,},{543.13960F,-127.4566F,},{895.02000F,968.45590F,}, + {65.022700F,5.1458000F,},{203.36110F,32.767800F,},{99.442400F,-280.2416F,},{385.57300F,174.81870F,},{303.53400F,86.087500F,},{316.97760F,81.139300F,},{545.10640F,789.31480F,},{585.50660F,162.80340F,}, + } +}; + +const float AR_TCVQ_CB_SUB2[2][64][2] = +{ + { + {-139.4748F,-20.51230F,},{-205.2710F,65.240700F,},{-90.66390F,99.509000F,},{-51.55990F,-140.1515F,},{-367.2977F,-86.40560F,},{-101.5758F,-506.4093F,},{-467.6164F,-177.7713F,},{-325.3952F,19.243000F,}, + {-51.50950F,-0.580700F,},{-156.7042F,-109.3179F,},{-82.92030F,-84.85600F,},{-75.64660F,36.105400F,},{-226.3753F,-277.4524F,},{-336.8399F,-293.0652F,},{-261.4553F,168.08600F,},{-203.4850F,280.69810F,}, + {-242.0593F,-177.4998F,},{-93.17880F,198.93370F,},{-6.034900F,-224.4959F,},{152.10510F,274.83370F,},{-347.4922F,202.31740F,},{-450.9290F,32.755600F,},{-246.8381F,-399.5943F,},{-242.2880F,-493.4214F,}, + {-104.8258F,-183.7260F,},{-127.2704F,-288.3692F,},{17.116300F,247.94440F,},{28.590000F,141.33180F,},{-88.39520F,-8.409100F,},{-244.1211F,-41.49450F,},{-281.3448F,-44.43050F,},{-435.1837F,-417.8239F,}, + {7.2419000F,-97.64420F,},{32.515300F,38.550200F,},{13.574300F,-6.174500F,},{102.88080F,-123.3195F,},{184.39410F,428.29360F,},{-20.13120F,-127.9658F,},{-97.25060F,379.22250F,},{541.89470F,342.12550F,}, + {3.8567000F,79.183500F,},{339.32440F,253.39800F,},{87.921000F,66.552800F,},{117.63820F,32.476100F,},{490.72400F,188.26100F,},{152.82630F,-303.6073F,},{415.46300F,-125.0126F,},{20.317700F,471.51620F,}, + {120.83170F,146.52980F,},{183.34470F,88.231900F,},{241.62970F,156.33030F,},{23.616600F,-36.17640F,},{130.82320F,95.319300F,},{123.34420F,-25.34570F,},{-17.53680F,-385.5626F,},{253.17360F,-114.7059F,}, + {85.112600F,-25.82990F,},{-42.33470F,-51.85570F,},{195.47230F,-7.405400F,},{322.01970F,63.832500F,},{188.75460F,-173.2249F,},{506.79120F,93.875700F,},{390.46690F,470.76120F,},{243.34080F,526.34460F,}, + }, + + { + {-165.6917F,-377.1008F,},{-17.98370F,-75.86160F,},{7.9923000F,116.25350F,},{-130.2646F,-108.4639F,},{-311.2591F,-203.8264F,},{-339.0670F,-23.57200F,},{-7.653600F,-54.53950F,},{-423.8622F,-353.1093F,}, + {-240.0843F,-95.08200F,},{-143.2687F,8.5443000F,},{-101.9498F,-202.8074F,},{-43.42630F,-10.37850F,},{-291.0372F,55.326100F,},{-189.0665F,-593.2565F,},{-128.3240F,5.0444000F,},{-420.8219F,35.762800F,}, + {-206.5327F,85.114800F,},{-202.6915F,-233.0529F,},{-107.8853F,-28.10810F,},{-33.95630F,-155.5147F,},{-19.77350F,-490.9996F,},{-113.7118F,159.73310F,},{-345.0899F,238.75620F,},{68.787700F,-156.6325F,}, + {-52.29900F,-95.54260F,},{14.606500F,197.56230F,},{9.1784000F,-3.906100F,},{-88.07510F,114.63690F,},{-356.4571F,-517.1363F,},{-68.02240F,-113.1240F,},{-424.2482F,-150.8795F,},{-54.13860F,-30.29230F,}, + {-48.11040F,48.722800F,},{-9.974700F,-288.3043F,},{44.249300F,-134.2835F,},{68.270600F,70.915400F,},{294.67340F,-174.3828F,},{471.33110F,206.81070F,},{363.89680F,386.90480F,},{52.930000F,47.618800F,}, + {104.26640F,127.63530F,},{149.10830F,-71.25040F,},{280.53550F,183.93680F,},{288.38200F,42.039600F,},{61.611600F,50.856600F,},{170.86680F,156.74650F,},{139.90090F,-260.6101F,},{539.24370F,326.70950F,}, + {71.975100F,-6.711500F,},{169.81850F,90.253300F,},{157.30500F,24.483300F,},{59.160200F,-48.84550F,},{-42.61460F,-92.55310F,},{270.15440F,-94.32920F,},{487.06470F,75.464100F,},{345.55540F,126.52380F,}, + {-110.4957F,258.30830F,},{17.373900F,41.055800F,},{60.912700F,355.85580F,},{151.18090F,229.57390F,},{269.34040F,569.72710F,},{259.50450F,412.82330F,},{-14.73050F,568.47830F,},{252.07040F,354.99801F,}, + } +}; + +const float AR_TCVQ_CB_SUB3[4][32][2] = +{ + { + {-190.2462F,3.7460000F,},{-178.0891F,-156.6944F,},{37.733100F,176.00550F,},{-93.45970F,165.15130F,},{-267.7612F,-511.1700F,},{27.017600F,-276.8829F,},{-118.0160F,-462.8076F,},{188.15520F,-112.6265F,}, + {-112.2084F,-272.1046F,},{-75.63800F,28.803700F,},{-62.17480F,-51.65160F,},{-62.91250F,-122.3795F,},{-315.9380F,163.32500F,},{-335.8190F,-361.7829F,},{-10.02270F,-28.26150F,},{-411.0079F,-169.0698F,}, + {21.274600F,52.847800F,},{41.786600F,-55.20310F,},{131.61950F,-6.998400F,},{157.68690F,287.15550F,},{-42.42940F,-201.8275F,},{281.21280F,-25.80890F,},{-13.25970F,522.18800F,},{-66.78560F,354.06180F,}, + {20.563700F,-135.3851F,},{140.59070F,104.26130F,},{279.11580F,136.98410F,},{39.195800F,51.957500F,},{34.262500F,51.346000F,},{381.14700F,390.58580F,},{491.52390F,213.96490F,},{288.60580F,536.49710F,}, + }, + + { + {-133.0008F,-181.1299F,},{-84.55430F,-304.3680F,},{40.548600F,-157.9567F,},{-35.81290F,-86.14820F,},{-296.9231F,-235.1026F,},{-357.0671F,-316.6972F,},{-258.1654F,-349.4409F,},{-504.7979F,-113.4180F,}, + {-123.9764F,51.459200F,},{-224.7199F,-60.69300F,},{-89.06170F,-50.36220F,},{-100.2134F,190.61760F,},{-111.9099F,-529.1262F,},{-36.32900F,-101.2426F,},{-311.5327F,69.813400F,},{-318.3195F,-534.8423F,}, + {84.270600F,222.53200F,},{-0.942100F,28.769200F,},{213.25620F,65.535600F,},{97.994500F,73.849700F,},{30.130700F,19.067100F,},{-368.2725F,229.34600F,},{148.61930F,481.44170F,},{418.05130F,44.184400F,}, + {45.929700F,-10.41460F,},{151.92930F,-55.78590F,},{7.0662000F,84.175000F,},{287.46830F,226.85480F,},{429.16810F,486.29900F,},{176.48300F,159.59660F,},{579.15160F,254.26680F,},{-68.04440F,453.68870F,}, + }, + + { + {-100.1363F,-189.9851F,},{-26.01900F,223.37290F,},{-2.345900F,62.933400F,},{-66.92170F,59.692200F,},{-463.9627F,-172.0395F,},{-422.4871F,43.361300F,},{-250.2149F,-359.6565F,},{-90.88240F,-37.63640F,}, + {-199.5678F,57.586700F,},{-112.5751F,-36.52960F,},{189.51950F,260.19820F,},{-238.2629F,-142.8535F,},{-139.3418F,-351.6046F,},{-336.3076F,-424.9823F,},{-30.62490F,-40.98700F,},{-103.6085F,-330.2230F,}, + {5.6849000F,7.1876000F,},{31.018100F,-149.6002F,},{-80.41110F,-100.6484F,},{119.56500F,103.01690F,},{11.508400F,27.501500F,},{13.331700F,25.835000F,},{457.61300F,261.34590F,},{52.531100F,28.992900F,}, + {203.48110F,71.918000F,},{51.549200F,32.858000F,},{141.30200F,-35.55590F,},{22.330400F,-70.91510F,},{349.22210F,178.05560F,},{447.99330F,289.70830F,},{82.904000F,107.10660F,},{348.09590F,102.38850F,}, + }, + + { + {37.061900F,181.46230F,},{3.6812000F,53.960400F,},{-142.5384F,-250.3814F,},{-155.8055F,67.085000F,},{-97.44510F,-42.54350F,},{-36.71330F,-123.6734F,},{-63.68890F,-97.47460F,},{-233.4995F,-274.8922F,}, + {-72.26240F,14.184600F,},{-183.6676F,-77.60290F,},{25.462700F,93.954700F,},{-40.64230F,-141.5510F,},{-85.75550F,-313.0151F,},{-338.1776F,-25.63660F,},{-363.6425F,-156.2840F,},{-67.37240F,-51.54950F,}, + {-58.24200F,-193.3120F,},{181.77980F,98.461400F,},{-70.01130F,-27.99830F,},{171.39450F,112.01820F,},{321.84770F,218.43910F,},{12.987700F,52.170200F,},{22.943500F,52.400800F,},{34.529100F,56.928800F,}, + {72.765700F,16.633700F,},{26.847700F,-102.3211F,},{104.45050F,-37.68410F,},{15.601300F,31.425000F,},{32.724900F,50.955400F,},{264.88060F,147.81980F,},{316.65590F,175.13690F,},{359.29350F,211.19690F,}, + } +}; + +const float SN_TCVQ_CB_SUB1[2][128][2] = +{ + { + {-249.7201F,40.935000F,},{-190.5588F,-175.3474F,},{-207.0069F,-316.9469F,},{-163.5806F,-247.6570F,},{-304.9679F,-414.6172F,},{-228.6147F,150.62910F,},{-195.6332F,-287.7428F,},{-190.9146F,-284.4862F,}, + {-274.4084F,-267.7108F,},{-199.2563F,-297.6162F,},{-152.2094F,-112.0928F,},{-148.0732F,-148.0190F,},{-223.7592F,-331.2033F,},{-227.6105F,-303.8584F,},{-195.2056F,-316.4586F,},{-262.2246F,-164.0172F,}, + {-201.5461F,313.27600F,},{-103.5079F,-192.2481F,},{-204.4250F,-221.9848F,},{-76.03550F,1125.8286F,},{-234.5633F,-67.04640F,},{-221.8844F,-339.4012F,},{-194.2347F,258.93820F,},{-251.0932F,-362.9766F,}, + {-135.0324F,-147.6629F,},{-98.67180F,-122.1392F,},{-163.4477F,232.42880F,},{-93.88090F,-181.8259F,},{-165.4640F,-213.2693F,},{-217.3162F,-119.1242F,},{-194.1371F,958.06900F,},{-176.2805F,-91.93370F,}, + {-176.7314F,-261.5485F,},{-143.7121F,-243.8883F,},{-148.1108F,-258.7831F,},{-118.9980F,-33.07910F,},{-214.2710F,155.74650F,},{-213.2181F,-251.6092F,},{-188.9855F,-166.4937F,},{-151.3290F,-213.3292F,}, + {-127.0467F,-214.8412F,},{-89.61480F,46.211900F,},{-32.48210F,392.23270F,},{-46.92120F,181.57460F,},{-113.0420F,-86.90470F,},{-201.7185F,60.547200F,},{-187.6557F,583.69500F,},{-161.9915F,53.907100F,}, + {-163.7852F,-39.11590F,},{-135.6215F,426.20040F,},{-169.3460F,29.788000F,},{-53.86960F,-113.5168F,},{-169.7033F,-280.7249F,},{-200.7809F,368.96580F,},{-184.8111F,-10.30170F,},{-56.33640F,-124.8625F,}, + {-146.8623F,587.82200F,},{-128.5270F,146.07030F,},{-123.4510F,-196.9422F,},{-22.75330F,-2.165400F,},{-105.3485F,-182.0782F,},{-198.0657F,-211.0788F,},{-181.9700F,-70.67280F,},{-100.1089F,-202.3083F,}, + {-76.38740F,283.61110F,},{-34.55220F,-139.0253F,},{-72.58420F,-153.9831F,},{11.931600F,-78.54570F,},{-30.11220F,-124.4284F,},{159.48950F,53.219000F,},{246.00260F,265.74940F,},{341.77020F,533.29990F,}, + {-78.13370F,-74.09460F,},{64.957700F,503.70880F,},{234.41130F,423.72930F,},{107.71920F,181.32610F,},{221.30620F,615.15230F,},{166.00660F,108.59500F,},{260.32690F,147.33710F,},{472.14910F,915.47850F,}, + {-71.05110F,-159.7740F,},{-37.06930F,-55.00150F,},{25.370000F,198.17320F,},{49.636800F,82.767400F,},{132.76160F,91.831000F,},{187.70590F,159.38410F,},{281.83160F,469.86870F,},{434.41380F,295.44770F,}, + {63.308300F,141.27590F,},{54.061700F,294.21520F,},{-65.88060F,-50.19340F,},{72.918300F,-12.50020F,},{26.680200F,-36.36690F,},{206.31630F,1119.4720F,},{306.99130F,308.17540F,},{487.14390F,573.31600F,}, + {-185.9491F,948.56350F,},{7.6792000F,52.069300F,},{0.9533000F,-92.26370F,},{166.57380F,312.24880F,},{153.64230F,230.62340F,},{207.81570F,610.05630F,},{315.18780F,208.51600F,},{550.64840F,410.71780F,}, + {-5.303600F,-102.8303F,},{32.350300F,-61.52830F,},{61.661100F,-14.86550F,},{240.57980F,214.70890F,},{329.97410F,212.08160F,},{209.52500F,92.791300F,},{356.06930F,594.08890F,},{638.68310F,525.05230F,}, + {45.061100F,-21.59060F,},{102.92090F,33.850300F,},{-49.38050F,91.477600F,},{147.03860F,74.554000F,},{179.35820F,1032.6932F,},{211.70910F,362.16160F,},{367.65010F,370.43750F,},{740.51460F,596.78260F,}, + {-7.303000F,724.00010F,},{177.80790F,142.93470F,},{213.00960F,110.61410F,},{324.63510F,326.04950F,},{475.33930F,330.59920F,},{218.87990F,211.76850F,},{395.71800F,253.94620F,},{744.16310F,915.21080F,}, + }, + + { + {-206.2475F,-95.90960F,},{-246.3082F,21.747300F,},{-280.0828F,-108.0290F,},{-15.81770F,518.20420F,},{-394.8764F,-268.7632F,},{-323.0682F,-133.0426F,},{-256.3050F,-624.6605F,},{-387.5242F,-608.8890F,}, + {-175.6982F,364.49880F,},{-210.8799F,823.99400F,},{-233.7273F,-494.8845F,},{-151.1368F,-199.8177F,},{-429.7681F,-772.9858F,},{-317.0574F,-240.9158F,},{-253.5630F,-57.26850F,},{-341.3936F,228.86220F,}, + {-281.1353F,-234.9062F,},{-109.7592F,-108.9512F,},{-225.6748F,247.90130F,},{65.929400F,31.226900F,},{-398.6104F,-52.49470F,},{-310.1716F,101.05650F,},{-249.3468F,320.56650F,},{-354.3097F,16.494000F,}, + {-277.0976F,-595.7491F,},{-188.3772F,523.29140F,},{-90.61150F,-382.6038F,},{40.513800F,903.74660F,},{-358.6226F,-460.4389F,},{-308.4215F,501.50370F,},{-237.7401F,882.27940F,},{-333.4506F,-381.9203F,}, + {-243.6204F,127.42030F,},{-75.62440F,666.13180F,},{-34.39620F,414.18390F,},{149.42210F,464.74430F,},{-162.1738F,5.7292000F,},{-308.1293F,-447.4555F,},{-236.0531F,158.90870F,},{-339.5853F,443.61930F,}, + {-196.4904F,-408.9761F,},{-212.8717F,-310.0990F,},{-50.11780F,183.79020F,},{32.747800F,249.33110F,},{-231.0534F,-589.2890F,},{-273.0207F,681.87410F,},{-234.5115F,-144.0888F,},{-306.1589F,641.38990F,}, + {-86.46690F,-261.1131F,},{-87.17310F,101.82230F,},{-32.13380F,-174.4069F,},{-147.5939F,-474.4269F,},{-289.3846F,378.38780F,},{-269.2454F,-337.1601F,},{-222.4565F,-232.3191F,},{-395.3117F,-157.5576F,}, + {-129.1616F,202.52440F,},{-68.35150F,307.27670F,},{-85.86670F,-1.271900F,},{-17.84710F,-328.4484F,},{-374.8384F,115.94100F,},{-260.0821F,26.484400F,},{-220.8236F,-532.8561F,},{-103.5023F,-8.057100F,}, + {253.68710F,299.43310F,},{99.798300F,140.48320F,},{132.05620F,-133.5340F,},{649.87660F,635.39510F,},{80.181400F,-88.45330F,},{377.92370F,11.967000F,},{475.26380F,362.41510F,},{663.04860F,481.53290F,}, + {125.93200F,564.57300F,},{125.00390F,699.34770F,},{161.43320F,82.756400F,},{388.46600F,81.488500F,},{299.40020F,103.03960F,},{380.48160F,344.82180F,},{479.55360F,94.266000F,},{656.04440F,313.06860F,}, + {29.314100F,121.82290F,},{294.35730F,556.75000F,},{136.00140F,242.52100F,},{251.75710F,185.26940F,},{393.60200F,297.97100F,},{404.77110F,790.64840F,},{528.97090F,207.17710F,},{629.35130F,831.62210F,}, + {63.429500F,363.62860F,},{344.74340F,320.98350F,},{386.67160F,190.67860F,},{240.19720F,-79.32440F,},{753.49380F,482.21660F,},{413.70600F,537.17310F,},{539.83860F,557.06520F,},{800.08120F,624.70540F,}, + {234.99860F,63.354100F,},{148.31920F,320.29180F,},{277.09270F,415.69540F,},{456.34320F,536.84340F,},{214.59280F,227.59820F,},{414.97560F,183.63070F,},{552.78850F,426.47270F,},{818.25130F,872.82940F,}, + {73.162100F,-246.0924F,},{46.113400F,-192.6345F,},{278.84370F,698.09160F,},{506.97560F,263.00580F,},{373.99370F,491.39020F,},{422.46610F,438.95710F,},{570.45150F,307.05580F,},{829.71370F,470.72770F,}, + {13.191300F,-73.93830F,},{20.994200F,-13.84500F,},{311.61780F,0.1251000F,},{291.89030F,929.08090F,},{554.80360F,450.16100F,},{436.77840F,653.52060F,},{582.72210F,893.43050F,},{943.77210F,632.08490F,}, + {452.66180F,701.26420F,},{152.06640F,-49.38430F,},{466.26870F,391.67580F,},{616.44670F,391.50590F,},{505.32310F,142.80040F,},{448.40750F,271.20620F,},{590.86500F,699.51280F,},{1072.8364F,818.59820F,}, + } +}; + +const float SN_TCVQ_CB_SUB2[2][64][2] = +{ + { + {-276.9441F,-237.9956F,},{-240.2330F,-400.5215F,},{-168.0618F,-125.3249F,},{-17.18770F,403.15550F,},{-410.3021F,-12.59720F,},{-401.4485F,-725.0255F,},{-378.9797F,-42.53260F,},{-223.4008F,-557.0544F,}, + {-221.8536F,60.339100F,},{-55.66380F,-73.67660F,},{-31.18270F,208.03420F,},{-14.70030F,-246.7032F,},{-152.7168F,497.98040F,},{-385.0540F,-285.9732F,},{-187.2953F,-199.3057F,},{-377.2813F,37.510600F,}, + {-330.8419F,-541.7451F,},{-349.7656F,237.12440F,},{-143.6113F,-363.2778F,},{-150.6399F,137.64050F,},{-113.2274F,3.7534000F,},{-325.2374F,36.570200F,},{-206.2273F,671.09990F,},{-82.19470F,45.011800F,}, + {-206.7859F,334.70390F,},{-283.9658F,-89.72660F,},{-50.10190F,12.089100F,},{51.980300F,29.857900F,},{-107.5514F,-303.3203F,},{-240.0561F,-533.9766F,},{-132.4427F,-5.247100F,},{-404.3979F,480.69020F,}, + {175.02300F,332.36460F,},{233.95710F,41.575700F,},{430.97410F,434.21950F,},{248.10350F,487.89410F,},{297.34090F,302.33480F,},{207.50040F,-27.75610F,},{281.96760F,184.93040F,},{299.70790F,161.32720F,}, + {100.61040F,107.78600F,},{135.17980F,-148.3558F,},{190.27510F,196.71720F,},{435.19680F,47.673600F,},{344.53480F,606.71120F,},{774.72370F,483.79650F,},{830.43490F,475.25730F,},{680.48470F,492.90810F,}, + {52.827400F,-98.47120F,},{84.402600F,213.06580F,},{195.15830F,-48.72150F,},{538.51170F,746.06460F,},{118.75210F,29.688100F,},{589.58180F,237.71470F,},{602.54520F,540.84130F,},{211.57020F,715.21980F,}, + {-93.92180F,-182.2399F,},{301.03150F,254.59590F,},{356.44790F,109.52270F,},{510.59830F,279.64910F,},{716.35110F,402.13940F,},{409.68830F,191.91910F,},{634.49470F,286.14310F,},{974.51980F,759.27030F,}, + }, + + { + {-284.8923F,-332.8634F,},{-230.3763F,119.65300F,},{-155.3427F,115.29910F,},{-12.21440F,5.0214000F,},{-257.4728F,-29.15460F,},{-235.7490F,-480.0754F,},{-202.7355F,-263.5491F,},{-321.4648F,18.445600F,}, + {-294.7758F,-80.74580F,},{-319.5455F,-165.6476F,},{-275.4234F,-501.8569F,},{-100.6586F,-323.5581F,},{-315.1043F,-276.3239F,},{-71.14410F,-278.0978F,},{-362.3847F,1.2822000F,},{-177.8863F,-448.9796F,}, + {-329.8557F,164.76280F,},{-232.8216F,-393.7935F,},{-196.9382F,-183.5567F,},{-179.3588F,287.84510F,},{-131.8585F,-284.4139F,},{-326.5890F,401.69820F,},{-239.3882F,485.08990F,},{-238.0748F,504.86220F,}, + {-111.2109F,13.897700F,},{-109.4982F,-165.7892F,},{39.187700F,49.242200F,},{-179.4392F,-52.56030F,},{-62.00650F,-58.79660F,},{-112.2621F,74.326700F,},{21.768200F,-102.5222F,},{-103.2492F,-123.8958F,}, + {-2.999300F,235.37390F,},{24.464500F,117.61140F,},{209.73120F,-60.41300F,},{112.71650F,222.38860F,},{75.577500F,-161.0497F,},{337.52400F,31.008400F,},{267.89200F,155.94850F,},{328.81130F,647.32140F,}, + {45.064300F,-82.58150F,},{237.66130F,132.73260F,},{4.8216000F,-253.8600F,},{277.79930F,430.66600F,},{39.273100F,199.22940F,},{139.99440F,-162.6469F,},{494.67560F,176.94150F,},{207.76570F,239.06330F,}, + {-100.0752F,-265.5905F,},{15.938200F,454.44360F,},{233.38360F,309.59500F,},{189.17920F,-23.98650F,},{185.76940F,100.17430F,},{675.38230F,486.70190F,},{472.14070F,579.37430F,},{575.03280F,434.82210F,}, + {152.01630F,129.07580F,},{68.559300F,-151.6359F,},{400.30690F,123.64090F,},{409.88600F,286.04450F,},{578.27810F,432.67370F,},{502.13100F,240.50900F,},{675.71990F,390.09750F,},{781.79560F,651.86880F,}, + } +}; + +const float SN_TCVQ_CB_SUB3[4][32][2] = +{ + { + {-147.1049F,-340.6287F,},{-158.8735F,313.47230F,},{-238.5137F,-175.2864F,},{-154.9957F,-34.27780F,},{-186.0273F,-415.2119F,},{-311.3175F,-97.27870F,},{-102.8572F,-258.6216F,},{-184.6271F,589.29930F,}, + {-279.5144F,121.03210F,},{-240.5628F,-383.6411F,},{-289.7553F,-518.3302F,},{77.502600F,128.26760F,},{-349.3453F,-608.3804F,},{-340.3397F,-491.6917F,},{-276.4456F,-539.0219F,},{-308.0319F,-331.5846F,}, + {25.470200F,-122.3889F,},{-23.10160F,-214.1888F,},{-0.632900F,26.756400F,},{142.04180F,-65.81690F,},{247.83350F,718.83400F,},{90.964100F,-139.8895F,},{485.82500F,582.96200F,},{641.17530F,379.95140F,}, + {79.709900F,202.16160F,},{199.84410F,369.96700F,},{239.35830F,94.047800F,},{423.70620F,282.88420F,},{317.36140F,127.76640F,},{337.65540F,94.710900F,},{217.43590F,208.86400F,},{764.35860F,815.30510F,}, + }, + + { + {-370.2650F,11.518200F,},{-323.1142F,-461.2694F,},{-135.8559F,-129.8608F,},{-14.09620F,84.290400F,},{-567.7608F,-453.9710F,},{-266.5970F,-249.6583F,},{-291.9762F,-592.7589F,},{-274.9419F,479.50260F,}, + {-208.9252F,-386.0126F,},{-214.9314F,-42.54240F,},{-186.7444F,227.07210F,},{-121.1719F,-272.9866F,},{-510.8044F,-87.79140F,},{-302.7620F,-617.7623F,},{-324.5998F,-240.0224F,},{-47.00890F,-86.66380F,}, + {12.928800F,78.024900F,},{47.313200F,-86.25450F,},{183.98160F,182.61360F,},{316.09290F,122.14870F,},{371.33160F,278.26560F,},{168.42590F,-225.2161F,},{775.28210F,548.66520F,},{642.86270F,346.51310F,}, + {51.413000F,448.60110F,},{112.29160F,198.86870F,},{133.44860F,-92.65510F,},{392.28070F,469.91310F,},{124.10680F,-283.7072F,},{583.68000F,286.00210F,},{521.95260F,271.37440F,},{931.01620F,692.52800F,}, + }, + + { + {-341.3078F,-146.2225F,},{-92.54280F,10.245600F,},{6.3784000F,340.04950F,},{-277.1624F,169.62960F,},{15.939400F,-300.4278F,},{-413.4964F,-527.4807F,},{25.713000F,81.620300F,},{-395.4344F,-535.2822F,}, + {-30.72550F,-179.8318F,},{-261.9265F,-367.7827F,},{-4.797200F,22.196000F,},{-63.59540F,-168.5926F,},{-320.1832F,-419.0108F,},{-346.2061F,-53.06720F,},{-127.6520F,-195.8498F,},{-21.51770F,-5.277200F,}, + {254.60570F,253.18280F,},{143.04340F,160.79980F,},{240.36910F,98.565800F,},{60.270300F,84.249700F,},{4.6884000F,24.362900F,},{88.200900F,69.498000F,},{659.95560F,473.75490F,},{293.20990F,70.108000F,}, + {11.956700F,71.243400F,},{109.95050F,-114.0644F,},{-138.5130F,-251.0179F,},{366.76410F,361.08470F,},{241.70930F,34.973000F,},{654.41940F,441.34520F,},{322.92560F,106.27710F,},{605.58650F,564.89110F,}, + }, + + { + {-142.8305F,-357.6638F,},{-135.1517F,-91.95450F,},{-202.7971F,-55.12860F,},{10.622800F,119.25650F,},{-99.61230F,-36.02510F,},{-247.5775F,-381.3310F,},{-193.0612F,-420.8008F,},{-130.4904F,-356.4558F,}, + {-220.9295F,27.109700F,},{40.264600F,84.888100F,},{-115.6413F,-362.4221F,},{-195.5899F,-402.2075F,},{-170.5517F,-393.0729F,},{-56.84850F,-56.71290F,},{-82.37190F,-78.84410F,},{24.433000F,140.77510F,}, + {63.625500F,-48.12080F,},{296.32420F,215.87390F,},{32.041200F,80.732200F,},{-69.63830F,-95.39770F,},{63.503200F,133.94610F,},{450.10010F,363.00900F,},{76.867200F,96.687600F,},{16.700500F,-57.93000F,}, + {66.165600F,144.72830F,},{-183.0404F,-407.2658F,},{268.25850F,163.71400F,},{219.75790F,95.572100F,},{411.11030F,329.38500F,},{101.35990F,133.20170F,},{415.09750F,248.72830F,},{337.80520F,255.31020F,}, + } +}; + + + +const float AR_SVQ_CB1[32][8] = +{ + {-0.339000F, 1.5012220F, 6.1853590F, 1.6161480F, 17.3955550F, -42.95738F, 3.77089400F, 65.3032460F}, + {-1.351974F, 0.8601210F, 3.1036570F, -4.589009F, -2.7011160F, 9.0795180F, 109.094322F, -18.118401F}, + {-0.051575F, 0.6542590F, 0.3318340F, 3.1915060F, -28.443743F, -15.45044F, 27.7376230F, -38.083717F}, + {-0.147188F, 0.7379020F, 16.596052F, 29.073309F, -15.221093F, 27.937109F, 10.4191210F, 3.21426900F}, + {-0.174719F, 0.3557820F, 3.3571020F, -2.442146F, 15.4601880F, -25.54004F, -21.377092F, -50.052696F}, + {-0.080591F, -0.031826F, 3.2809340F, -3.976039F, -16.756672F, 41.078621F, -1.8470560F, -49.312294F}, + {0.0404590F, -0.057671F, 4.6628590F, -1.082124F, -38.447117F, -7.158832F, -34.349442F, -28.560730F}, + {-0.191480F, 0.3673300F, -2.228691F, -4.763459F, -19.210003F, -70.05153F, -11.678687F, -5.9500840F}, + {-0.475299F, -0.021802F, 9.2386790F, 30.398779F, 9.72456700F, -26.96944F, -10.201661F, -5.2955280F}, + {-0.118115F, 0.3768040F, -0.202488F, -11.21918F, 8.99932300F, -25.32194F, -49.176136F, 13.3742710F}, + {0.6345730F, -1.451740F, -8.976882F, -2.891539F, -5.2668590F, -0.626124F, -8.6982240F, -1.6381660F}, + {-0.238382F, 0.4619150F, -0.689163F, 17.277664F, -21.009787F, -22.53389F, 41.9676740F, 23.4523370F}, + {0.1244690F, 0.2248090F, -1.099318F, -5.740384F, -21.103287F, 37.994751F, -39.226761F, 15.9438480F}, + {0.1411080F, -0.771317F, -31.48548F, 36.181248F, -5.2501020F, 7.1155840F, -12.062582F, -29.405684F}, + {-0.496825F, 0.9002190F, 0.1078140F, -1.812450F, 64.9175870F, -25.02316F, -18.672247F, 3.00326800F}, + {-0.877380F, -0.101788F, -10.38443F, -42.23261F, 14.1089240F, 1.3607690F, 4.64615900F, -31.426619F}, + {0.0982910F, 0.0130060F, -0.021137F, 1.7109680F, 32.0608750F, -0.580048F, 30.8528560F, 20.9283330F}, + {0.3703540F, -1.599935F, 1.9165930F, -3.437332F, -15.018585F, 112.87896F, 6.09581900F, 6.06509400F}, + {-0.239501F, 0.5997340F, 2.2582460F, -26.70808F, 23.7027260F, 26.134411F, -12.169220F, 39.0906330F}, + {1.1549010F, -2.333077F, 0.9387050F, -0.701751F, -0.2820180F, -2.514828F, -84.775269F, 106.470406F}, + {-0.120044F, 0.4967050F, -16.62750F, -24.21043F, -2.7719380F, -23.45862F, 10.9770750F, 30.4632150F}, + {-0.452348F, 0.9215980F, 4.0024690F, -0.181623F, 29.6472510F, 32.739918F, -21.457884F, -17.419983F}, + {-0.247916F, -0.922579F, 1.4429350F, 1.8360180F, -12.594628F, 29.236597F, 27.3443550F, 68.9287800F}, + {0.7650280F, -0.545622F, -0.185167F, 2.1660980F, 10.6230550F, 11.247939F, -85.990189F, -37.903763F}, + {-0.236738F, 0.4044940F, 35.338413F, -21.96892F, -4.0015380F, -6.422642F, 11.3325710F, 3.03891400F}, + {-0.526660F, 1.1162520F, -3.871234F, -0.059409F, 0.78312500F, -9.391847F, 18.9848520F, -131.23975F}, + {-0.433725F, 0.2320700F, -3.264241F, -3.579835F, 21.6186620F, -52.31819F, 41.0296550F, -17.336693F}, + {-0.150218F, 0.2436480F, -6.385384F, 26.976192F, 20.1004640F, 15.708211F, -20.112616F, 38.2443770F}, + {-0.024170F, 0.8500570F, -4.579786F, -12.50560F, -54.536289F, 19.191902F, 19.6398750F, 10.2497080F}, + {-0.124103F, 1.0465660F, 3.0224720F, 11.137490F, 30.1374190F, 9.5446160F, 29.8574750F, -40.261337F}, + {-0.196671F, 0.7005810F, -9.238495F, -7.187382F, 2.81278600F, 38.941822F, 36.7256850F, 1.86695500F}, + {0.0413730F, -0.259086F, 3.8143860F, 10.183937F, -33.918419F, -13.19506F, -21.927582F, 40.2238810F}, +}; + +const float AR_SVQ_CB2[16][8] = +{ + {-14.44511F, -23.12155F, 81.241760F, -34.49714F, 21.0647720F, 22.618990F, -6.4248760F, -9.472386F}, + {-0.129507F, -38.33505F, 3.5780910F, -25.32102F, -71.163628F, -8.083008F, 7.34998800F, 3.5089460F}, + {-0.531659F, 42.984482F, -2.949942F, 23.185688F, 78.3983150F, 3.3631430F, -14.996096F, -8.493151F}, + {-0.553943F, 15.531711F, -8.511508F, -71.40907F, 18.1345100F, -63.29620F, -15.015837F, -2.255207F}, + {4.7402910F, 0.7143230F, -75.55894F, 25.115595F, -16.831573F, -18.81928F, 4.13968000F, 3.3929720F}, + {-32.50397F, 68.406067F, -3.199107F, -21.32696F, -25.471333F, 25.902178F, 10.0576690F, 2.3217050F}, + {11.180623F, 1.3522740F, 0.9572140F, -3.889576F, -39.069595F, 114.30133F, 29.1799030F, -4.798602F}, + {2.5571490F, -21.08170F, -29.49300F, -35.49685F, 24.4835700F, 46.452934F, -32.716568F, -32.81908F}, + {1.2645100F, 2.9239020F, 2.2633560F, 2.5141150F, -11.900713F, 5.8893120F, -68.704033F, 65.771515F}, + {-4.081663F, 17.567835F, 10.064315F, 22.194927F, -36.000233F, -26.37986F, -45.523380F, -52.28128F}, + {0.0228670F, -14.62688F, -13.12301F, -27.02922F, 41.2410550F, 21.242199F, 47.1964420F, 51.328987F}, + {-9.871984F, -24.99879F, 2.6157990F, 80.172798F, 0.43614800F, 36.480019F, 10.4512970F, 2.2055040F}, + {25.002769F, 10.773156F, 19.834276F, 2.9322950F, -2.5556860F, 6.9424410F, 10.6092970F, 0.1834710F}, + {-7.853089F, 17.244720F, 22.289469F, 30.428480F, -21.601667F, -66.57227F, 34.5492820F, 36.391033F}, + {4.8071940F, -49.02123F, 4.8164340F, 21.801281F, 39.0447200F, -62.45168F, -33.871502F, -1.336098F}, + {-2.572755F, -7.192194F, -2.623712F, -2.309371F, 14.2487590F, -21.16166F, 68.2372970F, -68.92265F}, +}; + + + +const float W_DTX_HO[HO_HIST_SIZE] = +{ + 0.2f, 0.16f, 0.128f, 0.1024f, 0.08192f, 0.065536f, 0.0524288f, 0.01048576f +}; +const float ENR_ATT[5] = +{ + 1.7938412f, 1.3952098f, 1.0962363f, 0.9965784f, 0.9965784f +}; +const float HO_ATT[5] = +{ + 0.5370318f, 0.6165950f, 0.6839116f, 0.7079458f, 0.7079458f +}; + +const short uniform_model[] = { MAX_AR_FREQ, MAX_AR_FREQ / 2, 0 }; + + +/*-----------------------------------------------------------------* + * LSF quantization - mid-frame quantization tables + *-----------------------------------------------------------------*/ + +const float tbl_mid_gen_wb_2b[] = +{ + 0.4656f, 0.6281f, 0.7148f, 0.6457f, 0.6442f, 0.5957f, 0.5953f, 0.5216f, 0.4722f, 0.4609f, 0.4141f, 0.3861f, 0.3809f, 0.3685f, 0.4144f, 0.7097f, + 0.1809f, 0.1051f, 0.2402f, 0.3904f, 0.3790f, 0.4562f, 0.4577f, 0.5524f, 0.6081f, 0.5894f, 0.6131f, 0.6512f, 0.6503f, 0.6465f, 0.6216f, 0.4204f, + 0.4828f, 0.4701f, 0.1855f, 0.2034f, 0.1897f, 0.1691f, 0.1876f, 0.1558f, 0.1762f, 0.1863f, 0.1950f, 0.1997f, 0.2279f, 0.2492f, 0.3031f, 0.2513f, + 0.8591f, 0.9902f, 0.8941f, 0.8507f, 0.8395f, 0.8579f, 0.8529f, 0.8665f, 0.8549f, 0.8490f, 0.8456f, 0.8310f, 0.8161f, 0.7884f, 0.7167f, 0.7381f +}; + + +const float tbl_mid_gen_wb_5b[] = +{ + 0.7947f, 0.9837f, 0.8671f, 0.7440f, 0.7914f, 0.7161f, 0.7356f, 0.7865f, 0.8401f, 0.8431f, 0.8563f, 0.8033f, 0.6896f, 0.4937f, 0.3437f, 0.3075f, + 0.4612f, 0.2591f, 0.4370f, 0.5153f, 0.3171f, 0.5653f, 0.3472f, 0.5987f, 0.6648f, 0.5528f, 0.6331f, 0.7603f, 0.7581f, 0.6949f, 0.7584f, -0.5701f, + 1.1047f, 1.2127f, 1.0304f, 0.9669f, 0.9211f, 0.9570f, 0.9737f, 1.0175f, 1.0595f, 1.0628f, 1.0624f, 1.0506f, 1.0449f, 1.0223f, 0.9471f, 0.7819f, + 0.5180f, 0.7050f, 0.3588f, 0.7186f, 0.4978f, 0.3805f, 0.6429f, 0.6934f, 0.5602f, 0.2931f, 0.0892f, 0.1234f, 0.2023f, 0.5777f, 0.8607f, 0.4873f, + 0.3062f, 0.3852f, 0.4086f, 0.1959f, 0.5432f, 0.5655f, 0.4243f, 0.7347f, 0.4984f, 0.4668f, 0.6266f, 0.7349f, 0.3971f, 0.1670f, 0.2119f, 1.6488f, + 0.7244f, 0.7778f, 0.5486f, 0.3610f, 0.5400f, 0.8138f, 0.9969f, 1.0270f, 0.9713f, 0.8714f, 0.6736f, 0.3734f, 0.3453f, 0.3443f, 0.3385f, 0.3996f, + 0.6084f, 0.6795f, 0.7118f, 0.5561f, 0.6997f, 0.8225f, 0.8165f, 0.5717f, 0.2765f, 0.5144f, 0.8840f, 1.2194f, 1.1934f, 1.1069f, 0.5796f, 0.2798f, + 0.3175f, 0.6022f, 0.3374f, 0.6010f, 0.4594f, 0.4490f, 0.6831f, 0.2538f, 0.7456f, 0.8330f, 0.6722f, 0.6850f, 0.8292f, 0.6778f, 0.1392f, 1.2199f, + 0.8647f, 0.8161f, 0.6485f, 0.6343f, 0.3797f, 0.6515f, 0.4315f, 0.3022f, 0.3024f, 0.2120f, 0.2551f, 0.4923f, 0.6934f, 0.7993f, 0.8923f, 1.4418f, + 0.9937f, 1.0501f, 0.8747f, 0.8225f, 0.7346f, 0.6469f, 0.6941f, 0.5764f, 0.5015f, 0.5440f, 0.4532f, 0.3822f, 0.3245f, 0.2851f, 0.2747f, 0.9828f, + 0.0887f, 0.2277f, 0.7413f, 0.4800f, 0.2756f, 0.2946f, 0.5888f, 0.6998f, 0.6227f, 0.7478f, 0.5725f, 0.1379f, 0.1431f, 0.1805f, 0.4829f, 0.8794f, + 0.7376f, 0.1250f, 0.6556f, 0.7320f, 0.6059f, 0.6806f, 0.6199f, 0.7132f, 0.8434f, 1.0333f, 1.0499f, 0.7492f, 0.6957f, 0.9826f, 1.2112f, 1.0154f, + 0.3330f, 0.1984f, 0.5798f, 0.6109f, 0.7079f, 0.6028f, 0.7755f, 0.3997f, 0.2174f, 0.3778f, 0.1806f, 0.3828f, 0.6677f, 0.1698f, -0.0764f, 0.2957f, + 0.5380f, 0.3941f, 0.1545f, 0.1817f, 0.1492f, 0.1176f, 0.1401f, 0.1443f, 0.1624f, 0.2161f, 0.1050f, 0.0465f, 0.0992f, 0.1548f, 0.2871f, 0.4829f, + 0.2054f, -0.0147f, 0.0101f, 0.1512f, 0.1155f, 0.1964f, 0.2419f, 0.3925f, 0.4822f, 0.5127f, 0.5489f, 0.5979f, 0.5555f, 0.4388f, 0.2863f, 0.2983f, + 0.1288f, 0.3915f, 0.9106f, 0.8310f, 0.8671f, 0.8521f, 0.9646f, 1.0005f, 0.8326f, 0.7556f, 0.7819f, 0.9050f, 0.9725f, 0.9163f, 0.8449f, 1.2049f, + 0.3862f, 0.9760f, 1.0310f, 1.0706f, 1.0307f, 1.0134f, 0.8999f, 0.8605f, 0.7434f, 0.6955f, 0.6213f, 0.5850f, 0.6099f, 0.5950f, 0.5231f, 0.8160f, + 0.4494f, 0.0389f, 0.0654f, 0.3875f, 0.5487f, 0.6697f, 0.7089f, 0.7020f, 0.6666f, 0.5399f, 0.4341f, 0.4210f, 0.6284f, 0.9229f, 0.7662f, 0.4618f, + 0.2426f, 0.5138f, 0.8489f, 0.7178f, 0.9105f, 0.9475f, 0.5281f, 0.6052f, 0.6291f, 0.2624f, 0.3647f, 0.3014f, 0.1434f, 0.1341f, 0.4881f, 0.4822f, + 0.1594f, 0.2811f, 0.9458f, 1.0056f, 0.7466f, 0.3447f, 0.2163f, 0.1379f, 0.3098f, 0.4083f, 0.6490f, 0.5827f, 0.4478f, 0.6663f, 0.6737f, 0.6829f, + 0.5054f, 0.5285f, 0.4076f, 0.3663f, 0.3258f, -0.0096f, -0.0710f, -0.2110f, -0.0830f, 0.1579f, 0.3359f, 0.4516f, 0.4427f, 0.5405f, 0.6043f, 0.3350f, + 0.6481f, 0.4408f, 0.1212f, 0.4304f, 0.2494f, 0.4807f, 0.2526f, 0.1751f, 0.5094f, 0.3185f, 0.3301f, 0.4504f, 0.4499f, 0.2312f, 0.1710f, -0.2053f, + 0.7435f, 0.5872f, 0.1184f, 0.1298f, 0.2084f, 0.3730f, 0.5612f, 0.8230f, 0.9030f, 0.8439f, 0.8983f, 0.9624f, 0.9242f, 0.8337f, 0.7372f, 0.4667f, + 0.8055f, 0.7332f, 0.1523f, 0.5286f, 0.8466f, 0.4619f, 0.4315f, 0.4763f, 0.3932f, 0.6572f, 0.6947f, 0.7321f, 0.7294f, 0.8217f, 1.1139f, 0.6574f, + 0.0249f, 0.0296f, 0.2452f, 0.4120f, 0.4165f, 0.4159f, 0.3285f, 0.3109f, 0.0730f, -0.0183f, 0.0082f, 0.0305f, 0.0754f, 0.1446f, 0.2425f, 0.1412f, + 0.6086f, 0.9737f, 0.8510f, 0.1865f, 0.0105f, 0.0343f, 0.1827f, 0.3665f, 0.5118f, 0.5408f, 0.5763f, 0.6490f, 0.7326f, 0.7545f, 0.8498f, 0.6690f, + 0.8440f, 0.9721f, 0.6413f, 0.3723f, 0.6549f, 0.3935f, 0.4616f, 0.3716f, 0.3139f, 0.3851f, 0.2738f, 0.1968f, 0.2633f, 0.3083f, 0.3398f, -0.1988f, + 0.8972f, 0.8181f, 0.2972f, 0.2365f, 0.3111f, 0.2415f, 0.3441f, 0.3439f, 0.2514f, 0.3043f, 0.4160f, 0.2861f, 0.1513f, 0.1437f, 0.1116f, 0.4593f, + 0.5325f, 0.3790f, -0.1778f, -0.2148f, 0.0383f, 0.1772f, 0.3178f, 0.2004f, 0.2038f, 0.2017f, 0.2756f, 0.3042f, 0.4692f, 0.5370f, 0.6363f, 0.0806f, + 0.0427f, 0.0436f, 0.0133f, 0.0101f, -0.0678f, -0.1081f, -0.0871f, -0.0717f, -0.0147f, 0.0031f, 0.0231f, 0.0648f, 0.0721f, 0.0178f, 0.0190f, 0.1752f, + 0.0608f, 0.0258f, 0.3738f, 0.8259f, 0.8728f, 0.9939f, 0.9193f, 0.9188f, 0.9589f, 0.8421f, 0.8073f, 0.7910f, 0.6457f, 0.5261f, 0.6520f, 0.5040f, + 0.3360f, 0.8495f, 0.8652f, 0.5642f, 0.3230f, 0.2924f, 0.2144f, 0.0397f, 0.0596f, 0.0316f, -0.0152f, -0.0704f, -0.0675f, 0.0751f, 0.0680f, 0.5636f +}; + + + +const float tbl_mid_voi_wb_1b[] = +{ + 0.5556f, 0.5614f, 0.5803f, 0.6146f, 0.6082f, 0.6382f, 0.6492f, 0.6840f, 0.6957f, 0.6899f, 0.6887f, 0.7039f, 0.7110f, 0.7170f, 0.7103f, 0.7392f, + 0.4658f, 0.4096f, 0.2833f, 0.3310f, 0.3540f, 0.3314f, 0.3406f, 0.3062f, 0.3059f, 0.3186f, 0.3194f, 0.2953f, 0.3098f, 0.3201f, 0.3667f, 0.3327f +}; +const float tbl_mid_voi_wb_4b[] = +{ + 0.5294f, 0.5170f, 0.4304f, 0.4984f, 0.4290f, 0.6661f, 0.3867f, 0.3063f, 0.5393f, 0.6129f, 0.1603f, 0.3603f, 0.6527f, 0.4752f, 1.0162f, 1.4353f, + 0.5102f, 0.4928f, 0.4840f, 0.4249f, 0.4917f, 0.4009f, 0.3227f, 0.5597f, 0.5797f, 0.3755f, 0.3920f, 0.1344f, 0.5097f, 0.9082f, 0.7013f, -0.5011f, + 0.5175f, 0.4830f, 0.5432f, 0.6072f, 0.6592f, 0.7000f, 0.7624f, 0.8040f, 0.9490f, 0.3295f, 0.3397f, 0.4241f, 0.1642f, -0.0386f, 0.6188f, 0.5986f, + 0.4839f, 0.4651f, 0.3263f, 0.3700f, 0.2745f, 0.3867f, 0.3851f, 0.5132f, 0.8931f, 0.8760f, 1.0596f, 0.8724f, 0.6003f, 0.5049f, 0.3836f, 0.3676f, + 0.4969f, 0.4703f, 0.4758f, 0.4850f, 0.4228f, 0.3513f, 0.7059f, 0.6520f, 0.2106f, 0.0978f, 0.1457f, 0.5174f, 0.8381f, 0.6043f, 0.0969f, 0.7654f, + 0.4801f, 0.4578f, 0.6019f, 0.4476f, 0.4376f, 0.3113f, 0.5259f, 0.7027f, 0.5497f, 0.8644f, 0.5973f, 0.1313f, 0.0133f, 0.2014f, 0.2304f, 1.0817f, + 0.5863f, 0.5892f, 0.6066f, 0.6727f, 0.7041f, 0.5282f, 0.6442f, 0.6023f, 0.8434f, 0.9365f, 0.6537f, 0.4810f, 1.2195f, 1.1746f, 0.9103f, 0.5129f, + 0.5512f, 0.5199f, 0.2983f, 0.5917f, 0.4551f, 0.5614f, 0.6073f, 0.7500f, 0.4989f, 0.5331f, 0.8576f, 0.6138f, 0.2936f, 0.8562f, 1.6316f, 0.7646f, + 0.5793f, 0.5562f, 0.6601f, 0.7161f, 0.5777f, 0.4990f, 0.4840f, 0.4064f, 0.5700f, 0.3790f, 0.7224f, 0.9551f, 0.7356f, 1.1203f, 0.2266f, 1.6149f, + 0.5042f, 0.5144f, 0.3071f, 0.4324f, 0.5917f, 0.4579f, 0.4522f, 0.2905f, 0.5115f, 0.5843f, 0.5678f, 0.6080f, 0.6961f, -0.0033f, -0.3615f, 0.0158f, + 0.5445f, 0.5767f, 0.6388f, 0.5713f, 0.7336f, 0.8816f, 0.7753f, 0.3746f, 0.0739f, 0.7244f, 0.6869f, 0.4683f, 0.4260f, 0.7398f, 0.4341f, 0.3155f, + 0.5650f, 0.5765f, 0.6671f, 0.5102f, 0.5444f, 0.7536f, 0.7220f, 0.8862f, 0.5741f, 0.5022f, 0.4807f, 1.1700f, 0.9869f, 0.4616f, 0.9180f, 0.0763f, + 0.6106f, 0.6861f, 0.7754f, 0.8440f, 0.8752f, 0.9422f, 0.9259f, 1.0264f, 1.0205f, 0.9623f, 0.8996f, 0.8816f, 0.8076f, 0.7327f, 0.6793f, 1.1467f, + 0.4955f, 0.5031f, 0.5100f, 0.5392f, 0.4195f, 0.1782f, 0.1258f, 0.0135f, 0.0714f, 0.2085f, 0.5150f, 0.6615f, 0.3156f, 0.3900f, 0.7506f, 0.3932f, + 0.4143f, 0.3389f, 0.2405f, 0.3305f, 0.3641f, 0.4799f, 0.3964f, 0.2111f, 0.0548f, -0.0133f, -0.0056f, -0.0572f, 0.0485f, 0.2417f, 0.2814f, 0.1920f, + 0.3978f, 0.2283f, 0.0296f, 0.0478f, 0.0913f, 0.0751f, 0.1447f, 0.1568f, 0.2758f, 0.3280f, 0.2700f, 0.2151f, 0.2654f, 0.2303f, 0.2255f, 0.2530f +}; + +const float tbl_mid_voi_wb_5b[] = +{ + 0.5105f, 0.4663f, 0.5008f, 0.6860f, 0.5005f, 0.5466f, 0.4820f, 0.6168f, 0.3562f, 0.3763f, 0.5162f, 0.4556f, 0.2225f, 0.7751f, 2.1033f, 0.5617f, + 0.5323f, 0.4977f, 0.2730f, 0.5039f, 0.3926f, 0.5704f, 0.7351f, 0.7961f, 0.7014f, 0.5227f, 0.3810f, 0.5430f, 0.7882f, 1.5348f, 0.5372f, 0.9516f, + 0.5161f, 0.4988f, 0.5340f, 0.5273f, 0.5461f, 0.5780f, 0.5404f, 0.6856f, 0.7294f, 0.0169f, 0.7186f, 0.4543f, 0.2812f, -0.4187f, 0.6098f, 0.7624f, + 0.5273f, 0.5303f, 0.4892f, 0.5282f, 0.4056f, 0.8344f, 0.4427f, 0.4065f, 0.3812f, 0.4848f, 0.2908f, 0.2198f, 0.7839f, 0.3860f, 1.1033f, 1.7247f, + 0.5119f, 0.5130f, 0.5387f, 0.3300f, 0.5096f, 0.5286f, 0.3192f, 0.9277f, 0.2096f, 0.4280f, 0.6923f, 0.8753f, 0.4327f, 0.2869f, -0.3342f, 0.8895f, + 0.5090f, 0.4776f, 0.5277f, 0.4664f, 0.5432f, 0.8258f, 0.9150f, 0.9896f, 0.9090f, 0.6744f, 0.3770f, 0.2396f, 0.2459f, 0.4065f, 0.1192f, 0.1223f, + 0.5595f, 0.5394f, 0.4375f, 0.5036f, 0.5839f, 0.6266f, 0.3891f, 0.6103f, 0.5874f, 0.5663f, 1.2253f, 0.8567f, 0.6243f, 0.6796f, 0.4019f, -0.7769f, + 0.4793f, 0.4995f, 0.3308f, 0.3321f, 0.2196f, 0.4284f, 0.5544f, 0.4090f, 0.5595f, 0.7174f, 0.7982f, 0.6268f, 0.1198f, 0.4918f, 0.8815f, 0.0723f, + 0.5645f, 0.5575f, 0.5454f, 0.5652f, 0.6970f, 0.6375f, 0.7182f, 0.3128f, 1.0318f, 0.3448f, 0.0133f, 0.7923f, 0.1477f, 0.3566f, 0.8901f, 0.8689f, + 0.5182f, 0.5078f, 0.6249f, 0.5317f, 0.6768f, 0.3704f, 0.1840f, 0.5101f, 0.7289f, 0.2379f, 0.4136f, 0.0748f, 0.6097f, 1.1010f, 0.8246f, -0.0766f, + 0.5988f, 0.6057f, 0.5528f, 0.8575f, 0.5987f, 0.5457f, 0.6180f, 0.4199f, 0.7749f, 0.7449f, 0.5272f, 0.5365f, 0.9174f, 0.7994f, -0.4513f, 0.7950f, + 0.5716f, 0.5605f, 0.6473f, 0.5607f, 0.5092f, 0.6426f, 0.7466f, 0.9075f, 0.5011f, 0.6658f, 0.3106f, 1.0367f, 0.7924f, 0.1091f, 1.0966f, -0.2937f, + 0.4433f, 0.4193f, 0.4868f, 0.5121f, 0.4497f, 0.2652f, 0.8222f, 0.5557f, -0.0414f, 0.0932f, 0.0376f, 0.4227f, 0.7474f, 0.3534f, 0.3456f, 0.6976f, + 0.5268f, 0.5018f, 0.2730f, 0.3274f, 0.1291f, 0.0664f, 0.3102f, 0.2047f, 0.4332f, 0.3378f, 0.4121f, 0.7203f, 0.8165f, 0.7094f, 0.8077f, 0.4042f, + 0.5477f, 0.5231f, 0.6094f, 0.4463f, 0.7288f, 0.5550f, 0.4852f, 0.7322f, 0.6085f, 0.8074f, 0.5868f, 0.2406f, 1.8234f, 0.5357f, 0.7511f, 0.4092f, + 0.5616f, 0.5749f, 0.6051f, 0.5437f, 0.5948f, 0.8798f, 0.7179f, 0.4225f, 0.2786f, 0.2233f, 0.6857f, 1.2117f, 1.2260f, 0.9426f, 0.3945f, 0.5651f, + 0.4840f, 0.4684f, 0.2549f, 0.5206f, 0.6155f, 0.4246f, 0.5436f, 0.3423f, 0.5080f, 0.5930f, 0.5267f, 0.5302f, 0.6339f, -0.2225f, -0.6138f, -0.1388f, + 0.4198f, 0.3463f, 0.3111f, 0.4959f, 0.3487f, 0.3243f, 0.3250f, 0.6211f, 1.2876f, 1.0880f, 0.8094f, 0.7806f, 0.6797f, 0.3919f, 0.2967f, 0.4151f, + 0.4972f, 0.4686f, 0.7088f, 0.6465f, 0.4597f, 0.2859f, 0.3155f, 0.1088f, 0.3838f, 0.3647f, 0.8309f, 0.5647f, 0.4517f, 0.7146f, 0.1884f, 1.9724f, + 0.5113f, 0.4938f, 0.5241f, 0.5526f, 0.4893f, 0.1725f, 0.5946f, 0.7423f, 0.4025f, 0.7991f, 0.6111f, -0.0446f, -0.2892f, 0.1679f, 0.6741f, 1.0726f, + 0.5833f, 0.5838f, 0.6032f, 0.5539f, 0.5489f, 0.3820f, 0.6023f, 0.5336f, 0.8758f, 0.8451f, 1.0522f, 1.2495f, 1.0576f, 1.2314f, 1.3334f, 0.8928f, + 0.6036f, 0.6123f, 0.7860f, 0.7755f, 0.8086f, 0.7890f, 0.8469f, 0.9213f, 0.8550f, 0.8890f, 0.9344f, 0.8727f, 0.9338f, 0.3353f, 0.4170f, 1.8179f, + 0.5830f, 0.6630f, 0.6732f, 0.7561f, 0.6958f, 0.6695f, 0.3412f, 0.6684f, 0.4912f, 1.0853f, 0.3577f, 0.9663f, 0.4184f, 0.9851f, 0.7226f, 1.6406f, + 0.5759f, 0.6087f, 0.5859f, 0.6453f, 0.8016f, 0.8000f, 0.8058f, 0.1508f, -0.1484f, 0.8003f, 0.7444f, 0.4837f, 0.5323f, 0.6758f, 0.6735f, 0.4804f, + 0.5787f, 0.5712f, 0.6827f, 0.5971f, 0.4699f, 0.6927f, 0.7919f, 0.7616f, 0.8621f, 1.4702f, 1.3328f, 0.2976f, 0.4855f, 0.8906f, 1.0309f, 0.8087f, + 0.5932f, 0.7057f, 0.8047f, 0.9032f, 0.9799f, 1.0813f, 0.9935f, 1.0927f, 1.0693f, 0.6721f, 0.7683f, 0.7983f, 0.7954f, 0.9188f, 0.9385f, 0.4985f, + 0.4977f, 0.4603f, 0.4455f, 0.4127f, 0.4110f, 0.4941f, 0.4759f, 0.5349f, 0.3683f, -0.2632f, -0.1787f, -0.2694f, 0.1011f, 0.5906f, 0.2528f, 0.2884f, + 0.4634f, 0.4195f, 0.4343f, 0.4690f, 0.2649f, 0.5263f, 0.3176f, 0.0849f, 0.2367f, 0.3145f, 0.1513f, 0.0400f, -0.0157f, -0.0790f, 0.2078f, 0.3531f, + 0.4901f, 0.4280f, 0.0448f, 0.1648f, 0.4062f, 0.4517f, 0.4672f, 0.2977f, 0.1751f, 0.4745f, 0.2782f, 0.1945f, 0.4484f, 0.6724f, 0.4767f, -0.3629f, + 0.4990f, 0.4870f, 0.4556f, 0.3975f, 0.5759f, 0.1679f, 0.0186f, -0.0121f, -0.0310f, 0.1391f, 0.4368f, 0.4048f, 0.2680f, 0.2939f, 0.6137f, 0.1220f, + 0.4576f, 0.3876f, 0.1800f, 0.0838f, 0.2449f, 0.2391f, 0.1902f, 0.3734f, 0.6560f, 0.6120f, 0.2977f, 0.2925f, 0.3012f, 0.2707f, 0.1258f, 0.9602f, + 0.2486f, 0.0856f, 0.0151f, 0.0339f, 0.0400f, 0.0309f, 0.0806f, 0.0645f, 0.1008f, 0.0578f, 0.0978f, 0.0977f, 0.1286f, 0.1623f, 0.0981f, 0.1181f +}; + +const float tbl_mid_unv_wb_4b[] = +{ + 0.6335f, 0.3837f, 0.0061f, 0.3077f, 0.6323f, 0.7715f, 0.4749f, 0.4108f, 0.4372f, 0.4293f, 0.4158f, 0.3722f, 0.3496f, 0.1979f, 0.2359f, -0.1160f, + 0.8317f, 0.8118f, 0.2606f, 0.1187f, 0.0552f, 0.1774f, 0.3932f, 0.2072f, 0.3864f, 0.5424f, 0.7232f, 0.7687f, 0.4769f, 0.3494f, 0.4378f, 0.5646f, + 0.3911f, 0.3263f, 0.7933f, 0.5272f, 0.1287f, 0.0682f, 0.5376f, 0.7098f, 0.6191f, 0.8087f, 0.5485f, 0.3026f, 0.2164f, 0.1960f, 0.2562f, 1.0169f, + 0.2349f, 0.3254f, 0.5092f, 0.6735f, 0.7200f, 0.8835f, 0.8933f, 0.9395f, 0.8850f, 0.7653f, 0.7524f, 0.7371f, 0.6408f, 0.5230f, 0.5062f, 0.3452f, + 0.3460f, 0.0962f, 0.0094f, 0.2461f, 0.2226f, 0.3936f, 0.4201f, 0.5459f, 0.7673f, 0.8199f, 0.8280f, 0.8231f, 0.8197f, 0.8607f, 0.8010f, 0.3089f, + 0.7795f, 0.6877f, 0.7032f, 0.6328f, 0.4300f, 0.5229f, 0.2279f, 0.1276f, 0.0707f, 0.1435f, 0.2128f, 0.3172f, 0.6441f, 0.6792f, 0.6553f, 0.9661f, + 0.2191f, 0.1685f, 0.6328f, 1.1384f, 0.9794f, 0.3831f, 0.1536f, 0.2111f, 0.4062f, 0.4802f, 0.6310f, 0.6891f, 0.6434f, 0.7195f, 0.6825f, 0.6281f, + 0.7000f, 0.7134f, 1.0741f, 1.0685f, 0.6870f, 0.6970f, 0.6415f, 0.5947f, 0.6529f, 0.4188f, 0.3670f, 0.3035f, 0.1731f, 0.1189f, 0.1361f, 0.2484f, + 0.5120f, 1.0280f, 0.2212f, 0.7419f, 0.3666f, 0.4217f, 0.8202f, 0.9157f, 0.2588f, 0.2309f, 0.3245f, 0.2828f, 0.2803f, 0.7001f, 0.7999f, 0.5475f, + 0.9854f, 1.3984f, 0.7880f, 0.6188f, 0.6003f, 0.6025f, 0.5882f, 0.6020f, 0.7360f, 0.7624f, 0.7677f, 0.8184f, 0.8239f, 0.6515f, 0.5525f, 0.4851f, + 0.4527f, 0.6817f, 0.5962f, -0.1834f, 0.5938f, 0.2848f, 0.0740f, 0.7295f, 0.7859f, 0.2945f, 0.2364f, 0.4472f, 0.6828f, 0.8532f, 0.7874f, 0.4340f, + 0.4691f, -0.8407f, 0.4513f, 0.4736f, 0.5430f, 0.5205f, 0.7277f, 0.5125f, 0.4374f, 0.4812f, 0.4402f, 0.4600f, 0.5441f, 0.5339f, 0.5000f, 0.5523f, + 0.3114f, 0.8277f, 0.8566f, 0.3543f, 1.1264f, 1.0654f, 0.8704f, 0.2286f, 0.2817f, 0.5363f, 0.4860f, 0.4854f, 0.4885f, 0.4981f, 0.5884f, 0.6849f, + 0.0269f, -0.0212f, -0.0053f, -0.0662f, 0.0548f, 0.1794f, 0.2147f, 0.2311f, 0.1580f, 0.1215f, 0.0883f, 0.0883f, 0.0939f, 0.1213f, 0.1671f, 0.5387f, + 0.2015f, 0.2757f, 0.3759f, 0.3556f, 0.1435f, -0.0599f, -0.1540f, -0.1010f, -0.0265f, 0.1109f, 0.1375f, 0.2138f, 0.2321f, 0.2154f, 0.3242f, 0.0302f, + 0.6567f, 0.8920f, 0.9432f, 0.9931f, 1.0095f, 1.0340f, 1.0733f, 1.0465f, 1.0174f, 1.0278f, 0.9835f, 0.9231f, 0.8690f, 0.9104f, 0.8308f, 0.9015f +}; + +const float tbl_mid_unv_wb_5b[] = +{ + 0.7613f, 0.7719f, 0.1405f, 0.0932f, 0.5149f, 0.7991f, 1.0299f, 1.0621f, 0.9101f, 0.8061f, 0.5653f, 0.3541f, 0.3723f, 0.2189f, 0.2387f, 0.2759f, + 0.6765f, 0.5271f, 0.6522f, 0.6740f, 0.7323f, 0.6686f, 0.6427f, 0.6389f, 0.5635f, 0.4064f, 0.4204f, 0.2217f, -0.0540f, 0.0055f, -0.0003f, 1.0891f, + 0.7776f, 1.0019f, 0.8036f, 0.6873f, 0.6593f, 0.6663f, 0.6333f, 0.6830f, 0.8102f, 0.8412f, 0.8499f, 0.8505f, 0.8562f, 0.7727f, 0.6647f, 0.3785f, + 0.3357f, 0.3489f, 0.6355f, 0.5608f, 0.4041f, 0.4265f, 0.3007f, 0.4162f, 0.4157f, 0.7509f, 0.9377f, 1.0489f, 0.5420f, 0.4535f, 0.3596f, -0.5336f, + 0.1412f, 0.0807f, 0.4569f, 0.7835f, 0.9173f, 1.0155f, 0.9137f, 0.8909f, 0.9678f, 0.9173f, 0.8315f, 0.6923f, 0.6220f, 0.6253f, 0.6100f, 0.4810f, + 0.6266f, 0.4207f, 0.3287f, 0.1977f, 0.2270f, 0.3251f, 0.5619f, 0.7677f, 0.9096f, 0.8856f, 0.9169f, 0.9138f, 1.0827f, 1.0625f, 1.0292f, 0.8096f, + 0.3048f, 0.8186f, 0.8589f, 0.4195f, 1.3250f, 1.0856f, 0.7364f, 0.3688f, 0.3584f, 0.5818f, 0.5060f, 0.5001f, 0.6320f, 0.5961f, 0.7227f, 0.9292f, + -0.0186f, -0.0066f, 0.4828f, 0.1428f, 0.6790f, 0.5731f, 0.1672f, 1.0123f, 0.3792f, 0.2371f, 0.6724f, 0.5954f, 0.4266f, 0.1336f, 0.1317f, 0.6593f, + 0.0588f, 0.0455f, 0.0269f, -0.0433f, -0.0288f, -0.0401f, -0.0520f, -0.0180f, 0.0298f, 0.0687f, 0.0692f, 0.1117f, 0.1235f, 0.0825f, 0.0981f, 0.3321f, + 0.0534f, 0.0996f, 0.3916f, 0.4144f, 0.3053f, 0.4633f, 0.5347f, 0.3117f, 0.0487f, 0.0038f, -0.0633f, -0.0580f, -0.0198f, 0.2142f, 0.3482f, 0.1270f, + 0.2523f, 0.2594f, 0.1522f, 0.2921f, 0.3506f, 0.2707f, 0.4275f, 0.4855f, 0.5752f, 0.5218f, 0.3174f, 0.2905f, 0.2825f, 0.3531f, 0.4339f, 1.7003f, + 0.4843f, -0.0775f, -0.2139f, 0.3039f, 0.0370f, 0.1183f, 0.1276f, 0.3465f, 0.6921f, 0.5677f, 0.6350f, 0.6406f, 0.5105f, 0.5348f, 0.6704f, 0.0065f, + 0.3712f, 0.3044f, 1.1308f, 0.6067f, 0.0439f, -0.4632f, 0.7686f, 0.7904f, 0.5471f, 0.8138f, 0.6427f, 0.3550f, 0.2907f, 0.3527f, 0.4539f, 0.6299f, + 0.4107f, 0.5028f, 0.7238f, 0.3862f, -0.0910f, 1.1435f, 0.2016f, -0.0878f, 0.7719f, 0.6242f, 0.2342f, 0.1538f, 0.3210f, 0.4376f, 0.2715f, 0.3880f, + 0.2006f, 0.1022f, 0.9856f, 1.0177f, 0.5172f, 0.2847f, 0.2673f, -0.1435f, 0.2402f, 0.1511f, 0.2873f, 0.5806f, 0.6432f, 0.7030f, 0.6057f, 0.6605f, + 0.9265f, 0.7899f, 0.3217f, 0.2282f, 0.1476f, 0.1837f, 0.2586f, 0.1089f, 0.2017f, 0.4537f, 0.6116f, 0.4845f, 0.2765f, 0.2964f, 0.4001f, 0.6137f, + 0.8898f, 1.0569f, 1.3651f, 1.0880f, 0.7427f, 0.8146f, 0.7277f, 0.4933f, 0.4686f, 0.3226f, 0.2556f, 0.3925f, 0.3609f, 0.3534f, 0.4061f, 0.6180f, + 0.7097f, -0.6082f, 0.1367f, 0.2578f, 0.5352f, 0.6455f, 0.7388f, 0.5255f, 0.5767f, 0.6179f, 0.4126f, 0.5127f, 0.7127f, 0.8766f, 0.7792f, 0.5824f, + 0.4750f, 0.8985f, 0.5078f, 0.1736f, 0.6068f, 0.1146f, 0.0343f, 0.4376f, 0.5880f, 0.1435f, -0.0373f, 0.0317f, 0.4657f, 1.0099f, 0.8661f, 0.1866f, + 0.9984f, 2.3701f, 0.4294f, 0.4330f, 0.5639f, 0.5165f, 0.4100f, 0.4402f, 0.6263f, 0.5455f, 0.6353f, 0.6244f, 0.6031f, 0.5825f, 0.5097f, 0.6299f, + 0.5541f, 0.6583f, 0.3303f, 0.6556f, 0.1792f, 1.0361f, 1.2642f, 0.3391f, 0.1741f, 0.0453f, 0.9879f, 0.9531f, 0.6357f, 0.7319f, 0.7423f, 0.6173f, + 0.3987f, 0.4249f, -0.6046f, -0.6882f, 0.4910f, 0.6716f, 0.4378f, 0.3805f, 0.3341f, 0.4671f, 0.4465f, 0.4801f, 0.4397f, 0.6006f, 0.6054f, 0.4252f, + 0.4695f, 1.1709f, 0.4102f, 0.7910f, 0.1483f, 0.3870f, 0.6370f, 1.0548f, 0.0811f, 0.3290f, 0.4093f, 0.1806f, 0.2059f, 0.7384f, 0.8635f, 0.5733f, + 0.2723f, 0.5489f, 0.8253f, 0.8299f, 0.7252f, 0.6647f, 0.9867f, 0.9697f, 0.7177f, 0.4570f, 0.3074f, 0.7912f, 0.8034f, 0.7441f, 0.7787f, -0.0162f, + 0.4101f, 0.7419f, 0.1299f, 1.6854f, 0.9991f, 0.4401f, 0.5282f, 0.4610f, 0.7582f, 0.6075f, 0.6122f, 0.5946f, 0.7110f, 0.3059f, 0.2600f, 0.6038f, + 0.6606f, 0.5502f, 0.1162f, 0.5003f, 0.6136f, 0.4821f, 0.4274f, 0.2171f, 0.2387f, 0.2595f, 0.1985f, 0.4479f, 0.5427f, -0.1344f, 0.0898f, -0.3306f, + 0.5889f, 0.9132f, 1.0845f, -0.3197f, -0.3362f, 0.0343f, 0.5076f, 0.3968f, 0.5618f, 0.3596f, 0.4779f, 0.7531f, 0.7416f, 0.4266f, 0.3987f, 0.5340f, + 0.7489f, 0.3257f, 0.8281f, 1.2605f, 0.8413f, 0.6688f, 0.1844f, 0.3748f, 0.7825f, 1.1222f, 0.8489f, 0.1323f, 0.3507f, 0.8581f, 0.9935f, 0.6921f, + 0.8856f, 0.7036f, 0.6252f, 0.7064f, 0.3820f, 0.6683f, -0.3320f, 0.4602f, -0.1010f, 0.1065f, 0.1942f, 0.5670f, 0.8811f, 0.6730f, 0.7053f, 0.7718f, + 0.1447f, -1.5991f, 0.6787f, 0.7162f, 0.5069f, 0.3163f, 0.6009f, 0.4212f, 0.2517f, 0.5189f, 0.5235f, 0.4147f, 0.4682f, 0.2541f, 0.2860f, 0.3872f, + 0.5444f, 0.5385f, 0.4809f, 0.5395f, 1.1487f, -0.3404f, -0.3082f, -0.3512f, -0.2280f, 0.3479f, 0.5481f, 0.4996f, 0.3860f, 0.4747f, 0.4639f, 0.4263f, + 0.7822f, 1.0122f, 1.0295f, 1.0430f, 1.0629f, 1.1165f, 1.1447f, 1.1354f, 1.1063f, 1.0919f, 1.0188f, 0.9977f, 0.8758f, 0.8855f, 0.7471f, 0.9058f +}; + + + +/*------------------------------------------------------------------------------* + * AVQ - RE8 tables + *------------------------------------------------------------------------------*/ + +/* NOTE: Many values here could fit in shorts instead of ints */ +const int select_table22[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 int vals_a[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 int vals_q[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 unsigned int Is[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 int AA3[NB_LDQ3] = +{ + 0, 1, 4, 2, 3, 7, 11, 17, 22 +}; + +/* A4 - Number of the absolute leaders in codebook Q4 */ +const int AA4[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 unsigned int II3[NB_LDQ3] = +{ + 0, 128, 240, 256, 1376, 2400, 3744, 3856, 4080 +}; + +/* I4 - Cardinality offset for absolute leaders in Q4 */ +const unsigned int II4[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 +}; + +/*------------------------------------------------------------------------------* + * Position of the first absolute leader on a spherical shell (or sphere) + *------------------------------------------------------------------------------*/ + +const int Da_pos[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 +}; + +/*------------------------------------------------------------------------------* + * Number of absolute leaders on a spherical shell + *------------------------------------------------------------------------------*/ + +const int Da_nb[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 +}; + +/*------------------------------------------------------------------------------* + * Identification code of an absolute leader + *------------------------------------------------------------------------------*/ + +const int Da_id[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 +}; + +/*------------------------------------------------------------------------------* + * Codebook number for each absolute leader + *------------------------------------------------------------------------------*/ + +const int Da_nq[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 +}; + + +/*------------------------------------------------------------------------------* + * SWB TBE tables + *------------------------------------------------------------------------------*/ + +const short 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 short skip_bands_WB_TBE[NUM_SHB_SUBFR/2+1] = {0, 10, 20, 30, 40, 50, 60, 70, 80}; /* bands for WB TBE quantisation */ + +const float interpol_frac_shb[NB_SUBFR*2] = { 0.7f, 0.3f, 0.4f, 0.6f, 0.1f, 0.9f, 0.0f, 1.0f }; + +/* All pass filter coeffs for interpolation and decimation by a factor of 2 */ +const float AP1_STEEP[ALLPASSSECTIONS_STEEP] = +{ 0.06056541924291f, 0.42943401549235f, 0.80873048306552f }; + +const float AP2_STEEP[ALLPASSSECTIONS_STEEP] = +{ 0.22063024829630f, 0.63593943961708f, 0.94151583095682f }; + +const float cos_fb_exc[32] = +{ + 9.536743164062500e-007f,9.353497034680913e-007f,8.810801546133007e-007f,7.929511980364623e-007f,6.743495646333031e-007f,5.298330165715015e-007f,3.649553264040151e-007f,1.860525884467279e-007f, + 0.000000000000000e+000f,-1.860526737118562e-007f,-3.649554116691434e-007f,-5.298331302583392e-007f,-6.743496214767220e-007f,-7.929512548798812e-007f,-8.810802114567196e-007f,-9.353497603115102e-007f, + -9.536743164062500e-007f,-9.353497034680913e-007f,-8.810801546133007e-007f,-7.929511411930434e-007f,-6.743495077898842e-007f,-5.298329597280826e-007f,-3.649552411388868e-007f,-1.860525173924543e-007f, + 0.000000000000000e+000f,1.860527589769845e-007f,3.649554969342717e-007f,5.298331871017581e-007f,6.743496783201408e-007f,7.929513117233000e-007f,8.810802683001384e-007f,9.353497603115102e-007f +}; + +const float recip_order[15] = +{ + 0.0000000f, 1.0000000f, 0.5000000f, 0.3333333f, 0.2500000f, + 0.2000000f, 0.1666667f, 0.1428571f, 0.1250000f, 0.1111111f, + 0.1000000f, 0.0909091f, 0.0833333f, 0.0769231f, 0.0714286f +}; + +const float STEPS[4] = { 0.00635f, 0.003175f, 0.0015875f, 0.00079375f}; + +const float Hilbert_coeffs[4*NUM_HILBERTS][HILBERT_ORDER1+1] = +{ + { 0.0f, 0.8740234375f, 0.0f, -1.87371826171875f, 0.0f, 1.0f}, /* num_Real[0] */ + {0.72613525390625f, 0.0f, -1.7236328125f, 0.0f, 1.0f, 0.0f}, /* num_Imag[0] */ + { 1.0f, 0.0f, -1.87371826171875f, 0.0f, 0.8740234375f, 0.0f}, /* den_Real[0] */ + { 1.0f, 0.0f, -1.7236328125f, 0.0f, 0.72613525390625f, 0.0f}, /* den_Imag[0] */ + {0.46820068359375f, 0.0f, -1.45599365234375f, 0.0f, 1.0f, 0.0f}, /* num_Real[1] */ + {0.15289306640625f, 0.0f, -1.10711669921875f, 0.0f, 1.0f, 0.0f}, /* num_Imag[1] */ + { 1.0f, 0.0f, -1.45599365234375f, 0.0f, 0.46820068359375f, 0.0f}, /* den_Real[1] */ + { 1.0f, 0.0f, -1.10711669921875f, 0.0f, 0.15289306640625f, 0.0f} /* den_Imag[1] */ +}; + +/* Overlap add window for SHB excitation used in analysis and synthesis */ +const float window_shb[L_SHB_LAHEAD]= /* sin, 1, sin */ +{ + 4.618346E-02f, 1.381564E-01f, 2.289505E-01f, 3.177914E-01f, 4.039210E-01f, 4.866045E-01f, 5.651364E-01f, 6.388468E-01f, 7.071068E-01f, 7.693340E-01f, + 8.249975E-01f, 8.736224E-01f, 9.147939E-01f, 9.481606E-01f, 9.734381E-01f, 9.904104E-01f, 9.989330E-01f, 1.000000e+000f, 1.000000e+000f, 1.000000e+000f +}; + +/* Upsampled overlap add window for SHB excitation used transition generation */ +const float window_shb_32k[2*L_SHB_LAHEAD]= +{ + 4.618346E-02f, 9.216993E-02f, 1.381564E-01f, 1.835534E-01f, 2.289505E-01f, 2.733710E-01f, 3.177914E-01f, 3.608562E-01f, 4.039210E-01f, 4.452628E-01f, + 4.866045E-01f, 5.258704E-01f, 5.651364E-01f, 6.019916E-01f, 6.388468E-01f, 6.729768E-01f, 7.071068E-01f, 7.382205E-01f, 7.693340E-01f, 7.971658E-01f, + 8.249975E-01f, 8.493099E-01f, 8.736224E-01f, 8.942082E-01f, 9.147939E-01f, 9.314773E-01f, 9.481606E-01f, 9.607993E-01f, 9.734381E-01f, 9.819242E-01f, + 9.904104E-01f, 9.946717E-01f, 9.989330E-01f, 9.994665E-01f, 1.000000e+000f, 1.000000e+000f, 1.000000e+000f, 1.000000e+000f, 1.000000e+000f, 1.000000e+000f +}; + +/* Short overlap add window for SHB excitation used in anal and synth */ +const float subwin_shb[SHB_OVERLAP_LEN+1]= +{ + 0.000000000f, 0.006155830f, 0.024471742f, 0.054496738f, 0.095491503f, + 0.146446609f, 0.206107374f, 0.273004750f, 0.345491503f, 0.421782767f, + 0.500000000f, 0.578217233f, 0.654508497f, 0.726995250f, 0.793892626f, + 0.853553391f, 0.904508497f, 0.945503262f, 0.975528258f, 0.993844170f, + 1.000000000f +}; + +const float window_wb[L_SHB_LAHEAD/4]=/* sin, 1 */ +{ 2.289505E-001f, 5.651364E-001f, 8.249975E-001f, 9.734381E-001f, 1.000000e+000f}; + +/* Short overlap add window for SHB excitation used in anal and synth */ +const float subwin_wb[SHB_OVERLAP_LEN/2+1]= +{0.00000000f, 0.15643448f, 0.30901700f, 0.45399052f, 0.58778524f, 0.70710677f, 0.80901700f, 0.89100653f, 0.95105654f, 0.98768836f, 1.0000000f}; + +/* Window for calculating SHB LPC coeffs */ +const float win_lpc_shb[(L_LOOK_12k8 + L_SUBFR + L_FRAME) * 5/8]= +{ + 0.0000337210f, 0.0001348794f, 0.0003034616f, 0.0005394449f, 0.0008427974f, 0.0012134782f, 0.0016514373f, 0.0021566156f, 0.0027289450f, 0.0033683483f, + 0.0040747393f, 0.0048480226f, 0.0056880940f, 0.0065948401f, 0.0075681387f, 0.0086078584f, 0.0097138590f, 0.0108859914f, 0.0121240975f, 0.0134280101f, + 0.0147975536f, 0.0162325430f, 0.0177327850f, 0.0192980770f, 0.0209282080f, 0.0226229582f, 0.0243820988f, 0.0262053927f, 0.0280925938f, 0.0300434477f, + 0.0320576912f, 0.0341350526f, 0.0362752518f, 0.0384779999f, 0.0407430000f, 0.0430699465f, 0.0454585255f, 0.0479084149f, 0.0504192842f, 0.0529907947f, + 0.0556225996f, 0.0583143439f, 0.0610656645f, 0.0638761903f, 0.0667455422f, 0.0696733332f, 0.0726591683f, 0.0757026449f, 0.0788033524f, 0.0819608725f, + 0.0851747795f, 0.0884446397f, 0.0917700121f, 0.0951504482f, 0.0985854920f, 0.1020746802f, 0.1056175421f, 0.1092136000f, 0.1128623686f, 0.1165633559f, + 0.1203160626f, 0.1241199826f, 0.1279746028f, 0.1318794033f, 0.1358338573f, 0.1398374315f, 0.1438895859f, 0.1479897739f, 0.1521374423f, 0.1563320319f, + 0.1605729768f, 0.1648597049f, 0.1691916381f, 0.1735681920f, 0.1779887763f, 0.1824527948f, 0.1869596453f, 0.1915087200f, 0.1960994051f, 0.2007310816f, + 0.2054031247f, 0.2101149041f, 0.2148657844f, 0.2196551248f, 0.2244822791f, 0.2293465964f, 0.2342474205f, 0.2391840904f, 0.2441559401f, 0.2491622991f, + 0.2542024921f, 0.2592758392f, 0.2643816562f, 0.2695192543f, 0.2746879405f, 0.2798870178f, 0.2851157847f, 0.2903735361f, 0.2956595627f, 0.3009731516f, + 0.3063135860f, 0.3116801456f, 0.3170721065f, 0.3224887415f, 0.3279293199f, 0.3333931079f, 0.3388793684f, 0.3443873616f, 0.3499163444f, 0.3554655711f, + 0.3610342931f, 0.3666217595f, 0.3722272163f, 0.3778499077f, 0.3834890752f, 0.3891439582f, 0.3948137938f, 0.4004978174f, 0.4061952622f, 0.4119053598f, + 0.4176273399f, 0.4233604308f, 0.4291038591f, 0.4348568502f, 0.4406186280f, 0.4463884155f, 0.4521654343f, 0.4579489052f, 0.4637380481f, 0.4695320822f, + 0.4753302259f, 0.4811316971f, 0.4869357134f, 0.4927414919f, 0.4985482494f, 0.5043552028f, 0.5101615687f, 0.5159665639f, 0.5217694055f, 0.5275693108f, + 0.5333654974f, 0.5391571836f, 0.5449435881f, 0.5507239304f, 0.5564974308f, 0.5622633107f, 0.5680207922f, 0.5737690989f, 0.5795074552f, 0.5852350873f, + 0.5909512225f, 0.5966550899f, 0.6023459200f, 0.6080229454f, 0.6136854001f, 0.6193325205f, 0.6249635449f, 0.6305777137f, 0.6361742697f, 0.6417524579f, + 0.6473115260f, 0.6528507242f, 0.6583693052f, 0.6638665247f, 0.6693416413f, 0.6747939164f, 0.6802226146f, 0.6856270037f, 0.6910063547f, 0.6963599419f, + 0.7016870434f, 0.7069869405f, 0.7122589184f, 0.7175022660f, 0.7227162760f, 0.7279002451f, 0.7330534742f, 0.7381752681f, 0.7432649359f, 0.7483217913f, + 0.7533451519f, 0.7583343404f, 0.7632886838f, 0.7682075137f, 0.7730901667f, 0.7779359842f, 0.7827443127f, 0.7875145034f, 0.7922459131f, 0.7969379034f, + 0.8015898416f, 0.8062011002f, 0.8107710572f, 0.8152990961f, 0.8197846062f, 0.8242269825f, 0.8286256258f, 0.8329799428f, 0.8372893461f, 0.8415532545f, + 0.8457710928f, 0.8499422922f, 0.8540662899f, 0.8581425298f, 0.8621704620f, 0.8661495432f, 0.8700792367f, 0.8739590124f, 0.8777883471f, 0.8815667242f, + 0.8852936341f, 0.8889685740f, 0.8925910483f, 0.8961605683f, 0.8996766527f, 0.9031388271f, 0.9065466245f, 0.9098995853f, 0.9131972572f, 0.9164391954f, + 0.9196249627f, 0.9227541293f, 0.9258262731f, 0.9288409798f, 0.9317978427f, 0.9346964630f, 0.9375364498f, 0.9403174198f, 0.9430389982f, 0.9457008176f, + 0.9483025192f, 0.9508437519f, 0.9533241731f, 0.9557434481f, 0.9581012506f, 0.9603972626f, 0.9626311744f, 0.9648026847f, 0.9669115005f, 0.9689573374f, + 0.9709399196f, 0.9728589795f, 0.9747142583f, 0.9765055057f, 0.9782324802f, 0.9798949488f, 0.9814926873f, 0.9830254801f, 0.9844931206f, 0.9858954107f, + 0.9872321612f, 0.9885031920f, 0.9897083316f, 0.9908474173f, 0.9919202956f, 0.9929268217f, 0.9938668599f, 0.9947402834f, 0.9955469743f, 0.9962868239f, + 0.9969597324f, 0.9975656090f, 0.9981043719f, 0.9985759486f, 0.9989802753f, 0.9993172977f, 0.9995869701f, 0.9997892562f, 0.9999241288f, 0.9999915697f +}; + +const float win_lpc_hb_wb[(L_LOOK_12k8 + L_SUBFR + L_FRAME) * 5/32]= +{ + 0.000171338f, 0.001541333f, 0.004277569f, 0.008372546f, 0.01381504f, 0.020590133f, 0.028679254f, 0.038060234f, + 0.048707358f, 0.060591444f, 0.073679918f, 0.087936906f, 0.10332333f, 0.119797017f, 0.137312814f, 0.155822712f, + 0.175275976f, 0.195619285f, 0.216796882f, 0.238750718f, 0.26142062f, 0.284744452f, 0.308658284f, 0.33309657f, + 0.357992328f, 0.383277318f, 0.408882237f, 0.434736904f, 0.460770452f, 0.486911526f, 0.513088474f, 0.539229548f, + 0.565263096f, 0.591117763f, 0.616722682f, 0.642007672f, 0.66690343f, 0.691341716f, 0.715255548f, 0.73857938f, + 0.761249282f, 0.783203118f, 0.804380715f, 0.824724024f, 0.844177288f, 0.862687186f, 0.880202983f, 0.89667667f, + 0.912063094f, 0.926320082f, 0.939408556f, 0.951292642f, 0.961939766f, 0.971320746f, 0.979409867f, 0.98618496f, + 0.991627454f, 0.995722431f, 0.998458667f, 0.999828662f +}; + +const float ola_win_shb_switch_fold[L_SUBFR16k] = +{ + 0.009817319f, 0.029448173f, 0.049067674f, 0.068668259f, 0.088242371f, 0.107782463f, 0.127281003f, 0.146730474f, + 0.166123378f, 0.185452238f, 0.204709603f, 0.223888048f, 0.242980180f, 0.261978638f, 0.280876099f, 0.299665277f, + 0.318338928f, 0.336889853f, 0.355310901f, 0.373594970f, 0.391735011f, 0.409724030f, 0.427555093f, 0.445221326f, + 0.462715917f, 0.480032122f, 0.497163266f, 0.514102744f, 0.530844026f, 0.547380657f, 0.563706262f, 0.579814548f, + 0.595699304f, 0.611354407f, 0.626773822f, 0.641951603f, 0.656881899f, 0.671558955f, 0.685977112f, 0.700130812f, + 0.714014598f, 0.727623118f, 0.740951125f, 0.753993482f, 0.766745160f, 0.779201243f, 0.791356929f, 0.803207531f, + 0.814748483f, 0.825975333f, 0.836883753f, 0.847469539f, 0.857728610f, 0.867657010f, 0.877250911f, 0.886506616f, + 0.895420555f, 0.903989293f, 0.912209526f, 0.920078084f, 0.927591935f, 0.934748182f, 0.941544065f, 0.947976965f, + 0.954044402f, 0.959744037f, 0.965073672f, 0.970031253f, 0.974614869f, 0.978822751f, 0.982653279f, 0.986104976f, + 0.989176510f, 0.991866698f, 0.994174502f, 0.996099033f, 0.997639549f, 0.998795456f, 0.999566309f, 0.999951809f +}; + +/* Window for calculating whitening filter for SHB excitation */ +const float win_flatten[ L_FRAME16k/2]= +{ + 9.57802E-05f, 0.000383084f, 0.000861802f, 0.00153175f, 0.002392671f, 0.003444236f, 0.004686042f, 0.006117614f, + 0.007738401f, 0.009547785f, 0.011545071f, 0.013729494f, 0.016100218f, 0.018656334f, 0.021396862f, 0.024320754f, + 0.027426888f, 0.030714075f, 0.034181054f, 0.037826499f, 0.041649013f, 0.04564713f, 0.049819319f, 0.054163981f, + 0.058679453f, 0.063364004f, 0.068215839f, 0.0732331f, 0.078413864f, 0.083756147f, 0.089257901f, 0.094917019f, + 0.100731333f, 0.106698615f, 0.112816579f, 0.119082881f, 0.12549512f, 0.13205084f, 0.138747529f, 0.145582621f, + 0.152553498f, 0.159657489f, 0.166891873f, 0.174253877f, 0.181740681f, 0.189349417f, 0.197077169f, 0.204920978f, + 0.212877838f, 0.2209447f, 0.229118474f, 0.237396028f, 0.245774191f, 0.254249754f, 0.262819469f, 0.271480052f, + 0.280228187f, 0.28906052f, 0.297973669f, 0.306964218f, 0.316028723f, 0.325163712f, 0.334365684f, 0.343631114f, + 0.352956452f, 0.362338126f, 0.37177254f, 0.381256082f, 0.390785116f, 0.400355993f, 0.409965046f, 0.419608593f, + 0.42928294f, 0.43898438f, 0.448709196f, 0.458453663f, 0.468214047f, 0.477986609f, 0.487767604f, 0.497553287f, + 0.507339906f, 0.517123714f, 0.526900961f, 0.536667901f, 0.546420794f, 0.556155902f, 0.565869495f, 0.575557852f, + 0.585217262f, 0.594844023f, 0.604434447f, 0.61398486f, 0.623491603f, 0.632951034f, 0.642359529f, 0.651713483f, + 0.661009312f, 0.670243455f, 0.679412375f, 0.688512557f, 0.697540517f, 0.706492795f, 0.715365961f, 0.724156616f, + 0.732861391f, 0.741476953f, 0.75f, 0.758427267f, 0.766755524f, 0.774981583f, 0.78310229f, 0.791114534f, + 0.799015247f, 0.8068014f, 0.814470012f, 0.822018143f, 0.829442903f, 0.836741446f, 0.843910977f, 0.850948748f, + 0.857852063f, 0.864618278f, 0.871244799f, 0.87772909f, 0.884068664f, 0.890261093f, 0.896304006f, 0.902195086f, + 0.907932076f, 0.91351278f, 0.918935058f, 0.924196833f, 0.92929609f, 0.934230874f, 0.938999296f, 0.943599527f, + 0.948029807f, 0.952288437f, 0.956373785f, 0.960284288f, 0.964018446f, 0.967574828f, 0.970952073f, 0.974148887f, + 0.977164044f, 0.97999639f, 0.982644839f, 0.985108376f, 0.987386059f, 0.989477014f, 0.99138044f, 0.993095607f, + 0.99462186f, 0.995958613f, 0.997105353f, 0.998061642f, 0.998827114f, 0.999401474f, 0.999784503f, 0.999976054f +}; + +const float win_flatten_4k[ L_FRAME16k/8]= +{ + 0.000385482f, 0.003465772f, 0.00960736f, 0.018772382f, 0.030904332f, 0.045928413f, 0.063751996f, 0.084265194f, + 0.107341535f, 0.132838745f, 0.160599627f, 0.190453025f, 0.222214883f, 0.255689379f, 0.290670131f, 0.326941471f, + 0.364279775f, 0.402454839f, 0.441231301f, 0.480370092f, 0.519629908f, 0.558768699f, 0.597545161f, 0.635720225f, + 0.673058529f, 0.709329869f, 0.744310621f, 0.777785117f, 0.809546975f, 0.839400373f, 0.867161255f, 0.892658465f, + 0.915734806f, 0.936248004f, 0.954071587f, 0.969095668f, 0.981227618f, 0.99039264f, 0.996534228f, 0.999614518f +}; + +const float wb_bwe_lsfvq_cbook_8bit[256*6] = +{ + 0.064311408f, 0.10468847f, 0.15634165f, 0.20375369f, 0.28696818f, 0.40275119f, + 0.123011120f, 0.15468679f, 0.22408577f, 0.27191057f, 0.32490698f, 0.37368365f, + 0.062166951f, 0.10810068f, 0.20470853f, 0.26741467f, 0.32058192f, 0.38620580f, + 0.174916950f, 0.19449120f, 0.24146226f, 0.29131976f, 0.38403433f, 0.43426356f, + 0.061881055f, 0.10185221f, 0.16703630f, 0.24048992f, 0.31339988f, 0.37993594f, + 0.177282270f, 0.19826299f, 0.25380750f, 0.29369257f, 0.35085620f, 0.42745721f, + 0.074096108f, 0.12090045f, 0.17319672f, 0.23572965f, 0.34671734f, 0.40846492f, + 0.193731520f, 0.25350369f, 0.27155532f, 0.30359655f, 0.33746877f, 0.40740063f, + 0.108401970f, 0.13491719f, 0.17991717f, 0.21799053f, 0.30440233f, 0.40384627f, + 0.174536930f, 0.19361701f, 0.22834544f, 0.25644155f, 0.32851965f, 0.41061748f, + 0.107099060f, 0.13363550f, 0.17994689f, 0.22695679f, 0.35903688f, 0.43662047f, + 0.137970100f, 0.24785769f, 0.26827308f, 0.30078557f, 0.34276146f, 0.42785187f, + 0.066387915f, 0.12114685f, 0.23766229f, 0.29916662f, 0.34589517f, 0.39398126f, + 0.137657570f, 0.24889487f, 0.27118048f, 0.31891228f, 0.38713554f, 0.45651107f, + 0.128872750f, 0.16127981f, 0.21523141f, 0.25706016f, 0.34536624f, 0.44451874f, + 0.218467830f, 0.25571942f, 0.27589334f, 0.30889302f, 0.36007931f, 0.43548091f, + 0.056956662f, 0.09351124f, 0.14796259f, 0.22055691f, 0.34257293f, 0.42610824f, + 0.180505310f, 0.20235648f, 0.26672026f, 0.30524807f, 0.34745481f, 0.38838059f, + 0.101998340f, 0.13874827f, 0.19761236f, 0.28698298f, 0.36602473f, 0.40947282f, + 0.187859700f, 0.20997279f, 0.27259784f, 0.31595901f, 0.37782186f, 0.41948720f, + 0.080803553f, 0.15174572f, 0.23117477f, 0.28917899f, 0.36979528f, 0.42341956f, + 0.177685260f, 0.19914809f, 0.26693575f, 0.33390045f, 0.38670310f, 0.42635921f, + 0.123052730f, 0.15593820f, 0.23170087f, 0.28281293f, 0.34711335f, 0.43915513f, + 0.209470720f, 0.25584593f, 0.27727828f, 0.32496712f, 0.39502842f, 0.45856840f, + 0.111734840f, 0.14147902f, 0.20349777f, 0.25418848f, 0.31658104f, 0.37184560f, + 0.177056760f, 0.19666426f, 0.25464026f, 0.29941442f, 0.37334871f, 0.45296459f, + 0.109640340f, 0.13537075f, 0.20335155f, 0.26529530f, 0.35213594f, 0.43554990f, + 0.155959700f, 0.25239450f, 0.27483222f, 0.32663911f, 0.37442742f, 0.42423408f, + 0.060802584f, 0.098534495f, 0.17139797f, 0.27724784f, 0.34847788f, 0.40446891f, + 0.131805190f, 0.17878972f, 0.29302125f, 0.34778777f, 0.39172069f, 0.43333138f, + 0.117051780f, 0.14714169f, 0.25283080f, 0.31096928f, 0.35792401f, 0.40593001f, + 0.244642480f, 0.26542671f, 0.31064604f, 0.34894237f, 0.39502788f, 0.45113983f, + 0.057704683f, 0.10158624f, 0.18821861f, 0.25351465f, 0.33014694f, 0.43374062f, + 0.177105410f, 0.19658676f, 0.24332913f, 0.27865263f, 0.33845007f, 0.38627285f, + 0.085525863f, 0.16781621f, 0.24699003f, 0.29584215f, 0.34250327f, 0.39210727f, + 0.189876270f, 0.21305679f, 0.26289427f, 0.30053004f, 0.36670247f, 0.40832210f, + 0.077609843f, 0.14485938f, 0.23309675f, 0.28603452f, 0.33963436f, 0.41664103f, + 0.180406410f, 0.20188257f, 0.27483060f, 0.32204807f, 0.36496152f, 0.40626347f, + 0.109972660f, 0.13794764f, 0.23344532f, 0.30007610f, 0.37112553f, 0.45007031f, + 0.243211860f, 0.26638262f, 0.29846135f, 0.32926348f, 0.38096489f, 0.42680115f, + 0.115753390f, 0.14391596f, 0.21486068f, 0.26084368f, 0.32379458f, 0.41507919f, + 0.172120490f, 0.19028171f, 0.22318579f, 0.25543954f, 0.36796374f, 0.43638971f, + 0.114912990f, 0.14340870f, 0.20702577f, 0.29029375f, 0.38645739f, 0.43383786f, + 0.141428780f, 0.25522990f, 0.28059674f, 0.31690999f, 0.35024347f, 0.40617629f, + 0.075129960f, 0.14698488f, 0.26110380f, 0.31719769f, 0.36377356f, 0.41101429f, + 0.112868350f, 0.24334299f, 0.28096316f, 0.33454465f, 0.41219625f, 0.46410751f, + 0.114073120f, 0.14243275f, 0.23024102f, 0.32882107f, 0.39744618f, 0.44429863f, + 0.221774120f, 0.26274601f, 0.29020551f, 0.34374641f, 0.39126416f, 0.44235948f, + 0.080079738f, 0.13106315f, 0.18837026f, 0.27151645f, 0.37668958f, 0.43255839f, + 0.192999400f, 0.21775426f, 0.26678052f, 0.30557605f, 0.38446194f, 0.43054658f, + 0.135743140f, 0.17819346f, 0.26983813f, 0.31540557f, 0.35817370f, 0.39888741f, + 0.187602960f, 0.21325656f, 0.29023036f, 0.33244221f, 0.37354374f, 0.41305910f, + 0.092309319f, 0.15685370f, 0.21826152f, 0.28145456f, 0.34801734f, 0.40449806f, + 0.182635620f, 0.20695883f, 0.29330586f, 0.34611408f, 0.38827609f, 0.42744945f, + 0.142778630f, 0.18181581f, 0.24718913f, 0.30036890f, 0.36118151f, 0.41174750f, + 0.236204610f, 0.26138275f, 0.28782872f, 0.31976781f, 0.38485547f, 0.44582109f, + 0.116877780f, 0.14600852f, 0.23439658f, 0.29078582f, 0.33978214f, 0.38680132f, + 0.175246750f, 0.19919182f, 0.25508981f, 0.32738942f, 0.40268065f, 0.44634249f, + 0.137050570f, 0.17196927f, 0.22227536f, 0.26698633f, 0.35381724f, 0.42069877f, + 0.206672940f, 0.25909379f, 0.28239012f, 0.33396266f, 0.38073064f, 0.42642507f, + 0.061761568f, 0.10948738f, 0.22960285f, 0.31900229f, 0.37225715f, 0.42291697f, + 0.176470360f, 0.27105045f, 0.30450833f, 0.35896554f, 0.40397125f, 0.45254757f, + 0.121439660f, 0.15285670f, 0.25458177f, 0.31503554f, 0.37326878f, 0.43680361f, + 0.248663160f, 0.27168576f, 0.31107735f, 0.34636713f, 0.40424762f, 0.44219064f, + 0.070101929f, 0.11626106f, 0.17205417f, 0.22172190f, 0.27958755f, 0.35136489f, + 0.177289590f, 0.19891422f, 0.23900178f, 0.26750187f, 0.31516079f, 0.36488918f, + 0.077375897f, 0.14011343f, 0.22628590f, 0.27710762f, 0.32419150f, 0.37404180f, + 0.181505360f, 0.20134192f, 0.25984204f, 0.30768103f, 0.38822145f, 0.43297287f, + 0.074548254f, 0.13055888f, 0.20082796f, 0.24940258f, 0.30161427f, 0.36031073f, + 0.180461770f, 0.19943970f, 0.27094461f, 0.31420032f, 0.37052353f, 0.43473550f, + 0.074096252f, 0.11976634f, 0.19559390f, 0.30014559f, 0.36503791f, 0.41589500f, + 0.226750330f, 0.26034000f, 0.28387883f, 0.31307141f, 0.34924905f, 0.39466978f, + 0.112939270f, 0.14324718f, 0.19444530f, 0.23409602f, 0.28823566f, 0.35312882f, + 0.177658770f, 0.19744005f, 0.23826049f, 0.27114023f, 0.35113598f, 0.44339139f, + 0.114194520f, 0.13976692f, 0.19017221f, 0.23985925f, 0.34337933f, 0.40059157f, + 0.174247680f, 0.25422512f, 0.27291618f, 0.31259836f, 0.35694641f, 0.44284664f, + 0.079551504f, 0.12808054f, 0.20489528f, 0.31763242f, 0.38800666f, 0.43699908f, + 0.125618080f, 0.25750129f, 0.29652463f, 0.33625458f, 0.37097478f, 0.41695760f, + 0.128908580f, 0.16228143f, 0.22845947f, 0.30852429f, 0.38999548f, 0.43734932f, + 0.169819550f, 0.25672921f, 0.27816521f, 0.33356870f, 0.38415880f, 0.45040976f, + 0.057932155f, 0.096138661f, 0.17637437f, 0.28982999f, 0.37938107f, 0.44064176f, + 0.191452430f, 0.21929421f, 0.28254485f, 0.31749442f, 0.35804814f, 0.39526710f, + 0.112918430f, 0.14011863f, 0.23116641f, 0.29091351f, 0.34974963f, 0.42044500f, + 0.190242080f, 0.21680224f, 0.27563442f, 0.33525335f, 0.39940885f, 0.43998378f, + 0.071851696f, 0.13973452f, 0.23632015f, 0.30396344f, 0.38541794f, 0.45171152f, + 0.184630070f, 0.20535151f, 0.28517376f, 0.32789614f, 0.37951171f, 0.43497879f, + 0.132603770f, 0.16874406f, 0.24771421f, 0.29658241f, 0.37943509f, 0.43056925f, + 0.244405020f, 0.26554052f, 0.30099568f, 0.33429706f, 0.39811794f, 0.44169908f, + 0.127688830f, 0.15825875f, 0.20983321f, 0.25719782f, 0.34290920f, 0.39590250f, + 0.186549100f, 0.20879511f, 0.25591707f, 0.29476812f, 0.39344232f, 0.44883705f, + 0.121737520f, 0.15062455f, 0.21825312f, 0.27097532f, 0.35836887f, 0.41602781f, + 0.157742360f, 0.25669794f, 0.28102574f, 0.34671864f, 0.41050850f, 0.46008611f, + 0.073161878f, 0.13388489f, 0.21462934f, 0.27572797f, 0.36075527f, 0.41919188f, + 0.110086280f, 0.24803245f, 0.31035821f, 0.35293169f, 0.39119687f, 0.43174112f, + 0.135783090f, 0.17715049f, 0.27354016f, 0.32581513f, 0.38440836f, 0.44428392f, + 0.241434570f, 0.26676851f, 0.30639927f, 0.35469044f, 0.41439486f, 0.46056301f, + 0.072374815f, 0.13092581f, 0.21330540f, 0.26565725f, 0.32462099f, 0.41762579f, + 0.187292630f, 0.21108778f, 0.25580340f, 0.28624311f, 0.33138816f, 0.37684385f, + 0.098711036f, 0.18228306f, 0.24984319f, 0.31049971f, 0.37903925f, 0.43890093f, + 0.185453530f, 0.20642460f, 0.26094355f, 0.29915816f, 0.37078354f, 0.42966194f, + 0.090091891f, 0.15555244f, 0.20914149f, 0.27320212f, 0.36822053f, 0.42967380f, + 0.201609780f, 0.23445421f, 0.29016518f, 0.32638897f, 0.37174990f, 0.41508051f, + 0.113139770f, 0.14155327f, 0.22791682f, 0.31995140f, 0.37521299f, 0.41972433f, + 0.242912130f, 0.26597026f, 0.30674398f, 0.34632679f, 0.38930327f, 0.42944494f, + 0.126299270f, 0.15994217f, 0.23121635f, 0.27579474f, 0.33301124f, 0.41152335f, + 0.178158900f, 0.19664722f, 0.23704785f, 0.27359930f, 0.39265986f, 0.45771152f, + 0.129551450f, 0.16291546f, 0.22120094f, 0.28045517f, 0.37621782f, 0.42867219f, + 0.187946560f, 0.27082805f, 0.30209272f, 0.33978012f, 0.37078287f, 0.41235280f, + 0.068654959f, 0.13086497f, 0.26542795f, 0.33399948f, 0.38525278f, 0.43688097f, + 0.096004458f, 0.20898133f, 0.30225243f, 0.35934752f, 0.41301071f, 0.45632845f, + 0.123398330f, 0.15749653f, 0.25528304f, 0.31414621f, 0.39506227f, 0.45492910f, + 0.225770510f, 0.26622774f, 0.29947052f, 0.36073788f, 0.40423935f, 0.44409324f, + 0.064717384f, 0.11872284f, 0.20919028f, 0.28301016f, 0.36802144f, 0.44747754f, + 0.193151690f, 0.21918993f, 0.26823232f, 0.30766049f, 0.39674668f, 0.45522504f, + 0.136849720f, 0.17581869f, 0.26349318f, 0.31417345f, 0.36960066f, 0.42791831f, + 0.193061690f, 0.21996506f, 0.29517646f, 0.33806725f, 0.39153706f, 0.44340380f, + 0.098565179f, 0.16979528f, 0.23333485f, 0.30380484f, 0.36654435f, 0.41758552f, + 0.142901030f, 0.21043695f, 0.30522982f, 0.36025073f, 0.40676141f, 0.45003224f, + 0.145613190f, 0.18443712f, 0.24662242f, 0.31447027f, 0.38225381f, 0.42837277f, + 0.251176660f, 0.28085865f, 0.31587424f, 0.34871696f, 0.39445892f, 0.44662421f, + 0.133816690f, 0.17622163f, 0.24380327f, 0.28396237f, 0.32809307f, 0.37532433f, + 0.177315700f, 0.20318793f, 0.27655558f, 0.35488501f, 0.40768754f, 0.44723190f, + 0.130848580f, 0.16442355f, 0.23815274f, 0.28617893f, 0.35951574f, 0.41662766f, + 0.134220490f, 0.26123559f, 0.29436035f, 0.34059452f, 0.38761183f, 0.45385345f, + 0.059422872f, 0.10497064f, 0.21978301f, 0.33427086f, 0.40351136f, 0.45184884f, + 0.142994260f, 0.27380337f, 0.32392882f, 0.36784687f, 0.40465562f, 0.44600403f, + 0.116004830f, 0.14796778f, 0.27228987f, 0.34179617f, 0.39311954f, 0.44016822f, + 0.245996100f, 0.26896363f, 0.31898875f, 0.36352887f, 0.40696431f, 0.44890165f, + 0.072173498f, 0.11864839f, 0.17283789f, 0.22419420f, 0.31759785f, 0.43734225f, + 0.139241880f, 0.17819210f, 0.22803594f, 0.26501417f, 0.32263158f, 0.39061689f, + 0.079146669f, 0.12807914f, 0.20505754f, 0.28451768f, 0.34267396f, 0.39425014f, + 0.185581160f, 0.20673854f, 0.24816327f, 0.28211183f, 0.37238530f, 0.42474096f, + 0.073407181f, 0.12148770f, 0.18750487f, 0.26671948f, 0.34627834f, 0.42100649f, + 0.176786130f, 0.19666658f, 0.25287274f, 0.30668454f, 0.37086389f, 0.41259755f, + 0.085308694f, 0.14425344f, 0.19922831f, 0.25959335f, 0.34555917f, 0.41120310f, + 0.188639580f, 0.26239423f, 0.28521213f, 0.32391588f, 0.35782756f, 0.41337293f, + 0.122131020f, 0.15263056f, 0.20129258f, 0.23778684f, 0.30478596f, 0.39871654f, + 0.175429700f, 0.19423608f, 0.23678906f, 0.27549846f, 0.36067030f, 0.41160394f, + 0.119189400f, 0.14839651f, 0.19721773f, 0.23690964f, 0.32670187f, 0.43820403f, + 0.131684130f, 0.25721459f, 0.28448545f, 0.32294678f, 0.36442816f, 0.44250607f, + 0.085802449f, 0.14103937f, 0.22418659f, 0.30627724f, 0.35842445f, 0.40982625f, + 0.128820440f, 0.25444798f, 0.28309633f, 0.34424530f, 0.39272354f, 0.43691562f, + 0.132605980f, 0.16563241f, 0.21732948f, 0.26659585f, 0.39024087f, 0.45279860f, + 0.234312330f, 0.26289148f, 0.28858043f, 0.31923045f, 0.36693357f, 0.42273091f, + 0.066913619f, 0.11174564f, 0.17118640f, 0.24009352f, 0.37462610f, 0.44981068f, + 0.185639320f, 0.20948515f, 0.27095540f, 0.30761470f, 0.35471667f, 0.41869175f, + 0.125534910f, 0.15639919f, 0.22045213f, 0.29690027f, 0.36034274f, 0.40578263f, + 0.194798190f, 0.22069282f, 0.28234110f, 0.32713553f, 0.38517899f, 0.42816026f, + 0.085073073f, 0.15836545f, 0.24638386f, 0.30374430f, 0.35995427f, 0.43827551f, + 0.185516870f, 0.21322354f, 0.26435247f, 0.32313780f, 0.37976277f, 0.43915130f, + 0.136729910f, 0.17363096f, 0.23523415f, 0.27817766f, 0.36010086f, 0.44481285f, + 0.239499040f, 0.26742173f, 0.29913088f, 0.33337737f, 0.38191519f, 0.45262276f, + 0.109306830f, 0.13962816f, 0.20534886f, 0.27722030f, 0.33992319f, 0.39062291f, + 0.179595260f, 0.19941354f, 0.27015954f, 0.31834604f, 0.38647809f, 0.45654088f, + 0.118738240f, 0.14800700f, 0.21956599f, 0.27258212f, 0.36918433f, 0.44755545f, + 0.176908270f, 0.26077464f, 0.28640628f, 0.35265194f, 0.39663136f, 0.43922160f, + 0.059878687f, 0.10816162f, 0.21481956f, 0.28530654f, 0.34399690f, 0.42289176f, + 0.125298830f, 0.16761966f, 0.29455499f, 0.36736398f, 0.41514581f, 0.45568637f, + 0.132064950f, 0.16520436f, 0.24257245f, 0.31378956f, 0.37122182f, 0.41558003f, + 0.248260440f, 0.27214823f, 0.30690390f, 0.33828614f, 0.40254065f, 0.45821278f, + 0.082464811f, 0.14120604f, 0.19676137f, 0.24440753f, 0.31120215f, 0.41734941f, + 0.183048080f, 0.20313040f, 0.25374041f, 0.28978449f, 0.35392058f, 0.40046587f, + 0.096008750f, 0.19205652f, 0.26031936f, 0.30998267f, 0.36005002f, 0.41374267f, + 0.194524100f, 0.22245612f, 0.26543764f, 0.29833795f, 0.36269526f, 0.43446257f, + 0.096760412f, 0.17681885f, 0.23611019f, 0.28616845f, 0.34521951f, 0.42352547f, + 0.191620720f, 0.21818699f, 0.28052740f, 0.31781127f, 0.36781149f, 0.43254535f, + 0.125638810f, 0.15853683f, 0.23819940f, 0.29029299f, 0.37995224f, 0.45315055f, + 0.243017800f, 0.27328285f, 0.30734326f, 0.33963007f, 0.37608978f, 0.41520298f, + 0.133222750f, 0.16798774f, 0.21402212f, 0.24935760f, 0.32005623f, 0.41682314f, + 0.186885370f, 0.21039202f, 0.25286530f, 0.28529456f, 0.36191248f, 0.44972585f, + 0.114535160f, 0.14259486f, 0.19594154f, 0.24858528f, 0.38835896f, 0.45716846f, + 0.166527800f, 0.26567252f, 0.29289306f, 0.33677574f, 0.37519203f, 0.43541243f, + 0.084944791f, 0.15003156f, 0.24253235f, 0.32251109f, 0.37827375f, 0.43099351f, + 0.119303270f, 0.24856258f, 0.29065368f, 0.36470470f, 0.42883150f, 0.46638276f, + 0.120605420f, 0.15682171f, 0.24962093f, 0.34730291f, 0.41806540f, 0.46035776f, + 0.219732780f, 0.27560250f, 0.30592696f, 0.35044880f, 0.39439534f, 0.45312034f, + 0.077308553f, 0.13464280f, 0.19751880f, 0.25325059f, 0.34806166f, 0.44638905f, + 0.200278980f, 0.22979005f, 0.27661907f, 0.31333340f, 0.38330744f, 0.44013638f, + 0.147984570f, 0.20195322f, 0.26483855f, 0.31025032f, 0.36569269f, 0.42239969f, + 0.195086490f, 0.23098500f, 0.30395854f, 0.34483682f, 0.38586214f, 0.42438066f, + 0.096725831f, 0.15616494f, 0.21843296f, 0.29493721f, 0.35664482f, 0.43073450f, + 0.186832170f, 0.21579466f, 0.30557582f, 0.35804882f, 0.40192237f, 0.44148013f, + 0.131465720f, 0.16604695f, 0.23214633f, 0.30213654f, 0.36326612f, 0.43615662f, + 0.248074080f, 0.27538389f, 0.30784390f, 0.33816285f, 0.38664576f, 0.43811284f, + 0.129804270f, 0.16455588f, 0.24948399f, 0.29846586f, 0.34646629f, 0.39636043f, + 0.166400470f, 0.20256213f, 0.26232918f, 0.34952652f, 0.42374855f, 0.46579300f, + 0.142332960f, 0.18013006f, 0.23247726f, 0.28747540f, 0.37225279f, 0.42277361f, + 0.218164380f, 0.27036123f, 0.29741317f, 0.33658242f, 0.37288172f, 0.43297122f, + 0.070747526f, 0.12972708f, 0.23503772f, 0.30178403f, 0.35944976f, 0.43280902f, + 0.203817720f, 0.28320849f, 0.32265104f, 0.36469291f, 0.39977801f, 0.44224295f, + 0.122382190f, 0.15795076f, 0.27432170f, 0.33024348f, 0.37383108f, 0.41668653f, + 0.246445660f, 0.27118517f, 0.31770823f, 0.35773353f, 0.39648445f, 0.43540417f, + 0.070426224f, 0.12260340f, 0.18382397f, 0.23249431f, 0.29712141f, 0.39919694f, + 0.183126440f, 0.20602093f, 0.24375562f, 0.27361644f, 0.33459363f, 0.41471750f, + 0.088748459f, 0.16327910f, 0.22175401f, 0.26667908f, 0.31866453f, 0.39616098f, + 0.187460500f, 0.20871643f, 0.27548782f, 0.31634516f, 0.39309748f, 0.43994220f, + 0.081379567f, 0.12891936f, 0.18833934f, 0.25567206f, 0.32705903f, 0.38458961f, + 0.191505080f, 0.21728053f, 0.28226653f, 0.32386961f, 0.38391795f, 0.45235836f, + 0.082156793f, 0.13994262f, 0.21264164f, 0.30082758f, 0.36988471f, 0.43363836f, + 0.237145870f, 0.26759673f, 0.29733906f, 0.32792373f, 0.36448143f, 0.40360639f, + 0.128199820f, 0.16341814f, 0.21755898f, 0.25443908f, 0.30439771f, 0.35908714f, + 0.189707910f, 0.21668527f, 0.25769184f, 0.28813697f, 0.34477993f, 0.41777603f, + 0.125467980f, 0.15380570f, 0.20025914f, 0.24632028f, 0.36725388f, 0.42488725f, + 0.203165520f, 0.26241863f, 0.28495340f, 0.32547246f, 0.36743034f, 0.44873687f, + 0.093381965f, 0.15915305f, 0.22155271f, 0.30877697f, 0.38380526f, 0.43903641f, + 0.155729460f, 0.27199100f, 0.30995504f, 0.35152115f, 0.38662749f, 0.43394669f, + 0.141375780f, 0.18067408f, 0.23815984f, 0.29034933f, 0.38882061f, 0.44831617f, + 0.205067360f, 0.26200850f, 0.28831845f, 0.35265548f, 0.41227841f, 0.46066867f, + 0.072047472f, 0.12115468f, 0.18961933f, 0.28488105f, 0.40495409f, 0.46004731f, + 0.198557750f, 0.22705201f, 0.27591618f, 0.31064014f, 0.36695315f, 0.41465139f, + 0.128799860f, 0.16494038f, 0.25362087f, 0.29961433f, 0.35336792f, 0.42859765f, + 0.189710480f, 0.22045927f, 0.29038955f, 0.34755716f, 0.41335089f, 0.45984727f, + 0.087636105f, 0.16804885f, 0.24880519f, 0.32500502f, 0.39871150f, 0.45243576f, + 0.183164490f, 0.20372954f, 0.28663902f, 0.33639693f, 0.39567505f, 0.45029614f, + 0.135442360f, 0.17219131f, 0.25232067f, 0.30812818f, 0.37522467f, 0.44933943f, + 0.237947800f, 0.26313746f, 0.29423846f, 0.33363250f, 0.40548313f, 0.46136835f, + 0.136450240f, 0.17206573f, 0.23044273f, 0.28127300f, 0.34912154f, 0.39454258f, + 0.184673430f, 0.21026600f, 0.27179282f, 0.32517703f, 0.41007950f, 0.46131088f, + 0.120635550f, 0.15057589f, 0.23738282f, 0.29356081f, 0.37244051f, 0.42760875f, + 0.165980800f, 0.26393604f, 0.29879643f, 0.37329254f, 0.42416075f, 0.46364654f, + 0.083243472f, 0.13716891f, 0.20532429f, 0.28573678f, 0.34618078f, 0.42885349f, + 0.124185840f, 0.25817832f, 0.30013923f, 0.35832406f, 0.40788565f, 0.45242538f, + 0.148751310f, 0.21168861f, 0.28155588f, 0.33399871f, 0.39200642f, 0.44392882f, + 0.250092790f, 0.27749655f, 0.31714030f, 0.35382269f, 0.40755488f, 0.45807079f, + 0.090218008f, 0.15844407f, 0.21605547f, 0.26747762f, 0.33611136f, 0.43256724f, + 0.194821460f, 0.22238574f, 0.26892332f, 0.29957274f, 0.34593681f, 0.39087253f, + 0.088872041f, 0.18684006f, 0.27868480f, 0.33185291f, 0.38399584f, 0.43532623f, + 0.187631470f, 0.21132813f, 0.26919143f, 0.30608744f, 0.37267119f, 0.45037854f, + 0.078499578f, 0.14581909f, 0.22353298f, 0.28124283f, 0.35460841f, 0.44710837f, + 0.203049030f, 0.23554188f, 0.29130760f, 0.32976939f, 0.38552827f, 0.43804459f, + 0.132090630f, 0.16828557f, 0.25117965f, 0.33118164f, 0.39126122f, 0.43521955f, + 0.245699330f, 0.28091560f, 0.31693809f, 0.35063725f, 0.38679310f, 0.42687325f, + 0.141120120f, 0.18351512f, 0.24129878f, 0.28194334f, 0.34056397f, 0.42074436f, + 0.176576340f, 0.19930558f, 0.25055988f, 0.30421218f, 0.40924681f, 0.46535353f, + 0.117761100f, 0.14946364f, 0.21764598f, 0.29577606f, 0.40879019f, 0.46136645f, + 0.204842420f, 0.27294301f, 0.30601511f, 0.35160404f, 0.38727312f, 0.43085356f, + 0.073765998f, 0.14878616f, 0.27867445f, 0.35617826f, 0.40839136f, 0.45292538f, + 0.125517660f, 0.25496685f, 0.32758337f, 0.38197773f, 0.42435415f, 0.46126376f, + 0.135962010f, 0.17555426f, 0.24178151f, 0.31425983f, 0.40720232f, 0.45869366f, + 0.213570120f, 0.27094587f, 0.30863435f, 0.37331744f, 0.42018011f, 0.46102471f, + 0.082998736f, 0.14651530f, 0.21003822f, 0.28279492f, 0.38739390f, 0.45279145f, + 0.198570550f, 0.22875204f, 0.28417900f, 0.32642267f, 0.40238371f, 0.45320042f, + 0.141324200f, 0.19351582f, 0.27967266f, 0.32946724f, 0.37612094f, 0.41912905f, + 0.201481430f, 0.23856193f, 0.30309500f, 0.34633198f, 0.40074668f, 0.44775506f, + 0.094264220f, 0.16969966f, 0.23129383f, 0.28788431f, 0.37402386f, 0.44657509f, + 0.190612400f, 0.23544456f, 0.31650278f, 0.36818431f, 0.41389673f, 0.45404931f, + 0.145178650f, 0.19384152f, 0.26072685f, 0.31177170f, 0.38904763f, 0.44618125f, + 0.249738030f, 0.28583093f, 0.32433884f, 0.36184735f, 0.40237550f, 0.44552961f, + 0.144466440f, 0.19269281f, 0.25474986f, 0.29651925f, 0.34405115f, 0.39494788f, + 0.177748120f, 0.20967896f, 0.29994813f, 0.37438345f, 0.42341220f, 0.46196806f, + 0.144017810f, 0.18743776f, 0.25098351f, 0.29549083f, 0.36361608f, 0.43793137f, + 0.191890800f, 0.26774988f, 0.29463282f, 0.34191791f, 0.38746328f, 0.45369258f, + 0.081212845f, 0.13994797f, 0.22358119f, 0.33366778f, 0.41201077f, 0.45855130f, + 0.181044650f, 0.28450829f, 0.33194281f, 0.38005566f, 0.41856023f, 0.45789922f, + 0.136313630f, 0.18429069f, 0.26984493f, 0.34070980f, 0.40759216f, 0.45475266f, + 0.240476170f, 0.27948010f, 0.32327234f, 0.37258368f, 0.41532038f, 0.45744253f +}; + +const float swb_tbe_lsfvq_cbook_8b[256*LPC_SHB_ORDER] = +{ + 0.052035f, 0.098557f, 0.128235f, 0.155222f, 0.187634f, 0.220354f, 0.248003f, 0.327378f, 0.416763f, 0.468886f, + 0.050902f, 0.090274f, 0.123988f, 0.172234f, 0.224479f, 0.288101f, 0.337089f, 0.374172f, 0.403673f, 0.442608f, + 0.047188f, 0.089025f, 0.128973f, 0.167152f, 0.212901f, 0.254805f, 0.296290f, 0.362619f, 0.403389f, 0.449070f, + 0.035345f, 0.083282f, 0.158003f, 0.212631f, 0.253206f, 0.293314f, 0.325157f, 0.356067f, 0.389327f, 0.439909f, + 0.049324f, 0.091699f, 0.133308f, 0.177313f, 0.216889f, 0.248068f, 0.286140f, 0.319129f, 0.388743f, 0.452730f, + 0.037590f, 0.074792f, 0.126499f, 0.196718f, 0.236226f, 0.274430f, 0.316669f, 0.363084f, 0.433737f, 0.467349f, + 0.049999f, 0.094260f, 0.156667f, 0.193806f, 0.224624f, 0.253432f, 0.298661f, 0.377723f, 0.419777f, 0.464133f, + 0.038569f, 0.077613f, 0.169806f, 0.204031f, 0.242844f, 0.289350f, 0.336338f, 0.381981f, 0.423438f, 0.462244f, + 0.039797f, 0.077432f, 0.113315f, 0.148404f, 0.200326f, 0.241409f, 0.286872f, 0.359925f, 0.404895f, 0.452684f, + 0.050430f, 0.099036f, 0.143005f, 0.195455f, 0.242036f, 0.281478f, 0.323205f, 0.366833f, 0.402614f, 0.450408f, + 0.039724f, 0.079916f, 0.130839f, 0.179575f, 0.218692f, 0.261122f, 0.320798f, 0.380589f, 0.420132f, 0.460065f, + 0.062070f, 0.105792f, 0.170204f, 0.199290f, 0.234202f, 0.268038f, 0.333250f, 0.390551f, 0.418930f, 0.457810f, + 0.079997f, 0.120714f, 0.160981f, 0.199639f, 0.229158f, 0.259921f, 0.288582f, 0.329020f, 0.380142f, 0.430256f, + 0.045641f, 0.080952f, 0.126548f, 0.172023f, 0.224929f, 0.281759f, 0.360638f, 0.396302f, 0.426277f, 0.459174f, + 0.067880f, 0.101438f, 0.143420f, 0.179072f, 0.220060f, 0.263601f, 0.346964f, 0.387408f, 0.415045f, 0.444299f, + 0.038652f, 0.093084f, 0.143655f, 0.192895f, 0.264359f, 0.309455f, 0.341003f, 0.380032f, 0.409710f, 0.453003f, + 0.050708f, 0.090949f, 0.126797f, 0.165211f, 0.202591f, 0.237959f, 0.282372f, 0.346666f, 0.391780f, 0.440679f, + 0.046423f, 0.087161f, 0.150877f, 0.194305f, 0.229067f, 0.270295f, 0.334805f, 0.371802f, 0.405116f, 0.457953f, + 0.044360f, 0.087261f, 0.139254f, 0.182219f, 0.219289f, 0.261504f, 0.309799f, 0.359196f, 0.408816f, 0.457282f, + 0.034881f, 0.089771f, 0.160723f, 0.208734f, 0.255654f, 0.288616f, 0.323156f, 0.354465f, 0.423951f, 0.466020f, + 0.051086f, 0.093155f, 0.140520f, 0.176030f, 0.216785f, 0.257930f, 0.308053f, 0.359569f, 0.390408f, 0.419868f, + 0.051928f, 0.099511f, 0.144135f, 0.190596f, 0.241070f, 0.289741f, 0.335984f, 0.378008f, 0.417474f, 0.459764f, + 0.041656f, 0.085336f, 0.164968f, 0.198531f, 0.228507f, 0.264871f, 0.318823f, 0.366222f, 0.416159f, 0.459177f, + 0.063772f, 0.119952f, 0.176631f, 0.218406f, 0.251883f, 0.296547f, 0.335911f, 0.368682f, 0.403997f, 0.454099f, + 0.059576f, 0.096358f, 0.126102f, 0.157582f, 0.193300f, 0.225485f, 0.274787f, 0.360048f, 0.430168f, 0.473165f, + 0.050090f, 0.098011f, 0.150107f, 0.194228f, 0.239956f, 0.284161f, 0.328550f, 0.373362f, 0.417904f, 0.459405f, + 0.050455f, 0.091803f, 0.128564f, 0.163400f, 0.213005f, 0.269193f, 0.341329f, 0.387102f, 0.424272f, 0.465410f, + 0.056626f, 0.105111f, 0.157033f, 0.200776f, 0.238054f, 0.282274f, 0.337598f, 0.395108f, 0.431675f, 0.466636f, + 0.041642f, 0.108843f, 0.169446f, 0.197564f, 0.223758f, 0.251886f, 0.303709f, 0.346790f, 0.412135f, 0.456278f, + 0.045415f, 0.088367f, 0.137979f, 0.191624f, 0.240474f, 0.288265f, 0.348450f, 0.394310f, 0.440392f, 0.471964f, + 0.046252f, 0.096877f, 0.163695f, 0.195612f, 0.222631f, 0.252841f, 0.329557f, 0.384350f, 0.432499f, 0.470718f, + 0.053043f, 0.104263f, 0.159826f, 0.209898f, 0.257555f, 0.321633f, 0.369402f, 0.398653f, 0.424938f, 0.462350f, + 0.043656f, 0.081158f, 0.119295f, 0.162597f, 0.202663f, 0.242606f, 0.285262f, 0.336831f, 0.412286f, 0.457530f, + 0.042710f, 0.080739f, 0.129188f, 0.194265f, 0.236487f, 0.281364f, 0.322263f, 0.353819f, 0.398147f, 0.457506f, + 0.034022f, 0.067080f, 0.110067f, 0.161100f, 0.245813f, 0.298294f, 0.336441f, 0.379210f, 0.426400f, 0.464858f, + 0.041504f, 0.104317f, 0.174678f, 0.212809f, 0.241453f, 0.277049f, 0.329887f, 0.379542f, 0.415948f, 0.452461f, + 0.043385f, 0.093120f, 0.156620f, 0.187415f, 0.219909f, 0.252543f, 0.285489f, 0.331396f, 0.421562f, 0.463942f, + 0.032947f, 0.067948f, 0.125627f, 0.195426f, 0.246592f, 0.284364f, 0.333690f, 0.378531f, 0.417714f, 0.452488f, + 0.049156f, 0.104448f, 0.150380f, 0.189623f, 0.226621f, 0.266196f, 0.320491f, 0.363628f, 0.410110f, 0.460970f, + 0.059406f, 0.107544f, 0.158619f, 0.213862f, 0.255056f, 0.305344f, 0.347819f, 0.379775f, 0.414531f, 0.461875f, + 0.042551f, 0.081551f, 0.122191f, 0.173384f, 0.212196f, 0.253318f, 0.299526f, 0.366219f, 0.418377f, 0.460170f, + 0.054564f, 0.097456f, 0.139734f, 0.189857f, 0.240306f, 0.279858f, 0.341376f, 0.385962f, 0.412633f, 0.443663f, + 0.047246f, 0.085779f, 0.123843f, 0.162683f, 0.199213f, 0.237097f, 0.335143f, 0.388883f, 0.421806f, 0.461765f, + 0.053449f, 0.122299f, 0.157276f, 0.197221f, 0.242155f, 0.288987f, 0.338839f, 0.378598f, 0.407019f, 0.443119f, + 0.061169f, 0.096794f, 0.155005f, 0.186632f, 0.216953f, 0.248877f, 0.315884f, 0.372060f, 0.409344f, 0.450829f, + 0.050160f, 0.097186f, 0.144946f, 0.191946f, 0.238536f, 0.282942f, 0.336958f, 0.391570f, 0.431474f, 0.468178f, + 0.070512f, 0.115329f, 0.156141f, 0.186164f, 0.223411f, 0.278915f, 0.315935f, 0.370299f, 0.422165f, 0.463007f, + 0.052587f, 0.101896f, 0.154071f, 0.206102f, 0.254920f, 0.314033f, 0.367686f, 0.401531f, 0.433527f, 0.471797f, + 0.067698f, 0.106830f, 0.141570f, 0.175913f, 0.207186f, 0.239077f, 0.299182f, 0.363370f, 0.402273f, 0.448275f, + 0.050042f, 0.096846f, 0.142801f, 0.189262f, 0.233767f, 0.278335f, 0.328758f, 0.378276f, 0.424023f, 0.463870f, + 0.048564f, 0.093699f, 0.138452f, 0.183259f, 0.224028f, 0.268624f, 0.319818f, 0.373529f, 0.420181f, 0.461720f, + 0.035663f, 0.110208f, 0.182596f, 0.215274f, 0.262474f, 0.305840f, 0.334102f, 0.363985f, 0.391665f, 0.450045f, + 0.052124f, 0.097379f, 0.141664f, 0.187867f, 0.225707f, 0.268701f, 0.306038f, 0.358072f, 0.403022f, 0.453386f, + 0.046364f, 0.094056f, 0.145010f, 0.197890f, 0.235910f, 0.284683f, 0.329466f, 0.366312f, 0.443226f, 0.473416f, + 0.065692f, 0.108572f, 0.157530f, 0.204882f, 0.236869f, 0.270301f, 0.305422f, 0.366582f, 0.418869f, 0.464143f, + 0.081775f, 0.123697f, 0.162035f, 0.213510f, 0.253580f, 0.285130f, 0.316195f, 0.376374f, 0.434072f, 0.472957f, + 0.071914f, 0.116132f, 0.153572f, 0.182184f, 0.211027f, 0.240482f, 0.272342f, 0.368056f, 0.422300f, 0.463416f, + 0.055135f, 0.104947f, 0.151424f, 0.197856f, 0.244545f, 0.291623f, 0.334237f, 0.376193f, 0.417664f, 0.459559f, + 0.047928f, 0.088506f, 0.128407f, 0.196811f, 0.234221f, 0.262202f, 0.339912f, 0.389867f, 0.432755f, 0.470636f, + 0.061209f, 0.130070f, 0.168080f, 0.195727f, 0.232576f, 0.266266f, 0.329227f, 0.384677f, 0.415326f, 0.450918f, + 0.054489f, 0.114179f, 0.160730f, 0.204526f, 0.247099f, 0.288682f, 0.320040f, 0.350371f, 0.393345f, 0.454259f, + 0.050257f, 0.098343f, 0.146333f, 0.195038f, 0.244345f, 0.293566f, 0.353243f, 0.395361f, 0.430313f, 0.469396f, + 0.046313f, 0.098069f, 0.159706f, 0.198648f, 0.234593f, 0.268660f, 0.359439f, 0.425175f, 0.450429f, 0.472752f, + 0.065195f, 0.111302f, 0.163983f, 0.223289f, 0.264603f, 0.313139f, 0.359677f, 0.394680f, 0.421766f, 0.463443f, + 0.049833f, 0.099641f, 0.142577f, 0.172120f, 0.206797f, 0.237530f, 0.271835f, 0.310803f, 0.368226f, 0.442268f, + 0.051561f, 0.092407f, 0.127677f, 0.184605f, 0.228561f, 0.264833f, 0.337058f, 0.373648f, 0.408072f, 0.458254f, + 0.050312f, 0.093979f, 0.133001f, 0.176857f, 0.224745f, 0.262482f, 0.313019f, 0.370051f, 0.406746f, 0.461218f, + 0.056453f, 0.100292f, 0.164556f, 0.206451f, 0.238837f, 0.280290f, 0.320629f, 0.359375f, 0.404283f, 0.462747f, + 0.064422f, 0.107489f, 0.148611f, 0.185763f, 0.218563f, 0.255882f, 0.294328f, 0.331455f, 0.376622f, 0.436460f, + 0.046651f, 0.088769f, 0.126223f, 0.207005f, 0.246095f, 0.284572f, 0.333915f, 0.369094f, 0.423764f, 0.462912f, + 0.056372f, 0.100125f, 0.145020f, 0.186096f, 0.223092f, 0.266834f, 0.309121f, 0.374704f, 0.413627f, 0.455613f, + 0.035065f, 0.084427f, 0.179107f, 0.228245f, 0.259827f, 0.296722f, 0.342853f, 0.375360f, 0.423312f, 0.459834f, + 0.051556f, 0.093559f, 0.131989f, 0.171289f, 0.206668f, 0.242179f, 0.276215f, 0.370322f, 0.418996f, 0.458514f, + 0.064906f, 0.103567f, 0.160614f, 0.209947f, 0.240290f, 0.279374f, 0.314472f, 0.370362f, 0.411818f, 0.440592f, + 0.051333f, 0.093194f, 0.134650f, 0.184715f, 0.225233f, 0.258320f, 0.299595f, 0.380254f, 0.431966f, 0.466464f, + 0.054906f, 0.104680f, 0.156332f, 0.201242f, 0.242115f, 0.293254f, 0.350097f, 0.390361f, 0.417661f, 0.453152f, + 0.057964f, 0.111565f, 0.163839f, 0.193942f, 0.229367f, 0.268561f, 0.301745f, 0.355413f, 0.397475f, 0.426184f, + 0.043021f, 0.099243f, 0.155661f, 0.184626f, 0.228258f, 0.302504f, 0.358238f, 0.390818f, 0.429834f, 0.463440f, + 0.045380f, 0.120045f, 0.163293f, 0.195013f, 0.229454f, 0.271296f, 0.350581f, 0.391168f, 0.420733f, 0.455968f, + 0.047668f, 0.096305f, 0.154868f, 0.214976f, 0.270766f, 0.313434f, 0.350305f, 0.385491f, 0.424396f, 0.457538f, + 0.047251f, 0.089307f, 0.132379f, 0.176882f, 0.213945f, 0.248516f, 0.284924f, 0.345563f, 0.410789f, 0.454839f, + 0.043366f, 0.088702f, 0.144534f, 0.191411f, 0.235903f, 0.273950f, 0.319010f, 0.377616f, 0.422360f, 0.464893f, + 0.045624f, 0.091445f, 0.137199f, 0.184217f, 0.230245f, 0.275709f, 0.321477f, 0.366635f, 0.411549f, 0.456497f, + 0.042352f, 0.097756f, 0.173684f, 0.215934f, 0.261779f, 0.294833f, 0.331844f, 0.376147f, 0.440475f, 0.470683f, + 0.038091f, 0.091036f, 0.161878f, 0.196009f, 0.230216f, 0.262778f, 0.314032f, 0.356498f, 0.393785f, 0.443990f, + 0.045665f, 0.091177f, 0.141352f, 0.193543f, 0.239618f, 0.284706f, 0.341027f, 0.382868f, 0.419859f, 0.463306f, + 0.041904f, 0.103110f, 0.154646f, 0.188554f, 0.225202f, 0.267803f, 0.305332f, 0.349841f, 0.431723f, 0.469552f, + 0.077431f, 0.117466f, 0.168864f, 0.221652f, 0.253857f, 0.294713f, 0.346262f, 0.377031f, 0.425887f, 0.467332f, + 0.064470f, 0.103906f, 0.134849f, 0.160779f, 0.196409f, 0.244298f, 0.314086f, 0.379702f, 0.416731f, 0.463122f, + 0.049451f, 0.112350f, 0.166433f, 0.195509f, 0.227644f, 0.285465f, 0.331780f, 0.367291f, 0.432216f, 0.466286f, + 0.058067f, 0.098622f, 0.137834f, 0.175730f, 0.218379f, 0.270120f, 0.325626f, 0.378807f, 0.443060f, 0.474998f, + 0.052308f, 0.115312f, 0.157669f, 0.200104f, 0.247392f, 0.279777f, 0.322273f, 0.392271f, 0.433586f, 0.467817f, + 0.058782f, 0.111246f, 0.168484f, 0.215834f, 0.244122f, 0.273877f, 0.299244f, 0.338369f, 0.412816f, 0.466858f, + 0.055542f, 0.086661f, 0.144229f, 0.216409f, 0.252097f, 0.297799f, 0.342351f, 0.370742f, 0.429205f, 0.465769f, + 0.063246f, 0.100799f, 0.164514f, 0.204780f, 0.229008f, 0.259317f, 0.319118f, 0.378226f, 0.441896f, 0.474270f, + 0.049656f, 0.100510f, 0.158979f, 0.226797f, 0.269956f, 0.309657f, 0.351457f, 0.393377f, 0.442146f, 0.470304f, + 0.066278f, 0.103915f, 0.139783f, 0.171615f, 0.205432f, 0.233412f, 0.258944f, 0.302518f, 0.408815f, 0.464278f, + 0.048237f, 0.093317f, 0.141389f, 0.189982f, 0.235703f, 0.281926f, 0.328964f, 0.373539f, 0.416565f, 0.460637f, + 0.051115f, 0.089333f, 0.124829f, 0.175556f, 0.227688f, 0.272289f, 0.313617f, 0.356144f, 0.426854f, 0.468024f, + 0.057016f, 0.110189f, 0.160396f, 0.211405f, 0.246994f, 0.287899f, 0.335640f, 0.370610f, 0.408313f, 0.462788f, + 0.045706f, 0.110933f, 0.160922f, 0.208233f, 0.238788f, 0.272099f, 0.299401f, 0.332730f, 0.381907f, 0.454209f, + 0.044199f, 0.080129f, 0.119936f, 0.210423f, 0.254754f, 0.297418f, 0.348033f, 0.383461f, 0.436047f, 0.467678f, + 0.059370f, 0.103993f, 0.152197f, 0.193477f, 0.232752f, 0.273256f, 0.312825f, 0.377850f, 0.411394f, 0.457251f, + 0.059698f, 0.114702f, 0.164424f, 0.210373f, 0.258366f, 0.304006f, 0.349730f, 0.389369f, 0.431678f, 0.467558f, + 0.050972f, 0.099832f, 0.140005f, 0.182190f, 0.219279f, 0.255299f, 0.294189f, 0.366548f, 0.411624f, 0.452662f, + 0.059947f, 0.105101f, 0.147291f, 0.189602f, 0.242184f, 0.277632f, 0.329136f, 0.385035f, 0.415412f, 0.464746f, + 0.050246f, 0.103445f, 0.142498f, 0.184607f, 0.213644f, 0.242299f, 0.319253f, 0.380800f, 0.447847f, 0.479237f, + 0.067193f, 0.115430f, 0.155858f, 0.206126f, 0.252681f, 0.293822f, 0.356656f, 0.397588f, 0.423304f, 0.464089f, + 0.071847f, 0.116894f, 0.157883f, 0.194092f, 0.230547f, 0.274564f, 0.325945f, 0.365502f, 0.398749f, 0.451080f, + 0.071752f, 0.107567f, 0.149280f, 0.194893f, 0.232418f, 0.278702f, 0.361895f, 0.398599f, 0.425587f, 0.457898f, + 0.068739f, 0.115103f, 0.157316f, 0.197895f, 0.237993f, 0.279071f, 0.328650f, 0.383319f, 0.420022f, 0.465113f, + 0.052303f, 0.094829f, 0.144186f, 0.186062f, 0.279484f, 0.319196f, 0.354590f, 0.387530f, 0.437802f, 0.465583f, + 0.055846f, 0.106998f, 0.151640f, 0.182290f, 0.210559f, 0.239134f, 0.274479f, 0.338376f, 0.407908f, 0.453481f, + 0.056627f, 0.103955f, 0.149473f, 0.194316f, 0.238331f, 0.280339f, 0.318046f, 0.371471f, 0.426297f, 0.467870f, + 0.061231f, 0.103217f, 0.144741f, 0.186145f, 0.226738f, 0.267120f, 0.329755f, 0.373349f, 0.417263f, 0.463712f, + 0.045494f, 0.110081f, 0.163067f, 0.227778f, 0.280124f, 0.307836f, 0.336439f, 0.369219f, 0.402807f, 0.456421f, + 0.053383f, 0.102864f, 0.156288f, 0.198372f, 0.233337f, 0.267640f, 0.304209f, 0.356227f, 0.407078f, 0.455673f, + 0.056676f, 0.107005f, 0.155125f, 0.201255f, 0.250254f, 0.297223f, 0.339905f, 0.382321f, 0.423693f, 0.461944f, + 0.054333f, 0.117799f, 0.170332f, 0.204234f, 0.239159f, 0.274313f, 0.314448f, 0.375919f, 0.415366f, 0.461096f, + 0.066036f, 0.136196f, 0.172592f, 0.232898f, 0.276089f, 0.302787f, 0.329116f, 0.395210f, 0.449302f, 0.475747f, + 0.070331f, 0.100716f, 0.133253f, 0.171137f, 0.209264f, 0.237895f, 0.305371f, 0.364686f, 0.438728f, 0.479133f, + 0.049672f, 0.104018f, 0.154836f, 0.206341f, 0.253671f, 0.295628f, 0.338852f, 0.376356f, 0.415621f, 0.460077f, + 0.056211f, 0.101148f, 0.145610f, 0.197140f, 0.227748f, 0.264313f, 0.341533f, 0.388764f, 0.445317f, 0.477085f, + 0.055185f, 0.133050f, 0.180174f, 0.209627f, 0.248220f, 0.279970f, 0.328967f, 0.384183f, 0.427107f, 0.462356f, + 0.090510f, 0.132862f, 0.173536f, 0.213099f, 0.242241f, 0.277461f, 0.307068f, 0.358492f, 0.406083f, 0.445895f, + 0.058962f, 0.100504f, 0.149829f, 0.208057f, 0.234691f, 0.276924f, 0.357507f, 0.397315f, 0.440325f, 0.472359f, + 0.060359f, 0.115102f, 0.165680f, 0.200810f, 0.227294f, 0.259266f, 0.358724f, 0.400750f, 0.443988f, 0.474842f, + 0.057406f, 0.110946f, 0.171732f, 0.222531f, 0.261630f, 0.332974f, 0.376127f, 0.402824f, 0.429325f, 0.465189f, + 0.043822f, 0.082882f, 0.122127f, 0.163180f, 0.199988f, 0.233325f, 0.273271f, 0.326231f, 0.395731f, 0.451164f, + 0.043530f, 0.086208f, 0.128358f, 0.174740f, 0.247178f, 0.286590f, 0.326910f, 0.374201f, 0.412175f, 0.456349f, + 0.044183f, 0.084451f, 0.124772f, 0.160673f, 0.219266f, 0.265006f, 0.316722f, 0.374047f, 0.409896f, 0.451766f, + 0.050936f, 0.101062f, 0.152285f, 0.210171f, 0.245676f, 0.292805f, 0.333955f, 0.366681f, 0.401168f, 0.455315f, + 0.046805f, 0.085866f, 0.127908f, 0.181072f, 0.225619f, 0.265095f, 0.301043f, 0.341348f, 0.395446f, 0.449907f, + 0.042622f, 0.082584f, 0.131883f, 0.184679f, 0.232497f, 0.279794f, 0.335535f, 0.379437f, 0.425137f, 0.465917f, + 0.052394f, 0.096555f, 0.141288f, 0.193157f, 0.229466f, 0.269961f, 0.307875f, 0.369736f, 0.427604f, 0.463768f, + 0.049014f, 0.101187f, 0.157612f, 0.211850f, 0.252631f, 0.293740f, 0.349772f, 0.390796f, 0.430148f, 0.466887f, + 0.061472f, 0.102460f, 0.130638f, 0.154914f, 0.188934f, 0.224962f, 0.289961f, 0.378839f, 0.409509f, 0.454753f, + 0.040355f, 0.111547f, 0.160810f, 0.198176f, 0.232341f, 0.282372f, 0.328114f, 0.365421f, 0.405953f, 0.452666f, + 0.051498f, 0.100439f, 0.143970f, 0.177506f, 0.213658f, 0.248304f, 0.327782f, 0.387335f, 0.423694f, 0.464601f, + 0.068825f, 0.113622f, 0.169531f, 0.214249f, 0.247214f, 0.285172f, 0.328523f, 0.387739f, 0.417886f, 0.464554f, + 0.072521f, 0.113366f, 0.160172f, 0.198528f, 0.226144f, 0.254678f, 0.310546f, 0.354542f, 0.387805f, 0.442152f, + 0.056215f, 0.098619f, 0.133402f, 0.181712f, 0.239008f, 0.278502f, 0.344724f, 0.388895f, 0.423036f, 0.467855f, + 0.062429f, 0.109771f, 0.162502f, 0.196939f, 0.224387f, 0.262071f, 0.323117f, 0.368722f, 0.416985f, 0.462413f, + 0.060110f, 0.108774f, 0.150308f, 0.199802f, 0.264652f, 0.304578f, 0.347395f, 0.390206f, 0.426311f, 0.464915f, + 0.045681f, 0.089659f, 0.149800f, 0.186117f, 0.216751f, 0.246327f, 0.290352f, 0.344660f, 0.389432f, 0.444891f, + 0.050829f, 0.096543f, 0.155589f, 0.190895f, 0.224301f, 0.271682f, 0.326354f, 0.381553f, 0.421373f, 0.457146f, + 0.044771f, 0.084669f, 0.139044f, 0.192501f, 0.226907f, 0.263807f, 0.306407f, 0.377071f, 0.414961f, 0.450916f, + 0.058452f, 0.110406f, 0.157460f, 0.204676f, 0.258762f, 0.290562f, 0.319844f, 0.352065f, 0.432222f, 0.472393f, + 0.056675f, 0.105769f, 0.145256f, 0.189372f, 0.223155f, 0.268584f, 0.316662f, 0.365541f, 0.401645f, 0.434404f, + 0.049272f, 0.094814f, 0.143723f, 0.196904f, 0.246241f, 0.301437f, 0.346313f, 0.383753f, 0.419651f, 0.459244f, + 0.047694f, 0.094350f, 0.151873f, 0.209061f, 0.245856f, 0.275424f, 0.315157f, 0.371735f, 0.428434f, 0.463634f, + 0.070013f, 0.117284f, 0.176432f, 0.220387f, 0.259562f, 0.300623f, 0.342089f, 0.390694f, 0.417372f, 0.462571f, + 0.058921f, 0.104850f, 0.142858f, 0.178126f, 0.210803f, 0.238810f, 0.288098f, 0.384526f, 0.432185f, 0.467076f, + 0.047972f, 0.097327f, 0.148890f, 0.203855f, 0.243240f, 0.283598f, 0.334893f, 0.372088f, 0.412174f, 0.464413f, + 0.053684f, 0.096809f, 0.143044f, 0.181581f, 0.228389f, 0.270800f, 0.322361f, 0.391276f, 0.430659f, 0.466880f, + 0.044586f, 0.122337f, 0.167705f, 0.201662f, 0.240097f, 0.289818f, 0.345058f, 0.382092f, 0.438138f, 0.472021f, + 0.058657f, 0.131647f, 0.175035f, 0.201389f, 0.228297f, 0.262383f, 0.300653f, 0.346236f, 0.427618f, 0.466306f, + 0.038131f, 0.079609f, 0.143124f, 0.213799f, 0.246000f, 0.274980f, 0.350246f, 0.403256f, 0.438897f, 0.468033f, + 0.068699f, 0.115225f, 0.168266f, 0.197077f, 0.222782f, 0.246507f, 0.334509f, 0.387455f, 0.435752f, 0.475064f, + 0.051779f, 0.102976f, 0.156663f, 0.213128f, 0.264735f, 0.326526f, 0.372141f, 0.403846f, 0.432850f, 0.471923f, + 0.060586f, 0.101498f, 0.135493f, 0.173480f, 0.209652f, 0.250462f, 0.291284f, 0.342503f, 0.417229f, 0.462133f, + 0.044335f, 0.086169f, 0.144113f, 0.197628f, 0.235900f, 0.273515f, 0.311798f, 0.358357f, 0.413356f, 0.462417f, + 0.037139f, 0.074523f, 0.116614f, 0.165055f, 0.223223f, 0.273117f, 0.329507f, 0.383426f, 0.435814f, 0.470269f, + 0.047181f, 0.097768f, 0.171023f, 0.205397f, 0.245358f, 0.295311f, 0.336586f, 0.369485f, 0.421233f, 0.465914f, + 0.062309f, 0.104500f, 0.147401f, 0.193110f, 0.228058f, 0.260174f, 0.286437f, 0.328216f, 0.408873f, 0.457704f, + 0.033758f, 0.076535f, 0.146968f, 0.223914f, 0.256314f, 0.293898f, 0.344191f, 0.380044f, 0.429295f, 0.458511f, + 0.053820f, 0.100870f, 0.151208f, 0.199506f, 0.237034f, 0.278242f, 0.317503f, 0.365012f, 0.414293f, 0.458401f, + 0.048959f, 0.115875f, 0.173948f, 0.217520f, 0.259862f, 0.301989f, 0.347552f, 0.382497f, 0.417961f, 0.461917f, + 0.049542f, 0.091687f, 0.132903f, 0.189723f, 0.224344f, 0.257479f, 0.299641f, 0.352070f, 0.426438f, 0.468136f, + 0.074975f, 0.118701f, 0.151425f, 0.178468f, 0.223099f, 0.296570f, 0.342204f, 0.375124f, 0.418237f, 0.461155f, + 0.048862f, 0.101636f, 0.141831f, 0.184422f, 0.217823f, 0.249609f, 0.343243f, 0.399113f, 0.450686f, 0.477330f, + 0.074971f, 0.112223f, 0.157913f, 0.196284f, 0.243594f, 0.305898f, 0.340704f, 0.371399f, 0.418209f, 0.461180f, + 0.047352f, 0.115276f, 0.160725f, 0.193027f, 0.229854f, 0.263731f, 0.301940f, 0.378552f, 0.414083f, 0.446173f, + 0.059846f, 0.105671f, 0.144046f, 0.198296f, 0.245954f, 0.283923f, 0.350516f, 0.391352f, 0.430367f, 0.471737f, + 0.074555f, 0.112890f, 0.160280f, 0.193719f, 0.233102f, 0.266509f, 0.312007f, 0.386544f, 0.420167f, 0.458038f, + 0.067261f, 0.111598f, 0.155216f, 0.207272f, 0.253291f, 0.309808f, 0.375775f, 0.406060f, 0.429646f, 0.466527f, + 0.072015f, 0.113855f, 0.152641f, 0.185966f, 0.212160f, 0.244403f, 0.279304f, 0.353568f, 0.397873f, 0.432053f, + 0.057609f, 0.105877f, 0.148922f, 0.188700f, 0.232036f, 0.282119f, 0.329612f, 0.375947f, 0.416782f, 0.457815f, + 0.050973f, 0.100177f, 0.140092f, 0.185550f, 0.238056f, 0.273150f, 0.321487f, 0.383660f, 0.415638f, 0.456817f, + 0.039806f, 0.126350f, 0.178948f, 0.213873f, 0.255655f, 0.294524f, 0.330344f, 0.360261f, 0.416162f, 0.466911f, + 0.063393f, 0.108247f, 0.149242f, 0.189683f, 0.222867f, 0.262691f, 0.299364f, 0.359972f, 0.412753f, 0.457277f, + 0.050600f, 0.099234f, 0.150035f, 0.198292f, 0.246257f, 0.290806f, 0.336586f, 0.382631f, 0.424274f, 0.463374f, + 0.067312f, 0.111338f, 0.151025f, 0.202518f, 0.240338f, 0.269562f, 0.300697f, 0.385260f, 0.440923f, 0.472259f, + 0.092753f, 0.142329f, 0.176758f, 0.223424f, 0.268502f, 0.296763f, 0.319964f, 0.376238f, 0.441441f, 0.477606f, + 0.057530f, 0.097677f, 0.159509f, 0.201106f, 0.224079f, 0.245637f, 0.286003f, 0.375766f, 0.445386f, 0.477458f, + 0.055718f, 0.105169f, 0.156792f, 0.203385f, 0.244396f, 0.285413f, 0.325547f, 0.384007f, 0.421448f, 0.459753f, + 0.044415f, 0.093549f, 0.159707f, 0.192449f, 0.225942f, 0.267813f, 0.348584f, 0.389866f, 0.428214f, 0.465053f, + 0.073100f, 0.142639f, 0.179538f, 0.209861f, 0.241096f, 0.284495f, 0.333600f, 0.382609f, 0.420087f, 0.454347f, + 0.056150f, 0.133011f, 0.171789f, 0.209798f, 0.243168f, 0.280293f, 0.313300f, 0.361975f, 0.402894f, 0.441400f, + 0.050711f, 0.100022f, 0.148476f, 0.200043f, 0.247876f, 0.305520f, 0.362364f, 0.399378f, 0.431164f, 0.470519f, + 0.050151f, 0.102726f, 0.178139f, 0.214644f, 0.239684f, 0.272465f, 0.350549f, 0.395865f, 0.439724f, 0.472007f, + 0.057321f, 0.112456f, 0.176664f, 0.223544f, 0.265943f, 0.332838f, 0.374528f, 0.400087f, 0.422190f, 0.452780f, + 0.068936f, 0.111462f, 0.152424f, 0.184775f, 0.213783f, 0.241083f, 0.269875f, 0.305906f, 0.384801f, 0.449720f, + 0.047841f, 0.090004f, 0.137440f, 0.184176f, 0.226672f, 0.280565f, 0.332422f, 0.379775f, 0.414877f, 0.455906f, + 0.051208f, 0.095910f, 0.134766f, 0.179194f, 0.228900f, 0.267574f, 0.317929f, 0.370086f, 0.401118f, 0.446217f, + 0.057304f, 0.108307f, 0.167260f, 0.219044f, 0.253957f, 0.285245f, 0.321407f, 0.369771f, 0.413636f, 0.462874f, + 0.062714f, 0.102112f, 0.146902f, 0.188999f, 0.226385f, 0.267241f, 0.309584f, 0.346847f, 0.387502f, 0.451009f, + 0.045352f, 0.084823f, 0.120662f, 0.187181f, 0.252978f, 0.294385f, 0.328589f, 0.369623f, 0.440700f, 0.470814f, + 0.054539f, 0.107161f, 0.151423f, 0.184774f, 0.222621f, 0.270311f, 0.310645f, 0.379532f, 0.421532f, 0.464395f, + 0.041931f, 0.097165f, 0.176126f, 0.244078f, 0.285457f, 0.311564f, 0.343280f, 0.380534f, 0.427693f, 0.465345f, + 0.049656f, 0.089927f, 0.123487f, 0.158143f, 0.207460f, 0.251012f, 0.298147f, 0.386381f, 0.434882f, 0.470227f, + 0.064608f, 0.113031f, 0.152816f, 0.202317f, 0.244207f, 0.281442f, 0.321974f, 0.369506f, 0.411120f, 0.458796f, + 0.041667f, 0.088042f, 0.149426f, 0.187507f, 0.226638f, 0.278825f, 0.313814f, 0.388390f, 0.448889f, 0.473167f, + 0.063255f, 0.112633f, 0.161884f, 0.207517f, 0.248243f, 0.290171f, 0.339946f, 0.392358f, 0.424077f, 0.465045f, + 0.047738f, 0.124639f, 0.167770f, 0.198211f, 0.225569f, 0.260577f, 0.319448f, 0.357208f, 0.390762f, 0.448737f, + 0.056281f, 0.097031f, 0.133672f, 0.175612f, 0.249666f, 0.302816f, 0.358207f, 0.396586f, 0.431468f, 0.464859f, + 0.065840f, 0.114000f, 0.154376f, 0.181022f, 0.219481f, 0.272109f, 0.342283f, 0.390114f, 0.425579f, 0.463533f, + 0.054385f, 0.087287f, 0.133120f, 0.219075f, 0.277198f, 0.318550f, 0.353398f, 0.394571f, 0.451311f, 0.473024f, + 0.050377f, 0.099870f, 0.139986f, 0.179622f, 0.215723f, 0.254691f, 0.298673f, 0.344156f, 0.401375f, 0.451981f, + 0.047282f, 0.095779f, 0.154096f, 0.204588f, 0.238142f, 0.277769f, 0.328001f, 0.383819f, 0.421546f, 0.464335f, + 0.051096f, 0.097245f, 0.143694f, 0.189341f, 0.232614f, 0.275390f, 0.321690f, 0.370345f, 0.414317f, 0.459688f, + 0.057607f, 0.108697f, 0.166883f, 0.217010f, 0.265314f, 0.303576f, 0.339093f, 0.374926f, 0.429392f, 0.466921f, + 0.058130f, 0.096368f, 0.163828f, 0.194469f, 0.230519f, 0.266092f, 0.322506f, 0.379323f, 0.410417f, 0.440281f, + 0.059593f, 0.104108f, 0.143990f, 0.199751f, 0.246890f, 0.283738f, 0.342763f, 0.388274f, 0.417119f, 0.460115f, + 0.044521f, 0.105111f, 0.173587f, 0.207942f, 0.239336f, 0.273945f, 0.308799f, 0.369491f, 0.436878f, 0.469005f, + 0.074773f, 0.133154f, 0.177818f, 0.224283f, 0.264970f, 0.306138f, 0.340046f, 0.370218f, 0.412563f, 0.459546f, + 0.075738f, 0.111821f, 0.145360f, 0.181385f, 0.219465f, 0.256030f, 0.308392f, 0.373355f, 0.418157f, 0.463492f, + 0.056087f, 0.105731f, 0.160372f, 0.206032f, 0.244637f, 0.282396f, 0.334056f, 0.375992f, 0.420837f, 0.468046f, + 0.076209f, 0.108262f, 0.143499f, 0.182696f, 0.233318f, 0.271088f, 0.327756f, 0.373740f, 0.439247f, 0.474235f, + 0.052399f, 0.112281f, 0.162812f, 0.201017f, 0.261354f, 0.299326f, 0.327620f, 0.386801f, 0.447769f, 0.474791f, + 0.074893f, 0.121992f, 0.163699f, 0.207822f, 0.244930f, 0.271999f, 0.296466f, 0.345316f, 0.435127f, 0.476239f, + 0.058176f, 0.105085f, 0.149574f, 0.194188f, 0.249818f, 0.296524f, 0.337963f, 0.402402f, 0.448624f, 0.472243f, + 0.060779f, 0.099068f, 0.167491f, 0.198796f, 0.227494f, 0.254019f, 0.329803f, 0.403981f, 0.450520f, 0.475438f, + 0.052532f, 0.104934f, 0.160049f, 0.218916f, 0.277885f, 0.331831f, 0.371634f, 0.402258f, 0.429073f, 0.470420f, + 0.066857f, 0.108497f, 0.146533f, 0.186402f, 0.214087f, 0.239551f, 0.273028f, 0.339210f, 0.442001f, 0.475864f, + 0.058742f, 0.098634f, 0.140424f, 0.200627f, 0.237759f, 0.274315f, 0.336864f, 0.374803f, 0.415969f, 0.461915f, + 0.055406f, 0.096635f, 0.130990f, 0.174857f, 0.231572f, 0.277597f, 0.327848f, 0.376613f, 0.419923f, 0.465467f, + 0.063142f, 0.117506f, 0.165530f, 0.207973f, 0.252515f, 0.292023f, 0.332960f, 0.374855f, 0.422203f, 0.463402f, + 0.073810f, 0.115150f, 0.161374f, 0.201145f, 0.234138f, 0.271883f, 0.300056f, 0.334944f, 0.401703f, 0.457714f, + 0.037073f, 0.082702f, 0.150719f, 0.196430f, 0.266875f, 0.302676f, 0.341803f, 0.383090f, 0.434380f, 0.469480f, + 0.056987f, 0.107639f, 0.156686f, 0.198247f, 0.233643f, 0.272298f, 0.323545f, 0.383539f, 0.424062f, 0.466175f, + 0.068935f, 0.128609f, 0.175519f, 0.221849f, 0.262138f, 0.308833f, 0.354349f, 0.391305f, 0.431214f, 0.465646f, + 0.058327f, 0.099513f, 0.135693f, 0.173498f, 0.210477f, 0.259223f, 0.309074f, 0.365292f, 0.418318f, 0.460997f, + 0.053768f, 0.108301f, 0.148739f, 0.187783f, 0.248594f, 0.294002f, 0.326224f, 0.362744f, 0.418485f, 0.459503f, + 0.072347f, 0.113391f, 0.145826f, 0.186488f, 0.216571f, 0.246055f, 0.321765f, 0.384969f, 0.449111f, 0.479851f, + 0.068789f, 0.114708f, 0.171724f, 0.209662f, 0.240956f, 0.286235f, 0.354813f, 0.393328f, 0.420976f, 0.466079f, + 0.076792f, 0.122064f, 0.164111f, 0.196669f, 0.228773f, 0.263496f, 0.298068f, 0.369577f, 0.412072f, 0.446788f, + 0.072788f, 0.097673f, 0.130704f, 0.203771f, 0.250741f, 0.295679f, 0.355656f, 0.375931f, 0.431577f, 0.468953f, + 0.084680f, 0.123747f, 0.166460f, 0.199970f, 0.238683f, 0.271627f, 0.332322f, 0.389857f, 0.417976f, 0.454237f, + 0.047850f, 0.120236f, 0.163003f, 0.208247f, 0.285501f, 0.314491f, 0.348042f, 0.393049f, 0.436136f, 0.467946f, + 0.074354f, 0.116190f, 0.158181f, 0.188861f, 0.216650f, 0.247676f, 0.294654f, 0.344099f, 0.416305f, 0.461946f, + 0.053571f, 0.101937f, 0.148655f, 0.194776f, 0.237718f, 0.284302f, 0.333285f, 0.379409f, 0.424284f, 0.464382f, + 0.058960f, 0.099074f, 0.140467f, 0.196967f, 0.231626f, 0.264843f, 0.323752f, 0.385782f, 0.425341f, 0.465240f, + 0.043253f, 0.133255f, 0.191933f, 0.224667f, 0.269958f, 0.309788f, 0.340578f, 0.370291f, 0.414823f, 0.464356f, + 0.055527f, 0.103077f, 0.145933f, 0.195951f, 0.237681f, 0.276359f, 0.307310f, 0.343951f, 0.415470f, 0.466831f, + 0.056607f, 0.103731f, 0.150533f, 0.199143f, 0.247090f, 0.294661f, 0.337006f, 0.380695f, 0.436417f, 0.469044f, + 0.058017f, 0.111478f, 0.184738f, 0.222470f, 0.248826f, 0.274226f, 0.313164f, 0.396522f, 0.439606f, 0.469562f, + 0.059766f, 0.131086f, 0.177741f, 0.250119f, 0.292365f, 0.314884f, 0.343841f, 0.383029f, 0.418571f, 0.469165f, + 0.063549f, 0.123913f, 0.167854f, 0.196007f, 0.222730f, 0.248052f, 0.296431f, 0.381363f, 0.440747f, 0.474918f, + 0.057303f, 0.104523f, 0.145906f, 0.215521f, 0.258023f, 0.293742f, 0.329884f, 0.375696f, 0.425649f, 0.463893f, + 0.062113f, 0.113749f, 0.146593f, 0.190918f, 0.221197f, 0.281815f, 0.352860f, 0.400393f, 0.454168f, 0.477972f, + 0.065394f, 0.121516f, 0.199177f, 0.235275f, 0.266790f, 0.299190f, 0.343026f, 0.386286f, 0.439359f, 0.470243f, + 0.079123f, 0.135214f, 0.178870f, 0.220386f, 0.255756f, 0.285377f, 0.317392f, 0.361228f, 0.405450f, 0.467724f, + 0.056167f, 0.115899f, 0.166770f, 0.207524f, 0.241655f, 0.297597f, 0.366322f, 0.404801f, 0.440200f, 0.470576f, + 0.065840f, 0.126504f, 0.164612f, 0.196957f, 0.220935f, 0.267816f, 0.338526f, 0.391567f, 0.453372f, 0.479359f, + 0.044781f, 0.115425f, 0.177337f, 0.247881f, 0.284229f, 0.319088f, 0.355269f, 0.403159f, 0.444401f, 0.467850f +}; + +const float wac_swb[LPC_SHB_ORDER + 1] = +{ + 1.00030000f, 0.99972246f, 0.99889029f, 0.99750487f, + 0.99556853f, 0.99308446f, 0.99005679f, 0.98649053f, + 0.98239158f, 0.97776669f, 0.97262346f +}; + +const float lbr_wb_bwe_lsfvq_cbook_2bit[4*4] = {0.11829331f, 0.18065347f, 0.27315149f, 0.36268139f, + 0.20006990f, 0.24350365f, 0.33066865f, 0.40078221f, + 0.13430431f, 0.20694768f, 0.32580520f, 0.41176145f, + 0.25797083f, 0.29579351f, 0.36694117f, 0.42482337f + }; + +const float wac[LPC_SHB_ORDER + 1] = { 1.000030000f, 0.999876638f, + 0.999506642f, 0.998890286f, + 0.998028026f, 0.996920500f, + 0.995568526f, 0.993973102f, + 0.992135406f, 0.990056789f, + 0.987738783f + }; + +/* 5-bit TD SWB BWE temporal shaping codebook */ +const float SHBCB_SubGain5bit[128] = +{ + -0.1457681f, -0.4764620f, -0.4013963f, -0.3677013f, + -0.4313035f, -0.3313996f, -0.3050383f, -0.2133066f, + -1.0206577f, -0.9364462f, -0.0586007f, -0.4846374f, + -1.6047017f, -0.3614168f, -0.3000874f, -0.2672006f, + -0.0931186f, -0.4041055f, -0.5172903f, -0.5874190f, + -0.4911704f, -0.2494092f, -0.5456603f, -0.1857298f, + -0.2215641f, -0.3130259f, -0.3029806f, -0.4504822f, + -0.0164831f, -1.1390385f, -1.4790464f, -1.5514144f, + -0.5643114f, -0.4608741f, -0.3408080f, -0.1252954f, + -0.1276388f, -0.2821012f, -0.5614353f, -0.8928169f, + -0.2834879f, -0.1340739f, -0.6259241f, -0.5918277f, + -0.1487753f, -0.5728573f, -0.7163700f, -0.2789117f, + -0.8768165f, -0.6980218f, -0.5036601f, -0.0499640f, + -0.9883066f, -0.9968036f, -1.0402167f, -0.0137106f, + -0.3300310f, -0.5241924f, -0.4624851f, -0.1401303f, + -1.6058040f, -1.3385040f, -0.4591369f, -0.1534372f, + -0.1989556f, -0.2591312f, -0.4850197f, -0.4037134f, + -0.1111035f, -0.3369072f, -0.9321365f, -1.2062822f, + -0.2261946f, -0.2280687f, -0.3570638f, -0.6421078f, + -0.6153073f, -0.2471987f, -0.2481002f, -0.3052209f, + -0.2385272f, -0.6048125f, -0.1758713f, -0.5861754f, + -0.0317327f, -0.6809157f, -0.7702834f, -0.7792925f, + -0.2770282f, -0.3142404f, -0.3788958f, -0.2723185f, + -0.2970077f, -0.4682712f, -0.2584636f, -0.2690060f, + -0.5592654f, -0.8185204f, -0.1815633f, -0.2389702f, + -0.7487352f, -0.4618911f, -0.2345186f, -0.1725288f, + -0.4382800f, -0.2999320f, -0.1591911f, -0.5732270f, + -0.3830038f, -0.1750423f, -0.3638722f, -0.3974119f, + -0.7911282f, -0.0631017f, -0.5198654f, -0.6708761f, + -0.5033713f, -0.4643340f, -0.1527029f, -0.3067638f, + -0.3547296f, -0.3050630f, -0.2355810f, -0.3526833f, + -1.0319320f, -0.3646283f, -0.2706210f, -0.1999401f +}; + +/* 5-bit TD WB BWE temporal shaping codebook */ +const float HBCB_SubGain5bit[128] = +{ + -59.470337f, -69.488670f, -38.659931f, -19.719824f, + -1.7830310f, -4.812642f, -8.744000f, -10.867781f, + -13.246320f, -15.094897f, -15.727152f, -15.801854f, + -7.879738f, -5.120556f, -3.429671f, -7.706632f, + -50.144310f, -60.062901f, -32.317268f, -16.175051f, + -10.900867f, -11.864854f, -9.386131f, -1.335022f, + -13.235695f, -14.241489f, -13.557719f, -11.050961f, + -0.612834f, -7.908495f, -9.054081f, -8.763001f, + -57.235970f, -64.192162f, -30.073193f, -4.640105f, + -10.025522f, -6.857354f, -1.353238f, -6.571805f, + -8.077633f, -9.067668f, -9.157619f, -9.171074f, + -6.871120f, -4.052971f, -7.285939f, -7.970854f, + -44.516933f, -53.591618f, -30.267939f, -10.678650f, + -3.160364f, -7.559843f, -7.367127f, -3.052069f, + -8.343053f, -7.577167f, -3.678010f, -6.135194f, + -7.522539f, -9.290725f, -10.048427f, -8.378534f, + -68.482224f, -75.261124f, -30.160120f, -10.437404f, + -2.787138f, -2.637044f, -5.920231f, -8.091020f, + -7.519012f, -9.081453f, -9.857375f, -10.380337f, + -6.422596f, -6.540410f, -7.954427f, -7.877131f, + -49.924343f, -57.036163f, -26.225056f, -5.391133f, + -8.174749f, -6.656519f, -4.389360f, -2.953642f, + -10.844235f, -10.494500f, -8.072153f, -4.695106f, + -4.305107f, -2.655748f, -7.638941f, -9.281904f, + -56.389565f, -61.898930f, -19.212666f, -8.088096f, + -6.302619f, -2.904698f, -7.059662f, -5.392998f, + -2.423694f, -5.054863f, -7.913060f, -8.444733f, + -3.101384f, -6.855487f, -4.557333f, -6.881396f, + -45.418392f, -52.252014f, -22.952511f, -7.653957f, + -3.941019f, -7.339684f, -4.011926f, -7.481068f, + -6.772878f, -4.939885f, -7.817589f, -3.977276f, + -2.728315f, -6.770474f, -8.485444f, -4.669493f +}; + + +/* 6 bit Quantizer table for SHB overall gain */ +const float SHBCB_FrameGain64[64]= +{ + 0.044072020f, 0.074116257f, 0.104772820f, 0.137129910f, 0.172361440f, 0.209110170f, 0.248146360f, 0.290349910f, + 0.336033220f, 0.384576680f, 0.436074570f, 0.491054220f, 0.550217560f, 0.613450140f, 0.681455200f, 0.753997600f, + 0.831286250f, 0.914336560f, 1.003638100f, 1.100985500f, 1.205300400f, 1.317519300f, 1.437191800f, 1.566197500f, + 1.704663300f, 1.853099500f, 2.013720200f, 2.190476500f, 2.382512800f, 2.591447500f, 2.818724200f, 3.064693900f, + 3.331486000f, 3.621288500f, 3.936974000f, 4.279052900f, 4.652247100f, 5.063426700f, 5.516226500f, 6.014047700f, + 6.565030700f, 7.179005400f, 7.869640600f, 8.646445300f, 9.521977600f, 10.52553600f, 11.67516800f, 13.00652900f, + 14.56494800f, 16.38657700f, 18.56994600f, 21.17650800f, 24.29317200f, 27.95810000f, 32.33308400f, 37.72507700f, + 44.44091200f, 52.62181300f, 62.89529200f, 76.21739000f, 94.34608600f, 119.5521800f, 160.0594500f, 245.1366400f +}; + +/* 4 bit Quantizer table for SHB overall gain */ +const float SHBCB_FrameGain16[16]= +{ + 0.148650413f, + 0.477894376f, + 0.970739390f, + 1.882108080f, + 3.981442531f, + 7.946689290f, + 14.46817648f, + 24.39527659f, + 39.12384197f, + 60.03913602f, + 88.76762784f, + 130.1507349f, + 184.4881647f, + 271.3320980f, + 409.9269865f, + 735.8126500f +}; + +/* 18th order elliptic Bandpass filter at 14.15 to 20 kHz sampled at 48 kHz b0,b1,b2,a0,a1,a2 */ +const float full_band_bpf_1[6][5] = +{ + { 9.6362039055508E-02f, 9.7862105350605E-02f, 3.0245537519444E-02f, 9.7862105350605E-02f, 9.6362039055508E-02f}, + { 9.6362039055508E-02f, 1.4633143118038E-01f, 1.0233713813742E-01f, 1.4633143118038E-01f, 9.6362039055508E-02f}, + { 9.6362039055508E-02f, 1.6626923151583E-02f, -1.3709502682285E-01f, 1.6626923151583E-02f, 9.6362039055508E-02f}, + { 1.0000000000000E+00f, 2.3991100643722E+00f, 2.9774531499625E+00f, 2.0824517848412E+00f, 8.0090184246950E-01f}, + { 1.0000000000000E+00f, 1.8724727524876E+00f, 2.4558672940808E+00f, 1.6868952908597E+00f, 7.5556052044790E-01f}, + { 1.0000000000000E+00f, 2.5823882989829E+00f, 3.2419903202957E+00f, 2.1041782509434E+00f, 6.8348510539492E-01f} +}; + +/* 12th order elliptic Bandpass filter at 16.3 to 19.8 kHz sampled at 48 kHz b0,b1,b2,a0,a1,a2 */ +const float full_band_bpf_2[6][5] = +{ + { 6.0003889556380E-02f, 1.1128037231775E-01f, 1.1894140617207E-01f, 1.1128037231775E-01f, 6.0003889556380E-02f}, + { 6.0003889556380E-02f, 1.4172832594169E-01f, 1.6515046627146E-01f, 1.4172832594169E-01f, 6.0003889556380E-02f}, + { 6.0003889556380E-02f, 3.1639978682801E-02f, -3.7925280401819E-02f, 3.1639978682801E-02f, 6.0003889556380E-02f}, + { 1.0000000000000E+00f, 2.7969061159585E+00f, 3.7380107651703E+00f, 2.5896033662624E+00f, 8.7195105769838E-01f}, + { 1.0000000000000E+00f, 2.4858753840930E+00f, 3.3360972572945E+00f, 2.3002595115472E+00f, 8.4059566462167E-01f}, + { 1.0000000000000E+00f, 2.8681737877693E+00f, 3.8085295994769E+00f, 2.5421873471575E+00f, 7.9182537841461E-01f} +}; + +/* 12th order elliptic Bandpass filter at 15.4 to 20.0 kHz sampled at 48 kHz b0,b1,b2,a0,a1,a2 */ +const float full_band_bpf_3[6][5] = +{ + {7.4636437949154E-02f, 1.0834902081890E-01f, 8.7514468139390E-02f, 1.0834902081890E-01f, 7.4636437949154E-02f}, + {7.4636437949154E-02f, 1.4782752996297E-01f, 1.4824632166087E-01f, 1.4782752996297E-01f, 7.4636437949154E-02f}, + {7.4636437949154E-02f, 2.4020393588811E-02f, -8.1869063979759E-02f, 2.4020393588811E-02f, 7.4636437949154E-02f}, + {1.0000000000000E+00f, 2.6521893008573E+00f, 3.4460829518042E+00f, 2.3910633156124E+00f, 8.3876600358846E-01f}, + {1.0000000000000E+00f, 2.2507856816983E+00f, 2.9756720931932E+00f, 2.0502894449026E+00f, 8.0167514850932E-01f}, + {1.0000000000000E+00f, 2.7689100300130E+00f, 3.5940097427365E+00f, 2.3681560760262E+00f, 7.4233948915492E-01f} +}; + + +/* 4-bit/3-bit TD SWB BWE differential LSF scalar quantizer tables */ +const float lsf_q_cb_4b[16] = +{ + 0.01798018f, 0.02359377f, 0.02790103f, 0.03181538f, + 0.03579450f, 0.03974377f, 0.04364637f, 0.04754591f, + 0.05181858f, 0.05624165f, 0.06022101f, 0.06419064f, + 0.06889389f, 0.07539274f, 0.08504436f, 0.10014875f +}; + +const float lsf_q_cb_3b[8] = +{ + 0.02070812f, 0.02978384f, 0.03800822f, 0.04548685f, + 0.05307309f, 0.06137543f, 0.07216742f, 0.09013262f +}; + +const float *const lsf_q_cb[NUM_Q_LSF] = { lsf_q_cb_4b, lsf_q_cb_4b, lsf_q_cb_3b, lsf_q_cb_3b, lsf_q_cb_3b }; +const short lsf_q_cb_size[NUM_Q_LSF] = {16, 16, 8, 8, 8}; +const short lsf_q_num_bits[NUM_Q_LSF] = { 4, 4, 3, 3, 3 }; + +/* Tables for approximation of upper half of SWB LSFs */ +const float mirror_point_q_cb[MIRROR_POINT_Q_CB_SIZE] = { 0.01436178f, 0.02111641f, 0.02735687f, 0.03712105f }; + +const float lsf_grid[4][5] = +{ + { 0.15998503f, 0.31215086f, 0.47349756f, 0.66540429f, 0.84043882f }, + { 0.15614473f, 0.30697672f, 0.45619822f, 0.62493785f, 0.77798001f }, + { 0.14185823f, 0.26648724f, 0.39740108f, 0.55685745f, 0.74688616f }, + { 0.15416561f, 0.27238427f, 0.39376780f, 0.59287916f, 0.86613986f } +}; + +const float grid_smoothing[5] = { 0.2f, 0.35f, 0.5f, 0.75f, 0.8f }; + +const float allpass_poles_3_ov_2[9] = +{ + 0.072265625000000f, + 0.626983642578125f, + 0.934020996093750f, + 0.778808593750000f, + 0.219360351562500f, + 0.970703125000000f, + 0.872039794921875f, + 0.438964843750000f, + 0.990966796875000f +}; + +const float decimate_3_ov_2_lowpass_num[3] = +{ + 0.195271809895833f, + 0.390543619791667f, + 0.195271809895833f +}; + +const float decimate_3_ov_2_lowpass_den[3] = +{ + 1.0f, + 0.0f, + 0.171630859375f +}; + + +/*------------------------------------------------------------------------------* + * WB BWE tables + *------------------------------------------------------------------------------*/ + +const float F_2_5[64] = +{ + 1.1606680f, 0.6594560f, + -4.9874350f, -5.1700310f, + 10.230799f, -0.0125740f, + 10.605126f, 9.7910260f, + -0.3739880f, -0.6027910f, + 6.2753817f, 0.3307670f, + 9.4537100f, 8.8558020f, + 2.9320890f, 2.1643160f, + 3.1332030f, 2.9710870f, + 8.061906f, -0.5905290f, + 15.754963f, 5.0496380f, + 17.227070f, 18.329395f, + -2.4710190f, -3.1725330f, + -1.4136470f, -1.9457110f, + 15.147771f, 14.506490f, + 11.358370f, 11.714662f, + 9.4275510f, -0.1223030f, + 7.0970160f, -1.5805260f, + 12.498663f, 3.1614850f, + 10.349261f, 1.5185040f, + 5.3809850f, -1.7341900f, + 1.1224600f, -2.2397020f, + 12.362551f, 12.133788f, + 4.2788690f, -1.7729040f, + 6.1577130f, 5.4971410f, + 3.3243130f, -2.5710470f, + 19.097071f, 9.3576920f, + 7.6509204f, 7.4404626f, + -0.5055090f, -3.7073090f, + 18.584702f, 11.302494f, + 18.706564f, 18.308905f, + 23.010420f, 22.915377f +}; + +/*------------------------------------------------------------------------------* + * SWB BWE tables + *------------------------------------------------------------------------------*/ + +const short swb_bwe_trans_subband[SWB_FENV_TRANS+1] = {240, 316, 392, 476, 560}; +const short swb_bwe_trans_subband_width[SWB_FENV_TRANS] = {76, 76, 84, 84}; +const short swb_bwe_subband[SWB_FENV+1] = {240, 256, 280, 296, 320, 336, 360, 376, 400, 424, 448, 472, 496, 528, 560}; +const float swb_inv_bwe_subband_width[SWB_FENV] = {0.0625f, 0.04167f, 0.0625f, 0.04167f, 0.0625f, 0.04167f, 0.0625f, 0.04167f, 0.04167f, 0.04167f, 0.04167f, 0.04167f, 0.03125f, 0.03125f}; +const short swb_bwe_sm_subband[SWB_FENV] = {248, 268, 288, 308, 328, 348, 368, 388, 412, 436, 460, 484, 512, 544}; +const float smooth_factor[SWB_FENV-1] = {0.05f, 0.05f, 0.05f, 0.05f, 0.05f, 0.05f, 0.05f, 0.0417f, 0.0417f, 0.0417f, 0.0417f, 0.03125f, 0.03125f}; + +const short fb_bwe_subband[DIM_FB+1] = {640, 680, 720, 800}; +const float fb_inv_bwe_subband_width[DIM_FB] = {0.0250f, 0.0250f, 0.0125f}; +const short fb_bwe_sm_subband[DIM_FB] = {656, 696, 760}; +const float fb_smooth_factor[DIM_FB] = {0.03125f, 0.0250f, 0.015625f}; + +const float EnvCdbk11 [N_CB11 * DIM11] = +{ + -8.6703f, 0.1116f, 4.5639f, 8.2950f, 8.5148f, 4.7195f, 2.8963f, + 5.9419f, -1.2168f, -3.2933f, -5.9491f, -7.6969f, -8.6146f, -9.9275f, + 2.9127f, 7.1689f, 13.5188f, 17.1801f, 16.7640f, 16.3455f, 13.5231f, + 6.3569f, 9.6697f, 11.4712f, 11.0915f, 8.5859f, 6.7523f, 5.1755f, + -2.0082f, -2.8539f, -2.1756f, -0.7832f, 0.3904f, 1.8543f, 2.1094f, + 2.5602f, 3.7358f, 4.9688f, 4.2290f, 3.0234f, 2.6829f, 1.7943f, + 23.3857f, 21.3282f, 18.3157f, 16.3757f, 15.0204f, 14.1209f, 13.2521f, + 13.9500f, 18.9069f, 22.5926f, 24.4781f, 23.1748f, 20.1496f, 17.3157f, + 11.5571f, 8.1506f, 4.6099f, 3.8231f, 4.6089f, 5.3538f, 6.3890f, + 23.5508f, 24.0512f, 25.1225f, 26.4155f, 27.3361f, 27.9432f, 27.5377f, + -3.2117f, 0.8204f, 1.7588f, 0.6950f, -2.4959f, -5.2582f, -6.1620f, + 17.3871f, 16.3436f, 16.0602f, 16.9090f, 18.8782f, 20.4382f, 21.5310f, + 13.3594f, 15.6030f, 16.8792f, 16.4242f, 14.3912f, 12.3198f, 10.3571f, + -14.5849f, -9.0025f, -5.4218f, -1.2669f, 0.0853f, -3.3069f, -4.4553f, + 3.3195f, 1.9941f, 3.5010f, 6.9539f, 8.3192f, 10.5007f, 11.0406f, + 12.8683f, 11.0255f, 9.8051f, 9.8299f, 11.8326f, 13.3332f, 15.0119f, + -13.9167f, -13.3153f, -12.4970f, -11.3929f, -10.0932f, -8.9132f, -7.7378f, + -10.6935f, -12.4430f, -14.6553f, -16.8742f, -17.5158f, -17.6704f, -16.9116f, + -29.4308f, -29.2243f, -28.4494f, -28.0282f, -26.3950f, -24.5370f, -22.9103f, + -19.0168f, -18.8921f, -17.9786f, -17.2745f, -15.9625f, -14.5997f, -12.9787f, + -54.2808f, -53.8105f, -52.6712f, -52.1042f, -50.4929f, -48.4342f, -46.7588f, + 32.8477f, 32.8894f, 32.4420f, 31.6529f, 31.0708f, 30.3821f, 29.2828f, + 28.0454f, 26.7402f, 24.8801f, 23.3249f, 21.7053f, 20.7367f, 19.6371f, + 18.0979f, 15.6543f, 12.7634f, 9.4607f, 8.0952f, 6.9453f, 5.8996f, + 39.5644f, 40.7490f, 41.1718f, 40.9096f, 39.7482f, 38.4272f, 37.4463f, + 11.4554f, 10.5291f, 8.0459f, 5.0217f, 1.6581f, -0.9919f, -3.2238f, + -39.1890f, -38.4633f, -37.2799f, -36.7970f, -35.1580f, -33.2348f, -31.5786f, + 7.1490f, 3.6224f, -0.6163f, -1.5147f, -1.4079f, -1.4364f, -1.1211f, + -85.7873f, -85.5637f, -84.1707f, -83.8699f, -82.0486f, -80.1192f, -78.3737f, + -23.7889f, -23.9925f, -23.1930f, -22.8609f, -21.4574f, -19.9363f, -18.2458f, + -5.3981f, -6.4065f, -8.6148f, -9.9870f, -10.8787f, -11.7942f, -11.6944f, + -5.0767f, -6.1222f, -6.8130f, -6.4157f, -5.5037f, -4.2203f, -3.5243f, +}; + +const float EnvCdbk1st [N_CB1ST * DIM1ST] = +{ + -7.1064f, -4.4453f, 2.9351f, + -1.9308f, 0.6335f, -3.2258f, + -12.4978f, -0.4815f, 9.6818f, + -8.0902f, 0.9278f, -1.6759f, + -7.1051f, 6.9529f, 4.8166f, + 1.1089f, 4.6364f, -4.3871f, + -6.5985f, -2.8197f, -1.8909f, + -4.9078f, 0.2022f, -5.2175f, + -2.3609f, 14.6030f, -5.0669f, + 2.1685f, 1.6108f, 2.9025f, + -2.4455f, -6.5834f, 5.9636f, + 0.5645f, 6.0806f, -0.8753f, + -2.4904f, 5.3534f, 6.2069f, + -4.6416f, 0.1448f, -1.6019f, + -1.6724f, -12.9702f, 7.2641f, + 10.1438f, -0.3729f, -11.2325f, + -2.8994f, -2.2776f, -2.6711f, + 6.2755f, -6.5279f, -7.3185f, + -4.3406f, -3.6577f, -5.3655f, + 1.0746f, -9.0396f, 2.0233f, + 10.4764f, 9.2495f, -1.1811f, + 7.0665f, -2.1678f, -2.2621f, + 12.4715f, -4.9604f, -4.7190f, + 2.9306f, 0.3267f, 0.6027f, + -4.5326f, 1.6741f, 4.2905f, + 3.1882f, -2.3954f, -11.3147f, + 8.4338f, -7.3615f, 4.8623f, + -2.6210f, 1.6649f, 12.4120f, + 3.3880f, -0.5639f, -2.4950f, + 3.2948f, -7.3733f, 8.8713f, + 6.0225f, 1.0109f, -0.5767f, + -6.5622f, 4.0120f, 1.1130f, + 0.6314f, -2.9813f, 6.5088f, + -7.4838f, 4.5892f, -4.7926f, + -1.3492f, -3.5415f, -0.5914f, + 7.7312f, 4.1477f, 1.5695f, + -4.8092f, 9.5178f, 12.2277f, + -9.4609f, 1.4097f, 4.0613f, + -16.8501f, -16.0390f, -16.4874f, + 0.5711f, -4.6892f, -7.1391f, + 1.8938f, 3.4746f, -15.0275f, + 1.5014f, -9.6125f, -11.1128f, + 5.9617f, -2.3434f, 6.2473f, + -3.2715f, -2.2302f, 4.2871f, + 6.9371f, -13.2527f, 15.8528f, + -13.0084f, 9.4873f, 6.7652f, + 1.8265f, -8.3584f, -3.6477f, + 3.2532f, 8.9518f, -4.4112f, + -0.0785f, -4.0189f, 2.5487f, + -1.3509f, 0.6566f, 7.1658f, + -6.7577f, 3.2716f, 8.7273f, + 6.3343f, -6.6206f, -0.7569f, + -12.4925f, -3.0187f, 0.8888f, + 4.1806f, 6.8020f, 1.1128f, + 6.4660f, -0.8290f, -6.3590f, + 8.5089f, 2.3611f, 6.9696f, + 7.0355f, -12.5942f, -3.3116f, + -3.1974f, 1.3584f, 0.7314f, + 0.0624f, 1.1725f, 0.9528f, + 3.0031f, 0.7847f, 6.0715f, + 2.8083f, -1.5392f, 3.0486f, + 1.2144f, 11.1444f, 0.7234f, + 4.5417f, 1.9083f, -3.9930f, + -1.2897f, 1.7931f, 3.4268f, + 0.4267f, -2.1125f, -2.6993f, + -1.9870f, -1.0444f, 1.8659f, + -1.3273f, -1.6306f, -5.4788f, + -3.3603f, -2.6373f, -10.5580f, + 4.0034f, 3.2267f, 0.9765f, + -4.0725f, 3.9372f, -1.6940f, + -4.0711f, -2.4655f, 0.2350f, + -0.6742f, 1.2957f, -8.1420f, + 3.8434f, 3.5916f, -7.9753f, + -4.9118f, -8.9335f, 1.3240f, + 1.4296f, -5.1151f, -0.6183f, + 4.0664f, 4.0592f, 4.2287f, + 13.9299f, 3.5845f, 0.8860f, + 0.2439f, -0.5414f, 3.6573f, + 9.4697f, 2.8531f, -3.9907f, + -2.9106f, 7.6316f, 1.6666f, + -4.2611f, -5.3043f, -1.8686f, + -0.6757f, 8.2847f, -9.2447f, + -8.4955f, 9.9028f, -7.6020f, + -3.4387f, -7.6714f, -6.0496f, + -0.9730f, -4.6977f, -3.6204f, + -9.2868f, -1.7316f, -6.9325f, + -5.6205f, -2.2721f, 7.9555f, + -2.0678f, -14.3696f, -2.1494f, + 2.3769f, -1.1084f, -6.1183f, + 0.7835f, 0.2474f, -1.3438f, + 5.3736f, 0.8512f, 3.1856f, + 9.6507f, -1.3584f, 1.8708f, + -5.4226f, 3.8576f, -10.4452f, + 5.5806f, -13.8209f, 4.3938f, + 3.3739f, -5.2782f, 3.3015f, + 1.1772f, 3.8147f, 1.5955f, + -4.3838f, 13.1395f, 4.3243f, + -0.8337f, 2.8533f, -1.2842f, + 3.2788f, -2.6680f, -0.3603f, + 2.4648f, 4.5784f, 9.2339f, + 2.3348f, 2.6773f, -1.2865f, + -3.0488f, -5.1440f, 1.7493f, + -1.6552f, -0.5978f, -0.7764f, + 3.0011f, -1.2935f, 11.0366f, + 3.4439f, -4.0880f, -3.8069f, + -1.4637f, -7.1676f, -1.1671f, + 11.1758f, -13.1846f, -12.3361f, + 8.1990f, 8.4704f, -10.2721f, + 6.2564f, 7.5395f, 5.6662f, + 5.0554f, 4.9418f, -2.2877f, + -9.7668f, -10.0395f, -10.4193f, + -3.1503f, -5.9735f, 12.7823f, + -2.0408f, 4.1857f, 1.8667f, + 15.7600f, -9.7299f, 1.8762f, + -7.4519f, 9.4311f, -0.6946f, + -6.1047f, -0.5603f, 1.7096f, + 0.8003f, 3.3634f, 5.0259f, + -2.6989f, 3.7629f, -5.3679f, + -9.2139f, -7.9377f, -3.4621f, + 0.6323f, -1.7255f, 0.6234f, + 0.7594f, 9.7404f, 7.6543f, + -9.8933f, -10.0711f, 7.5139f, + 1.0426f, 6.6449f, 3.6587f, + 11.4042f, 11.5230f, 9.3039f, + -2.6163f, 8.2102f, -3.3574f, + -12.2920f, 5.4115f, -0.8387f, + 5.7900f, -2.3232f, 1.6209f, + 0.8904f, 1.1318f, -4.1407f, +}; + +const float EnvCdbk2nd [N_CB2ND * DIM2ND] = +{ + 4.3123f, -7.1616f, -4.3357f, -3.7263f, + 2.9572f, 3.3303f, -0.6874f, 1.1173f, + -3.4084f, -2.2922f, -0.0278f, 5.6960f, + -1.8039f, -2.1619f, -1.3655f, 0.4079f, + 7.5721f, 7.6436f, -5.2359f, -2.7457f, + 4.6943f, -3.0448f, 0.0822f, 7.7951f, + -11.1369f, -0.6607f, 4.0977f, 3.6717f, + -5.2941f, -2.8345f, -6.9855f, 4.2023f, + -2.9965f, -2.5020f, -2.5223f, -3.4361f, + 0.5260f, -3.2518f, -0.7710f, -3.4717f, + -3.2275f, 0.0098f, 1.0879f, -1.9621f, + -2.7904f, 2.1268f, -2.0540f, 1.4661f, + 1.1360f, -4.2031f, -3.1894f, -15.3458f, + -4.5909f, -1.8549f, 8.6689f, -2.5094f, + 0.7713f, -0.8552f, -4.1104f, -6.2533f, + 4.5892f, -0.6343f, -2.7162f, -1.3109f, + 4.3900f, 0.4919f, -9.0866f, -6.1448f, + 4.5483f, -5.1698f, -7.6465f, 4.1951f, + -8.1259f, -8.4044f, 0.4404f, 2.5339f, + -2.4877f, -3.3596f, 2.8155f, 1.0442f, + -2.3782f, 6.4752f, -3.9302f, -5.2807f, + 6.3692f, 8.6921f, 8.3109f, 7.1381f, + -4.3445f, -5.2789f, 7.2494f, 6.4679f, + -8.3291f, 3.9280f, 3.0088f, -5.0540f, + -1.8438f, 3.0318f, 6.4879f, 8.7826f, + -0.4718f, -2.2438f, -5.7862f, -1.2336f, + 10.0184f, -4.2246f, 0.7347f, 1.1461f, + 1.5549f, 10.1485f, 2.7490f, -4.4112f, + 3.9959f, 0.4078f, 2.1473f, 1.9496f, + -1.6255f, 0.4947f, 0.9865f, -7.3990f, + 1.7798f, -10.0697f, 0.7408f, 3.9759f, + -5.8117f, 1.1179f, -4.6947f, -3.5752f, + -4.5471f, 7.3211f, 6.4493f, 1.1780f, + -5.1254f, -6.0444f, -6.3492f, -5.9237f, + 0.6636f, -0.9113f, 3.1921f, 4.7217f, + -4.2586f, 1.3321f, 2.7703f, 2.8306f, + 3.3356f, 3.2010f, -1.0860f, -4.2324f, + -0.0572f, 0.4406f, 1.1161f, 1.1049f, + 4.5545f, -3.5389f, 7.3418f, 1.1747f, + 1.3350f, -0.0281f, -2.2930f, 3.0295f, + -3.0651f, -4.9167f, -4.5557f, 12.4767f, + -6.3679f, -4.1824f, 1.1715f, -4.2173f, + -0.0461f, 0.7412f, -2.1034f, -1.9263f, + 1.3714f, 3.5413f, 7.5363f, -5.9934f, + 1.8748f, 0.1406f, 2.3146f, -2.0562f, + 3.1775f, 4.7516f, 3.8512f, 0.3460f, + 0.3842f, 3.9440f, -8.8737f, 1.0470f, + 10.8029f, -0.3986f, -5.1051f, -3.4119f, + -6.4836f, -1.8259f, -1.4253f, 0.1826f, + 5.8438f, 4.9884f, -0.8889f, -10.9021f, + 6.1138f, -2.6130f, 2.0330f, -6.2434f, + -1.4101f, 4.2119f, 1.7856f, -1.4207f, + 2.1209f, -3.7111f, 0.1093f, 0.9671f, + 7.4373f, 3.1851f, -4.0372f, 4.3934f, + -0.0516f, -7.6212f, 4.2391f, -3.9245f, + -8.6836f, 5.9347f, -2.4382f, 3.3478f, + 4.3786f, 3.2445f, 3.4065f, 5.0603f, + 0.7547f, 8.9234f, -1.6469f, 2.3801f, + -0.6099f, 3.2294f, -2.8632f, 8.0661f, + -13.2408f, -13.2180f, -12.4864f, -12.5763f, + 0.1226f, 3.5019f, 2.1036f, 3.8209f, + -0.0830f, 1.5923f, 5.8683f, 1.5813f, + -2.2786f, -6.4905f, -2.5958f, -0.6420f, + 8.5661f, 3.8130f, 2.3928f, -1.7038f, +}; + +const float EnvCdbk3rd [N_CB3RD * DIM3RD] = +{ + 4.0282f, -9.5862f, 2.9221f, + 10.8219f, 9.5405f, 6.8798f, + -9.1733f, 15.9318f, -3.7461f, + 7.3196f, -2.8702f, -8.7570f, + -0.2304f, 0.1350f, 0.7863f, + -5.9316f, 0.6347f, 7.0661f, + -7.7220f, -4.1510f, -0.4015f, + 9.7056f, 4.7338f, -3.3708f, + 3.4447f, 0.7509f, 0.1539f, + 5.2980f, 3.3256f, 3.8228f, + -5.3770f, -11.5675f, -5.7681f, + 1.9411f, -3.1576f, 2.3162f, + -1.5410f, -2.9216f, -6.1087f, + -3.7107f, -0.7720f, -1.7048f, + -1.9664f, -5.5485f, -0.9158f, + 1.2430f, 3.8485f, -7.4409f, + -0.4624f, 6.9662f, 6.1050f, + 0.8584f, 3.6275f, 1.5624f, + 3.3487f, 0.1438f, -3.8870f, + -3.1533f, 7.5889f, -1.5958f, + -2.9036f, -2.0471f, 2.1555f, + 3.6715f, 6.4176f, -1.1670f, + 3.1461f, -5.5497f, -3.0001f, + -9.1009f, 2.7549f, 0.6103f, + 0.2373f, 0.7927f, 4.7365f, + -0.5389f, 2.0197f, -2.5074f, + 0.2485f, -1.9583f, -1.6996f, + 8.5694f, -2.4399f, 0.6128f, + -6.2513f, 1.3320f, -6.2922f, + 4.4430f, -1.3696f, 9.1921f, + -3.1673f, -6.6975f, 5.9466f, + -3.3971f, 2.3931f, 1.7433f, +}; + +const float EnvCdbk4th [N_CB4TH * DIM4TH] = +{ + 3.9996f, -0.8196f, -0.8101f, 2.3072f, + -1.0920f, -9.7095f, -3.7135f, 3.7429f, + 6.0104f, 4.4383f, 1.6047f, 5.1343f, + 6.8807f, -0.7893f, 5.2292f, 0.7940f, + -9.5225f, -8.2399f, -7.9213f, -8.3027f, + 7.2240f, -5.4987f, -2.6163f, 0.5630f, + -1.8336f, 10.4454f, -6.2079f, -14.0773f, + 6.4124f, -2.7411f, 0.5417f, 9.6735f, + -1.8885f, 1.4517f, -3.3639f, 2.1092f, + -0.4634f, 3.2291f, 3.3717f, 3.7183f, + 0.0901f, 0.3886f, -0.0922f, -1.1829f, + 1.9060f, -8.7228f, -5.5919f, -5.4642f, + 0.2125f, -0.1681f, 0.3767f, -5.9653f, + 4.5684f, 0.5205f, -0.4649f, -2.8002f, + 1.0087f, -4.7453f, -1.7135f, 0.6236f, + -4.0975f, 3.0989f, 3.7884f, -3.0078f, + -7.4785f, -4.8629f, 5.0050f, 1.6473f, + -4.6660f, 3.9258f, 0.6885f, -9.2509f, + -6.3693f, 5.1420f, -4.3946f, -1.4094f, + 4.3917f, 4.4225f, 0.2383f, -8.5391f, + 3.0850f, -8.0277f, 4.5875f, 3.6649f, + 11.6159f, 15.1327f, 9.0448f, 7.9694f, + -1.1705f, 9.7014f, 0.2305f, -3.3610f, + 2.1195f, 5.1060f, -7.2972f, -2.8333f, + 1.5208f, -0.4510f, -3.6906f, -0.5684f, + -7.1756f, -2.2582f, -2.4200f, 3.8082f, + 1.5182f, 6.9508f, 6.7654f, 1.1582f, + 1.4735f, 3.5020f, 6.0723f, 8.8626f, + -3.3340f, 0.1007f, 2.3028f, 5.5202f, + -3.0476f, -3.8494f, 5.4259f, 10.3093f, + 1.2195f, -1.0819f, -3.6514f, -12.8475f, + 6.7971f, 7.2347f, 2.5053f, -2.0263f, + 2.8809f, 3.5069f, -1.8220f, 0.4511f, + 4.6384f, -1.1164f, -5.9159f, -5.1137f, + 0.2896f, -3.1271f, -2.2772f, -3.8561f, + 1.9906f, -2.6068f, 1.6778f, -0.7475f, + 1.6325f, -1.1855f, 3.1499f, 4.9140f, + -4.2298f, -4.1599f, 1.4122f, -8.2593f, + -4.1992f, 0.3220f, 1.0148f, 1.1155f, + -10.0725f, 0.0539f, 0.2930f, -3.3347f, + -2.5810f, -2.4752f, 1.8829f, -2.2701f, + -1.3208f, -1.1970f, 12.7140f, 1.5150f, + -0.8982f, -0.0921f, 4.5338f, 0.8027f, + 1.0017f, 2.1335f, -0.5513f, 5.3882f, + -0.2457f, -3.0283f, -1.8919f, 5.7746f, + -2.0213f, -2.1347f, -1.7599f, 0.3340f, + 5.7553f, -4.6913f, 1.6804f, -7.3915f, + 1.5389f, 3.2468f, 2.4237f, -2.5921f, + 1.3040f, 0.2492f, 6.9277f, -6.1561f, + -6.9638f, 4.9625f, 3.9857f, 3.6889f, + 3.9950f, 0.3810f, -7.4544f, 5.1955f, + -2.1874f, -4.0774f, 1.4863f, 2.7600f, + -1.6673f, -2.7653f, -7.0891f, -0.3532f, + -0.2106f, 8.9759f, -2.0994f, 4.4973f, + -1.9481f, 2.7454f, -3.9753f, 12.9773f, + 0.3607f, 2.7997f, -2.3719f, -4.0297f, + -5.1272f, -5.4413f, -2.2644f, -1.8938f, + 0.1319f, -8.5628f, 3.0773f, -3.3584f, + 10.3160f, 2.4523f, -3.0328f, -1.0118f, + -2.7438f, -0.6207f, -5.7929f, -6.3978f, + -0.1295f, -0.2443f, 0.3800f, 2.1601f, + 2.7023f, 2.0427f, 2.1407f, 1.3633f, + -3.5645f, 0.2107f, -1.7811f, -2.7432f, + -1.3301f, 3.6876f, 0.6120f, 0.3900f, +}; + +const float EnvCdbkFB [N_CB_FB * DIM_FB] = +{ + -16.6120f, -9.7056f, -7.3815f, + 12.7223f, -5.3619f, -4.2098f, + 9.6082f, 17.5423f, 19.7838f, + 22.0461f, 24.1701f, 20.8503f, + -96.6904f, -89.9023f, -88.6123f, + 20.9213f, 27.6011f, 27.4229f, + 3.8206f, 7.0540f, 5.3791f, + 15.0749f, 22.8806f, 23.6351f, + 26.7480f, 32.6483f, 31.6408f, + -19.5344f, -13.3342f, -11.0528f, + -27.4315f, -20.0228f, -17.3748f, + -6.7548f, -7.7102f, -9.4666f, + -3.3129f, 6.9621f, 14.9937f, + 15.4388f, 19.6911f, 17.7925f, + 5.2569f, 13.0270f, 15.1931f, + 40.3814f, 47.0644f, 46.7397f, + -10.6760f, -3.9121f, -1.8455f, + -1.9827f, 5.3065f, 7.7240f, + -148.2341f, -141.3109f, -139.3314f, + -179.7394f, -172.2927f, -172.7284f, + 17.6754f, 17.9788f, -4.8806f, + -0.9671f, 3.3663f, 2.9027f, + 11.3567f, 15.3245f, 13.9899f, + 1.5588f, 8.5468f, 10.5230f, + -7.7918f, -0.8556f, 1.6643f, + -5.4487f, 2.0822f, 4.7052f, + -23.9540f, -16.9712f, -14.6548f, + -34.0472f, -27.2912f, -24.7197f, + -2.8087f, 0.4624f, -3.6887f, + -14.1611f, -7.1801f, -4.6916f, + 32.8420f, 38.8016f, 38.3823f, + 7.4425f, 11.3804f, 9.7292f +}; + +const float Mean_env_fb[DIM_FB] = {13.75f, 6.29f, 3.70f}; + +const float w_NOR[SWB_FENV] = {1.f,0.97826087f,0.957446809f,0.9375f,0.918367347f,0.9f,0.882352941f,0.865384615f,0.849056604f,0.833333333f,0.818181818f,0.803571429f,0.789473684f,0.775862069f}; +const float Mean_env[SWB_FENV] = {28.62f, 28.96f, 28.05f, 27.97f, 26.91f, 26.82f, 26.35f, 25.98f, 24.94f, 24.03f, 22.94f, 22.14f, 21.23f, 20.40f}; + +const float Env_TR_Cdbk1 [N_CB_TR1 * DIM_TR1] = +{ + 0.8936f, -9.1696f, + 32.0275f, 30.1795f, + -1.2201f, 6.6391f, + 38.5962f, 23.2366f, + 34.9278f, 32.6481f, + 15.0969f, 12.8381f, + 9.3963f, 3.1078f, + 14.3113f, 5.5971f, + 11.9502f, 8.6515f, + 2.4150f, 3.4154f, + -21.4020f, -18.1087f, + 8.7368f, 9.8116f, + 16.6597f, 9.4849f, + 25.7150f, 8.0681f, + 17.7652f, 25.6994f, + 44.2378f, 28.6702f, + 41.3199f, 36.1883f, + 33.1667f, 25.2245f, + -5.3921f, -9.7030f, + 13.1902f, 19.8007f, + 28.8781f, 20.0006f, + 18.7409f, 17.3426f, + 21.5070f, 29.7424f, + -13.1680f, -15.5559f, + 10.9594f, 11.5574f, + 8.7570f, 13.8680f, + 5.2123f, 11.9711f, + 8.0290f, -5.2743f, + 3.1843f, 21.5110f, + 19.2978f, 5.6924f, + -7.6163f, -4.0852f, + 2.5510f, -4.4247f, + 3.4072f, -14.1479f, + -6.8577f, 0.9589f, + 22.6250f, 21.6469f, + 15.9534f, 30.0623f, + 17.8474f, 20.3281f, + -3.1654f, -6.0729f, + 39.5602f, 40.5625f, + 44.3017f, 45.7556f, + 24.8628f, 19.5166f, + 33.7547f, 41.1213f, + 23.1020f, 13.1469f, + 17.6623f, 12.7562f, + 20.3773f, 11.0551f, + 31.6668f, 35.0770f, + 15.4383f, 22.8811f, + 22.8419f, 35.1167f, + 25.0950f, 23.1698f, + 20.2523f, 14.9332f, + 24.8694f, 27.0211f, + 13.8576f, 10.4789f, + 6.3835f, 8.1955f, + 10.6597f, -0.3484f, + 27.2026f, 29.9373f, + 12.4182f, 13.9096f, + 24.9543f, 16.3771f, + 15.7197f, 18.8608f, + -1.4782f, 1.6952f, + 36.4783f, 37.1348f, + 29.6594f, 13.6072f, + -26.6995f, -24.6742f, + 20.3405f, 19.6463f, + 44.2412f, 40.9698f, + 28.9498f, 23.7751f, + 39.3428f, 32.2458f, + -23.8252f, -22.0790f, + 27.6318f, 33.9910f, + -47.7664f, -44.4696f, + -44.8104f, -41.2774f, + -50.8776f, -47.8616f, + -50.3099f, -44.0979f, + -54.5008f, -51.0234f, + -63.3373f, -60.1146f, + -45.5444f, -42.1435f, + -48.2447f, -44.8312f, + -49.9558f, -46.6690f, + -59.1385f, -55.6583f, + -44.2409f, -43.8251f, + -46.6791f, -43.3332f, + -46.0956f, -42.6861f, + -92.7279f, -89.3799f, + 49.9817f, 46.4450f, + -14.8152f, -11.2475f, + -106.9255f, -103.4843f, + -46.5934f, -45.0424f, + -47.3033f, -43.9775f, + -80.0456f, -76.6952f, + -56.1359f, -53.1578f, + -49.1835f, -45.8131f, + -54.9042f, -45.8573f, + 36.9949f, 28.4050f, + -43.6866f, -40.3702f, + -52.0047f, -45.5982f, + -47.6930f, -41.4457f, + -52.5989f, -49.8475f, + 30.0399f, 27.7911f, + 10.0141f, 17.5614f, + 21.8223f, 17.7785f, + -3.1767f, -2.1954f, + -17.5132f, -21.5664f, + 6.0779f, 0.3815f, + 0.0063f, 13.5452f, + 5.5074f, 5.2318f, + 15.8166f, 0.6300f, + -17.7247f, -15.7262f, + -38.5381f, -35.6042f, + -6.3132f, -18.4667f, + 9.5978f, 6.4559f, + 2.4632f, 8.4172f, + -70.2432f, -66.7283f, + 10.2658f, 23.7825f, + -42.1539f, -38.8022f, + -48.5397f, -45.1815f, + 16.8840f, 15.6262f, + -6.1500f, 8.4442f, + -31.1246f, -29.6824f, + 5.9496f, 16.3765f, + 21.9557f, 25.5364f, + -9.8102f, -7.7609f, + 48.7145f, 36.0093f, + 34.1627f, 19.4172f, + 14.2249f, 16.2026f, + 19.8782f, 23.2358f, + 1.3653f, -0.3587f, + 27.4538f, 26.1047f, + -9.4912f, -12.5633f, + -15.5232f, -3.4597f +}; + +const float Env_TR_Cdbk2 [N_CB_TR2 * DIM_TR2] = +{ + 10.3071f, 1.4647f, + -1.8782f, 6.6168f, + -9.3764f, -12.9146f, + 0.3372f, -15.6956f, + -5.0830f, 0.1825f, + 2.8660f, 1.1668f, + 3.7385f, -4.0567f, + 8.6094f, 5.8040f, + 1.4099f, -4.4378f, + 10.2655f, -3.2743f, + -7.8499f, 5.0612f, + 1.4560f, 0.4976f, + -2.2400f, 10.1737f, + 2.6910f, -6.0696f, + 6.5484f, -1.4502f, + 5.0708f, 1.0902f, + -3.5214f, 4.2403f, + 6.8248f, -10.6363f, + 0.8362f, -2.5676f, + -2.8563f, -3.5507f, + 6.0370f, -6.4758f, + -1.4405f, -8.6255f, + -4.9844f, 6.8277f, + 4.4568f, -2.0374f, + 0.7265f, -7.3953f, + -4.9226f, -7.8758f, + -1.8669f, -1.9698f, + 5.0262f, 7.3509f, + -0.3770f, -5.4681f, + -5.3582f, -4.5491f, + 3.1235f, -0.5936f, + 1.6121f, -0.9381f, + -0.8137f, -3.3498f, + -0.3523f, -1.5590f, + 1.9211f, 9.8411f, + 3.5654f, 5.3423f, + -1.3437f, 1.1031f, + 1.1914f, 2.0560f, + -0.9800f, 3.3605f, + -4.1634f, 2.2153f, + -10.9385f, -2.6849f, + 0.0040f, 2.6311f, + 0.6873f, 3.4294f, + -2.7967f, -0.5984f, + 2.7559f, 3.2450f, + -4.2294f, -1.6565f, + 1.6359f, 4.6566f, + -0.5137f, 2.2080f, + 2.7641f, -9.3968f, + 2.3449f, -2.5829f, + 6.6876f, 11.5962f, + -7.7096f, 1.4816f, + -2.6264f, 0.8111f, + 0.1002f, 1.1574f, + -7.1116f, -1.9581f, + -2.0027f, 2.4814f, + 1.0402f, 6.7866f, + -0.8642f, 4.8143f, + -13.6639f, 6.3768f, + -1.3155f, -0.2595f, + -2.1558f, -5.5755f, + 5.1910f, 3.3215f, + -2.8061f, -11.5155f, + -0.0134f, 0.0015f +}; + +const float Mean_env_tr[5] = { 27.23f, 23.81f, 23.87f, 19.51f }; + +/*------------------------------------------------------------------------------* + * LR MDCT SWB BWE coding tables + *------------------------------------------------------------------------------*/ + +const float gain_table_SWB_BWE[NB_SWB_SUBBANDS] = {-0.4f, 0.1f, 0.6f, 1.1f}; + +const short bits_lagIndices_modeNormal[NB_SWB_SUBBANDS] = {2, 2, 1, 1}; +const short subband_offsets_12KBPS[NB_SWB_SUBBANDS] = {SWB_SB_OFF0_12KBPS, SWB_SB_OFF1_12KBPS, SWB_SB_OFF2_12KBPS, SWB_SB_OFF3_12KBPS}; +const short subband_offsets_16KBPS[NB_SWB_SUBBANDS] = {SWB_SB_OFF0_16KBPS, SWB_SB_OFF1_16KBPS, SWB_SB_OFF2_16KBPS, SWB_SB_OFF3_16KBPS}; + +/* Search offset for the subbands that use a partial search */ +const short subband_search_offsets[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 short bits_lagIndices_mode0_Har[NB_SWB_SUBBANDS_HAR_SEARCH_SB] = {1,1}; + +/* 13.2 kbps */ +const short subband_offsets_sub5_13p2kbps_Har[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 short subband_search_offsets_13p2kbps_Har[NB_SWB_SUBBANDS_HAR_SEARCH_SB] = +{ + 120, 210 +}; + +/* 16.4 kbps */ +const short subband_offsets_sub5_16p4kbps_Har[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 short subband_search_offsets_16p4kbps_Har[NB_SWB_SUBBANDS_HAR_SEARCH_SB] = +{ + 120, 210 +}; + + +/*------------------------------------------------------------------------------* + * HQ core tables + *------------------------------------------------------------------------------*/ + +const float wscw16q15[] = +{ + -1.0f, -0.999939f, -0.999878f, -0.999725f, -0.999573f, -0.999359f, -0.999084f, -0.99881f, + -0.998444f, -0.998077f, -0.99765f, -0.997162f, -0.996643f, -0.996094f, -0.995514f, -0.994873f, + -0.994171f, -0.993439f, -0.992676f, -0.991852f, -0.990997f, -0.990112f, -0.989166f, -0.98819f, + -0.987183f, -0.986115f, -0.984985f, -0.983856f, -0.982666f, -0.981415f, -0.980133f, -0.978821f, + -0.977448f, -0.976074f, -0.974609f, -0.973114f, -0.971588f, -0.970032f, -0.968414f, -0.966766f, + -0.965088f, -0.963348f, -0.961548f, -0.959747f, -0.957886f, -0.955994f, -0.954041f, -0.952057f, + -0.950043f, -0.947968f, -0.945862f, -0.943726f, -0.941559f, -0.939331f, -0.937042f, -0.934753f, + -0.932404f, -0.930023f, -0.927582f, -0.92514f, -0.922607f, -0.920074f, -0.91748f, -0.914886f, + -0.912201f, -0.909515f, -0.906769f, -0.903992f, -0.901184f, -0.898315f, -0.895416f, -0.892487f, + -0.889526f, -0.886505f, -0.883453f, -0.880371f, -0.877258f, -0.874084f, -0.87088f, -0.867645f, + -0.86438f, -0.861084f, -0.857727f, -0.85434f, -0.850922f, -0.847473f, -0.843964f, -0.840454f, + -0.836884f, -0.833282f, -0.829651f, -0.825989f, -0.822266f, -0.818512f, -0.814758f, -0.810944f, + -0.807098f, -0.803223f, -0.799286f, -0.795349f, -0.791351f, -0.787354f, -0.783295f, -0.779205f, + -0.775085f, -0.770935f, -0.766754f, -0.762512f, -0.75827f, -0.753998f, -0.749664f, -0.745331f, + -0.740936f, -0.736542f, -0.732086f, -0.727631f, -0.723114f, -0.718567f, -0.71402f, -0.709412f, + 0.704803f, 0.700134f, 0.695435f, 0.690735f, 0.685974f, 0.681213f, 0.676392f, 0.67157f, + 0.666687f, 0.661804f, 0.656891f, 0.651947f, 0.646942f, 0.641937f, 0.636932f, 0.631866f, + 0.62677f, 0.621674f, 0.616516f, 0.611359f, 0.606171f, 0.600952f, 0.595703f, 0.590424f, + 0.585144f, 0.579803f, 0.574463f, 0.569092f, 0.563721f, 0.558289f, 0.552856f, 0.547394f, + 0.541901f, 0.536377f, 0.530853f, 0.525299f, 0.519714f, 0.514099f, 0.508484f, 0.502838f, + 0.497162f, 0.491486f, 0.485748f, 0.480042f, 0.474274f, 0.468506f, 0.462708f, 0.456909f, + 0.45108f, 0.445221f, 0.439362f, 0.433472f, 0.427551f, 0.421631f, 0.41568f, 0.409729f, + 0.403748f, 0.397736f, 0.391724f, 0.385712f, 0.379669f, 0.373596f, 0.367523f, 0.36142f, + 0.355316f, 0.349182f, 0.343048f, 0.336884f, 0.330719f, 0.324524f, 0.318329f, 0.312134f, + 0.305908f, 0.299652f, 0.293427f, 0.28714f, 0.280884f, 0.274597f, 0.26828f, 0.261993f, + 0.255646f, 0.249329f, 0.242981f, 0.236633f, 0.230255f, 0.223877f, 0.217499f, 0.211121f, + 0.204712f, 0.198303f, 0.191895f, 0.185455f, 0.179016f, 0.172577f, 0.166138f, 0.159668f, + 0.153198f, 0.146729f, 0.140259f, 0.133759f, 0.127289f, 0.120789f, 0.114288f, 0.107788f, + 0.101288f, 0.0947571f, 0.0882568f, 0.0817261f, 0.0751953f, 0.0686646f, 0.0621338f, 0.055603f, + 0.0490723f, 0.0425415f, 0.0359802f, 0.0294495f, 0.0229187f, 0.0163574f, 0.00982666f,0.00326538f +}; + +const float wscw16q15_32[160] = +{ + -0.99998795f, -0.99989157f, -0.99969882f, -0.99940971f, -0.99902428f, -0.99854256f, + -0.99796460f, -0.99729046f, -0.99652019f,-0.99565388f, -0.99469160f, -0.99363345f, + -0.99247953f, -0.99122996f, -0.98988485f, -0.98844433f, -0.98690855f, -0.98527764f, + -0.98355177f, -0.98173111f, -0.97981582f, -0.97780610f, -0.97570213f, -0.97350412f, + -0.97121229f, -0.96882685f, -0.96634802f, -0.96377607f, -0.96111122f, -0.95835373f, + -0.95550388f, -0.95256194f, -0.94952818f, -0.94640291f, -0.94318642f, -0.93987902f, + -0.93648104f, -0.93299280f, -0.92941463f, -0.92574689f, -0.92198992f, -0.91814408f, + -0.91420976f, -0.91018732f, -0.90607715f, -0.90187965f, -0.89759523f, -0.89322430f, + -0.88876728f, -0.88422459f, -0.87959669f, -0.87488400f, -0.87008699f, -0.86520612f, + -0.86024186f, -0.85519469f, -0.85006509f, -0.84485357f, -0.83956061f, -0.83418673f, + -0.82873246f, -0.82319831f, -0.81758481f, -0.81189252f, -0.80612197f, -0.80027373f, + -0.79434836f, -0.78834643f, -0.78226851f, -0.77611520f, -0.76988708f, -0.76358476f, + -0.75720885f, -0.75075995f, -0.74423869f, -0.73764570f, -0.73098162f, -0.72424708f, + -0.71744274f, -0.71056925f, 0.70362727f, 0.69661748f, 0.68954054f, 0.68239715f, + 0.67518798f, 0.66791374f, 0.66057513f, 0.65317284f, 0.64570760f, 0.63818013f, + 0.63059115f, 0.62294139f, 0.61523159f, 0.60746249f, 0.59963485f, 0.59174941f, + 0.58380693f, 0.57580819f, 0.56775395f, 0.55964499f, 0.55148209f, 0.54326604f, + 0.53499762f, 0.52667764f, 0.51830690f, 0.50988620f, 0.50141636f, 0.49289819f, + 0.48433252f, 0.47572016f, 0.46706195f, 0.45835873f, 0.44961133f, 0.44082059f, + 0.43198737f, 0.42311251f, 0.41419687f, 0.40524131f, 0.39624670f, 0.38721389f, + 0.37814376f, 0.36903718f, 0.35989504f, 0.35071820f, 0.34150757f, 0.33226402f, + 0.32298845f, 0.31368174f, 0.30434480f, 0.29497853f, 0.28558383f, 0.27616160f, + 0.26671276f, 0.25723821f, 0.24773886f, 0.23821564f, 0.22866946f, 0.21910124f, + 0.20951190f, 0.19990237f, 0.19027357f, 0.18062644f, 0.17096189f, 0.16128086f, + 0.15158430f, 0.14187312f, 0.13214826f, 0.12241068f, 0.11266129f, 0.10290104f, + 0.09313088f, 0.08335174f, 0.07356456f, 0.06377030f, 0.05396989f, 0.04416428f, + 0.03435441f, 0.02454123f, 0.01472568f, 0.00490872f +}; + +const float wscw16q15_16[80] = +{ + -0.99995181f, -0.99956631f, -0.99879546f, -0.99763955f, + -0.99609903f, -0.99417450f, -0.99186670f, -0.98917651f, + -0.98610498f, -0.98265328f, -0.97882275f, -0.97461487f, + -0.97003125f, -0.96507367f, -0.95974404f, -0.95404440f, + -0.94797697f, -0.94154407f, -0.93474818f, -0.92759194f, + -0.92007808f, -0.91220953f, -0.90398929f, -0.89542056f, + -0.88650662f, -0.87725091f, -0.86765701f, -0.85772861f, + -0.84746954f, -0.83688375f, -0.82597533f, -0.81474848f, + -0.80320753f, -0.79135693f, -0.77920124f, -0.76674516f, + -0.75399348f, -0.74095113f, -0.72762312f, -0.71401460f, + 0.70013081f, 0.68597711f, 0.67155895f, 0.65688190f, + 0.64195160f, 0.62677382f, 0.61135441f, 0.59569930f, + 0.57981455f, 0.56370626f, 0.54738066f, 0.53084403f, + 0.51410274f, 0.49716327f, 0.48003212f, 0.46271592f, + 0.44522133f, 0.42755509f, 0.40972403f, 0.39173501f, + 0.37359497f, 0.35531090f, 0.33688985f, 0.31833893f, + 0.29966528f, 0.28087610f, 0.26197864f, 0.24298018f, + 0.22388805f, 0.20470960f, 0.18545224f, 0.16612338f, + 0.14673047f, 0.12728100f, 0.10778246f, 0.08824237f, + 0.06866826f, 0.04906767f, 0.02944817f, 0.00981732f +}; + +const float wscw16q15_8[40] = +{ + -0.999816894531250f, -0.998260498046875f, -0.995178222656250f, -0.990570068359375f, + -0.984436035156250f, -0.976776123046875f, -0.967590332031250f, -0.956939697265625f, + -0.944793701171875f, -0.931213378906250f, -0.916198730468750f, -0.899749755859375f, + -0.881927490234375f, -0.862731933593750f, -0.842224121093750f, -0.820404052734375f, + -0.797332763671875f, -0.773010253906250f, -0.747497558593750f, -0.720855712890625f, + 0.693084716796875f, 0.664245605468750f, 0.634399414062500f, 0.603546142578125f, + 0.571777343750000f, 0.539123535156250f, 0.505645751953125f, 0.471405029296875f, + 0.436401367187500f, 0.400756835937500f, 0.364471435546875f, 0.327636718750000f, + 0.290283203125000f, 0.252502441406250f, 0.214294433593750f, 0.175781250000000f, + 0.137023925781250f, 0.098022460937500f, 0.058868408203125f, 0.019622802734375f, +}; + +/* Codebook for quantization of norms */ +const float dicn[40] = +{ + 131072.0f, 92681.900024f, + 65536.0f, 46340.950012f, + 32768.0f, 23170.475006f, + 16384.0f, 11585.237503f, + 8192.0f, 5792.618751f, + 4096.0f, 2896.309376f, + 2048.0f, 1448.154688f, + 1024.0f, 724.077344f, + 512.0f, 362.038672f, + 256.0f, 181.019336f, + 128.0f, 90.509668f, + 64.0f, 45.254834f, + 32.0f, 22.627417f, + 16.0f, 11.313708f, + 8.0f, 5.656854f, + 4.0f, 2.828427f, + 2.0f, 1.414214f, + 1.0f, 0.707107f, + 0.5f, 0.353553f, + 0.25f, 0.176777f +}; + +const float dicn_inv[40]= /* Inversion of the codebook for quantization of norms */ +{ + 0.00000762939453f, 0.00001078959322f, + 0.00001525878906f, 0.00002157918644f, + 0.00003051757813f, 0.00004315837288f, + 0.00006103515625f, 0.00008631674575f, + 0.0001220703125f, 0.00017263349151f, + 0.000244140625f, 0.00034526698297f, + 0.00048828125f, 0.00069053396594f, + 0.0009765625f, 0.00138106793188f, + 0.001953125f, 0.00276213586376f, + 0.00390625f, 0.00552427172752f, + 0.0078125f, 0.01104854345505f, + 0.015625f, 0.02209708691010f, + 0.03125f, 0.04419417382019f, + 0.0625f, 0.08838835154664f, + 0.125f, 0.17677670309327f, + 0.25f, 0.35355340618655f, + 0.5f, 0.70710656237316f, + 1.0f, 1.41421312474633f, + 2.0f, 2.82843024949583f, + 4.0f, 5.65684449900157f +}; + +/* Codebook for quantization of peak gain */ +const float dicn_pg[45] = +{ + 131072.0000000f, 110217.9749401f, + 92681.9000237f, 77935.8774888f, + 65536.0000000f, 55108.9874701f, + 46340.9500118f, 38967.9387444f, + 32768.0000000f, 27554.4937350f, + 23170.4750059f, 16384.0000000f, + 11585.2375030f, 8192.0000000f, + 5792.6187515f, 4096.0000000f, + 2896.3093757f, 2048.0000000f, + 1448.1546879f, 1024.0000000f, + 724.0773439f, 512.0000000f, + 362.0386720f, 256.0000000f, + 181.0193360f, 128.0000000f, + 90.5096680f, 64.0000000f, + 45.2548340f, 32.0000000f, + 22.6274170f, 16.0000000f, + 11.3137085f, 8.0000000f, + 5.6568542f, 4.0000000f, + 2.8284271f, 2.0000000f, + 1.4142136f, 1.0000000f, + 0.7071070f, 0.5000000f, + 0.3535530f, 0.2500000f, + 0.176777f +}; + +const short expPkEnrg_tbl[45] = +{ + 0, 0, 0, 0, 0, 2, 2, 2, 2, + 4, 4, 4, 6, 6, 8, 8, 10, 10, + 12, 12, 14, 14, 16, 16, 18, 18, 20, + 20, 22, 22, 24, 24, 26, 26, 28, 28, + 30, 30, 32, 32, 34, 34, 36, 36, 38 +}; + +const int manPkEnrg_tbl[45] = +{ + 2147483646, 1518500308, 1073741787, 759250076, 536870912, + 1518500294, 1073741787, 759250076, 536870912, 1518500294, + 1073741787, 536870912, 1073741787, 536870912, 1073741787, + 536870912, 1073741787, 536870912, 1073741606, 536870912, + 1073741968, 536870912, 1073741244, 536870912, 1073741244, + 536870912, 1073744140, 536870912, 1073744140, 536870912, + 1073744140, 536870912, 1073744140, 536870912, 1073697800, + 536870912, 1073697800, 536870912, 1073883168, 536870912, + 1073512448, 536870912, 1073512448, 536870912, 1073512448 +}; +const int E_max5_tbl[40] = +{ + 2047999999, 1448154663, 1024000000, 1448154663, 1024000000, + 1448154663, 1024000000, 1448154663, 1024000000, 1448154663, + 1024000000, 1448154663, 1024000000, 1448154663, 1024000000, + 1448154663, 1024000000, 1448154785, 1024000000, 1448154785, + 1024000000, 1448154296, 1024000000, 1448154296, 1024000000, + 1448156250, 1024000000, 1448156250, 1024000000, 1448156250, + 1024000000, 1448156250, 1024000000, 1448125000, 1024000000, + 1448125000, 1024000000, 1448250000, 1024000000, 1448000000 +}; + + +const short 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 short 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 short 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 short 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 short 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 short 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 short 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 short 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 short 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 short intl_bw_16[N_INTL_GRP_16] = {16, 16}; +const short intl_bw_32[N_INTL_GRP_32] = {16, 24}; +const short intl_bw_48[N_INTL_GRP_48] = {16, 24, 32}; + +const short intl_cnt_16[N_INTL_GRP_16] = {4, 1}; +const short intl_cnt_32[N_INTL_GRP_32] = {4, 4}; +const short intl_cnt_48[N_INTL_GRP_48] = {4, 3, 2}; + +const short 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 short 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 short 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 short 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 short 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 short 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 float rat[SFM_N_WB] = {1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, + 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.8f, 0.8f + }; + +const short sfm_width[20] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 7, 8}; +const short a_map[20] = {8, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, 7, 11}; + + +const Word32 SQRT_DIM_fx[65] = /* 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 +}; + + + +/*------------------------------------------------------------------------------* + * HQ core tables for SWB signals + *------------------------------------------------------------------------------*/ + + +const float window_8_16_32kHz[370] = +{ + 0.00009609f, 0.00028765f, 0.00058708f, 0.00099202f, 0.00150079f, 0.00211209f, 0.00282484f, 0.00363808f, + 0.00455097f, 0.00556272f, 0.00667261f, 0.00787994f, 0.00918405f, 0.01058429f, 0.01208004f, 0.01367067f, + 0.01535558f, 0.01713416f, 0.01900581f, 0.02096992f, 0.02302588f, 0.02517309f, 0.02741093f, 0.02973879f, + 0.03215604f, 0.03466206f, 0.03725620f, 0.03993782f, 0.04270627f, 0.04556089f, 0.04850099f, 0.05152591f, + 0.05463496f, 0.05782743f, 0.06110262f, 0.06445980f, 0.06789825f, 0.07141723f, 0.07501599f, 0.07869376f, + 0.08244978f, 0.08628326f, 0.09019341f, 0.09417944f, 0.09824051f, 0.10237582f, 0.10658453f, 0.11086578f, + 0.11521874f, 0.11964252f, 0.12413626f, 0.12869907f, 0.13333005f, 0.13802829f, 0.14279289f, 0.14762290f, + 0.15251740f, 0.15747544f, 0.16249607f, 0.16757831f, 0.17272120f, 0.17792375f, 0.18318496f, 0.18850384f, + 0.19387938f, 0.19931055f, 0.20479633f, 0.21033568f, 0.21592756f, 0.22157091f, 0.22726467f, 0.23300778f, + 0.23879915f, 0.24463771f, 0.25052236f, 0.25645201f, 0.26242554f, 0.26844185f, 0.27449982f, 0.28059832f, + 0.28673623f, 0.29291240f, 0.29912569f, 0.30537495f, 0.31165902f, 0.31797676f, 0.32432698f, 0.33070852f, + 0.33712021f, 0.34326770f, 0.34902538f, 0.35469475f, 0.36039689f, 0.36612343f, 0.37187036f, 0.37763517f, + 0.38341599f, 0.38921132f, 0.39501987f, 0.40084050f, 0.40667214f, 0.41251382f, 0.41836457f, 0.42422351f, + 0.43008975f, 0.43596242f, 0.44184069f, 0.44772373f, 0.45361072f, 0.45950085f, 0.46539332f, 0.47128734f, + 0.47718210f, 0.48307684f, 0.48897077f, 0.49486311f, 0.50075309f, 0.50663994f, 0.51252290f, 0.51840120f, + 0.52427408f, 0.53014079f, 0.53600058f, 0.54185268f, 0.54769636f, 0.55353086f, 0.55935545f, 0.56516939f, + 0.57097193f, 0.57676236f, 0.58253993f, 0.58830393f, 0.59405363f, 0.59978832f, 0.60550728f, 0.61120980f, + 0.61689518f, 0.62256271f, 0.62821170f, 0.63384146f, 0.63945131f, 0.64504055f, 0.65060852f, 0.65615454f, + 0.66167795f, 0.66717809f, 0.67265431f, 0.67810596f, 0.68353240f, 0.68893300f, 0.69430713f, 0.69965417f, + 0.70497350f, 0.71026452f, 0.71552664f, 0.72075927f, 0.72596181f, 0.73113370f, 0.73627436f, 0.74053370f, + 0.74223132f, 0.74645982f, 0.75150351f, 0.75651380f, 0.76149018f, 0.76643212f, 0.77133911f, 0.77621068f, + 0.78104633f, 0.78584558f, 0.79060798f, 0.79533307f, 0.80002041f, 0.80466956f, 0.80928010f, 0.81385162f, + 0.81838372f, 0.82287601f, 0.82732812f, 0.83173967f, 0.83611032f, 0.84043971f, 0.84472753f, 0.84897345f, + 0.85317717f, 0.85733839f, 0.86145684f, 0.86553224f, 0.86956435f, 0.87355292f, 0.87749772f, 0.88139855f, + 0.88525520f, 0.88906748f, 0.89283524f, 0.89655830f, 0.90023654f, 0.90386982f, 0.90745805f, 0.91100112f, + 0.91449896f, 0.91795152f, 0.92135875f, 0.92472064f, 0.92803719f, 0.93130842f, 0.93453436f, 0.93771509f, + 0.94085071f, 0.94394132f, 0.94698708f, 0.94998816f, 0.95294479f, 0.95585723f, 0.95872577f, 0.96155077f, + 0.96433265f, 0.96707190f, 0.96976909f, 0.97242491f, 0.97504018f, 0.97761590f, 0.98015330f, 0.98265393f, + 0.98511982f, 0.98755371f, 0.98995949f, 0.99234319f, 0.99471536f, 0.99709994f, 0.99708681f, 0.99466528f, + 0.99222861f, 0.98975303f, 0.98722813f, 0.98464802f, 0.98200891f, 0.97930819f, 0.97654393f, 0.97371465f, + 0.97081921f, 0.96785667f, 0.96482628f, 0.96172739f, 0.95855948f, 0.95532207f, 0.95201479f, 0.94863729f, + 0.94518926f, 0.94167046f, 0.93808064f, 0.93441963f, 0.93068723f, 0.92688329f, 0.92300768f, 0.91906029f, + 0.91504101f, 0.91094975f, 0.90678646f, 0.90255106f, 0.89824351f, 0.89386377f, 0.88941182f, 0.88488765f, + 0.88029124f, 0.87562260f, 0.87088175f, 0.86606871f, 0.86118350f, 0.85622616f, 0.85119674f, 0.84609529f, + 0.84092187f, 0.83567654f, 0.83035938f, 0.82497048f, 0.81950991f, 0.81397777f, 0.80837415f, 0.80269917f, + 0.79695293f, 0.79113554f, 0.78524714f, 0.77928784f, 0.77325776f, 0.76715706f, 0.76098587f, 0.75474432f, + 0.74843257f, 0.74205077f, 0.73559908f, 0.72907763f, 0.72248661f, 0.71582617f, 0.70909647f, 0.70229768f, + 0.69542998f, 0.68849352f, 0.68148847f, 0.67559894f, 0.67322974f, 0.66727332f, 0.66006356f, 0.65278589f, + 0.64544049f, 0.63802752f, 0.63054716f, 0.62299955f, 0.61538487f, 0.60770327f, 0.59995491f, 0.59213992f, + 0.58425845f, 0.57631064f, 0.56829662f, 0.56021651f, 0.55207043f, 0.54385849f, 0.53558078f, 0.52723738f, + 0.51882839f, 0.51035385f, 0.50181382f, 0.49320834f, 0.48453743f, 0.47580109f, 0.46699931f, 0.45813206f, + 0.44919928f, 0.44020091f, 0.43113683f, 0.42200694f, 0.41281107f, 0.40354904f, 0.39422063f, 0.38482561f, + 0.37536367f, 0.36583448f, 0.35623768f, 0.34657285f, 0.33683949f, 0.32703708f, 0.31716502f, 0.30722265f, + 0.29720921f, 0.28712387f, 0.27696571f, 0.26673368f, 0.25642665f, 0.24604332f, 0.23558226f, 0.22504184f, + 0.21442026f, 0.20371546f, 0.19292514f, 0.18204665f, 0.17107697f, 0.16001264f, 0.14884960f, 0.13758311f, + 0.12620753f, 0.11471608f, 0.10310041f, 0.09135008f, 0.07945161f, 0.06738693f, 0.05513058f, 0.04264380f, + 0.02985996f, 0.01663146f +}; +const float window_256kHz[592] = /*ALDO at 25.6 maybe not needed ?*/ +{ + 0.00002505f, 0.00009623f, 0.00021144f, 0.00036963f, 0.00057004f, 0.00081212f, 0.00109541f, 0.00141951f, + 0.00178408f, 0.00218883f, 0.00263346f, 0.00311775f, 0.00364144f, 0.00420431f, 0.00480616f, 0.00544680f, + 0.00612602f, 0.00684364f, 0.00759949f, 0.00839340f, 0.00922518f, 0.01009468f, 0.01100174f, 0.01194618f, + 0.01292786f, 0.01394661f, 0.01500228f, 0.01609471f, 0.01722376f, 0.01838925f, 0.01959105f, 0.02082899f, + 0.02210292f, 0.02341269f, 0.02475814f, 0.02613912f, 0.02755547f, 0.02900704f, 0.03049367f, 0.03201520f, + 0.03357147f, 0.03516233f, 0.03678761f, 0.03844715f, 0.04014078f, 0.04186836f, 0.04362970f, 0.04542464f, + 0.04725302f, 0.04911467f, 0.05100942f, 0.05293708f, 0.05489750f, 0.05689050f, 0.05891590f, 0.06097352f, + 0.06306319f, 0.06518472f, 0.06733794f, 0.06952266f, 0.07173869f, 0.07398585f, 0.07626395f, 0.07857281f, + 0.08091223f, 0.08328201f, 0.08568197f, 0.08811192f, 0.09057164f, 0.09306095f, 0.09557964f, 0.09812751f, + 0.10070437f, 0.10330999f, 0.10594419f, 0.10860674f, 0.11129745f, 0.11401609f, 0.11676246f, 0.11953635f, + 0.12233753f, 0.12516579f, 0.12802091f, 0.13090267f, 0.13381086f, 0.13674524f, 0.13970559f, 0.14269169f, + 0.14570330f, 0.14874021f, 0.15180217f, 0.15488896f, 0.15800034f, 0.16113609f, 0.16429595f, 0.16747970f, + 0.17068710f, 0.17391790f, 0.17717186f, 0.18044875f, 0.18374831f, 0.18707031f, 0.19041448f, 0.19378059f, + 0.19716839f, 0.20057763f, 0.20400804f, 0.20745938f, 0.21093140f, 0.21442384f, 0.21793644f, 0.22146894f, + 0.22502109f, 0.22859261f, 0.23218326f, 0.23579277f, 0.23942087f, 0.24306730f, 0.24673180f, 0.25041408f, + 0.25411390f, 0.25783097f, 0.26156503f, 0.26531581f, 0.26908303f, 0.27286642f, 0.27666570f, 0.28048060f, + 0.28431085f, 0.28815616f, 0.29201627f, 0.29589088f, 0.29977972f, 0.30368251f, 0.30759896f, 0.31152881f, + 0.31547175f, 0.31942751f, 0.32339581f, 0.32737635f, 0.33136886f, 0.33537304f, 0.33938861f, 0.34341527f, + 0.34689352f, 0.35040979f, 0.35394433f, 0.35749191f, 0.36105010f, 0.36461744f, 0.36819295f, 0.37177588f, + 0.37536568f, 0.37896184f, 0.38256397f, 0.38617170f, 0.38978470f, 0.39340267f, 0.39702533f, 0.40065241f, + 0.40428366f, 0.40791884f, 0.41155771f, 0.41520004f, 0.41884562f, 0.42249422f, 0.42614564f, 0.42979966f, + 0.43345608f, 0.43711469f, 0.44077529f, 0.44443769f, 0.44810168f, 0.45176708f, 0.45543368f, 0.45910129f, + 0.46276972f, 0.46643878f, 0.47010827f, 0.47377802f, 0.47744783f, 0.48111751f, 0.48478688f, 0.48845574f, + 0.49212392f, 0.49579124f, 0.49945749f, 0.50312250f, 0.50678610f, 0.51044808f, 0.51410828f, 0.51776651f, + 0.52142258f, 0.52507633f, 0.52872755f, 0.53237609f, 0.53602175f, 0.53966436f, 0.54330374f, 0.54693971f, + 0.55057209f, 0.55420071f, 0.55782539f, 0.56144595f, 0.56506222f, 0.56867402f, 0.57228118f, 0.57588352f, + 0.57948087f, 0.58307305f, 0.58665990f, 0.59024124f, 0.59381690f, 0.59738672f, 0.60095051f, 0.60450811f, + 0.60805935f, 0.61160407f, 0.61514209f, 0.61867325f, 0.62219738f, 0.62571432f, 0.62922390f, 0.63272595f, + 0.63622033f, 0.63970685f, 0.64318537f, 0.64665571f, 0.65011773f, 0.65357125f, 0.65701613f, 0.66045220f, + 0.66387931f, 0.66729730f, 0.67070601f, 0.67410530f, 0.67749501f, 0.68087499f, 0.68424508f, 0.68760514f, + 0.69095502f, 0.69429456f, 0.69762363f, 0.70094207f, 0.70424975f, 0.70754651f, 0.71083222f, 0.71410673f, + 0.71736991f, 0.72062160f, 0.72386169f, 0.72709002f, 0.73030646f, 0.73351088f, 0.73670315f, 0.73988313f, + 0.74305069f, 0.74620570f, 0.74934804f, 0.75247757f, 0.75559418f, 0.75869773f, 0.76178811f, 0.76486519f, + 0.76792885f, 0.77097898f, 0.77401546f, 0.77703816f, 0.78004699f, 0.78304181f, 0.78602253f, 0.78898904f, + 0.79194121f, 0.79487896f, 0.79780216f, 0.80071072f, 0.80360454f, 0.80648352f, 0.80934755f, 0.81219653f, + 0.81503038f, 0.81784900f, 0.82065230f, 0.82344018f, 0.82621255f, 0.82896934f, 0.83171045f, 0.83443579f, + 0.83714529f, 0.83983887f, 0.84251645f, 0.84517794f, 0.84782328f, 0.85045240f, 0.85306521f, 0.85566165f, + 0.85824166f, 0.86080517f, 0.86335210f, 0.86588241f, 0.86839603f, 0.87089291f, 0.87337298f, 0.87583620f, + 0.87828250f, 0.88071185f, 0.88312419f, 0.88551948f, 0.88789767f, 0.89025873f, 0.89260261f, 0.89492928f, + 0.89723869f, 0.89953083f, 0.90180566f, 0.90406314f, 0.90630327f, 0.90852600f, 0.91073133f, 0.91291923f, + 0.91508969f, 0.91724270f, 0.91937824f, 0.92149632f, 0.92359691f, 0.92568004f, 0.92774569f, 0.92979387f, + 0.93182459f, 0.93383786f, 0.93583369f, 0.93781212f, 0.93977315f, 0.94171681f, 0.94364315f, 0.94555218f, + 0.94744396f, 0.94931853f, 0.95117594f, 0.95301624f, 0.95483951f, 0.95664580f, 0.95843521f, 0.96020781f, + 0.96196370f, 0.96370298f, 0.96542577f, 0.96713221f, 0.96882242f, 0.97049658f, 0.97215486f, 0.97379745f, + 0.97542459f, 0.97703653f, 0.97863356f, 0.98021601f, 0.98178428f, 0.98333882f, 0.98488019f, 0.98640904f, + 0.98792619f, 0.98943268f, 0.99092986f, 0.99241955f, 0.99390438f, 0.99538840f, 0.99687865f, 0.99839048f, + 0.99839048f, 0.99687316f, 0.99536647f, 0.99385512f, 0.99233208f, 0.99079337f, 0.98923638f, 0.98765934f, + 0.98606092f, 0.98444012f, 0.98279615f, 0.98112838f, 0.97943628f, 0.97771944f, 0.97597747f, 0.97421006f, + 0.97241695f, 0.97059790f, 0.96875269f, 0.96688116f, 0.96498313f, 0.96305846f, 0.96110701f, 0.95912868f, + 0.95712335f, 0.95509092f, 0.95303131f, 0.95094444f, 0.94883023f, 0.94668862f, 0.94451953f, 0.94232293f, + 0.94009875f, 0.93784694f, 0.93556747f, 0.93326028f, 0.93092535f, 0.92856264f, 0.92617212f, 0.92375376f, + 0.92130753f, 0.91883342f, 0.91633139f, 0.91380144f, 0.91124353f, 0.90865767f, 0.90604383f, 0.90340200f, + 0.90073218f, 0.89803436f, 0.89530852f, 0.89255467f, 0.88977280f, 0.88696291f, 0.88412500f, 0.88125907f, + 0.87836512f, 0.87544316f, 0.87249319f, 0.86951521f, 0.86650924f, 0.86347528f, 0.86041334f, 0.85732343f, + 0.85420557f, 0.85105976f, 0.84788602f, 0.84468436f, 0.84145481f, 0.83819737f, 0.83491207f, 0.83159893f, + 0.82825795f, 0.82488917f, 0.82149260f, 0.81806828f, 0.81461621f, 0.81113643f, 0.80762895f, 0.80409381f, + 0.80053104f, 0.79694065f, 0.79332267f, 0.78967714f, 0.78600409f, 0.78230354f, 0.77857552f, 0.77482007f, + 0.77103722f, 0.76722699f, 0.76338943f, 0.75952457f, 0.75563243f, 0.75171306f, 0.74776649f, 0.74379276f, + 0.73979190f, 0.73576394f, 0.73170893f, 0.72762691f, 0.72351790f, 0.71938195f, 0.71521909f, 0.71102937f, + 0.70681283f, 0.70256949f, 0.69829940f, 0.69400260f, 0.68967913f, 0.68532903f, 0.68095233f, 0.67654908f, + 0.67211932f, 0.66766308f, 0.66318040f, 0.65867133f, 0.65413589f, 0.64957414f, 0.64498610f, 0.64037182f, + 0.63573134f, 0.63106468f, 0.62637190f, 0.62165301f, 0.61690807f, 0.61213710f, 0.60734015f, 0.60251723f, + 0.59766840f, 0.59279367f, 0.58789308f, 0.58296667f, 0.57801446f, 0.57303647f, 0.56803275f, 0.56300331f, + 0.55794818f, 0.55286738f, 0.54776094f, 0.54262888f, 0.53747121f, 0.53228796f, 0.52707914f, 0.52184477f, + 0.51658486f, 0.51129942f, 0.50598845f, 0.50065198f, 0.49528999f, 0.48990250f, 0.48448950f, 0.47905099f, + 0.47358696f, 0.46809741f, 0.46258232f, 0.45704168f, 0.45147548f, 0.44588369f, 0.44026628f, 0.43462323f, + 0.42895451f, 0.42326008f, 0.41753990f, 0.41179392f, 0.40602210f, 0.40022438f, 0.39440070f, 0.38855100f, + 0.38267520f, 0.37677323f, 0.37084500f, 0.36489043f, 0.35890941f, 0.35290185f, 0.34686763f, 0.34080663f, + 0.33471872f, 0.32860376f, 0.32246161f, 0.31629211f, 0.31009508f, 0.30387035f, 0.29761773f, 0.29133699f, + 0.28502794f, 0.27869032f, 0.27232389f, 0.26592837f, 0.25950348f, 0.25304891f, 0.24656432f, 0.24004937f, + 0.23350366f, 0.22692680f, 0.22031833f, 0.21367779f, 0.20700468f, 0.20029842f, 0.19355844f, 0.18678407f, + 0.17997463f, 0.17312933f, 0.16624735f, 0.15932777f, 0.15236958f, 0.14537166f, 0.13833277f, 0.13125154f, + 0.12412643f, 0.11695568f, 0.10973731f, 0.10246907f, 0.09514831f, 0.08777196f, 0.08033640f, 0.07283723f, + 0.06526908f, 0.05762520f, 0.04989688f, 0.04207239f, 0.03413516f, 0.02605991f, 0.01780324f, 0.00927214f +}; + +const float small_overlap_48[R2_48/7]= +{ + 0.01308960f, 0.03925982f, 0.06540313f, 0.09150162f, 0.11753740f, 0.14349262f, 0.16934950f, 0.19509032f, + 0.22069744f, 0.24615329f, 0.27144045f, 0.29654157f, 0.32143947f, 0.34611706f, 0.37055744f, 0.39474386f, + 0.41865974f, 0.44228869f, 0.46561452f, 0.48862124f, 0.51129309f, 0.53361452f, 0.55557023f, 0.57714519f, + 0.59832460f, 0.61909395f, 0.63943900f, 0.65934582f, 0.67880075f, 0.69779046f, 0.71630194f, 0.73432251f, + 0.75183981f, 0.76884183f, 0.78531693f, 0.80125381f, 0.81664156f, 0.83146961f, 0.84572782f, 0.85940641f, + 0.87249601f, 0.88498764f, 0.89687274f, 0.90814317f, 0.91879121f, 0.92880955f, 0.93819134f, 0.94693013f, + 0.95501994f, 0.96245524f, 0.96923091f, 0.97534232f, 0.98078528f, 0.98555606f, 0.98965139f, 0.99306846f, + 0.99580493f, 0.99785892f, 0.99922904f, 0.99991433f +}; + +const float small_overlap_25[R2_25/7]= +{ + 0.02454123f, 0.07356456f, 0.12241068f, 0.17096189f, 0.21910124f, 0.26671276f, 0.31368174f, 0.35989504f, + 0.40524131f, 0.44961133f, 0.49289819f, 0.53499762f, 0.57580819f, 0.61523159f, 0.65317284f, 0.68954054f, + 0.72424708f, 0.75720885f, 0.78834643f, 0.81758481f, 0.84485357f, 0.87008699f, 0.89322430f, 0.91420976f, + 0.93299280f, 0.94952818f, 0.96377607f, 0.97570213f, 0.98527764f, 0.99247953f, 0.99729046f, 0.99969882f +}; + +const float small_overlap_int[R2_16/7]= +{ + 0.07845910f, 0.15643447f, + 0.23344536f, 0.30901699f, 0.38268343f, 0.45399050f, 0.52249856f, 0.58778525f, 0.64944805f, 0.69778617f, + 0.71630612f, 0.76040597f, 0.80901699f, 0.85264016f, 0.89100652f, 0.92387953f, 0.95105652f, 0.97236992f, + 0.98768834f, 0.99691733f +}; + + +const float half_overlap_48[3*R2_48/7]= +{ + 0.00436331f, 0.01308960f, + 0.02181489f, 0.03053851f, 0.03925982f, 0.04797813f, 0.05669279f, 0.06540313f, 0.07410849f, 0.08280821f, + 0.09150162f, 0.10018806f, 0.10886687f, 0.11753740f, 0.12619897f, 0.13485093f, 0.14349262f, 0.15212339f, + 0.16074257f, 0.16934950f, 0.17794355f, 0.18652404f, 0.19509032f, 0.20364175f, 0.21217767f, 0.22069744f, + 0.22920039f, 0.23768589f, 0.24615329f, 0.25460195f, 0.26303121f, 0.27144045f, 0.27982901f, 0.28819627f, + 0.29654157f, 0.30486430f, 0.31316381f, 0.32143947f, 0.32969065f, 0.33791672f, 0.34611706f, 0.35429104f, + 0.36243804f, 0.37055744f, 0.37864862f, 0.38671096f, 0.39474386f, 0.40274669f, 0.41071885f, 0.41865974f, + 0.42656874f, 0.43444526f, 0.44228869f, 0.45009844f, 0.45787392f, 0.46561452f, 0.47331967f, 0.48098877f, + 0.48862124f, 0.49621650f, 0.50377398f, 0.51129309f, 0.51877326f, 0.52621392f, 0.53361452f, 0.54097447f, + 0.54829323f, 0.55557023f, 0.56280493f, 0.56999676f, 0.57714519f, 0.58424967f, 0.59130965f, 0.59832460f, + 0.60529399f, 0.61221728f, 0.61909395f, 0.62592347f, 0.63270533f, 0.63943900f, 0.64612398f, 0.65275975f, + 0.65934582f, 0.66588167f, 0.67236681f, 0.67880075f, 0.68518299f, 0.69151306f, 0.69779046f, 0.70401472f, + 0.71018538f, 0.71630194f, 0.72236396f, 0.72837097f, 0.73432251f, 0.74021813f, 0.74605738f, 0.75183981f, + 0.75756498f, 0.76323247f, 0.76884183f, 0.77439264f, 0.77988448f, 0.78531693f, 0.79068957f, 0.79600200f, + 0.80125381f, 0.80644460f, 0.81157398f, 0.81664156f, 0.82164694f, 0.82658975f, 0.83146961f, 0.83628616f, + 0.84103901f, 0.84572782f, 0.85035222f, 0.85491187f, 0.85940641f, 0.86383551f, 0.86819881f, 0.87249601f, + 0.87672676f, 0.88089074f, 0.88498764f, 0.88901714f, 0.89297894f, 0.89687274f, 0.90069824f, 0.90445515f, + 0.90814317f, 0.91176204f, 0.91531148f, 0.91879121f, 0.92220097f, 0.92554050f, 0.92880955f, 0.93200787f, + 0.93513521f, 0.93819134f, 0.94117602f, 0.94408902f, 0.94693013f, 0.94969913f, 0.95239580f, 0.95501994f, + 0.95757136f, 0.96004985f, 0.96245524f, 0.96478732f, 0.96704594f, 0.96923091f, 0.97134207f, 0.97337926f, + 0.97534232f, 0.97723111f, 0.97904547f, 0.98078528f, 0.98245040f, 0.98404070f, 0.98555606f, 0.98699637f, + 0.98836151f, 0.98965139f, 0.99086590f, 0.99200495f, 0.99306846f, 0.99405634f, 0.99496852f, 0.99580493f, + 0.99656550f, 0.99725019f, 0.99785892f, 0.99839167f, 0.99884839f, 0.99922904f, 0.99953359f, 0.99976203f, + 0.99991433f, 0.99999048f +}; + +const float half_overlap_25[3*R2_25/7]= +{ + 0.00818114f, 0.02454123f, 0.04089475f, 0.05723732f, 0.07356456f, 0.08987211f, 0.10615561f, 0.12241068f, + 0.13863297f, 0.15481816f, 0.17096189f, 0.18705985f, 0.20310773f, 0.21910124f, 0.23503609f, 0.25090801f, + 0.26671276f, 0.28244610f, 0.29810383f, 0.31368174f, 0.32917568f, 0.34458148f, 0.35989504f, 0.37511224f, + 0.39022901f, 0.40524131f, 0.42014512f, 0.43493645f, 0.44961133f, 0.46416584f, 0.47859608f, 0.49289819f, + 0.50706834f, 0.52110274f, 0.53499762f, 0.54874927f, 0.56235401f, 0.57580819f, 0.58910822f, 0.60225052f, + 0.61523159f, 0.62804795f, 0.64069616f, 0.65317284f, 0.66547466f, 0.67759830f, 0.68954054f, 0.70129818f, + 0.71286806f, 0.72424708f, 0.73543221f, 0.74642045f, 0.75720885f, 0.76779452f, 0.77817464f, 0.78834643f, + 0.79830715f, 0.80805415f, 0.81758481f, 0.82689659f, 0.83598698f, 0.84485357f, 0.85349396f, 0.86190585f, + 0.87008699f, 0.87803519f, 0.88574831f, 0.89322430f, 0.90046115f, 0.90745693f, 0.91420976f, 0.92071783f, + 0.92697940f, 0.93299280f, 0.93875641f, 0.94426870f, 0.94952818f, 0.95453345f, 0.95928317f, 0.96377607f, + 0.96801094f, 0.97198664f, 0.97570213f, 0.97915640f, 0.98234852f, 0.98527764f, 0.98794298f, 0.99034383f, + 0.99247953f, 0.99434953f, 0.99595331f, 0.99729046f, 0.99836060f, 0.99916346f, 0.99969882f, 0.99996653f, +}; + +const float half_overlap_int[3*R2_16/7]= +{ + 0.02617695f, 0.05233596f, 0.07845910f, 0.10452846f, 0.13052619f, 0.15643447f, + 0.18223553f, 0.20791169f, 0.23344536f, 0.25881905f, 0.28401534f, 0.30901699f, 0.33380686f, 0.35836795f, + 0.38268343f, 0.40673664f, 0.43051110f, 0.45399050f, 0.47715876f, 0.50000000f, 0.52249856f, 0.54463904f, + 0.56640624f, 0.58778525f, 0.60876143f, 0.62932039f, 0.64944805f, 0.66913061f, 0.68835458f, 0.70401457f, + 0.71018553f, 0.72537437f, 0.74314483f, 0.76040597f, 0.77714596f, 0.79335334f, 0.80901699f, 0.82412619f, + 0.83867057f, 0.85264016f, 0.86602540f, 0.87881711f, 0.89100652f, 0.90258528f, 0.91354546f, 0.92387953f, + 0.93358043f, 0.94264149f, 0.95105652f, 0.95881973f, 0.96592583f, 0.97236992f, 0.97814760f, 0.98325491f, + 0.98768834f, 0.99144486f, 0.99452190f, 0.99691733f, 0.99862953f, 0.99965732f +}; + +const float window_48kHz[1110] = +{ + 0.00000717f, 0.00002765f, 0.00006087f, 0.00010657f, 0.00016454f, 0.00023464f, 0.00031674f, 0.00041075f, + 0.00051659f, 0.00063416f, 0.00076341f, 0.00090428f, 0.00105670f, 0.00122062f, 0.00139600f, 0.00158279f, + 0.00178095f, 0.00199044f, 0.00221121f, 0.00244323f, 0.00268646f, 0.00294088f, 0.00320644f, 0.00348313f, + 0.00377089f, 0.00406971f, 0.00437956f, 0.00470041f, 0.00503222f, 0.00537498f, 0.00572866f, 0.00609322f, + 0.00646865f, 0.00685492f, 0.00725200f, 0.00765987f, 0.00807851f, 0.00850788f, 0.00894798f, 0.00939876f, + 0.00986022f, 0.01033232f, 0.01081504f, 0.01130837f, 0.01181227f, 0.01232672f, 0.01285171f, 0.01338721f, + 0.01393319f, 0.01448963f, 0.01505652f, 0.01563383f, 0.01622153f, 0.01681961f, 0.01742804f, 0.01804680f, + 0.01867586f, 0.01931521f, 0.01996482f, 0.02062467f, 0.02129474f, 0.02197501f, 0.02266545f, 0.02336603f, + 0.02407675f, 0.02479757f, 0.02552847f, 0.02626943f, 0.02702042f, 0.02778143f, 0.02855244f, 0.02933340f, + 0.03012432f, 0.03092515f, 0.03173588f, 0.03255648f, 0.03338694f, 0.03422723f, 0.03507731f, 0.03593718f, + 0.03680680f, 0.03768616f, 0.03857522f, 0.03947397f, 0.04038238f, 0.04130042f, 0.04222808f, 0.04316532f, + 0.04411212f, 0.04506846f, 0.04603431f, 0.04700965f, 0.04799445f, 0.04898869f, 0.04999234f, 0.05100537f, + 0.05202776f, 0.05305949f, 0.05410053f, 0.05515085f, 0.05621043f, 0.05727924f, 0.05835725f, 0.05944444f, + 0.06054078f, 0.06164624f, 0.06276080f, 0.06388444f, 0.06501711f, 0.06615880f, 0.06730949f, 0.06846913f, + 0.06963771f, 0.07081519f, 0.07200155f, 0.07319676f, 0.07440080f, 0.07561362f, 0.07683522f, 0.07806555f, + 0.07930459f, 0.08055231f, 0.08180868f, 0.08307367f, 0.08434725f, 0.08562940f, 0.08692008f, 0.08821927f, + 0.08952693f, 0.09084304f, 0.09216756f, 0.09350047f, 0.09484173f, 0.09619131f, 0.09754919f, 0.09891534f, + 0.10028971f, 0.10167229f, 0.10306304f, 0.10446193f, 0.10586893f, 0.10728400f, 0.10870712f, 0.11013826f, + 0.11157738f, 0.11302444f, 0.11447943f, 0.11594230f, 0.11741303f, 0.11889158f, 0.12037792f, 0.12187201f, + 0.12337383f, 0.12488334f, 0.12640051f, 0.12792530f, 0.12945769f, 0.13099763f, 0.13254510f, 0.13410005f, + 0.13566247f, 0.13723231f, 0.13880953f, 0.14039412f, 0.14198602f, 0.14358521f, 0.14519166f, 0.14680532f, + 0.14842616f, 0.15005415f, 0.15168925f, 0.15333143f, 0.15498066f, 0.15663689f, 0.15830009f, 0.15997023f, + 0.16164727f, 0.16333117f, 0.16502191f, 0.16671943f, 0.16842371f, 0.17013472f, 0.17185240f, 0.17357674f, + 0.17530768f, 0.17704520f, 0.17878926f, 0.18053981f, 0.18229683f, 0.18406028f, 0.18583011f, 0.18760630f, + 0.18938880f, 0.19117758f, 0.19297259f, 0.19477381f, 0.19658119f, 0.19839469f, 0.20021428f, 0.20203992f, + 0.20387157f, 0.20570919f, 0.20755274f, 0.20940219f, 0.21125750f, 0.21311862f, 0.21498552f, 0.21685816f, + 0.21873650f, 0.22062050f, 0.22251012f, 0.22440532f, 0.22630606f, 0.22821231f, 0.23012402f, 0.23204116f, + 0.23396367f, 0.23589153f, 0.23782470f, 0.23976312f, 0.24170677f, 0.24365560f, 0.24560957f, 0.24756865f, + 0.24953278f, 0.25150194f, 0.25347607f, 0.25545514f, 0.25743911f, 0.25942794f, 0.26142158f, 0.26341999f, + 0.26542314f, 0.26743098f, 0.26944347f, 0.27146056f, 0.27348222f, 0.27550841f, 0.27753908f, 0.27957419f, + 0.28161370f, 0.28365757f, 0.28570575f, 0.28775820f, 0.28981489f, 0.29187576f, 0.29394078f, 0.29600991f, + 0.29808309f, 0.30016029f, 0.30224147f, 0.30432658f, 0.30641558f, 0.30850843f, 0.31060508f, 0.31270549f, + 0.31480962f, 0.31691743f, 0.31902887f, 0.32114389f, 0.32326246f, 0.32538454f, 0.32751007f, 0.32963901f, + 0.33177133f, 0.33390698f, 0.33604591f, 0.33818808f, 0.34033345f, 0.34248196f, 0.34432825f, 0.34619672f, + 0.34807434f, 0.34995817f, 0.35184686f, 0.35373965f, 0.35563601f, 0.35753559f, 0.35943811f, 0.36134336f, + 0.36325118f, 0.36516141f, 0.36707393f, 0.36898864f, 0.37090544f, 0.37282426f, 0.37474501f, 0.37666763f, + 0.37859204f, 0.38051820f, 0.38244605f, 0.38437553f, 0.38630659f, 0.38823918f, 0.39017326f, 0.39210879f, + 0.39404572f, 0.39598401f, 0.39792361f, 0.39986450f, 0.40180663f, 0.40374996f, 0.40569446f, 0.40764009f, + 0.40958682f, 0.41153461f, 0.41348342f, 0.41543322f, 0.41738398f, 0.41933567f, 0.42128825f, 0.42324169f, + 0.42519595f, 0.42715101f, 0.42910683f, 0.43106338f, 0.43302063f, 0.43497855f, 0.43693710f, 0.43889626f, + 0.44085600f, 0.44281628f, 0.44477708f, 0.44673836f, 0.44870009f, 0.45066225f, 0.45262480f, 0.45458771f, + 0.45655096f, 0.45851451f, 0.46047834f, 0.46244241f, 0.46440670f, 0.46637117f, 0.46833580f, 0.47030055f, + 0.47226541f, 0.47423033f, 0.47619530f, 0.47816027f, 0.48012523f, 0.48209014f, 0.48405498f, 0.48601971f, + 0.48798430f, 0.48994874f, 0.49191298f, 0.49387701f, 0.49584078f, 0.49780428f, 0.49976748f, 0.50173034f, + 0.50369284f, 0.50565495f, 0.50761664f, 0.50957789f, 0.51153865f, 0.51349892f, 0.51545865f, 0.51741783f, + 0.51937641f, 0.52133438f, 0.52329171f, 0.52524836f, 0.52720432f, 0.52915954f, 0.53111401f, 0.53306770f, + 0.53502057f, 0.53697261f, 0.53892378f, 0.54087405f, 0.54282340f, 0.54477180f, 0.54671922f, 0.54866564f, + 0.55061103f, 0.55255535f, 0.55449858f, 0.55644070f, 0.55838168f, 0.56032149f, 0.56226010f, 0.56419748f, + 0.56613362f, 0.56806847f, 0.57000202f, 0.57193423f, 0.57386509f, 0.57579455f, 0.57772261f, 0.57964922f, + 0.58157436f, 0.58349801f, 0.58542013f, 0.58734071f, 0.58925971f, 0.59117711f, 0.59309288f, 0.59500700f, + 0.59691943f, 0.59883016f, 0.60073915f, 0.60264638f, 0.60455182f, 0.60645545f, 0.60835724f, 0.61025717f, + 0.61215520f, 0.61405132f, 0.61594549f, 0.61783769f, 0.61972789f, 0.62161608f, 0.62350222f, 0.62538628f, + 0.62726824f, 0.62914809f, 0.63102578f, 0.63290129f, 0.63477461f, 0.63664570f, 0.63851454f, 0.64038110f, + 0.64224536f, 0.64410729f, 0.64596688f, 0.64782408f, 0.64967889f, 0.65153127f, 0.65338119f, 0.65522864f, + 0.65707360f, 0.65891602f, 0.66075590f, 0.66259321f, 0.66442791f, 0.66626000f, 0.66808944f, 0.66991621f, + 0.67174028f, 0.67356164f, 0.67538025f, 0.67719610f, 0.67900916f, 0.68081941f, 0.68262682f, 0.68443137f, + 0.68623303f, 0.68803180f, 0.68982763f, 0.69162050f, 0.69341041f, 0.69519731f, 0.69698119f, 0.69876203f, + 0.70053980f, 0.70231448f, 0.70408605f, 0.70585448f, 0.70761976f, 0.70938186f, 0.71114076f, 0.71289643f, + 0.71464886f, 0.71639803f, 0.71814390f, 0.71988647f, 0.72162570f, 0.72336158f, 0.72509409f, 0.72682320f, + 0.72854889f, 0.73027115f, 0.73198995f, 0.73370527f, 0.73541708f, 0.73712538f, 0.73883014f, 0.74053133f, + 0.74222894f, 0.74392295f, 0.74561334f, 0.74730009f, 0.74898317f, 0.75066257f, 0.75233827f, 0.75401025f, + 0.75567849f, 0.75734297f, 0.75900367f, 0.76066057f, 0.76231366f, 0.76396291f, 0.76560830f, 0.76724982f, + 0.76888745f, 0.77052118f, 0.77215097f, 0.77377682f, 0.77539870f, 0.77701660f, 0.77863050f, 0.78024038f, + 0.78184623f, 0.78344803f, 0.78504575f, 0.78663939f, 0.78822893f, 0.78981434f, 0.79139562f, 0.79297274f, + 0.79454569f, 0.79611446f, 0.79767902f, 0.79923936f, 0.80079547f, 0.80234733f, 0.80389492f, 0.80543823f, + 0.80697724f, 0.80851193f, 0.81004230f, 0.81156833f, 0.81309000f, 0.81460729f, 0.81612020f, 0.81762870f, + 0.81913279f, 0.82063245f, 0.82212766f, 0.82361842f, 0.82510470f, 0.82658650f, 0.82806380f, 0.82953658f, + 0.83100484f, 0.83246856f, 0.83392773f, 0.83538233f, 0.83683236f, 0.83827780f, 0.83971863f, 0.84115485f, + 0.84258645f, 0.84401340f, 0.84543571f, 0.84685336f, 0.84826633f, 0.84967462f, 0.85107821f, 0.85247710f, + 0.85387127f, 0.85526072f, 0.85664542f, 0.85802538f, 0.85940058f, 0.86077102f, 0.86213667f, 0.86349754f, + 0.86485361f, 0.86620487f, 0.86755132f, 0.86889294f, 0.87022973f, 0.87156168f, 0.87288878f, 0.87421101f, + 0.87552839f, 0.87684088f, 0.87814849f, 0.87945122f, 0.88074904f, 0.88204196f, 0.88332997f, 0.88461305f, + 0.88589122f, 0.88716444f, 0.88843273f, 0.88969608f, 0.89095447f, 0.89220791f, 0.89345638f, 0.89469988f, + 0.89593841f, 0.89717197f, 0.89840053f, 0.89962411f, 0.90084270f, 0.90205629f, 0.90326488f, 0.90446846f, + 0.90566704f, 0.90686060f, 0.90804915f, 0.90923267f, 0.91041118f, 0.91158466f, 0.91275311f, 0.91391654f, + 0.91507493f, 0.91622829f, 0.91737662f, 0.91851991f, 0.91965816f, 0.92079138f, 0.92191956f, 0.92304270f, + 0.92416080f, 0.92527386f, 0.92638188f, 0.92748486f, 0.92858281f, 0.92967572f, 0.93076360f, 0.93184645f, + 0.93292426f, 0.93399705f, 0.93506481f, 0.93612755f, 0.93718527f, 0.93823797f, 0.93928566f, 0.94032834f, + 0.94136602f, 0.94239870f, 0.94342639f, 0.94444909f, 0.94546681f, 0.94647956f, 0.94748733f, 0.94849015f, + 0.94948801f, 0.95048093f, 0.95146891f, 0.95245197f, 0.95343011f, 0.95440334f, 0.95537168f, 0.95633513f, + 0.95729371f, 0.95824743f, 0.95919630f, 0.96014034f, 0.96107957f, 0.96201399f, 0.96294363f, 0.96386850f, + 0.96478862f, 0.96570402f, 0.96661470f, 0.96752070f, 0.96842204f, 0.96931873f, 0.97021081f, 0.97109831f, + 0.97198124f, 0.97285966f, 0.97373358f, 0.97460304f, 0.97546808f, 0.97632874f, 0.97718506f, 0.97803710f, + 0.97888489f, 0.97972850f, 0.98056799f, 0.98140340f, 0.98223483f, 0.98306234f, 0.98388601f, 0.98470595f, + 0.98552225f, 0.98633502f, 0.98714441f, 0.98795054f, 0.98875359f, 0.98955376f, 0.99035126f, 0.99114636f, + 0.99193936f, 0.99273065f, 0.99352070f, 0.99431009f, 0.99509960f, 0.99589027f, 0.99668360f, 0.99748189f, + 0.99828914f, 0.99911401f, 0.99911401f, 0.99828759f, 0.99747571f, 0.99666970f, 0.99586557f, 0.99506104f, + 0.99425460f, 0.99344523f, 0.99263215f, 0.99181478f, 0.99099266f, 0.99016542f, 0.98933274f, 0.98849437f, + 0.98765009f, 0.98679972f, 0.98594310f, 0.98508007f, 0.98421052f, 0.98333434f, 0.98245143f, 0.98156170f, + 0.98066506f, 0.97976145f, 0.97885080f, 0.97793305f, 0.97700814f, 0.97607603f, 0.97513666f, 0.97419000f, + 0.97323600f, 0.97227462f, 0.97130583f, 0.97032960f, 0.96934589f, 0.96835468f, 0.96735594f, 0.96634965f, + 0.96533578f, 0.96431430f, 0.96328520f, 0.96224846f, 0.96120406f, 0.96015197f, 0.95909219f, 0.95802469f, + 0.95694946f, 0.95586649f, 0.95477576f, 0.95367726f, 0.95257097f, 0.95145688f, 0.95033498f, 0.94920527f, + 0.94806772f, 0.94692233f, 0.94576909f, 0.94460799f, 0.94343902f, 0.94226217f, 0.94107743f, 0.93988480f, + 0.93868427f, 0.93747583f, 0.93625947f, 0.93503520f, 0.93380299f, 0.93256285f, 0.93131476f, 0.93005873f, + 0.92879475f, 0.92752281f, 0.92624292f, 0.92495505f, 0.92365922f, 0.92235541f, 0.92104362f, 0.91972385f, + 0.91839609f, 0.91706034f, 0.91571660f, 0.91436487f, 0.91300513f, 0.91163740f, 0.91026166f, 0.90887792f, + 0.90748616f, 0.90608640f, 0.90467862f, 0.90326283f, 0.90183902f, 0.90040720f, 0.89896735f, 0.89751949f, + 0.89606360f, 0.89459969f, 0.89312776f, 0.89164780f, 0.89015982f, 0.88866382f, 0.88715979f, 0.88564773f, + 0.88412765f, 0.88259954f, 0.88106340f, 0.87951924f, 0.87796706f, 0.87640684f, 0.87483861f, 0.87326235f, + 0.87167807f, 0.87008576f, 0.86848544f, 0.86687709f, 0.86526073f, 0.86363635f, 0.86200395f, 0.86036353f, + 0.85871510f, 0.85705867f, 0.85539422f, 0.85372176f, 0.85204129f, 0.85035282f, 0.84865635f, 0.84695188f, + 0.84523941f, 0.84351895f, 0.84179049f, 0.84005404f, 0.83830960f, 0.83655718f, 0.83479677f, 0.83302839f, + 0.83125203f, 0.82946769f, 0.82767538f, 0.82587511f, 0.82406687f, 0.82225067f, 0.82042651f, 0.81859440f, + 0.81675434f, 0.81490633f, 0.81305038f, 0.81118649f, 0.80931466f, 0.80743490f, 0.80554721f, 0.80365160f, + 0.80174807f, 0.79983662f, 0.79791726f, 0.79599000f, 0.79405483f, 0.79211177f, 0.79016081f, 0.78820196f, + 0.78623522f, 0.78426061f, 0.78227812f, 0.78028777f, 0.77828954f, 0.77628346f, 0.77426952f, 0.77224773f, + 0.77021809f, 0.76818061f, 0.76613530f, 0.76408216f, 0.76202120f, 0.75995241f, 0.75787581f, 0.75579140f, + 0.75369919f, 0.75159918f, 0.74949138f, 0.74737580f, 0.74525243f, 0.74312128f, 0.74098237f, 0.73883570f, + 0.73668126f, 0.73451908f, 0.73234915f, 0.73017147f, 0.72798607f, 0.72579293f, 0.72359208f, 0.72138350f, + 0.71916722f, 0.71694323f, 0.71471154f, 0.71247217f, 0.71022510f, 0.70797036f, 0.70570794f, 0.70343786f, + 0.70116012f, 0.69887472f, 0.69658167f, 0.69428098f, 0.69197265f, 0.68965669f, 0.68733312f, 0.68500192f, + 0.68266311f, 0.68031670f, 0.67796269f, 0.67560109f, 0.67323190f, 0.67085514f, 0.66847080f, 0.66607889f, + 0.66367943f, 0.66127241f, 0.65885784f, 0.65643574f, 0.65400609f, 0.65156892f, 0.64912423f, 0.64667201f, + 0.64421229f, 0.64174507f, 0.63927035f, 0.63678813f, 0.63429843f, 0.63180125f, 0.62929660f, 0.62678447f, + 0.62426489f, 0.62173785f, 0.61920336f, 0.61666143f, 0.61411206f, 0.61155525f, 0.60899102f, 0.60641937f, + 0.60384030f, 0.60125382f, 0.59865994f, 0.59605866f, 0.59344998f, 0.59083391f, 0.58821046f, 0.58557964f, + 0.58294143f, 0.58029586f, 0.57764293f, 0.57498264f, 0.57231499f, 0.56963999f, 0.56695765f, 0.56426797f, + 0.56157095f, 0.55886660f, 0.55615492f, 0.55343592f, 0.55070960f, 0.54797596f, 0.54523501f, 0.54248675f, + 0.53973118f, 0.53696832f, 0.53419815f, 0.53142069f, 0.52863593f, 0.52584388f, 0.52304455f, 0.52023793f, + 0.51742403f, 0.51460284f, 0.51177438f, 0.50893864f, 0.50609563f, 0.50324534f, 0.50038778f, 0.49752294f, + 0.49465084f, 0.49177147f, 0.48888482f, 0.48599091f, 0.48308973f, 0.48018128f, 0.47726556f, 0.47434256f, + 0.47141230f, 0.46847477f, 0.46552996f, 0.46257788f, 0.45961852f, 0.45665188f, 0.45367796f, 0.45069676f, + 0.44770827f, 0.44471249f, 0.44170942f, 0.43869905f, 0.43568138f, 0.43265640f, 0.42962411f, 0.42658451f, + 0.42353758f, 0.42048333f, 0.41742175f, 0.41435283f, 0.41127656f, 0.40819293f, 0.40510195f, 0.40200359f, + 0.39889786f, 0.39578474f, 0.39266422f, 0.38953629f, 0.38640095f, 0.38325818f, 0.38010797f, 0.37695031f, + 0.37378519f, 0.37061258f, 0.36743249f, 0.36424489f, 0.36104978f, 0.35784713f, 0.35463693f, 0.35141916f, + 0.34819381f, 0.34496085f, 0.34172027f, 0.33847206f, 0.33521618f, 0.33195262f, 0.32868136f, 0.32540237f, + 0.32211564f, 0.31882113f, 0.31551882f, 0.31220868f, 0.30889070f, 0.30556483f, 0.30223106f, 0.29888935f, + 0.29553966f, 0.29218198f, 0.28881626f, 0.28544246f, 0.28206056f, 0.27867052f, 0.27527229f, 0.27186583f, + 0.26845112f, 0.26502809f, 0.26159670f, 0.25815692f, 0.25470869f, 0.25125196f, 0.24778667f, 0.24431278f, + 0.24083023f, 0.23733896f, 0.23383891f, 0.23033001f, 0.22681220f, 0.22328542f, 0.21974958f, 0.21620462f, + 0.21265047f, 0.20908703f, 0.20551423f, 0.20193197f, 0.19834018f, 0.19473875f, 0.19112758f, 0.18750657f, + 0.18387561f, 0.18023459f, 0.17658339f, 0.17292189f, 0.16924994f, 0.16556742f, 0.16187418f, 0.15817007f, + 0.15445492f, 0.15072857f, 0.14699084f, 0.14324154f, 0.13948047f, 0.13570741f, 0.13192214f, 0.12812442f, + 0.12431400f, 0.12049059f, 0.11665391f, 0.11280364f, 0.10893944f, 0.10506094f, 0.10116776f, 0.09725946f, + 0.09333558f, 0.08939561f, 0.08543899f, 0.08146510f, 0.07747327f, 0.07346273f, 0.06943264f, 0.06538204f, + 0.06130985f, 0.05721482f, 0.05309551f, 0.04895024f, 0.04477702f, 0.04057343f, 0.03633653f, 0.03206261f, + 0.02774685f, 0.02338280f, 0.01896129f, 0.01446831f, 0.00987977f, 0.00514389f +}; + + +const float short_window_8kHz[80] = +{ + 0.01963369f, 0.05887080f, 0.09801714f, 0.13701234f, 0.17579628f, 0.21430915f, 0.25249158f, 0.29028468f, + 0.32763018f, 0.36447050f, 0.40074883f, 0.43640924f, 0.47139674f, 0.50565737f, 0.53913832f, 0.57178796f, + 0.60355594f, 0.63439328f, 0.66425244f, 0.69308736f, 0.72085360f, 0.74750833f, 0.77301045f, 0.79732065f, + 0.82040144f, 0.84221723f, 0.86273439f, 0.88192126f, 0.89974828f, 0.91618796f, 0.93121493f, 0.94480605f, + 0.95694034f, 0.96759909f, 0.97676588f, 0.98442657f, 0.99056934f, 0.99518473f, 0.99826561f, 0.99980724f, + 0.99980724f, 0.99826561f, 0.99518473f, 0.99056934f, 0.98442657f, 0.97676588f, 0.96759909f, 0.95694034f, + 0.94480605f, 0.93121493f, 0.91618796f, 0.89974828f, 0.88192126f, 0.86273439f, 0.84221723f, 0.82040144f, + 0.79732065f, 0.77301045f, 0.74750833f, 0.72085360f, 0.69308736f, 0.66425244f, 0.63439328f, 0.60355594f, + 0.57178796f, 0.53913832f, 0.50565737f, 0.47139674f, 0.43640924f, 0.40074883f, 0.36447050f, 0.32763018f, + 0.29028468f, 0.25249158f, 0.21430915f, 0.17579628f, 0.13701234f, 0.09801714f, 0.05887080f, 0.01963369f +}; + +const float short_window_16kHz[160] = +{ + 0.00981732f, 0.02944817f, 0.04906767f, 0.06866826f, + 0.08824237f, 0.10778246f, 0.12728100f, 0.14673047f, + 0.16612338f, 0.18545224f, 0.20470960f, 0.22388805f, + 0.24298018f, 0.26197864f, 0.28087610f, 0.29966528f, + 0.31833893f, 0.33688985f, 0.35531090f, 0.37359497f, + 0.39173501f, 0.40972403f, 0.42755509f, 0.44522133f, + 0.46271592f, 0.48003212f, 0.49716327f, 0.51410274f, + 0.53084403f, 0.54738066f, 0.56370626f, 0.57981455f, + 0.59569930f, 0.61135441f, 0.62677382f, 0.64195160f, + 0.65688190f, 0.67155895f, 0.68597711f, 0.70013081f, + 0.71401460f, 0.72762312f, 0.74095113f, 0.75399348f, + 0.76674516f, 0.77920124f, 0.79135693f, 0.80320753f, + 0.81474848f, 0.82597533f, 0.83688375f, 0.84746954f, + 0.85772861f, 0.86765701f, 0.87725091f, 0.88650662f, + 0.89542056f, 0.90398929f, 0.91220953f, 0.92007808f, + 0.92759194f, 0.93474818f, 0.94154407f, 0.94797697f, + 0.95404440f, 0.95974404f, 0.96507367f, 0.97003125f, + 0.97461487f, 0.97882275f, 0.98265328f, 0.98610498f, + 0.98917651f, 0.99186670f, 0.99417450f, 0.99609903f, + 0.99763955f, 0.99879546f, 0.99956631f, 0.99995181f, + 0.99995181f, 0.99956631f, 0.99879546f, 0.99763955f, + 0.99609903f, 0.99417450f, 0.99186670f, 0.98917651f, + 0.98610498f, 0.98265328f, 0.97882275f, 0.97461487f, + 0.97003125f, 0.96507367f, 0.95974404f, 0.95404440f, + 0.94797697f, 0.94154407f, 0.93474818f, 0.92759194f, + 0.92007808f, 0.91220953f, 0.90398929f, 0.89542056f, + 0.88650662f, 0.87725091f, 0.86765701f, 0.85772861f, + 0.84746954f, 0.83688375f, 0.82597533f, 0.81474848f, + 0.80320753f, 0.79135693f, 0.77920124f, 0.76674516f, + 0.75399348f, 0.74095113f, 0.72762312f, 0.71401460f, + 0.70013081f, 0.68597711f, 0.67155895f, 0.65688190f, + 0.64195160f, 0.62677382f, 0.61135441f, 0.59569930f, + 0.57981455f, 0.56370626f, 0.54738066f, 0.53084403f, + 0.51410274f, 0.49716327f, 0.48003212f, 0.46271592f, + 0.44522133f, 0.42755509f, 0.40972403f, 0.39173501f, + 0.37359497f, 0.35531090f, 0.33688985f, 0.31833893f, + 0.29966528f, 0.28087610f, 0.26197864f, 0.24298018f, + 0.22388805f, 0.20470960f, 0.18545224f, 0.16612338f, + 0.14673047f, 0.12728100f, 0.10778246f, 0.08824237f, + 0.06866826f, 0.04906767f, 0.02944817f, 0.00981732f +}; + +const float short_window_32kHz[320] = +{ + 0.00490872f, 0.01472568f, 0.02454123f, 0.03435441f, 0.04416428f, 0.05396989f, + 0.06377030f, 0.07356456f, 0.08335174f, 0.09313088f, 0.10290104f, 0.11266129f, + 0.12241068f, 0.13214826f, 0.14187312f, 0.15158430f, 0.16128086f, 0.17096189f, + 0.18062644f, 0.19027357f, 0.19990237f, 0.20951190f, 0.21910124f, 0.22866946f, + 0.23821564f, 0.24773886f, 0.25723821f, 0.26671276f, 0.27616160f, 0.28558383f, + 0.29497853f, 0.30434480f, 0.31368174f, 0.32298845f, 0.33226402f, 0.34150757f, + 0.35071820f, 0.35989504f, 0.36903718f, 0.37814376f, 0.38721389f, 0.39624670f, + 0.40524131f, 0.41419687f, 0.42311251f, 0.43198737f, 0.44082059f, 0.44961133f, + 0.45835873f, 0.46706195f, 0.47572016f, 0.48433252f, 0.49289819f, 0.50141636f, + 0.50988620f, 0.51830690f, 0.52667764f, 0.53499762f, 0.54326604f, 0.55148209f, + 0.55964499f, 0.56775395f, 0.57580819f, 0.58380693f, 0.59174941f, 0.59963485f, + 0.60746249f, 0.61523159f, 0.62294139f, 0.63059115f, 0.63818013f, 0.64570760f, + 0.65317284f, 0.66057513f, 0.66791374f, 0.67518798f, 0.68239715f, 0.68954054f, + 0.69661748f, 0.70362727f, 0.71056925f, 0.71744274f, 0.72424708f, 0.73098162f, + 0.73764570f, 0.74423869f, 0.75075995f, 0.75720885f, 0.76358476f, 0.76988708f, + 0.77611520f, 0.78226851f, 0.78834643f, 0.79434836f, 0.80027373f, 0.80612197f, + 0.81189252f, 0.81758481f, 0.82319831f, 0.82873246f, 0.83418673f, 0.83956061f, + 0.84485357f, 0.85006509f, 0.85519469f, 0.86024186f, 0.86520612f, 0.87008699f, + 0.87488400f, 0.87959669f, 0.88422459f, 0.88876728f, 0.89322430f, 0.89759523f, + 0.90187965f, 0.90607715f, 0.91018732f, 0.91420976f, 0.91814408f, 0.92198992f, + 0.92574689f, 0.92941463f, 0.93299280f, 0.93648104f, 0.93987902f, 0.94318642f, + 0.94640291f, 0.94952818f, 0.95256194f, 0.95550388f, 0.95835373f, 0.96111122f, + 0.96377607f, 0.96634802f, 0.96882685f, 0.97121229f, 0.97350412f, 0.97570213f, + 0.97780610f, 0.97981582f, 0.98173111f, 0.98355177f, 0.98527764f, 0.98690855f, + 0.98844433f, 0.98988485f, 0.99122996f, 0.99247953f, 0.99363345f, 0.99469160f, + 0.99565388f, 0.99652019f, 0.99729046f, 0.99796460f, 0.99854256f, 0.99902428f, + 0.99940971f, 0.99969882f, 0.99989157f, 0.99998795f, 0.99998795f, 0.99989157f, + 0.99969882f, 0.99940971f, 0.99902428f, 0.99854256f, 0.99796460f, 0.99729046f, + 0.99652019f, 0.99565388f, 0.99469160f, 0.99363345f, 0.99247953f, 0.99122996f, + 0.98988485f, 0.98844433f, 0.98690855f, 0.98527764f, 0.98355177f, 0.98173111f, + 0.97981582f, 0.97780610f, 0.97570213f, 0.97350412f, 0.97121229f, 0.96882685f, + 0.96634802f, 0.96377607f, 0.96111122f, 0.95835373f, 0.95550388f, 0.95256194f, + 0.94952818f, 0.94640291f, 0.94318642f, 0.93987902f, 0.93648104f, 0.93299280f, + 0.92941463f, 0.92574689f, 0.92198992f, 0.91814408f, 0.91420976f, 0.91018732f, + 0.90607715f, 0.90187965f, 0.89759523f, 0.89322430f, 0.88876728f, 0.88422459f, + 0.87959669f, 0.87488400f, 0.87008699f, 0.86520612f, 0.86024186f, 0.85519469f, + 0.85006509f, 0.84485357f, 0.83956061f, 0.83418673f, 0.82873246f, 0.82319831f, + 0.81758481f, 0.81189252f, 0.80612197f, 0.80027373f, 0.79434836f, 0.78834643f, + 0.78226851f, 0.77611520f, 0.76988708f, 0.76358476f, 0.75720885f, 0.75075995f, + 0.74423869f, 0.73764570f, 0.73098162f, 0.72424708f, 0.71744274f, 0.71056925f, + 0.70362727f, 0.69661748f, 0.68954054f, 0.68239715f, 0.67518798f, 0.66791374f, + 0.66057513f, 0.65317284f, 0.64570760f, 0.63818013f, 0.63059115f, 0.62294139f, + 0.61523159f, 0.60746249f, 0.59963485f, 0.59174941f, 0.58380693f, 0.57580819f, + 0.56775395f, 0.55964499f, 0.55148209f, 0.54326604f, 0.53499762f, 0.52667764f, + 0.51830690f, 0.50988620f, 0.50141636f, 0.49289819f, 0.48433252f, 0.47572016f, + 0.46706195f, 0.45835873f, 0.44961133f, 0.44082059f, 0.43198737f, 0.42311251f, + 0.41419687f, 0.40524131f, 0.39624670f, 0.38721389f, 0.37814376f, 0.36903718f, + 0.35989504f, 0.35071820f, 0.34150757f, 0.33226402f, 0.32298845f, 0.31368174f, + 0.30434480f, 0.29497853f, 0.28558383f, 0.27616160f, 0.26671276f, 0.25723821f, + 0.24773886f, 0.23821564f, 0.22866946f, 0.21910124f, 0.20951190f, 0.19990237f, + 0.19027357f, 0.18062644f, 0.17096189f, 0.16128086f, 0.15158430f, 0.14187312f, + 0.13214826f, 0.12241068f, 0.11266129f, 0.10290104f, 0.09313088f, 0.08335174f, + 0.07356456f, 0.06377030f, 0.05396989f, 0.04416428f, 0.03435441f, 0.02454123f, + 0.01472568f, 0.00490872f +}; + +const float short_window_48kHz[480] = +{ + 0.00326538f, 0.00982666f, 0.0163574f, 0.0229187f, 0.0294495f, 0.0359802f, + 0.0425415f, 0.0490723f, 0.055603f, 0.0621338f, 0.0686646f, 0.0751953f, + 0.0817261f, 0.0882568f, 0.0947571f, 0.101288f, 0.107788f, 0.114288f, + 0.120789f, 0.127289f, 0.133759f, 0.140259f, 0.146729f, 0.153198f, + 0.159668f, 0.166138f, 0.172577f, 0.179016f, 0.185455f, 0.191895f, + 0.198303f, 0.204712f, 0.211121f, 0.217499f, 0.223877f, 0.230255f, + 0.236633f, 0.242981f, 0.249329f, 0.255646f, 0.261993f, 0.26828f, + 0.274597f, 0.280884f, 0.28714f, 0.293427f, 0.299652f, 0.305908f, + 0.312134f, 0.318329f, 0.324524f, 0.330719f, 0.336884f, 0.343048f, + 0.349182f, 0.355316f, 0.36142f, 0.367523f, 0.373596f, 0.379669f, + 0.385712f, 0.391724f, 0.397736f, 0.403748f, 0.409729f, 0.41568f, + 0.421631f, 0.427551f, 0.433472f, 0.439362f, 0.445221f, 0.45108f, + 0.456909f, 0.462708f, 0.468506f, 0.474274f, 0.480042f, 0.485748f, + 0.491486f, 0.497162f, 0.502838f, 0.508484f, 0.514099f, 0.519714f, + 0.525299f, 0.530853f, 0.536377f, 0.541901f, 0.547394f, 0.552856f, + 0.558289f, 0.563721f, 0.569092f, 0.574463f, 0.579803f, 0.585144f, + 0.590424f, 0.595703f, 0.600952f, 0.606171f, 0.611359f, 0.616516f, + 0.621674f, 0.62677f, 0.631866f, 0.636932f, 0.641937f, 0.646942f, + 0.651947f, 0.656891f, 0.661804f, 0.666687f, 0.67157f, 0.676392f, + 0.681213f, 0.685974f, 0.690735f, 0.695435f, 0.700134f, 0.704803f, + 0.709412f, 0.71402f, 0.718567f, 0.723114f, 0.727631f, 0.732086f, + 0.736542f, 0.740936f, 0.745331f, 0.749664f, 0.753998f, 0.75827f, + 0.762512f, 0.766754f, 0.770935f, 0.775085f, 0.779205f, 0.783295f, + 0.787354f, 0.791351f, 0.795349f, 0.799286f, 0.803223f, 0.807098f, + 0.810944f, 0.814758f, 0.818512f, 0.822266f, 0.825989f, 0.829651f, + 0.833282f, 0.836884f, 0.840454f, 0.843964f, 0.847473f, 0.850922f, + 0.85434f, 0.857727f, 0.861084f, 0.86438f, 0.867645f, 0.87088f, + 0.874084f, 0.877258f, 0.880371f, 0.883453f, 0.886505f, 0.889526f, + 0.892487f, 0.895416f, 0.898315f, 0.901184f, 0.903992f, 0.906769f, + 0.909515f, 0.912201f, 0.914886f, 0.91748f, 0.920074f, 0.922607f, + 0.92514f, 0.927582f, 0.930023f, 0.932404f, 0.934753f, 0.937042f, + 0.939331f, 0.941559f, 0.943726f, 0.945862f, 0.947968f, 0.950043f, + 0.952057f, 0.954041f, 0.955994f, 0.957886f, 0.959747f, 0.961548f, + 0.963348f, 0.965088f, 0.966766f, 0.968414f, 0.970032f, 0.971588f, + 0.973114f, 0.974609f, 0.976074f, 0.977448f, 0.978821f, 0.980133f, + 0.981415f, 0.982666f, 0.983856f, 0.984985f, 0.986115f, 0.987183f, + 0.98819f, 0.989166f, 0.990112f, 0.990997f, 0.991852f, 0.992676f, + 0.993439f, 0.994171f, 0.994873f, 0.995514f, 0.996094f, 0.996643f, + 0.997162f, 0.99765f, 0.998077f, 0.998444f, 0.99881f, 0.999084f, + 0.999359f, 0.999573f, 0.999725f, 0.999878f, 0.999939f, 0.999969f, + 0.999969f, 0.999939f, 0.999878f, 0.999725f, 0.999573f, 0.999359f, + 0.999084f, 0.99881f, 0.998444f, 0.998077f, 0.99765f, 0.997162f, + 0.996643f, 0.996094f, 0.995514f, 0.994873f, 0.994171f, 0.993439f, + 0.992676f, 0.991852f, 0.990997f, 0.990112f, 0.989166f, 0.98819f, + 0.987183f, 0.986115f, 0.984985f, 0.983856f, 0.982666f, 0.981415f, + 0.980133f, 0.978821f, 0.977448f, 0.976074f, 0.974609f, 0.973114f, + 0.971588f, 0.970032f, 0.968414f, 0.966766f, 0.965088f, 0.963348f, + 0.961548f, 0.959747f, 0.957886f, 0.955994f, 0.954041f, 0.952057f, + 0.950043f, 0.947968f, 0.945862f, 0.943726f, 0.941559f, 0.939331f, + 0.937042f, 0.934753f, 0.932404f, 0.930023f, 0.927582f, 0.92514f, + 0.922607f, 0.920074f, 0.91748f, 0.914886f, 0.912201f, 0.909515f, + 0.906769f, 0.903992f, 0.901184f, 0.898315f, 0.895416f, 0.892487f, + 0.889526f, 0.886505f, 0.883453f, 0.880371f, 0.877258f, 0.874084f, + 0.87088f, 0.867645f, 0.86438f, 0.861084f, 0.857727f, 0.85434f, + 0.850922f, 0.847473f, 0.843964f, 0.840454f, 0.836884f, 0.833282f, + 0.829651f, 0.825989f, 0.822266f, 0.818512f, 0.814758f, 0.810944f, + 0.807098f, 0.803223f, 0.799286f, 0.795349f, 0.791351f, 0.787354f, + 0.783295f, 0.779205f, 0.775085f, 0.770935f, 0.766754f, 0.762512f, + 0.75827f, 0.753998f, 0.749664f, 0.745331f, 0.740936f, 0.736542f, + 0.732086f, 0.727631f, 0.723114f, 0.718567f, 0.71402f, 0.709412f, + 0.704803f, 0.700134f, 0.695435f, 0.690735f, 0.685974f, 0.681213f, + 0.676392f, 0.67157f, 0.666687f, 0.661804f, 0.656891f, 0.651947f, + 0.646942f, 0.641937f, 0.636932f, 0.631866f, 0.62677f, 0.621674f, + 0.616516f, 0.611359f, 0.606171f, 0.600952f, 0.595703f, 0.590424f, + 0.585144f, 0.579803f, 0.574463f, 0.569092f, 0.563721f, 0.558289f, + 0.552856f, 0.547394f, 0.541901f, 0.536377f, 0.530853f, 0.525299f, + 0.519714f, 0.514099f, 0.508484f, 0.502838f, 0.497162f, 0.491486f, + 0.485748f, 0.480042f, 0.474274f, 0.468506f, 0.462708f, 0.456909f, + 0.45108f, 0.445221f, 0.439362f, 0.433472f, 0.427551f, 0.421631f, + 0.41568f, 0.409729f, 0.403748f, 0.397736f, 0.391724f, 0.385712f, + 0.379669f, 0.373596f, 0.367523f, 0.36142f, 0.355316f, 0.349182f, + 0.343048f, 0.336884f, 0.330719f, 0.324524f, 0.318329f, 0.312134f, + 0.305908f, 0.299652f, 0.293427f, 0.28714f, 0.280884f, 0.274597f, + 0.26828f, 0.261993f, 0.255646f, 0.249329f, 0.242981f, 0.236633f, + 0.230255f, 0.223877f, 0.217499f, 0.211121f, 0.204712f, 0.198303f, + 0.191895f, 0.185455f, 0.179016f, 0.172577f, 0.166138f, 0.159668f, + 0.153198f, 0.146729f, 0.140259f, 0.133759f, 0.127289f, 0.120789f, + 0.114288f, 0.107788f, 0.101288f, 0.0947571f, 0.0882568f, 0.0817261f, + 0.0751953f, 0.0686646f, 0.0621338f, 0.055603f, 0.0490723f, 0.0425415f, + 0.0359802f, 0.0294495f, 0.0229187f, 0.0163574f, 0.00982666f, 0.00326538f +}; +const short subf_norm_groups[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 float gain_att[MAX_P_ATT] = +{ + 0.4794745f, 0.5910453f, 0.6647078f, 0.7245839f, 0.7598486f, 0.7912783f, 0.8165831f, 0.8396713f, + 0.8562786f, 0.8716393f, 0.8848335f, 0.8971617f, 0.9061614f, 0.9146075f, 0.9220175f, 0.9290045f, + 0.9344148f, 0.9395265f, 0.9440797f, 0.9484073f, 0.9518549f, 0.9551361f, 0.9581067f, 0.9609474f, + 0.9632704f, 0.9654923f, 0.9675346f, 0.9694900f, 0.9711209f, 0.9726879f, 0.9741332f, 0.9755263f, + 0.9767067f, 0.9778463f, 0.9789108f, 0.9799438f, 0.9808353f, 0.9816967f, 0.9825032f, 0.9832868f +}; + +const Word16 stab_trans_fx[10] = /* Q15 */ +{ + 16384, 11381, 7232, 4292, 2433, + 1341, 728, 391, 209, 112 +}; +const float stab_trans[L_STAB_TBL] = +{ + 0.500000f, 0.347332f, 0.220704f, 0.130976f, 0.074252f, + 0.040937f, 0.022211f, 0.011944f, 0.006392f, 0.003412f +}; + +const float env_stab_tp[2][2] = +{ + {0.999f, 0.5f}, + {0.001f, 0.5f} +}; + +const float att_step[NB_G] = { 4.0000000f, 2.0000000f, 1.3333333f, 1.0000000f}; + +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 float DDP[4] = { 3.0f, 0.0f, 1.0f, 2.0f }; + + +const short step_tcq[8][STATES] = { {0,4}, {0,4}, {1,5}, {1,5}, {2,6}, {2,6}, {3,7}, {3,7} }; +const short denc[8][STATES] = { {0,2}, {2,0}, {1,3}, {3,1}, {2,0}, {0,2}, {3,1}, {1,3} }; /* enc trellis */ +const short ddec[8][STATES] = { {0,2}, {1,3}, {2,0}, {3,1}, {2,0}, {3,1}, {0,2}, {1,3} }; /* dec trellis */ + + +const short step_LSB[STATES_LSB][2] = { {0,1}, {2,3}, {0,1}, {2,3} }; +const short denc_LSB[STATES_LSB][2] = { {0,3}, {2,1}, {3,0}, {1,2} }; +const short dqnt_LSB[STATES_LSB][4] = { {0,8,1,8}, {0,8,1,8}, {8,0,8,1}, {8,0,8,1} }; + +const short dstep_LSB[4][2] = { {0,2}, {0,2}, {1,3}, {1,3} }; +const short ddec_LSB[4][2] = { {0,3}, {3,0}, {2,1}, {1,2} }; + + +const short 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 */ + +/*------------------------------------------------------------------------------* + * PVQ tables + *------------------------------------------------------------------------------*/ + +const short fine_gain_bits[8] = {0, 0, 0, 1, 2, 2, 4, 5}; +const float finegain_1[2] = {-0.7448924f, 0.7718827f}; +const float finegain_2[4] = {-1.0847910f, -0.3616628f, 0.3668007f, 1.1455675f}; +const float finegain_3[8] = {-1.0000000f, -0.7142857f, -0.4285714f, -0.1428571f, 0.1428571f, 0.4285714f, 0.7142857f, 1.0000000f}; +const float finegain_4[16] = {-1.3234321f, -1.1164439f, -0.9153915f, -0.7248241f, -0.5453916f, -0.3807825f, -0.2259278f, -0.0836715f, 0.0576803f, 0.1999166f, 0.3715899f, 0.5541582f, 0.7598588f, 0.9764980f, 1.2082281f, 1.4567725f}; +const float finegain_5[32] = {-1.3099370f, -1.1532731f, -0.9939113f, -0.8627403f, -0.7693628f, -0.6901322f, -0.6188556f, -0.5438313f, -0.4899869f, -0.4145289f, -0.3440915f, -0.2936875f, -0.2241453f, -0.1636186f, -0.1052746f, -0.0292431f, 0.0273763f, 0.0848355f, 0.1443042f, 0.2095194f, 0.2794882f, 0.3366661f, 0.4131591f, 0.4740591f, 0.5545165f, 0.6196313f, 0.6719442f, 0.7650533f, 0.9012053f, 1.0432675f, 1.2264170f, 1.5085750f}; +const float* const finegain[5] = { finegain_1, finegain_2, finegain_3, finegain_4, finegain_5 }; + +/* getk(16,8)+ maxqKIind=40 --> KMAX=127 needs support , 32bit- saturates at dim=6 + getK(21,9)+ maxqKInd=64 --> KMAX=512, needs support , 32bit saturates at dim=5 + getK(TBD,TBD)+ maxqKInd=TBD --> KMAX=1024, needs support , 32bit saturates at dim~=4 + getK(TBD,TBD)+ maxqKInd=TBD --> KMAX=32767, needs support, 32bit saturates at dim =3 +*/ +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 short dsHighDiracsTab[PVQ_MAX_BAND_SIZE - DS_INDEX_LINEAR_END ] = +{ + 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 short lim_neg_inv_tbl_fx[MAX_SPLITS + 1 ] = +{ + /* 1 = optimized inv_tbl_fx constant for div by 1, Q15 */ + /* 2-10 = negated inv_tbl_fx Q15*/ + 0, + -32768, -16384, -10923, -8192, -6554, + -5462, -4681, -4096, -3641, -3277 +}; + +const short fg_inv_tbl_fx [HQ_MAX_BAND_LEN/8 + 1 ] = +{ + /* i/8 , slice of inv_tbl_fx , Q15 */ + 0, + 4096, 2048, 1366, 1024, 820, 683, + 586, 512, 456, 410, 373, 342 +} ; + + +const unsigned int exactdivodd[ODD_DIV_SIZE] = +{ + /* exactdivodd[0]=1/1,exactdivodd[1]=1/3 , exactdivodd[n]=1/(2*n+1), 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 short gain_cb_size[MAX_GAIN_BITS] = {2, 4, 8, 16, 32}; + +const short inner_frame_tbl[4] = {L_FRAME8k, L_FRAME16k, L_FRAME32k, L_FRAME48k}; /* corresponds to NB, WB, SWB, FB */ + +/*------------------------------------------------------------------------------* + * LR-MDCT tables + *------------------------------------------------------------------------------*/ + +/* subband width tables */ + +/* NB short win: 7200/8000/9600, 13200/16400/24400 */ +const short band_width_40_4_6_0_0_0[4] = { 6, 8, 11, 15 }; +const short band_width_40_5_6_0_0_0[5] = { 6, 7, 7, 9, 11 }; + +/* NB long win: 7200, 8000, 9600, 13200, 16400 */ +const short band_width_160_13_6_2_0_0[13] = { 6, 6, 6, 6, 7, 8, 9, 10, 13, 15, 19, 24, 31 }; +const short band_width_160_14_6_3_0_0[14] = { 6, 6, 6, 6, 6, 7, 8, 9, 10, 12, 15, 18, 22, 29 }; +const short 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 }; +const short 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 */ +const short band_width_80_7_6_0_0_0[7] = { 6, 7, 8, 10, 12, 16, 21 }; + +/* WB long win: 13200, 16400 */ +const short 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 }; +const short 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: 13200, 16400 */ +const short band_width_142_8_8_0_0_0[8] = {7,8,10,11,15,21,29,41}; +const short band_width_160_8_8_0_0_0[8] = { 8, 9, 11,13,17,23,32,47}; + +/* SWB long win: 13200, 16400 */ +const short 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}; +const short 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 xcore_config_8kHz_007200bps_long = { 13, L_FRAME8k, band_width_160_13_6_2_0_0, 536870912L, 24576, 13107, 2, 2, 0, 0.0f, 0.40f, 0.13f, 1.2f, 0.32f }; +const Xcore_Config xcore_config_8kHz_008000bps_long = { 14, L_FRAME8k, band_width_160_14_6_3_0_0, 536870912L, 24576, 13107, 2, 2, 0, 0.0f, 0.40f, 0.13f, 1.2f, 0.32f }; +const Xcore_Config xcore_config_8kHz_013200bps_long = { 17, L_FRAME8k, band_width_160_17_6_3_0_0, 429496730L, 24576, 13107, 2, 4, 2, 12.0f, 0.40f, 0.13f, 1.2f, 0.32f }; +const Xcore_Config xcore_config_8kHz_016400bps_long = { 18, L_FRAME8k, band_width_160_18_6_4_0_0, 322122547L, 24576, 13107, 2, 2, 0, 0.0f, 0.40f, 0.13f, 1.2f, 0.32f }; + +const Xcore_Config xcore_config_8kHz_007200bps_short = { 4, L_FRAME8k / NUM_TIME_SWITCHING_BLOCKS, band_width_40_4_6_0_0_0, 966367642L, 24576, 13107, 2, 2, 0, 0.0f, 0.30f, 0.09f, 1.2f, 0.32f }; +const Xcore_Config xcore_config_8kHz_008000bps_short = { 4, L_FRAME8k / NUM_TIME_SWITCHING_BLOCKS, band_width_40_4_6_0_0_0, 1181116006L, 24576, 13107, 2, 4, 0, 0.0f, 0.30f, 0.09f, 1.2f, 0.32f }; +const Xcore_Config xcore_config_8kHz_013200bps_short = { 5, L_FRAME8k / NUM_TIME_SWITCHING_BLOCKS, band_width_40_5_6_0_0_0, 751619276L, 24576, 11469, 2, 4, 0, 0.0f, 0.70f, 0.11f, 1.2f, 0.32f }; +const Xcore_Config xcore_config_8kHz_016400bps_short = { 5, L_FRAME8k / NUM_TIME_SWITCHING_BLOCKS, band_width_40_5_6_0_0_0, 536870912L, 24576, 11469, 2, 6, 0, 0.0f, 0.90f, 0.11f, 1.2f, 0.32f }; + +/* LR-MDCT: WB configuration tables */ +const Xcore_Config xcore_config_16kHz_013200bps_long = { 18, L_FRAME16k, band_width_320_18_6_3_0_0, 429496730L, 24576, 13106, 2, 6, 3, 12.0f, 0.40f, 0.12f, 1.1f, 0.32f }; +const Xcore_Config xcore_config_16kHz_016400bps_long = { 20, L_FRAME16k, band_width_320_20_6_3_0_0, 429496730L, 24576, 13106, 2, 6, 3, 12.0f, 0.40f, 0.12f, 1.2f, 0.32f }; + +const Xcore_Config xcore_config_16kHz_013200bps_short = { 7, L_FRAME16k / NUM_TIME_SWITCHING_BLOCKS, band_width_80_7_6_0_0_0, 966367642L, 24576, 9830, 2, 4, 0, 0.0f, 0.30f, 0.13f, 1.1f, 0.32f }; +const Xcore_Config xcore_config_16kHz_016400bps_short = { 7, L_FRAME16k / NUM_TIME_SWITCHING_BLOCKS, band_width_80_7_6_0_0_0, 966367642L, 24576, 11468, 2, 8, 0, 0.0f, 0.30f, 0.13f, 1.2f, 0.32f }; + +/* LR-MDCT: SWB configuration tables */ +const Xcore_Config xcore_config_32kHz_013200bps_long = { 22, 568, band_width_568_22_6_2_0_0, 322122547L, 24576, 6554, 2, 4, 5, 14.0f, 0.40f, 0.13f, 1.2f, 0.26f }; +const Xcore_Config xcore_config_32kHz_016400bps_long = { 24, 640, band_width_640_24_6_4_0_0, 322122547L, 24576, 8192, 2, 4, 5, 14.0f, 0.40f, 0.13f, 1.2f, 0.26f }; +const Xcore_Config xcore_config_32kHz_013200bps_short = { 8, 568 / NUM_TIME_SWITCHING_BLOCKS, band_width_142_8_8_0_0_0, 1610612736L, 24576, 13107, 2, 4, 0, 0.0f, 0.50f, 0.11f, 1.2f, 0.48f }; +const Xcore_Config xcore_config_32kHz_016400bps_short = { 8, 640 / NUM_TIME_SWITCHING_BLOCKS, band_width_160_8_8_0_0_0, 644245094L, 24576, 8192, 2, 4, 0, 0.0f, 0.30f, 0.13f, 1.2f, 0.32f }; + +/* bandwidths */ +const short 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 short 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 +}; + + +/*------------------------------------------------------------------------------* + * GSC tables + *------------------------------------------------------------------------------*/ + +const short gsc_sfm_start[MBANDS_GN] = {0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240}; + +const short gsc_sfm_end[MBANDS_GN] = {16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 256}; + +const short gsc_sfm_size[MBANDS_GN] = {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; + +const float sm_table[] = +{ + 1.0f, 0.9804f, 0.9607f, 0.9411f, 0.9215f, 0.902f, 0.8825f, 0.863f, + 0.8436f, 0.8242f, 0.8049f, 0.7857f, 0.7666f, 0.7475f, 0.7286f, 0.7097f, 0.691f, 0.6724f, + 0.6539f, 0.6355f, 0.6173f, 0.5993f, 0.5813f, 0.5636f, 0.546f, 0.5286f, 0.5114f, 0.4943f, + 0.4775f, 0.4609f, 0.4444f, 0.4282f, 0.4122f, 0.3964f, 0.3809f, 0.3656f, 0.3506f, 0.3357f, + 0.3212f, 0.3069f, 0.2929f, 0.2791f, 0.2657f, 0.2525f, 0.2396f, 0.227f, 0.2147f, 0.2027f, + 0.191f, 0.1796f, 0.1685f, 0.1578f, 0.1474f, 0.1373f, 0.1275f, 0.1181f, 0.109f, 0.1003f, + 0.0919f, 0.0838f, 0.0761f, 0.0688f, 0.0618f, 0.0552f, 0.0489f, 0.0431f, 0.0375f, 0.0324f, + 0.0276f, 0.0232f, 0.0192f, 0.0156f, 0.0123f, 0.0094f, 0.0069f, 0.0048f, 0.0031f, 0.0017f, + 0.0008f, 0.0002f +}; + +const short 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*/ +}; + +const float mfreq_loc[] = { 175.0f, 375.0f, 775.0f, 1175.0f, 1575.0f, 1975.0f, 2375.0f, 2775.0f, 3175.0f, 3575.0f, 3975.0f, + 4375.0f, 4775.0f, 5175.0f, 5575.0f, 6375.0f, 7175.0f, 7975.0f + }; +const short mfreq_bindiv_loc[] = { 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 32, 32, 32 }; +const float mean_gp[] = { 0.5853f }; + +const float dic_gp[] = +{ + -0.5847f, + -0.4695f, + -0.3897f, + -0.2731f, + -0.1986f, + -0.1244f, + -0.0492f, + -0.005f, + 0.0631f, + 0.1379f, + 0.211f, + 0.2859f, + 0.3229f, + 0.3994f, + 0.5217f, + 0.6135f, + -0.5471f, + -0.5089f, + -0.4285f, + -0.3512f, + -0.3124f, + -0.235f, + -0.162f, + -0.0872f, + 0.0249f, + 0.1013f, + 0.1741f, + 0.2485f, + 0.361f, + 0.4376f, + 0.4776f, + 0.5645f +}; + +const float Gain_meanNB[] = { 2.4052f }; + +const float Gain_mean_dicNB[] = +{ + -0.3197f, + -0.2272f, + -0.1386f, + -0.0966f, + -0.0132f, + 0.1970f, + 0.2865f, + 0.3743f, + 0.4640f, + 0.5108f, + 0.5581f, + 0.6086f, + 0.6588f, + 0.7642f, + 0.7101f, + 0.0698f, + -0.1827f, + 0.2418f, + 0.1540f, + -0.2733f, + -0.4144f, + -0.5162f, + -0.6806f, + -1.3182f, + -2.4026f, + -0.4643f, + -0.7983f, + -1.9470f, + -1.8160f, + -1.6910f, + -1.7558f, + -0.5677f, + -0.3673f, + -0.6224f, + -0.7379f, + -0.8624f, + -0.9321f, + -1.0098f, + -1.1600f, + -1.2380f, + -1.4052f, + -1.4876f, + -2.1967f, + -1.5599f, + -2.1399f, + -2.3041f, + 0.8225f, + 0.9564f, + 0.8835f, + 1.1436f, + -2.0176f, + 1.0387f, + -1.0822f, + -1.6264f, + -2.2534f, + -1.8746f, + 1.4304f, + 0.0288f, + 0.1116f, + -0.0553f, + 0.4192f, + 0.3303f, + -2.0750f, + -2.3558f, +}; + +const float Mean_dic_NB[] = +{ + -0.1084f, + -0.0243f, + -0.0292f, + -0.0091f, + 0.0061f, + 0.0171f, + 0.0362f, + 0.0153f, + 0.0416f, + 0.0558f, +}; + +const float Gain_dic1_NB[] = +{ + -0.1479f, -0.0224f, 0.0013f, + -0.4797f, 0.0718f, 0.1627f, + -0.1073f, 0.0291f, 0.1613f, + -0.0258f, 0.0652f, 0.0264f, + -0.2961f, 0.0842f, -0.0332f, + -0.3053f, 0.1508f, 0.1381f, + -0.4650f, -0.1832f, 0.1581f, + -0.2546f, -0.0879f, -0.1215f, + -0.0043f, -0.0785f, 0.0235f, + 0.0816f, 0.0283f, -0.0604f, + -0.4709f, 0.1612f, 0.0056f, + -0.4504f, 0.2876f, 0.1183f, + -0.0440f, 0.2040f, 0.0408f, + -0.4619f, -0.2252f, -0.0783f, + 0.1016f, -0.1067f, -0.0839f, + 0.1452f, -0.1337f, 0.0386f, + -0.0648f, -0.1970f, -0.0826f, + -0.2599f, -0.2477f, -0.0048f, + -0.1528f, 0.1452f, -0.0814f, + -0.1389f, 0.2661f, 0.1590f, + 0.0066f, 0.1432f, -0.0809f, + -0.0450f, -0.0207f, -0.1229f, + -0.4643f, -0.4412f, 0.0796f, + -0.4543f, -0.0387f, -0.2415f, + -0.1626f, 0.0349f, -0.2839f, + -0.4194f, 0.2517f, -0.1816f, + 0.2068f, 0.0736f, -0.0144f, + 0.1757f, -0.2445f, -0.0527f, + 0.3370f, -0.2115f, -0.2366f, + 0.1961f, -0.0010f, -0.1484f, + 0.0568f, 0.0997f, -0.2436f, + 0.3561f, 0.0213f, 0.0641f, + 0.0842f, -0.1502f, -0.2506f, + 0.2140f, -0.0362f, -0.0016f, + 0.0165f, -0.2625f, 0.0660f, + 0.1958f, 0.0804f, 0.1159f, + -0.4695f, -0.0308f, -0.0092f, + 0.3114f, -0.1023f, -0.0851f, + 0.0979f, 0.2260f, 0.1403f, + 0.2066f, -0.0569f, 0.1335f, + 0.1691f, -0.4590f, 0.0869f, + -0.0883f, -0.4109f, -0.0535f, + 0.0565f, -0.0827f, 0.1460f, + 0.2996f, -0.1503f, 0.0652f, + 0.2724f, 0.0221f, -0.3213f, + -0.1344f, -0.1588f, 0.1293f, + 0.1083f, 0.0079f, 0.0442f, + -0.0937f, 0.2946f, -0.1892f, + -0.2424f, 0.2840f, 0.0099f, + 0.1915f, -0.2486f, 0.1314f, + 0.1551f, 0.1553f, -0.1036f, + 0.3353f, -0.3337f, 0.0364f, + 0.3521f, 0.0979f, -0.1083f, + 0.2671f, 0.2169f, 0.0300f, + 0.2135f, 0.2717f, -0.2642f, + -0.1578f, -0.2715f, -0.2692f, + 0.1316f, -0.3985f, -0.1668f, + 0.0981f, 0.1393f, 0.0241f, + -0.4342f, -0.4417f, -0.2072f, + -0.1788f, -0.4128f, 0.1708f, + -0.1655f, 0.1284f, 0.0670f, + 0.0782f, 0.2996f, -0.0288f, + -0.2984f, -0.0440f, 0.1108f, + 0.0423f, 0.0853f, 0.1295f, +}; + +const float Gain_dic2_NB[] = +{ + 0.0069f, 0.0000f, -0.0160f, + -0.1361f, 0.0009f, 0.0504f, + 0.0686f, -0.1568f, 0.0088f, + -0.1019f, 0.0198f, -0.1206f, + -0.0927f, 0.1671f, 0.1099f, + 0.1272f, -0.3770f, 0.0631f, + -0.2733f, 0.1496f, -0.2809f, + 0.1256f, 0.0058f, 0.1945f, + 0.0714f, -0.0204f, -0.1284f, + 0.0723f, 0.1021f, -0.0563f, + -0.1024f, -0.0165f, 0.2383f, + 0.0004f, -0.0753f, 0.0971f, + -0.1114f, -0.2459f, 0.0641f, + -0.2982f, -0.0906f, 0.1089f, + -0.0539f, -0.0952f, -0.0441f, + -0.2955f, 0.1435f, 0.1833f, + -0.2669f, 0.1288f, -0.0425f, + 0.1440f, 0.0907f, -0.3104f, + -0.0192f, -0.0612f, -0.3029f, + -0.2480f, -0.1188f, -0.1250f, + 0.1324f, 0.1419f, 0.0826f, + -0.0648f, 0.1114f, -0.0257f, + 0.1196f, -0.0173f, 0.0218f, + 0.0103f, 0.0574f, 0.0926f, + 0.0076f, 0.2916f, -0.0493f, + 0.0422f, -0.2048f, 0.2074f, + -0.0113f, 0.1221f, -0.1958f, + 0.0371f, 0.2279f, 0.2620f, + 0.2392f, 0.0843f, -0.0641f, + 0.1969f, -0.1415f, -0.1273f, + -0.0055f, -0.2421f, -0.1429f, + 0.2138f, -0.1407f, 0.1003f, +}; + +const float Gain_dic3_NB[] = +{ + -0.0039f, 0.0159f, -0.0553f, 0.0027f, + -0.0523f, 0.1349f, 0.0894f, 0.0451f, + 0.0334f, -0.0825f, -0.0732f, -0.1526f, + -0.0298f, 0.0199f, 0.1314f, -0.1946f, + 0.0391f, 0.0695f, -0.2694f, 0.0085f, + -0.1451f, 0.0762f, -0.0925f, -0.1033f, + 0.0412f, -0.1568f, -0.0964f, 0.0887f, + 0.0856f, -0.2846f, 0.1538f, -0.0637f, + -0.2905f, 0.0529f, 0.1016f, 0.0456f, + -0.1409f, 0.0596f, -0.1553f, 0.2095f, + 0.1415f, 0.1177f, -0.0536f, 0.1551f, + 0.1159f, -0.0458f, 0.0909f, 0.0066f, + -0.0159f, -0.0901f, 0.1231f, 0.2221f, + -0.1032f, -0.1080f, 0.0302f, -0.0098f, + 0.1173f, 0.1404f, -0.0101f, -0.1590f, + 0.1665f, 0.1661f, 0.2222f, 0.1193f, +}; + +const float Gain_dic2_NBHR[] = +{ + 0.0070f, 0.0001f, -0.0229f, + -0.1476f, -0.0493f, -0.0424f, + 0.0791f, -0.0927f, -0.0399f, + -0.0308f, -0.0735f, -0.0748f, + -0.0704f, 0.0302f, 0.0273f, + -0.0211f, 0.1279f, -0.0281f, + 0.0572f, 0.0045f, -0.1133f, + -0.0134f, -0.0686f, 0.0436f, + 0.0393f, 0.1088f, 0.1543f, + 0.0893f, -0.0201f, 0.0237f, + 0.0556f, -0.2804f, 0.0660f, + 0.0715f, 0.0698f, -0.0348f, + -0.0301f, -0.0085f, -0.2187f, + -0.1319f, -0.1649f, 0.0427f, + 0.0807f, -0.1180f, -0.1678f, + -0.1901f, 0.0498f, -0.1630f, + -0.1202f, 0.1876f, -0.1245f, + -0.2966f, -0.1514f, -0.1179f, + 0.1663f, -0.0185f, -0.0722f, + -0.1638f, 0.0966f, -0.0110f, + -0.1854f, 0.0728f, 0.1377f, + -0.0693f, 0.1437f, 0.0784f, + -0.3336f, -0.1445f, 0.1210f, + -0.1093f, -0.1429f, -0.1739f, + 0.0029f, -0.1845f, -0.0220f, + 0.1253f, 0.0407f, -0.2262f, + -0.2861f, 0.2587f, -0.2925f, + -0.1164f, 0.1825f, 0.2457f, + 0.0103f, 0.0251f, 0.3118f, + -0.2296f, 0.2562f, 0.0336f, + -0.2257f, -0.0035f, -0.3586f, + 0.1669f, 0.1657f, -0.3857f, + 0.1019f, -0.0912f, -0.3838f, + 0.1482f, 0.0660f, 0.0626f, + 0.1384f, 0.1899f, 0.2057f, + 0.3452f, -0.0544f, -0.1323f, + 0.0236f, 0.0488f, 0.0614f, + 0.0541f, 0.2623f, -0.1335f, + -0.1744f, -0.0697f, 0.2553f, + 0.0943f, -0.1671f, 0.2403f, + 0.0826f, 0.1646f, 0.0282f, + -0.0668f, 0.0418f, -0.0898f, + 0.1419f, -0.4567f, 0.0836f, + 0.0229f, 0.1079f, -0.1457f, + -0.0715f, -0.2943f, 0.2078f, + -0.0311f, 0.1224f, -0.3045f, + 0.0428f, 0.4151f, 0.3314f, + -0.0059f, 0.2989f, 0.0695f, + 0.1725f, -0.2325f, -0.0715f, + 0.1631f, 0.1202f, -0.0993f, + 0.2841f, 0.1833f, 0.0490f, + 0.0929f, -0.1452f, 0.0702f, + -0.3833f, 0.1174f, -0.1297f, + -0.1458f, -0.0391f, 0.0797f, + -0.1412f, -0.3200f, -0.0097f, + -0.0287f, -0.1278f, 0.1406f, + -0.3695f, 0.1286f, 0.1848f, + -0.0450f, 0.0097f, 0.1487f, + -0.2966f, 0.0239f, 0.0167f, + -0.0159f, -0.3233f, -0.2040f, + 0.2004f, -0.0729f, 0.0498f, + 0.1943f, 0.0051f, 0.2050f, + 0.0757f, -0.0325f, 0.1324f, + 0.2545f, -0.2377f, 0.1312f, +}; + +const float Gain_dic3_NBHR[] = +{ + 0.0715f, 0.0018f, -0.0493f, -0.0232f, + 0.1305f, 0.0268f, 0.1323f, -0.1251f, + -0.1410f, 0.0158f, -0.1367f, -0.0843f, + 0.0502f, 0.0811f, 0.0024f, -0.1302f, + -0.0186f, 0.0869f, -0.0034f, 0.0203f, + 0.0363f, -0.0908f, -0.0475f, -0.1196f, + -0.1168f, -0.0588f, -0.0135f, 0.0275f, + -0.0716f, -0.1147f, -0.1479f, 0.0151f, + 0.1947f, -0.3535f, 0.1525f, -0.2753f, + 0.0423f, 0.1132f, -0.4115f, -0.0120f, + -0.0956f, -0.0720f, -0.0388f, -0.1134f, + -0.1746f, 0.1026f, -0.0357f, -0.2402f, + -0.0087f, 0.0068f, -0.1182f, 0.0290f, + 0.1152f, 0.0665f, -0.1780f, -0.0283f, + 0.0167f, -0.0212f, -0.1534f, -0.1048f, + 0.1047f, -0.2240f, -0.0385f, -0.0466f, + -0.1331f, 0.0561f, -0.1063f, 0.0637f, + -0.0312f, 0.0037f, -0.1930f, 0.1494f, + 0.0655f, -0.0945f, -0.3072f, 0.0248f, + 0.0922f, 0.0580f, 0.0735f, 0.0007f, + -0.1207f, 0.0363f, 0.0319f, -0.0303f, + 0.1547f, -0.0751f, 0.0242f, 0.0058f, + 0.1397f, 0.1735f, 0.1842f, -0.2776f, + -0.2707f, 0.0977f, 0.2668f, 0.0901f, + -0.2028f, -0.1033f, 0.3865f, 0.2659f, + -0.0203f, 0.0380f, -0.0256f, 0.2631f, + -0.2270f, 0.1163f, 0.0372f, 0.0927f, + 0.1894f, 0.2838f, 0.1924f, -0.0104f, + 0.0680f, 0.0122f, 0.0997f, 0.1458f, + 0.1162f, 0.1180f, 0.0179f, 0.1828f, + 0.2204f, 0.1676f, 0.0196f, -0.1003f, + 0.0476f, -0.1876f, 0.0683f, 0.0840f, + -0.0641f, -0.2440f, -0.0112f, -0.0693f, + -0.0161f, 0.0641f, 0.0769f, -0.3024f, + 0.1061f, 0.1410f, -0.0572f, -0.2854f, + 0.0487f, -0.4075f, 0.0459f, 0.0278f, + -0.0140f, 0.1022f, -0.1243f, -0.1545f, + 0.0240f, -0.0290f, 0.0314f, -0.1991f, + -0.0383f, -0.0890f, -0.0607f, 0.1311f, + 0.0164f, -0.1524f, 0.0296f, 0.2814f, + 0.3526f, 0.0346f, -0.1425f, 0.0093f, + 0.2652f, -0.0205f, 0.0395f, 0.2426f, + 0.0958f, -0.0937f, -0.0302f, 0.1301f, + 0.0615f, 0.0446f, -0.2835f, -0.2160f, + -0.1053f, -0.2025f, 0.0248f, 0.1055f, + -0.1728f, 0.2409f, -0.2493f, -0.1572f, + -0.0157f, 0.0293f, -0.4112f, 0.2406f, + 0.0512f, -0.1206f, -0.2211f, 0.3179f, + 0.0121f, -0.0455f, 0.0431f, 0.0451f, + -0.0626f, 0.2130f, -0.2451f, 0.0946f, + 0.1376f, -0.0196f, -0.1657f, 0.1258f, + -0.1862f, -0.0097f, -0.2866f, 0.0556f, + -0.2513f, 0.0485f, -0.0144f, -0.0726f, + 0.0073f, -0.0115f, 0.0484f, -0.0645f, + -0.0966f, -0.3504f, 0.2229f, -0.2486f, + -0.0344f, 0.2348f, 0.0088f, 0.1117f, + 0.0088f, -0.0947f, 0.1894f, -0.2441f, + -0.0181f, 0.1194f, 0.2775f, 0.0341f, + -0.2369f, -0.1871f, 0.1625f, -0.0285f, + 0.0220f, 0.1462f, 0.4066f, 0.3429f, + -0.0763f, -0.1673f, -0.1866f, -0.1501f, + 0.1374f, -0.1128f, -0.1530f, -0.1874f, + 0.1933f, 0.1366f, -0.3527f, 0.1357f, + -0.1419f, 0.1760f, -0.1364f, 0.2775f, + -0.1707f, -0.0667f, 0.0668f, -0.2065f, + 0.2295f, -0.1684f, 0.1824f, -0.0617f, + -0.0431f, -0.1322f, 0.3309f, -0.0529f, + -0.1430f, 0.1042f, 0.2921f, -0.2119f, + 0.0358f, 0.1299f, -0.1342f, 0.0989f, + 0.0631f, 0.1654f, -0.0598f, -0.0405f, + 0.1884f, 0.2592f, -0.0807f, 0.1176f, + 0.0948f, 0.4565f, -0.1406f, 0.3869f, + 0.1129f, 0.2113f, 0.1108f, 0.2958f, + 0.1392f, 0.1289f, -0.1663f, 0.3001f, + -0.0943f, 0.1483f, 0.1463f, 0.2112f, + -0.0376f, -0.0049f, -0.0515f, -0.0564f, + 0.0234f, 0.1798f, 0.0996f, -0.0633f, + 0.1864f, -0.3743f, 0.2672f, 0.0607f, + 0.1720f, -0.2764f, 0.4289f, -0.2641f, + 0.0758f, -0.1174f, 0.0803f, -0.0964f, + 0.0473f, -0.1906f, 0.0144f, -0.2328f, + -0.2278f, -0.2336f, -0.0060f, 0.4555f, + -0.2079f, -0.0547f, -0.1176f, 0.2006f, + -0.3511f, 0.1197f, 0.0539f, 0.3127f, + 0.0956f, 0.1653f, 0.1317f, 0.0846f, + 0.2158f, -0.1499f, 0.4502f, 0.1656f, + -0.1886f, 0.1181f, -0.2266f, 0.6047f, + -0.0670f, -0.1125f, 0.0923f, -0.0642f, + -0.0690f, -0.0762f, 0.1423f, 0.0834f, + 0.1107f, -0.3762f, 0.0924f, 0.3090f, + 0.1900f, 0.2673f, 0.3150f, 0.2012f, + -0.2339f, -0.1082f, -0.0508f, -0.0173f, + 0.2405f, -0.2444f, -0.0301f, 0.1156f, + 0.0136f, -0.2449f, -0.1253f, 0.1158f, + -0.0633f, 0.3504f, 0.2381f, 0.0768f, + -0.0143f, -0.0412f, 0.1767f, 0.2347f, + -0.0512f, 0.2515f, 0.0832f, -0.2386f, + 0.2573f, 0.7121f, -0.0018f, -0.2141f, + -0.2079f, -0.0557f, 0.0805f, 0.1525f, + 0.0022f, -0.1280f, -0.0237f, -0.0035f, + 0.0038f, -0.0122f, 0.1163f, 0.5874f, + 0.0644f, -0.0581f, 0.1875f, 0.0136f, + 0.0457f, 0.0263f, -0.0413f, 0.1088f, + 0.1644f, 0.0582f, 0.2423f, 0.1638f, + -0.0532f, 0.0697f, 0.1184f, 0.0443f, + 0.1633f, -0.1285f, 0.1561f, 0.1394f, + 0.1586f, 0.0050f, -0.0458f, -0.1260f, + 0.2517f, 0.0403f, 0.1285f, 0.0333f, + -0.0813f, 0.0750f, 0.0248f, -0.1389f, + -0.0383f, 0.0755f, -0.2281f, -0.0295f, + -0.0820f, 0.0345f, 0.0096f, 0.1308f, + 0.1616f, 0.0888f, -0.0324f, 0.0543f, + -0.3135f, 0.1556f, -0.1552f, 0.0187f, + 0.3031f, 0.2066f, 0.1139f, 0.1557f, + 0.2055f, 0.0801f, 0.3248f, -0.0781f, + 0.0372f, -0.2464f, 0.1343f, -0.0524f, + -0.1885f, 0.0032f, 0.1451f, -0.0297f, + 0.0820f, -0.1000f, -0.1336f, -0.0005f, + 0.2121f, -0.0259f, 0.0784f, -0.2882f, + 0.1259f, 0.3045f, -0.2021f, -0.1408f, + -0.1636f, 0.2132f, 0.0897f, -0.0322f, + -0.1013f, 0.1537f, -0.0700f, -0.0400f, + -0.0256f, 0.0338f, 0.1603f, -0.1077f, + -0.0390f, -0.2649f, 0.2294f, 0.1718f, + -0.0313f, -0.0166f, -0.0901f, -0.2568f, + -0.3501f, 0.1449f, 0.1334f, -0.1623f, + -0.4515f, 0.0182f, 0.0428f, 0.0424f, + -0.3133f, 0.1780f, -0.3883f, 0.2519f, +}; + +const float YG_mean16[] = +{ + -0.0968f, + -0.0468f, + -0.0409f, + -0.0332f, + -0.0147f, + -0.0042f, + 0.0111f, + 0.0096f, + 0.0293f, + 0.0198f, + 0.0219f, + 0.0164f, + 0.0358f, + 0.0083f, + 0.0398f, + 0.0448f, +}; + +const float YG_dicMR_1[] = +{ + -0.4588f, 0.2016f, 0.1315f, -0.0513f, + -0.0294f, 0.0652f, -0.0335f, -0.0347f, + -0.1948f, -0.1154f, 0.1059f, 0.0594f, + 0.0724f, -0.2188f, 0.0901f, 0.0750f, + -0.4597f, -0.3254f, 0.1015f, 0.1244f, + -0.4774f, -0.1611f, -0.1151f, 0.0548f, + -0.2210f, -0.1962f, -0.1262f, 0.1056f, + -0.2346f, 0.0050f, -0.0631f, -0.0547f, + 0.0510f, 0.2386f, -0.0519f, -0.0042f, + 0.1308f, -0.0595f, 0.0388f, 0.0238f, + -0.0647f, 0.1891f, 0.1005f, -0.0799f, + 0.0823f, -0.0955f, -0.0579f, -0.1152f, + -0.4790f, -0.4482f, -0.1689f, 0.1149f, + 0.1525f, 0.0422f, -0.1130f, -0.0037f, + -0.2356f, 0.0643f, 0.0151f, 0.1466f, + -0.1910f, 0.2170f, -0.1056f, 0.0514f, + -0.4373f, 0.2081f, -0.1106f, -0.1895f, + -0.0445f, -0.0433f, -0.2631f, 0.0195f, + -0.0889f, 0.0855f, 0.0683f, 0.0715f, + -0.2201f, 0.2731f, 0.0719f, -0.2914f, + 0.0038f, 0.1073f, -0.0835f, 0.1121f, + -0.4455f, -0.3868f, -0.3375f, -0.1949f, + 0.1764f, 0.0140f, -0.3015f, -0.1613f, + 0.2167f, -0.3999f, 0.0677f, 0.0572f, + 0.0831f, 0.0842f, 0.0345f, -0.1490f, + 0.3124f, -0.0055f, 0.0042f, 0.0352f, + -0.1561f, -0.2081f, -0.1269f, -0.1350f, + 0.2519f, 0.2059f, 0.0364f, 0.1061f, + 0.1418f, 0.1911f, 0.1266f, -0.0479f, + 0.1115f, 0.2308f, 0.1216f, -0.3146f, + -0.4631f, -0.0101f, 0.1038f, 0.1255f, + 0.1921f, 0.0393f, 0.1236f, 0.0941f, + -0.1365f, 0.2635f, 0.0780f, 0.1258f, + 0.1220f, 0.0830f, 0.0146f, 0.0258f, + 0.0614f, -0.2434f, -0.2840f, -0.2344f, + 0.0638f, -0.3144f, -0.1540f, 0.0817f, + 0.3029f, -0.1514f, -0.0944f, -0.1617f, + 0.0407f, 0.0474f, 0.1163f, 0.0163f, + 0.2027f, -0.0636f, 0.1049f, -0.2933f, + -0.1169f, -0.0300f, 0.0174f, -0.2837f, + 0.0550f, -0.3618f, 0.0322f, -0.1958f, + 0.1659f, 0.1862f, -0.2466f, 0.1048f, + 0.0488f, -0.0304f, 0.0638f, 0.1441f, + 0.1882f, -0.1807f, -0.0447f, 0.0559f, + -0.4542f, -0.0850f, 0.0678f, -0.1340f, + -0.4317f, 0.2362f, 0.0687f, 0.1451f, + -0.4217f, -0.4143f, 0.0213f, -0.1866f, + 0.2853f, 0.1540f, -0.0279f, -0.1151f, + -0.3994f, -0.0247f, -0.3232f, -0.0221f, + 0.2004f, -0.1819f, 0.1119f, -0.0644f, + 0.2475f, -0.1406f, 0.0951f, 0.1147f, + 0.2541f, -0.1261f, -0.2486f, 0.0897f, + 0.2016f, 0.0042f, 0.1040f, -0.0797f, + -0.1140f, -0.4007f, 0.0491f, 0.0794f, + -0.4653f, 0.1045f, -0.0824f, 0.0541f, + -0.2492f, 0.1539f, 0.1023f, -0.0183f, + -0.0211f, -0.0926f, -0.0495f, 0.0572f, + 0.1609f, 0.1286f, -0.1199f, -0.3680f, + -0.1378f, -0.4261f, -0.2389f, -0.0422f, + -0.4306f, -0.1056f, -0.1813f, -0.2662f, + 0.0590f, 0.1732f, 0.0657f, 0.1213f, + 0.1749f, 0.0180f, -0.0507f, 0.1508f, + -0.0724f, 0.1574f, -0.2109f, -0.1965f, + -0.0112f, -0.0797f, 0.1006f, -0.0723f, +}; + +const float YG_dicMR_2[] = +{ + 0.0228f, 0.0529f, -0.0298f, 0.0091f, + -0.0032f, -0.0203f, 0.0257f, -0.1199f, + -0.0972f, -0.1446f, 0.0973f, -0.0390f, + 0.1325f, -0.0197f, -0.1147f, 0.0997f, + 0.0963f, -0.1539f, -0.0230f, -0.0630f, + -0.1623f, 0.0325f, -0.0331f, -0.0305f, + 0.0970f, -0.0857f, 0.1538f, -0.0361f, + -0.2846f, 0.0992f, -0.2111f, 0.1353f, + -0.0333f, -0.0737f, -0.0642f, 0.0198f, + -0.1646f, -0.1605f, -0.1393f, -0.1688f, + -0.0503f, 0.0930f, -0.1707f, 0.0298f, + 0.0665f, -0.3677f, 0.0868f, 0.0036f, + 0.1102f, -0.2346f, 0.1557f, -0.2765f, + 0.0772f, -0.1922f, 0.0404f, 0.1428f, + 0.0762f, -0.0352f, 0.0451f, 0.0668f, + 0.0095f, -0.1723f, -0.2433f, 0.0611f, + -0.2235f, -0.2127f, -0.0279f, 0.1118f, + -0.2035f, 0.0849f, 0.0888f, -0.2901f, + 0.1098f, 0.1764f, -0.0625f, 0.1007f, + 0.0902f, 0.1143f, -0.3346f, 0.1015f, + 0.0841f, 0.0401f, 0.0707f, -0.2672f, + 0.1622f, 0.0297f, 0.0082f, -0.0532f, + 0.1355f, 0.0621f, 0.1365f, 0.2015f, + 0.0762f, 0.1201f, 0.1211f, -0.0066f, + -0.0974f, 0.0770f, 0.1685f, -0.0806f, + -0.1118f, 0.1734f, 0.0503f, 0.1013f, + 0.0709f, 0.0217f, -0.1615f, -0.1139f, + -0.0176f, 0.1448f, -0.0264f, -0.1122f, + -0.0531f, 0.0113f, 0.0778f, 0.0461f, + -0.3335f, 0.0486f, 0.0892f, 0.0152f, + -0.1348f, -0.0405f, 0.1884f, 0.2103f, + -0.0387f, 0.0294f, -0.0525f, 0.1893f, +}; + +const float YG_dicMR_3[] = +{ + -0.0251f, -0.0350f, -0.0207f, -0.0047f, + -0.0986f, 0.0444f, -0.1942f, 0.0205f, + 0.0972f, -0.1449f, -0.0134f, -0.0624f, + 0.0691f, 0.0313f, -0.1153f, 0.0682f, + -0.0600f, -0.1532f, 0.0686f, 0.0726f, + -0.2082f, 0.1143f, 0.0874f, -0.2235f, + 0.0664f, 0.0363f, 0.0510f, -0.1081f, + -0.0409f, -0.1231f, 0.1104f, -0.1281f, + 0.1524f, -0.1042f, 0.1901f, 0.0286f, + 0.2634f, 0.0987f, -0.0240f, 0.0196f, + 0.0332f, 0.0404f, 0.0347f, -0.3404f, + 0.1252f, -0.1383f, -0.0367f, 0.2006f, + 0.0302f, 0.1576f, 0.0487f, 0.0664f, + -0.0403f, -0.1715f, -0.1502f, 0.0404f, + 0.0814f, 0.1978f, -0.1116f, 0.2533f, + -0.0878f, 0.0256f, -0.0268f, 0.1310f, + -0.0548f, 0.0305f, 0.1372f, -0.0063f, + 0.1706f, -0.2698f, 0.1976f, -0.3231f, + -0.3001f, 0.2054f, -0.1872f, 0.1393f, + -0.0756f, 0.1066f, -0.0278f, -0.0562f, + -0.2551f, 0.1538f, 0.1377f, 0.0787f, + 0.0689f, 0.2857f, -0.1765f, -0.0746f, + -0.0800f, -0.0604f, -0.0612f, -0.1461f, + 0.0864f, 0.0811f, -0.3889f, 0.1219f, + 0.0810f, -0.0055f, 0.0534f, 0.0743f, + 0.0794f, -0.3690f, 0.0922f, 0.0731f, + -0.0230f, -0.0132f, 0.1657f, 0.2333f, + 0.1238f, 0.2026f, 0.2103f, -0.1805f, + -0.2186f, -0.0329f, 0.0040f, -0.0083f, + 0.1654f, 0.1588f, 0.2346f, 0.1744f, + 0.1993f, -0.1624f, -0.4251f, -0.1638f, + 0.0670f, 0.0227f, -0.1506f, -0.1057f, +}; + +const float YG_dicMR_4[] = +{ + -0.0398f, -0.0108f, -0.0263f, 0.0079f, + 0.1358f, 0.0373f, 0.0281f, 0.0293f, + 0.1507f, 0.1997f, 0.1958f, 0.1756f, + -0.1560f, -0.1623f, 0.0297f, 0.1620f, + 0.0863f, -0.1354f, -0.0860f, -0.0209f, + -0.2836f, 0.2034f, -0.2525f, 0.0796f, + -0.1247f, -0.0991f, -0.1167f, -0.1276f, + 0.1198f, -0.3596f, 0.0987f, -0.0051f, + 0.0362f, 0.0702f, -0.0111f, -0.1328f, + -0.0148f, 0.0420f, -0.1931f, -0.0108f, + 0.1745f, -0.1095f, 0.2103f, 0.1230f, + -0.0264f, 0.0641f, 0.1489f, 0.0289f, + 0.2348f, 0.2016f, -0.2473f, -0.0091f, + -0.0077f, -0.1208f, 0.0883f, -0.0523f, + -0.0091f, 0.1614f, -0.0183f, 0.0706f, + -0.2039f, 0.0593f, 0.0207f, -0.0256f, +}; + +const float mean_m[] = { 2.8717f }; + +const float mean_gain_dic[] = +{ + -0.1804f, + -0.1267f, + -0.0185f, + 0.0358f, + 0.1402f, + 0.1903f, + 0.2399f, + 0.2894f, + 0.3379f, + 0.3858f, + 0.4356f, + 0.4857f, + 0.5380f, + 0.6452f, + 0.6992f, + 0.5914f, + 0.0885f, + -0.0721f, + -0.2922f, + -0.4726f, + -0.6732f, + -2.8699f, + -2.0059f, + 0.7528f, + 0.8083f, + -0.3501f, + -0.4106f, + -0.8156f, + -2.2665f, + -2.2112f, + -2.1036f, + -1.9001f, + -1.7967f, + -1.7001f, + -1.6094f, + -1.5218f, + -1.3355f, + -1.2328f, + -1.1354f, + -0.9654f, + -0.6031f, + -0.2352f, + -0.5368f, + -0.7426f, + -0.8894f, + -1.0479f, + -1.4292f, + -2.4899f, + 1.0016f, + 0.8661f, + 1.0718f, + 1.1517f, + 0.9318f, + -2.5695f, + -2.8128f, + -2.3365f, + -2.4168f, + -2.2389f, + -2.6467f, + -2.7259f, + 1.3428f, + 1.2399f, + 1.4988f, + 1.7072f, +}; + +const float YGain_mean_LR[] = +{ + -0.0940f, + -0.0435f, + -0.0348f, + -0.0284f, + -0.0113f, + -0.0029f, + 0.0156f, + 0.0123f, + 0.0288f, + 0.0167f, + 0.0324f, + 0.0369f, +}; + +const float YGain_dic1_LR[] = +{ + -0.4660f, 0.0389f, -0.0220f, + -0.0378f, 0.1016f, -0.0036f, + -0.0241f, -0.0205f, 0.0967f, + -0.4472f, -0.2070f, -0.0781f, + -0.1901f, 0.2501f, 0.0111f, + -0.4541f, -0.4299f, 0.0666f, + 0.0197f, -0.0832f, -0.0755f, + -0.1999f, -0.0008f, -0.0770f, + 0.1179f, 0.0525f, -0.0474f, + 0.0591f, 0.2288f, -0.0186f, + -0.4468f, -0.4279f, -0.2691f, + -0.3880f, 0.2118f, -0.1605f, + -0.2224f, 0.0950f, 0.1028f, + -0.4478f, 0.2234f, 0.0952f, + -0.0352f, 0.1378f, -0.2121f, + 0.2143f, -0.3769f, 0.0736f, + 0.1089f, 0.0811f, 0.0917f, + -0.1318f, -0.2008f, -0.2444f, + 0.1339f, -0.0469f, 0.0567f, + 0.2245f, -0.1437f, -0.0427f, + 0.2121f, 0.1750f, -0.1378f, + 0.1945f, -0.0252f, -0.2556f, + -0.0819f, -0.4228f, -0.0453f, + -0.4492f, -0.0842f, 0.1383f, + 0.2943f, 0.0266f, 0.0106f, + 0.2405f, -0.1113f, 0.1391f, + 0.1588f, -0.2987f, -0.2134f, + 0.2265f, 0.1837f, 0.0951f, + -0.0302f, 0.2034f, 0.1404f, + -0.4421f, -0.0608f, -0.2788f, + -0.1736f, -0.1872f, 0.0451f, + 0.0840f, -0.2138f, 0.0652f, +}; + +const float YGain_dic2_LR[] = +{ + -0.0718f, -0.0178f, -0.0101f, 0.0026f, + 0.0675f, 0.0806f, -0.3212f, 0.0423f, + 0.0064f, -0.1738f, 0.0211f, 0.0003f, + -0.2054f, -0.1316f, 0.0600f, -0.1170f, + 0.0105f, -0.0505f, 0.1732f, 0.0282f, + 0.0254f, -0.0482f, 0.0554f, -0.1338f, + 0.0638f, -0.0556f, 0.0402f, 0.1480f, + 0.1496f, 0.0983f, -0.0297f, -0.1025f, + 0.0034f, 0.0444f, -0.1327f, -0.1633f, + -0.1793f, 0.0958f, -0.1200f, -0.0319f, + -0.3214f, 0.0670f, 0.0283f, 0.0808f, + -0.3269f, 0.1307f, -0.3079f, 0.1485f, + -0.0844f, 0.0677f, -0.1040f, 0.1779f, + -0.2606f, -0.2042f, -0.1393f, 0.0948f, + 0.1570f, 0.1228f, 0.1182f, 0.1300f, + -0.0362f, 0.1092f, 0.0294f, -0.0957f, + -0.1465f, 0.0641f, 0.1266f, -0.0182f, + 0.1676f, -0.0844f, 0.0926f, 0.0055f, + 0.0318f, 0.0583f, 0.0917f, -0.3336f, + 0.0165f, 0.1601f, -0.0881f, 0.0224f, + 0.1485f, 0.0699f, -0.0988f, 0.1190f, + -0.2517f, 0.1238f, 0.1276f, -0.2371f, + 0.0124f, -0.0108f, -0.1272f, 0.0421f, + -0.1400f, -0.1221f, 0.0972f, 0.1542f, + 0.0587f, 0.0358f, 0.0254f, 0.0125f, + -0.0780f, -0.1659f, -0.2174f, -0.0971f, + -0.0475f, 0.1229f, 0.0746f, 0.1120f, + 0.0819f, 0.0898f, 0.1615f, -0.0950f, + 0.0923f, -0.1925f, -0.1311f, 0.1660f, + 0.1057f, -0.2756f, 0.1153f, -0.2155f, + 0.1153f, -0.0761f, -0.0735f, -0.0506f, + 0.0922f, -0.3286f, 0.1058f, 0.0996f, +}; + +const float YGain_dic3_LR[] = +{ + -0.0810f, -0.0466f, -0.0299f, -0.1110f, -0.0512f, + 0.0888f, -0.0116f, -0.1622f, 0.0996f, 0.0549f, + -0.1406f, -0.0835f, 0.0897f, 0.0128f, 0.0658f, + -0.0958f, -0.0384f, -0.0188f, 0.1526f, -0.0546f, + -0.0446f, -0.1591f, -0.0990f, 0.0242f, 0.0650f, + 0.0059f, 0.0158f, 0.0180f, 0.1281f, 0.1497f, + -0.1966f, 0.0746f, -0.0936f, -0.0051f, 0.0602f, + 0.0038f, 0.0325f, -0.1016f, -0.0009f, -0.1385f, + 0.0718f, -0.1831f, 0.1082f, -0.0897f, 0.0557f, + 0.1308f, 0.1992f, 0.1872f, 0.1371f, 0.1449f, + -0.0131f, 0.0489f, -0.2706f, -0.1422f, 0.0554f, + 0.0300f, -0.0106f, 0.1011f, -0.0918f, -0.1585f, + 0.1445f, -0.1593f, -0.1646f, -0.0943f, -0.0868f, + 0.0244f, -0.0142f, -0.0110f, -0.0264f, 0.0251f, + -0.1774f, -0.0473f, -0.2856f, 0.2274f, 0.2675f, + 0.1251f, 0.1851f, -0.1073f, -0.1877f, -0.2566f, + 0.0885f, 0.1921f, -0.0673f, -0.0339f, 0.0364f, + -0.0533f, 0.0944f, 0.1116f, -0.1010f, 0.0646f, + -0.0492f, 0.1618f, -0.2695f, 0.2154f, -0.0825f, + -0.0139f, 0.0988f, 0.0656f, 0.0628f, -0.0539f, + 0.0817f, 0.2109f, 0.2841f, -0.1492f, -0.1509f, + 0.3113f, 0.1205f, -0.4354f, 0.0290f, 0.2983f, + 0.1837f, 0.0186f, 0.0660f, 0.0179f, -0.0140f, + 0.0917f, -0.3063f, 0.0353f, 0.1767f, 0.1473f, + -0.2414f, 0.1508f, 0.1609f, 0.1647f, 0.1367f, + 0.0313f, -0.0359f, -0.0337f, -0.0899f, 0.2352f, + 0.0341f, -0.0414f, 0.2115f, 0.1313f, 0.0311f, + 0.0299f, -0.1503f, 0.0406f, 0.0575f, -0.0966f, + 0.0914f, 0.0680f, 0.0994f, 0.1587f, -0.3097f, + -0.2103f, 0.1496f, -0.1844f, -0.3256f, -0.2372f, + -0.2251f, 0.0767f, 0.1015f, -0.0279f, -0.1582f, + 0.0647f, 0.0207f, 0.0148f, -0.2710f, 0.0109f, +}; + +const short Odx_fft64[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 float w_fft64[32] = +{ + 1.0000000f,0.00000000f,0.70710677f,0.70710677f,0.92387950f,0.38268346f,0.38268346f,0.92387950f, + 0.98078525f,0.19509032f,0.55557024f,0.83146960f,0.83146960f,0.55557024f,0.19509032f,0.98078525f, + 0.99518472f,0.098017141f,0.63439327f,0.77301043f,0.88192123f,0.47139674f,0.29028469f,0.95694035f, + 0.95694035f,0.29028469f,0.47139674f,0.88192123f,0.77301043f,0.63439327f,0.098017141f,0.99518472f +}; + +const short Ip_fft64[6] = { 32,1,0,64,32,96 }; + +const short Odx_fft32_15[32] = { 0,17,2,19,4,21,6,23,8,25,10,27,12,29,14,31,16,1,18,3,20,5,22,7,24,9,26,11,28,13,30,15 }; + +const float w_fft32[16] = +{ + 1.0000000f,0.00000000f,0.70710677f,0.70710677f,0.92387950f,0.38268346f,0.38268346f,0.92387950f, + 0.98078525f,0.19509032f,0.55557024f,0.83146960f,0.83146960f,0.55557024f,0.19509032f,0.98078525f +}; + +const short Ip_fft32[6] = { 16,1,0,32,16,48 }; + +const short 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 short Odx_fft16[16] = {0,11,6,1,12,7,2,13,8,3,14,9,4,15,10,5}; + +const float w_fft16[8] = { 1.0000000f,0.00000000f,0.70710677f,0.70710677f,0.92387950f,0.38268346f,0.38268346f,0.92387950f }; + +const short Ip_fft16[6] = {8,1,0,16,8,24}; + +const float w_fft8[8] = {1.0000000f,0.00000000f,0.70710677f,0.70710677f }; + +const short Ip_fft8[6] = {4,1,0,8,4,12}; + +const short Idx_dortft80[80] = +{ + 0,65,50,35,20,5,70,55,40,25,10,75,60,45,30,15,16,1,66,51,36,21,6,71,56,41,26,11,76,61, + 46,31,32,17,2,67,52,37,22,7,72,57,42,27,12,77,62,47,48,33,18,3,68,53,38,23,8,73,58,43, + 28,13,78,63,64,49,34,19,4,69,54,39,24,9,74,59,44,29,14,79 +}; + +const short Idx_dortft120[120] = +{ + 0,105,90,75,60,45,30,15,16,1,106,91,76,61,46,31,32,17,2,107,92,77,62,47, + 48,33,18,3,108,93,78,63,64,49,34,19,4,109,94,79,80,65,50,35,20,5,110,95, + 96,81,66,51,36,21,6,111,112,97,82,67,52,37,22,7,8,113,98,83,68,53,38,23, + 24,9,114,99,84,69,54,39,40,25,10,115,100,85,70,55,56,41,26,11,116,101,86, + 71,72,57,42,27,12,117,102,87,88,73,58,43,28,13,118,103,104,89,74,59,44,29,14,119 +}; + +const short 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 short Idx_dortft320[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 short Idx_dortft480[480] = +{ + 0,225,450,195,420,165,390,135,360,105,330,75,300,45,270,15,240,465,210,435,180,405,150,375,120,345, + 90,315,60,285,30,255,256,1,226,451,196,421,166,391,136,361,106,331,76,301,46,271,16,241,466,211,436, + 181,406,151,376,121,346,91,316,61,286,31,32,257,2,227,452,197,422,167,392,137,362,107,332,77,302,47, + 272,17,242,467,212,437,182,407,152,377,122,347,92,317,62,287,288,33,258,3,228,453,198,423,168,393,138, + 363,108,333,78,303,48,273,18,243,468,213,438,183,408,153,378,123,348,93,318,63,64,289,34,259,4,229,454, + 199,424,169,394,139,364,109,334,79,304,49,274,19,244,469,214,439,184,409,154,379,124,349,94,319,320, + 65,290,35,260,5,230,455,200,425,170,395,140,365,110,335,80,305,50,275,20,245,470,215,440,185,410,155, + 380,125,350,95,96,321,66,291,36,261,6,231,456,201,426,171,396,141,366,111,336,81,306,51,276,21,246,471, + 216,441,186,411,156,381,126,351,352,97,322,67,292,37,262,7,232,457,202,427,172,397,142,367,112,337,82, + 307,52,277,22,247,472,217,442,187,412,157,382,127,128,353,98,323,68,293,38,263,8,233,458,203,428,173, + 398,143,368,113,338,83,308,53,278,23,248,473,218,443,188,413,158,383,384,129,354,99,324,69,294,39,264, + 9,234,459,204,429,174,399,144,369,114,339,84,309,54,279,24,249,474,219,444,189,414,159,160,385,130,355, + 100,325,70,295,40,265,10,235,460,205,430,175,400,145,370,115,340,85,310,55,280,25,250,475,220,445,190, + 415,416,161,386,131,356,101,326,71,296,41,266,11,236,461,206,431,176,401,146,371,116,341,86,311,56,281, + 26,251,476,221,446,191,192,417,162,387,132,357,102,327,72,297,42,267,12,237,462,207,432,177,402,147,372, + 117,342,87,312,57,282,27,252,477,222,447,448,193,418,163,388,133,358,103,328,73,298,43,268,13,238,463, + 208,433,178,403,148,373,118,343,88,313,58,283,28,253,478,223,224,449,194,419,164,389,134,359,104,329,74, + 299,44,269,14,239,464,209,434,179,404,149,374,119,344,89,314,59,284,29,254,479 +}; + +const short Ip_fft128[10] = { 64, 1, 0, 128, 64, 192, 32, 160, 96, 224 }; + +const float w_fft128[64] = +{ + 1.0000000f, 0.00000000f, 0.70710677f, 0.70710677f, 0.92387950f, 0.38268346f, 0.38268346f, 0.92387950f, + 0.98078525f, 0.19509032f, 0.55557024f, 0.83146960f, 0.83146960f, 0.55557024f, 0.19509032f, 0.98078525f, + 0.99518472f, 0.09801714f, 0.63439327f, 0.77301043f, 0.88192123f, 0.47139674f, 0.29028469f, 0.95694035f, + 0.95694035f, 0.29028469f, 0.47139674f, 0.88192123f, 0.77301043f, 0.63439327f, 0.09801714f, 0.99518472f, + 0.99879545f, 0.04906767f, 0.67155895f, 0.74095112f, 0.90398929f, 0.42755509f, 0.33688985f, 0.94154406f, + 0.97003125f, 0.24298017f, 0.51410274f, 0.85772861f, 0.80320753f, 0.59569930f, 0.14673047f, 0.98917650f, + 0.98917650f, 0.14673047f, 0.59569930f, 0.80320753f, 0.85772861f, 0.51410274f, 0.24298017f, 0.97003125f, + 0.94154406f, 0.33688985f, 0.42755509f, 0.90398929f, 0.74095112f, 0.67155895f, 0.04906767f, 0.99879545f +}; + +const short Ip_fft256[10] = {128, 1, 0, 256, 128, 384, 64, 320,192, 448}; + +const float w_fft256[128] = +{ + 1.00000000f, 0.00000000f, 0.70710678f, 0.70710678f, 0.92387953f, 0.38268343f, 0.38268343f, 0.92387953f, + 0.98078528f, 0.19509032f, 0.55557023f, 0.83146961f, 0.83146961f, 0.55557023f, 0.19509032f, 0.98078528f, + 0.99518473f, 0.09801714f, 0.63439328f, 0.77301045f, 0.88192126f, 0.47139674f, 0.29028468f, 0.95694034f, + 0.95694034f, 0.29028468f, 0.47139674f, 0.88192126f, 0.77301045f, 0.63439328f, 0.09801714f, 0.99518473f, + 0.99879546f, 0.04906767f, 0.67155895f, 0.74095113f, 0.90398929f, 0.42755509f, 0.33688985f, 0.94154407f, + 0.97003125f, 0.24298018f, 0.51410274f, 0.85772861f, 0.80320753f, 0.59569930f, 0.14673047f, 0.98917651f, + 0.98917651f, 0.14673047f, 0.59569930f, 0.80320753f, 0.85772861f, 0.51410274f, 0.24298018f, 0.97003125f, + 0.94154407f, 0.33688985f, 0.42755509f, 0.90398929f, 0.74095113f, 0.67155895f, 0.04906767f, 0.99879546f, + 0.99969882f, 0.02454123f, 0.68954054f, 0.72424708f, 0.91420976f, 0.40524131f, 0.35989504f, 0.93299280f, + 0.97570213f, 0.21910124f, 0.53499762f, 0.84485357f, 0.81758481f, 0.57580819f, 0.17096189f, 0.98527764f, + 0.99247953f, 0.12241068f, 0.61523159f, 0.78834643f, 0.87008699f, 0.49289819f, 0.26671276f, 0.96377607f, + 0.94952818f, 0.31368174f, 0.44961133f, 0.89322430f, 0.75720885f, 0.65317284f, 0.07356456f, 0.99729046f, + 0.99729046f, 0.07356456f, 0.65317284f, 0.75720885f, 0.89322430f, 0.44961133f, 0.31368174f, 0.94952818f, + 0.96377607f, 0.26671276f, 0.49289819f, 0.87008699f, 0.78834643f, 0.61523159f, 0.12241068f, 0.99247953f, + 0.98527764f, 0.17096189f, 0.57580819f, 0.81758481f, 0.84485357f, 0.53499762f, 0.21910124f, 0.97570213f, + 0.93299280f, 0.35989504f, 0.40524131f, 0.91420976f, 0.72424708f, 0.68954054f, 0.02454123f, 0.99969882f +}; + +const short Ip_fft512[18] = {256, 1, 0, 512, 256, 768, 128, 640,384, 896, 64, 576, 320, 832, 192, 704,448, 960}; + +const float w_fft512[256] = +{ + 1.00000000f, 0.00000000f, 0.70710678f, 0.70710678f, 0.92387953f, 0.38268343f, 0.38268343f, 0.92387953f, + 0.98078528f, 0.19509032f, 0.55557023f, 0.83146961f, 0.83146961f, 0.55557023f, 0.19509032f, 0.98078528f, + 0.99518473f, 0.09801714f, 0.63439328f, 0.77301045f, 0.88192126f, 0.47139674f, 0.29028468f, 0.95694034f, + 0.95694034f, 0.29028468f, 0.47139674f, 0.88192126f, 0.77301045f, 0.63439328f, 0.09801714f, 0.99518473f, + 0.99879546f, 0.04906767f, 0.67155895f, 0.74095113f, 0.90398929f, 0.42755509f, 0.33688985f, 0.94154407f, + 0.97003125f, 0.24298018f, 0.51410274f, 0.85772861f, 0.80320753f, 0.59569930f, 0.14673047f, 0.98917651f, + 0.98917651f, 0.14673047f, 0.59569930f, 0.80320753f, 0.85772861f, 0.51410274f, 0.24298018f, 0.97003125f, + 0.94154407f, 0.33688985f, 0.42755509f, 0.90398929f, 0.74095113f, 0.67155895f, 0.04906767f, 0.99879546f, + 0.99969882f, 0.02454123f, 0.68954054f, 0.72424708f, 0.91420976f, 0.40524131f, 0.35989504f, 0.93299280f, + 0.97570213f, 0.21910124f, 0.53499762f, 0.84485357f, 0.81758481f, 0.57580819f, 0.17096189f, 0.98527764f, + 0.99247953f, 0.12241068f, 0.61523159f, 0.78834643f, 0.87008699f, 0.49289819f, 0.26671276f, 0.96377607f, + 0.94952818f, 0.31368174f, 0.44961133f, 0.89322430f, 0.75720885f, 0.65317284f, 0.07356456f, 0.99729046f, + 0.99729046f, 0.07356456f, 0.65317284f, 0.75720885f, 0.89322430f, 0.44961133f, 0.31368174f, 0.94952818f, + 0.96377607f, 0.26671276f, 0.49289819f, 0.87008699f, 0.78834643f, 0.61523159f, 0.12241068f, 0.99247953f, + 0.98527764f, 0.17096189f, 0.57580819f, 0.81758481f, 0.84485357f, 0.53499762f, 0.21910124f, 0.97570213f, + 0.93299280f, 0.35989504f, 0.40524131f, 0.91420976f, 0.72424708f, 0.68954054f, 0.02454123f, 0.99969882f, + 0.99992470f, 0.01227154f, 0.69837625f, 0.71573083f, 0.91911385f, 0.39399204f, 0.37131719f, 0.92850608f, + 0.97831737f, 0.20711138f, 0.54532499f, 0.83822471f, 0.82458930f, 0.56573181f, 0.18303989f, 0.98310549f, + 0.99390697f, 0.11022221f, 0.62485949f, 0.78073723f, 0.87607009f, 0.48218377f, 0.27851969f, 0.96043052f, + 0.95330604f, 0.30200595f, 0.46053871f, 0.88763962f, 0.76516727f, 0.64383154f, 0.08579731f, 0.99631261f, + 0.99811811f, 0.06132074f, 0.66241578f, 0.74913639f, 0.89867447f, 0.43861624f, 0.32531029f, 0.94560733f, + 0.96697647f, 0.25486566f, 0.50353838f, 0.86397286f, 0.79583690f, 0.60551104f, 0.13458071f, 0.99090264f, + 0.98730142f, 0.15885814f, 0.58579786f, 0.81045720f, 0.85135519f, 0.52458968f, 0.23105811f, 0.97293995f, + 0.93733901f, 0.34841868f, 0.41642956f, 0.90916798f, 0.73265427f, 0.68060100f, 0.03680722f, 0.99932238f, + 0.99932238f, 0.03680722f, 0.68060100f, 0.73265427f, 0.90916798f, 0.41642956f, 0.34841868f, 0.93733901f, + 0.97293995f, 0.23105811f, 0.52458968f, 0.85135519f, 0.81045720f, 0.58579786f, 0.15885814f, 0.98730142f, + 0.99090264f, 0.13458071f, 0.60551104f, 0.79583690f, 0.86397286f, 0.50353838f, 0.25486566f, 0.96697647f, + 0.94560733f, 0.32531029f, 0.43861624f, 0.89867447f, 0.74913639f, 0.66241578f, 0.06132074f, 0.99811811f, + 0.99631261f, 0.08579731f, 0.64383154f, 0.76516727f, 0.88763962f, 0.46053871f, 0.30200595f, 0.95330604f, + 0.96043052f, 0.27851969f, 0.48218377f, 0.87607009f, 0.78073723f, 0.62485949f, 0.11022221f, 0.99390697f, + 0.98310549f, 0.18303989f, 0.56573181f, 0.82458930f, 0.83822471f, 0.54532499f, 0.20711138f, 0.97831737f, + 0.92850608f, 0.37131719f, 0.39399204f, 0.91911385f, 0.71573083f, 0.69837625f, 0.01227154f, 0.99992470f +}; + +const short Idx_dortft40[40] = +{ + 0, 25, 10, 35, 20, 5, 30, 15, 16, 1, 26, 11, 36, 21, 6, 31, 32, 17, 2, 27, + 12, 37, 22, 7, 8, 33, 18, 3, 28, 13, 38, 23, 24, 9, 34, 19, 4, 29, 14, 39 +}; + +const short Odx_fft8_5[8] = {0, 3, 6, 1, 4, 7, 2, 5}; +const short Idx_dortft20[20] = {0, 5, 10, 15, 16, 1, 6, 11, 12, 17, 2, 7, 8, 13, 18, 3, 4, 9, 14, 19}; +const short Odx_fft4_5[4] = {0, 3, 2, 1}; +const float w_fft4[2] = {1.0000000f, 0.00000000f}; +const short Ip_fft4[6] = {2,1,0,4,2,6}; +const short ip_edct2_64[6] = {16, 64, 0, 32, 16, 48}; + +const float w_edct2_64[80] = +{ + 1.00000000f, 0.00000000f, 0.70710678f, 0.70710678f, 0.92387953f, 0.38268343f, 0.38268343f, 0.92387953f, + 0.98078528f, 0.19509032f, 0.55557023f, 0.83146961f, 0.83146961f, 0.55557023f, 0.19509032f, 0.98078528f, + 0.70710678f, 0.49984940f, 0.49939772f, 0.49864522f, 0.49759236f, 0.49623976f, 0.49458825f, 0.49263882f, + 0.49039264f, 0.48785106f, 0.48501562f, 0.48188803f, 0.47847016f, 0.47476409f, 0.47077203f, 0.46649639f, + 0.46193976f, 0.45710487f, 0.45199464f, 0.44661215f, 0.44096063f, 0.43504349f, 0.42886430f, 0.42242678f, + 0.41573480f, 0.40879240f, 0.40160376f, 0.39417321f, 0.38650522f, 0.37860442f, 0.37047556f, 0.36212354f, + 0.35355339f, 0.34477027f, 0.33577947f, 0.32658642f, 0.31719664f, 0.30761579f, 0.29784965f, 0.28790409f, + 0.27778511f, 0.26749880f, 0.25705137f, 0.24644909f, 0.23569836f, 0.22480566f, 0.21377754f, 0.20262065f, + 0.19134171f, 0.17994751f, 0.16844492f, 0.15684087f, 0.14514233f, 0.13335637f, 0.12149008f, 0.10955062f, + 0.09754516f, 0.08548094f, 0.07336523f, 0.06120533f, 0.04900857f, 0.03678228f, 0.02453383f, 0.01227061f +}; + +/* HVQ */ +const float hvq_thr_adj[5] = { 0.7071068f, 0.5000000f, 0.2500000f, 0.5000000f, 0.7071068f}; + +const float hvq_class_c[16] = +{ + -0.2324457f, -0.4390556f, 0.0651793f, 0.2109977f, + 0.1471332f, -0.1351437f, 0.4312476f, -0.1384814f, + -0.1384814f, 0.4312476f, -0.1351437f, 0.1471332f, + 0.2109977f, 0.0651793f, -0.4390556f, -0.2324457f +}; + +const short hvq_cb_search_overlap24k[17] = +{ + 0, 8, 17, 27, + 39, 53, 69, 89, + 113, 128, 128, 128, + 128, 128, 128, 128, + 128 +}; + +const short 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 float hvq_peak_cb[1024] = +{ + -0.6912956f, -0.6271097f, -0.7024875f, 0.4262808f, + -0.7780800f, -0.8390081f, -0.2123103f, 0.1755754f, + -0.6005284f, -0.6187206f, -0.1867433f, 0.5583949f, + -0.1626335f, -0.6971197f, -0.6486326f, 0.4250869f, + -0.8399908f, -0.8860587f, 0.0171807f, 0.2217064f, + -0.7976624f, -0.4009260f, -0.2953390f, 0.2432917f, + -0.0157667f, -0.6356865f, -0.3266405f, 0.8188483f, + -0.8489450f, -0.6545582f, 0.0063441f, 0.1921560f, + -0.4517379f, -0.8665710f, -0.2336057f, 0.1562026f, + 0.4618506f, -0.7325841f, -0.6645442f, 0.7730063f, + -0.3442883f, -0.7223252f, -0.6207414f, -0.0612312f, + -0.4947599f, -0.7362953f, 0.2769519f, 0.6891029f, + -0.6117975f, -0.7841619f, -0.0077496f, 0.1986304f, + -0.5240943f, -0.9067913f, 0.0485043f, 0.2167943f, + -0.5396412f, -0.1256491f, -0.1235545f, 0.6819669f, + -0.8648130f, -0.4241201f, 0.0204877f, 0.2068082f, + -0.5605495f, -0.5470207f, -0.2261054f, 0.1577327f, + -0.6742380f, -0.5969556f, 0.0214089f, 0.1821478f, + -0.2017185f, -0.8361119f, -0.1487647f, 0.2677230f, + -0.9043679f, -0.1694224f, 0.0082920f, 0.2133927f, + -0.2797693f, -0.6069181f, -0.2787998f, 0.1967338f, + -0.7057108f, -0.7816155f, 0.2978523f, 0.1754361f, + -0.3176815f, -0.9099026f, 0.0490125f, 0.2141907f, + -0.4198575f, -0.7583196f, 0.0635993f, 0.2175556f, + -0.5430584f, -0.4931615f, 0.0181889f, 0.2223880f, + -0.6798062f, -0.3401114f, 0.0158910f, 0.1975791f, + -0.4111015f, -0.6318658f, -0.0022674f, 0.2056921f, + 0.0577086f, -0.4957561f, -0.3895008f, 0.4151040f, + -0.0493461f, -0.8356919f, -0.2944458f, 0.0766301f, + -0.6653519f, -0.3581038f, -0.1475882f, -0.0488843f, + -0.2951041f, -0.8518280f, 0.1970185f, 0.1934331f, + -0.7088394f, -0.1404796f, 0.0230110f, 0.1779071f, + -0.2349629f, -0.7451124f, 0.0672633f, 0.1989080f, + -0.8420037f, 0.0843352f, 0.0575119f, 0.2087238f, + -0.4653422f, -0.3204370f, 0.0104996f, 0.2118398f, + -0.4042698f, -0.2978680f, -0.1369022f, 0.1310524f, + -0.3691715f, -0.4627771f, 0.0194469f, 0.1874501f, + -0.7932880f, -0.4999925f, 0.5272518f, 0.1987127f, + -0.3157207f, -0.7989150f, 0.0281708f, -0.0724433f, + -0.4063714f, -0.5531399f, 0.2087681f, 0.2166726f, + -0.6433928f, -0.7400934f, 0.1283951f, -0.2888276f, + -0.6992665f, -0.2153651f, 0.2638986f, 0.2449246f, + 0.0759221f, -0.6326668f, -0.0243810f, 0.4197445f, + -0.1053094f, -0.3928218f, 0.0776661f, 0.5284011f, + 0.0786145f, -0.5979541f, -0.3155530f, 0.1330860f, + -0.2138216f, -0.5920822f, 0.0591093f, 0.2060311f, + 0.5341295f, -0.7605932f, -0.5172090f, 0.2604366f, + -0.1048604f, -0.8851262f, 0.1927255f, 0.1973499f, + -0.5168340f, -0.1512779f, 0.0180467f, 0.2015491f, + 0.0335269f, -0.8175794f, -0.0216168f, 0.1691676f, + -0.1815545f, -0.4323540f, -0.1449728f, 0.1241323f, + -0.3259940f, -0.4574721f, -0.2285515f, -0.1586095f, + 0.0051494f, -0.1975091f, -0.1569577f, 0.4943931f, + -0.6204569f, 0.0525578f, 0.0120660f, 0.1902273f, + -0.4779290f, -0.6992531f, 0.7534508f, 0.4339787f, + -0.1187649f, -0.6976845f, 0.1573026f, 0.1922948f, + -0.2681343f, -0.3088476f, 0.0065871f, 0.2084513f, + -0.3780985f, -0.3375740f, 0.1472063f, 0.1975328f, + -0.2351356f, -0.1280155f, -0.1625378f, 0.2005500f, + -0.0170806f, -0.6339361f, -0.0847550f, 0.0556140f, + -0.2045688f, -0.4398525f, 0.0735149f, 0.1856326f, + -0.3233196f, -0.7640965f, 0.4361117f, 0.1472444f, + 0.0629942f, -0.7853858f, 0.5146322f, 0.6244928f, + -0.0839811f, -0.8881392f, 0.3847862f, 0.2300789f, + -0.2330840f, -0.5500582f, 0.0594403f, 0.0210406f, + -0.3345076f, -0.1781868f, 0.0208460f, 0.1883004f, + -0.7935783f, 0.3725855f, 0.3278117f, 0.4754694f, + -0.0642284f, -0.2632120f, -0.1505273f, 0.2129149f, + -0.3033468f, -0.4616954f, 0.3710885f, 0.2992681f, + -0.4248384f, -0.0016876f, 0.0134380f, 0.1927050f, + -0.0092953f, -0.1855540f, 0.3449483f, 0.7852289f, + -0.3791312f, -0.0964576f, 0.2097941f, 0.3001604f, + -0.0848375f, -0.5015270f, 0.1259740f, 0.1763195f, + 0.5429158f, -0.3354102f, -0.2024174f, 0.6442416f, + 0.3773962f, -0.8102532f, -0.3228953f, -0.0772150f, + -0.2048677f, -0.3115774f, 0.1465945f, 0.1916357f, + -0.1810441f, 0.0864401f, 0.1519246f, 0.5593738f, + 0.0822840f, -0.7269843f, -0.3622333f, -0.4062700f, + 0.1607091f, -0.3317170f, -0.2421061f, 0.1359637f, + -0.0962719f, -0.3355251f, 0.0679005f, 0.1770951f, + 0.0250174f, -0.3651731f, -0.0426421f, 0.1630863f, + -0.1534063f, -0.2206571f, 0.0377216f, 0.1773635f, + -0.0503107f, -0.6410940f, 0.2730565f, 0.1690477f, + -0.4957757f, -0.0244409f, -0.0162808f, -0.0955787f, + -0.2524313f, -0.0397484f, 0.0112025f, 0.1818186f, + -0.8109849f, -0.1058945f, 0.2174591f, -0.2708842f, + -0.1470562f, -0.1641739f, -0.1197168f, 0.0447477f, + 0.0588656f, -0.6303298f, 0.1348466f, 0.1117979f, + 0.0743650f, -0.8166042f, 0.3325572f, 0.1713777f, + -0.2014585f, -0.3172087f, 0.0655640f, 0.0041949f, + 0.4579843f, -0.6991156f, -0.1204969f, 0.1891217f, + -0.2764455f, -0.8453921f, 0.7031553f, 0.1247506f, + 0.2536679f, -0.0081430f, 0.0907404f, 0.7806163f, + -0.1158093f, -0.1102171f, -0.0149151f, 0.1648406f, + 0.2353252f, -0.7899960f, 0.1050820f, 0.0800406f, + -0.7417480f, 0.0943212f, 0.4042825f, 0.0998893f, + -0.0950040f, -0.0430378f, 0.1080511f, 0.3676440f, + 0.0093255f, -0.3641596f, -0.1371177f, -0.0609554f, + -0.5714336f, 0.2519692f, 0.2317291f, 0.2202618f, + -0.4146698f, -0.2566845f, 0.2659634f, -0.0347036f, + -0.3670773f, 0.1802618f, 0.5463926f, 0.6508593f, + -0.0678326f, -0.7015804f, 0.3010046f, -0.0498279f, + -0.0220688f, -0.1813971f, 0.0217875f, 0.1577779f, + 0.0649310f, -0.4638375f, 0.0635012f, 0.0496216f, + -0.0147237f, -0.2600337f, 0.2481463f, 0.3285215f, + 0.0016037f, -0.3668163f, 0.1572298f, 0.1535826f, + 0.0720517f, -0.4195340f, 0.7542142f, 0.8043668f, + 0.0327889f, -0.8709202f, 0.5519686f, 0.1322237f, + 0.0325743f, -0.6758953f, 0.4356905f, 0.1690573f, + 0.0222460f, -0.4592628f, 0.2421902f, 0.1418606f, + -0.5079813f, -0.1937920f, 0.7216264f, 0.2938249f, + -0.0027737f, -0.2586997f, 0.1006489f, 0.1311191f, + 0.1067900f, -0.2263411f, -0.0675541f, 0.0894570f, + -0.1463278f, -0.1350150f, 0.1979781f, 0.1301280f, + -0.2848267f, 0.1030649f, 0.2004989f, 0.1749749f, + 0.0528965f, -0.5370577f, 0.3406753f, 0.1271570f, + -0.0828084f, -0.4938643f, 0.4483900f, 0.1278149f, + -0.7256999f, 0.2998409f, 0.7843215f, 0.4678534f, + 0.0178764f, -0.5886182f, 0.6584490f, 0.3674424f, + 0.3457182f, -0.4777862f, 0.0898507f, 0.2238471f, + 0.2808650f, -0.5159423f, -0.1746428f, -0.1639121f, + -0.2412612f, -0.1413623f, 0.3805663f, 0.1746805f, + -0.0037664f, -0.5041469f, 0.0297737f, -0.2529321f, + 0.0385025f, -0.1210239f, -0.0919721f, -0.0045255f, + 0.0070289f, -0.0661929f, 0.0154059f, 0.1206527f, + -0.0688511f, -0.3501640f, 0.3048728f, 0.0806736f, + 0.1477360f, -0.2446724f, -0.1408905f, -0.0903137f, + 0.7393242f, -0.6937444f, 0.2281068f, 0.5408337f, + 0.2058932f, -0.1764501f, 0.1488327f, 0.2644186f, + -0.2103685f, -0.7390670f, 0.3717342f, -0.4480860f, + 0.0866347f, -0.2311362f, 0.1469333f, 0.0725029f, + 0.0817948f, -0.1216286f, 0.0533709f, 0.0628859f, + -0.0171689f, 0.0986378f, 0.0927410f, 0.1758267f, + 0.0104681f, -0.1266550f, 0.2014265f, 0.1157332f, + 0.1939706f, 0.2196828f, 0.3266076f, 0.7405447f, + -0.7823431f, -0.3710044f, 0.6980741f, -0.4465685f, + 0.0743889f, -0.2648934f, 0.2536655f, 0.0943156f, + 0.2177452f, -0.0949112f, 0.0081777f, 0.1387556f, + 0.1303671f, 0.1490959f, 0.1788726f, 0.4326436f, + 0.3473369f, -0.3169577f, -0.0234188f, 0.0441885f, + 0.0540186f, -0.8776336f, 0.8440490f, 0.1417058f, + -0.0917870f, -0.3147601f, 0.5500574f, 0.1602690f, + 0.2136007f, -0.5448702f, 0.2987510f, 0.0277404f, + 0.0474804f, -0.6571059f, 0.6386938f, 0.0971133f, + 0.8189747f, -0.7255339f, -0.0875124f, 0.1071008f, + -0.3016306f, -0.4416167f, 0.7533376f, 0.0058841f, + -0.1006996f, -0.1797670f, 0.1598059f, -0.1746155f, + -0.2759751f, -0.4375621f, 0.5324653f, -0.2187090f, + -0.0208548f, 0.0007885f, 0.1221271f, -0.0071798f, + 0.0937424f, -0.3872427f, 0.4131232f, 0.0814878f, + 0.1091490f, -0.3197269f, 0.3081368f, 0.0438068f, + 0.5405672f, -0.7493672f, 0.2284625f, 0.0522655f, + 0.2024367f, -0.2027840f, 0.0568407f, -0.0238867f, + 0.0971868f, -0.2548049f, 0.1213150f, -0.1210491f, + 0.2468838f, -0.7298202f, 0.2279600f, -0.2664659f, + 0.0852271f, -0.5106476f, 0.5313835f, 0.0594584f, + -0.1823397f, -0.4332103f, 0.0531194f, -0.6742789f, + 0.1030347f, -0.0238603f, 0.5571925f, 0.5078690f, + 0.1173396f, -0.1079135f, 0.1567269f, 0.0102248f, + 0.0996963f, -0.0219312f, 0.3216055f, 0.2366872f, + -0.3354882f, 0.1576330f, 0.5458030f, 0.1454629f, + 0.1444273f, -0.2365381f, 0.4773806f, 0.2506996f, + 0.1122540f, 0.0514636f, 0.1089756f, 0.0667886f, + -0.3413622f, 0.0448554f, 0.1877440f, -0.3506308f, + 0.1328394f, -0.0670468f, 0.0414011f, -0.0965496f, + 0.1299393f, -0.1839806f, 0.2569631f, -0.0070157f, + 0.1898328f, -0.0451201f, 0.0642396f, -0.0240266f, + -0.1290649f, -0.1413532f, 0.4606663f, -0.0510201f, + 0.0606055f, -0.4923670f, 0.4283018f, -0.1857787f, + 0.2395181f, -0.4428843f, 0.0877497f, -0.3090582f, + 0.1463607f, -0.4354426f, -0.2673760f, -0.7759982f, + 0.0363660f, -0.7473857f, 0.6714249f, -0.1897013f, + 0.0078778f, -0.3179395f, 0.8379888f, 0.3211752f, + -0.0229962f, 0.2191676f, 0.2311431f, 0.1050956f, + 0.1829474f, 0.0992829f, 0.7687454f, 0.7776823f, + 0.1946814f, -0.1941786f, 0.0124760f, -0.2574112f, + -0.1012860f, 0.0992883f, 0.3672758f, 0.0414330f, + 0.0971759f, -0.1978175f, 0.3925655f, -0.0065848f, + 0.7740223f, -0.2335201f, -0.0906675f, 0.1745083f, + 0.1516487f, -0.1042227f, 0.2148387f, -0.0795036f, + 0.0798246f, -0.6448072f, 0.8609363f, 0.0393394f, + 0.0779220f, -0.4600459f, 0.7273327f, 0.0570835f, + 0.4454859f, -0.2072924f, 0.2193948f, 0.1384101f, + 0.1703254f, -0.0609580f, 0.1299055f, -0.1323671f, + 0.1839394f, -0.3244128f, 0.3025059f, -0.1719029f, + 0.1127521f, -0.3544195f, 0.5826200f, 0.0178632f, + 0.1347488f, -0.2685010f, 0.4751232f, -0.0335460f, + -0.0268326f, 0.0229464f, 0.5944858f, 0.1651578f, + 0.1752550f, 0.0136593f, 0.3010034f, 0.0409467f, + 0.6297039f, -0.5169880f, -0.2259630f, -0.5169126f, + -0.3645581f, 0.5447856f, 0.5927204f, 0.1806151f, + 0.3826406f, -0.6356577f, 0.6929637f, 0.0339571f, + 0.1438846f, -0.1324825f, 0.3836886f, -0.1131758f, + 0.1225381f, -0.2508278f, 0.1022063f, -0.5355556f, + 0.1951728f, -0.0473224f, 0.1347071f, -0.2533568f, + 0.7506700f, -0.7468928f, 0.6686158f, 0.2984126f, + 0.1631571f, 0.0422823f, 0.2118532f, -0.1436800f, + -0.0460037f, 0.0633928f, 0.2509617f, -0.3180083f, + 0.1858027f, -0.1040863f, 0.2692820f, -0.1939493f, + 0.2203176f, 0.5295745f, 0.6812901f, 0.7900824f, + 0.2034420f, -0.0552806f, 0.0599414f, -0.4107925f, + 0.2479052f, -0.1359192f, 0.8121924f, 0.3484631f, + 0.1398457f, -0.2176905f, 0.5621405f, -0.1195728f, + -0.0080597f, 0.3218221f, 0.7571263f, 0.3912670f, + 0.2116680f, -0.6982532f, 0.3125198f, -0.7360096f, + 0.0948572f, -0.2203334f, 0.3659414f, -0.3956103f, + 0.1293136f, -0.3171252f, 0.7146217f, -0.0790813f, + 0.1411146f, -0.4510387f, 0.8887131f, -0.0377003f, + 0.2301871f, -0.0353170f, 0.5297350f, 0.0379717f, + 0.6152722f, -0.1928382f, 0.0785710f, -0.1588030f, + 0.1337912f, 0.1823085f, 0.3354832f, -0.0887607f, + 0.0494082f, -0.1225804f, 0.7939893f, 0.0220200f, + 0.1421773f, 0.3523192f, 0.4413828f, 0.1457048f, + -0.0882652f, 0.3232748f, 0.4595339f, -0.1386560f, + 0.0601664f, -0.4816208f, 0.8133457f, -0.3112419f, + 0.1845199f, -0.0171361f, 0.3659768f, -0.2448125f, + 0.1891260f, -0.0106495f, 0.2419292f, -0.3683512f, + 0.6530412f, -0.4171780f, 0.4613151f, 0.0030213f, + 0.1778989f, -0.1239391f, 0.5100323f, -0.2197134f, + -0.2717385f, 0.1272452f, 0.7572512f, -0.2318920f, + 0.3716251f, 0.1855403f, 0.5916812f, 0.3385713f, + 0.1300696f, 0.0471288f, 0.5215391f, -0.1457248f, + -0.2123145f, -0.1802899f, 0.5974199f, -0.7072856f, + 0.2174739f, -0.7171207f, 0.7595373f, -0.5396347f, + 0.1682724f, -0.1652717f, 0.7105864f, -0.1779208f, + 0.1949437f, -0.0545715f, 0.4387951f, -0.3539158f, + 0.1556118f, -0.2676762f, 0.8786431f, -0.1395478f, + 0.1839802f, -0.1270819f, 0.0981727f, -0.8218095f, + 0.1961324f, 0.0044393f, 0.2839973f, -0.5454667f, + 0.1691811f, 0.1170212f, 0.7761239f, -0.0004658f, + 0.2532176f, -0.3257096f, 0.6409724f, -0.4603164f, + 0.1836927f, -0.2327923f, 0.4239208f, -0.6877027f, + 0.8283811f, 0.0514265f, 0.3075364f, 0.1290827f, + 0.1590365f, -0.0471006f, 0.6768611f, -0.3246488f, + 0.1948562f, 0.1742693f, 0.4112475f, -0.3959884f, + 0.1608810f, 0.5362161f, 0.7247152f, 0.1551418f, + -0.0640990f, 0.2785439f, 0.4195016f, -0.6363523f, + -0.4977460f, 0.4795997f, 0.6537622f, -0.7041565f, + 0.1993300f, -0.0009453f, 0.5226769f, -0.5072073f, + 0.1647024f, -0.1025920f, 0.8690643f, -0.2884946f, + 0.1903634f, 0.0383981f, 0.4024816f, -0.6858912f, + 0.3935245f, -0.1394052f, 0.2460183f, -0.8132467f, + 0.0876800f, 0.1823305f, 0.6760031f, -0.4640969f, + 0.1928370f, -0.0154626f, 0.7054892f, -0.5314507f, + 0.7363694f, -0.4335648f, 0.3939214f, -0.6439396f, + 0.2216142f, 0.2584981f, 0.7753125f, -0.2883786f, + 0.1655171f, -0.0354699f, 0.9000988f, -0.4917610f, + 0.6522388f, 0.6980886f, 0.7493314f, 0.5121635f, + 0.2039644f, 0.0748634f, 0.4817260f, -0.8814858f, + 0.1984904f, 0.0331222f, 0.6597681f, -0.7397799f, + 0.6551378f, 0.0189344f, 0.7086707f, -0.2207969f, + 0.3331688f, 0.2704824f, 0.5667230f, -0.6593540f, + 0.2047795f, -0.0638265f, 0.8838190f, -0.7884763f, + 0.2100875f, 0.6368825f, 0.8423747f, -0.2746185f, + 0.2074577f, 0.1714071f, 0.8760290f, -0.6561672f, + 0.1851064f, 0.1440378f, 0.7655031f, -0.8835155f +}; + +const short hvq_pg_huff_offset[NUM_PG_HUFFLEN] = {0,2,3,8,9,11,13,15,19}; +const short hvq_pg_huff_thres[NUM_PG_HUFFLEN] = {0,0x2,0x4,0x18,0x20,0x40,0x80,0x100,0x300}; + +const short 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 short 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 short 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 short hvq_cp_layer1_map5[HVQ_CP_MAP_LEN] = { 16, 8, 4, 2, 1, 18, 17, 9 }; + +const short hvq_cp_huff_thres[HVQ_CP_HUFF_NUM_LEN] = { 0x0, 0x2, 0xC, 0x20, 0x50, 0x60, 0x100, 0x180, 0x600, 0x1000, 0x1C00 }; +const short hvq_cp_huff_offset[HVQ_CP_HUFF_NUM_LEN] = { 0, 2, 7, 12, 18, 19, 24, 26, 35, 45, 51 }; + +const short 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 short pow2_angle_res[8] = {16384, 17867, 19484, 21247, 23170, 25268, 27554, 30048}; /* Q14 */ + +/*----------------------------------------------------------------------------------* + * FEC for HQ core + *----------------------------------------------------------------------------------*/ + +const short Num_bands_NB[MAX_SB_NB] = {8,8,2}; + +const float SmoothingWin_NB875[70] = +{ + 0.00000000f,0.00050347f,0.00201285f,0.00452512f,0.00803521f,0.01253604f,0.01801857f,0.02447174f,0.03188256f,0.04023611f, + 0.04951557f,0.05970223f,0.07077560f,0.08271337f,0.09549150f,0.10908426f,0.12346427f,0.13860257f,0.15446869f,0.17103064f, + 0.18825510f,0.20610736f,0.22455151f,0.24355036f,0.26306567f,0.28305814f,0.30348748f,0.32431260f,0.34549150f,0.36698157f, + 0.38873953f,0.41072154f,0.43288338f,0.45518035f,0.47756758f,0.50000000f,0.52243245f,0.54481965f,0.56711662f,0.58927846f, + 0.61126047f,0.63301843f,0.65450847f,0.67568743f,0.69651252f,0.71694189f,0.73693430f,0.75644964f,0.77544850f,0.79389262f, + 0.81174493f,0.82896936f,0.84553134f,0.86139745f,0.87653571f,0.89091575f,0.90450847f,0.91728663f,0.92922437f,0.94029778f, + 0.95048445f,0.95976388f,0.96811742f,0.97552824f,0.98198146f,0.98746395f,0.99196482f,0.99547487f,0.99798715f,0.99949653f +}; + +const float SmoothingWin_NB2[16] = +{ + 0.00000000f,0.00960736f,0.03806023f,0.08426519f,0.14644661f,0.22221488f,0.30865828f,0.40245484f,0.50000000f,0.59754516f, + 0.69134172f,0.77778512f,0.85355339f,0.91573481f,0.96193977f,0.99039264f +}; + +/*----------------------------------------------------------------------------------* + * SC-VBR + *----------------------------------------------------------------------------------*/ + +const float bp1_num_coef_wb[5] = {0.9329833984375,0,-1.865966796875,0,0.9329833984375}; +const float bp1_den_coef_wb[5] = {1,0,-1.8614501953125,0,0.8704833984375}; + +const float shape1_num_coef[11] = +{ + 0.959381103515625f, -0.074554443359375f, -0.4161376953125f, 0.1317138671875f, + -0.3109130859375f, 0.00146484375f, 0.080535888671875f, -0.109100341796875f, + -0.023681640625f, 0.03192138671875f, 0.012176513671875f +}; + +const float shape1_den_coef[11] = +{ + 1, 0.0897216796875f, -0.373443603515625f, 0.123046875f, -0.293243408203125f, + -0.06097412109375f, 0.071258544921875f, -0.1190185546875f, -0.048675537109375f, + 0.026153564453125f, 0.007720947265625f +}; + +const float shape2_num_coef[11] = +{ + 0.938720703125f, 0.000946044921875f, -0.295989990234375f, 0.2904052734375f, + -0.17938232421875f, -0.221221923828125f, -0.3194580078125f, 0.01348876953125f, + 0.10003662109375f, -0.001922607421875f, 0.034027099609375f +}; + +const float shape2_den_coef[11] = +{ + 1, 0.488861083984375f, -0.02716064453125f, 0.390594482421875f, 0.07159423828125f, + -0.213165283203125f, -0.402587890625f, -0.176849365234375f, -0.028961181640625f, + -0.0455322265625f, -0.00927734375f +}; + +const float shape3_num_coef[11] = +{ + 0.936431884765625f, -0.011688232421875f, -0.303253173828125f, -0.293121337890625f, + -0.183013916015625f, 0.232269287109375f, -0.317169189453125f, -0.010833740234375f, + 0.098846435546875f, 0.0003662109375f, 0.0364990234375f +}; + +const float shape3_den_coef[11] = +{ + 1, -0.50347900390625f, -0.027801513671875f, -0.395111083984375f, 0.06976318359375f, + 0.22674560546875f, -0.408477783203125f, 0.18511962890625f, -0.03607177734375f, + 0.0482177734375f, -0.008331298828125f +}; + +const float txlpf1_num_coef[11] = +{ + 0.016845703125, 0.024169921875, 0.062744140625, 0.0831298828125, 0.1124267578125, + 0.11767578125, 0.1124267578125, 0.0831298828125, 0.062744140625, 0.024169921875, + 0.016845703125 +}; + +const float txlpf1_den_coef[11] = +{ + 1, -2.3126220703125, 3.8590087890625, -3.8023681640625, 2.989990234375, + -1.5567626953125, 0.6748046875, -0.17529296875, 0.0423583984375, -0.0030517578125, + 0.00048828125 +}; + +const float txhpf1_num_coef[11] = +{ + 0.016845703125, -0.024169921875, 0.062744140625, -0.0831298828125, 0.1124267578125, + -0.11767578125, 0.1124267578125, -0.0831298828125, 0.062744140625, -0.024169921875, + 0.016845703125 +}; + +const float txhpf1_den_coef[11] = +{ + 1, 2.3126220703125, 3.8590087890625, 3.8023681640625, 2.989990234375, 1.5567626953125, + 0.6748046875, 0.17529296875, 0.0423583984375, 0.0030517578125, 0.00048828125 +}; + +/* NELP filter coefficients */ +const float bp1_num_coef_nb_fx_order7[8] = +{ + 0.180780569293627f, 0.821512462016641f, 1.901786162198923f, 2.798216464912205f, + 2.798216464912205f, 1.901786162198923f, 0.821512462016641f, 0.180780569293627f +}; + +const float bp1_den_coef_nb_fx_order7[8] = +{ + 1.0f, 1.972212566911875f, 2.906981567843655f, 2.667903533650106f, + 1.784691945273023f, 0.807367818229743f, 0.232764318343094f, 0.032669566591295f +}; + + +/* 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 float num_nelp_lp[NELP_LP_ORDER+1] = +{ + 0.088754442436105f, 0.427948705228526f, 1.097120864220837f, 1.834535180016855f, + 2.164546590741725f, 1.833722723336889f, 1.096120298806107f, 0.427341227067866f, 0.088564563680987f +}; + +const float den_nelp_lp[NELP_LP_ORDER+1] = +{ + 1.000000000000000f, 1.076558216566388f, 2.638952788853937f, 1.485213059043660f, + 1.941109655171129f, 0.433697456681428f, 0.488030665133170f, -0.014677457543018f, 0.043067530202687f +}; + + + +/* NELP gain tables */ +const float UVG1CB_WB[UVG1_CBSIZE][2] = +{ + { -0.271424f, -0.258097f, }, + { 1.546157f, 1.503115f, }, + { 0.454480f, 1.182801f, }, + { 2.182661f, 2.194626f, }, + { 0.504902f, 0.481656f, }, + { 1.416585f, 2.597607f, }, + { 1.193427f, 1.140118f, }, + { 2.649107f, 2.640023f, }, + { 0.132870f, 0.204961f, }, + { 1.708137f, 1.672001f, }, + { 1.274749f, 0.636471f, }, + { 2.405026f, 2.403867f, }, + { 0.666233f, 0.649061f, }, + { 2.081430f, 2.065141f, }, + { 1.734086f, 1.037998f, }, + { 2.969951f, 2.962773f, }, + { -0.014392f, -0.034103f, }, + { 1.417866f, 1.814293f, }, + { 0.842041f, 0.798819f, }, + { 2.308757f, 2.275084f, }, + { 0.139464f, 0.831392f, }, + { 1.952503f, 1.961636f, }, + { 0.844903f, 1.609146f, }, + { 2.790210f, 2.775995f, }, + { 0.368318f, 0.275885f, }, + { 1.825159f, 1.830021f, }, + { 0.998048f, 0.987868f, }, + { 2.529417f, 2.508405f, }, + { 0.908356f, 0.289270f, }, + { 2.184707f, 1.707541f, }, + { 1.341007f, 1.338580f, }, + { 3.185808f, 3.172863f, }, +}; + +const float UVG1CB_NB[UVG1_CBSIZE][2] = +{ + { -0.584898f, -0.629564f, }, + { 0.588898f, 0.602697f, }, + { -0.420328f, 0.440621f, }, + { 0.676153f, 1.866763f, }, + { -0.057218f, -0.486523f, }, + { 0.973746f, 0.995785f, }, + { 0.335472f, 0.304245f, }, + { 1.717476f, 1.710655f, }, + { -0.303435f, -0.349463f, }, + { 0.736475f, 0.719210f, }, + { 0.326864f, -0.053863f, }, + { 1.433214f, 1.440908f, }, + { -0.031290f, -0.103346f, }, + { 1.117363f, 1.089082f, }, + { -0.012970f, 0.729895f, }, + { 2.060025f, 2.043535f, }, + { -0.437514f, -0.472825f, }, + { 0.428648f, 1.164362f, }, + { 0.049001f, 0.050772f, }, + { 1.352832f, 1.287837f, }, + { -0.173046f, -0.210522f, }, + { 1.097114f, 0.641427f, }, + { 0.765980f, 0.138765f, }, + { 1.876515f, 1.861232f, }, + { -0.475929f, 0.036795f, }, + { 0.851593f, 0.866113f, }, + { 0.192944f, 0.177338f, }, + { 1.585417f, 1.565396f, }, + { 0.328590f, -0.377592f, }, + { 1.193646f, 1.239326f, }, + { 0.480756f, 0.442872f, }, + { 2.297758f, 2.282144f, }, +}; + +const float UVG2CB1_WB[UVG2_CBSIZE][5] = +{ + { 0.223040f, 0.241651f, 0.363680f, 1.453550f, 0.639043f, }, + { 1.367034f, 1.128134f, 0.995599f, 0.852711f, 0.746318f, }, + { 1.203618f, 0.984239f, 0.732146f, 0.524829f, 0.416474f, }, + { 1.885173f, 0.737643f, 0.440409f, 0.360901f, 0.354375f, }, + { 0.285902f, 0.339404f, 1.683466f, 0.632872f, 0.362779f, }, + { 1.014419f, 1.046733f, 1.076532f, 1.102226f, 1.117500f, }, + { 0.886868f, 0.893899f, 0.901808f, 0.906043f, 0.912148f, }, + { 3.225548f, 1.222902f, 0.637340f, 0.530948f, 0.499932f, }, + { 0.907185f, 0.704885f, 0.549973f, 0.479615f, 0.420607f, }, + { 1.743322f, 1.114901f, 0.838360f, 0.725076f, 0.584914f, }, + { 0.697213f, 0.741751f, 0.795735f, 0.849916f, 0.905532f, }, + { 1.447413f, 1.332714f, 1.201884f, 1.085950f, 0.997001f, }, + { 0.239259f, 0.250031f, 0.378390f, 1.388066f, 1.962520f, }, + { 0.858277f, 1.795467f, 2.537226f, 0.883659f, 0.697253f, }, + { 0.634313f, 0.755069f, 0.874414f, 1.167114f, 1.456359f, }, + { 0.479120f, 2.683769f, 1.225698f, 0.698405f, 0.631620f, }, + { 0.194304f, 0.223532f, 0.246663f, 0.286883f, 1.884711f, }, + { 1.085250f, 1.075760f, 1.060584f, 1.037376f, 1.019217f, }, + { 0.355082f, 1.585122f, 0.637538f, 0.429221f, 0.431000f, }, + { 1.537046f, 1.876537f, 1.162872f, 0.718938f, 0.537773f, }, + { 0.366750f, 0.384063f, 0.462624f, 0.727828f, 1.333889f, }, + { 1.159580f, 1.178847f, 1.198408f, 1.203392f, 1.195077f, }, + { 0.889680f, 0.921507f, 0.957437f, 0.985704f, 1.004871f, }, + { 2.209824f, 1.807385f, 1.465675f, 1.158738f, 0.996400f, }, + { 0.380420f, 0.456231f, 0.569092f, 0.732313f, 0.877647f, }, + { 1.140464f, 1.134349f, 1.126392f, 1.111634f, 1.094200f, }, + { 0.552280f, 0.636810f, 0.771019f, 0.949718f, 1.090795f, }, + { 1.356338f, 1.328390f, 1.665898f, 1.744565f, 1.397443f, }, + { 0.358875f, 0.378330f, 0.492142f, 2.726906f, 0.934503f, }, + { 1.339929f, 1.530712f, 1.653071f, 2.002372f, 2.265826f, }, + { 0.848927f, 0.901721f, 1.004240f, 1.088962f, 1.148716f, }, + { 2.655634f, 4.390627f, 2.488829f, 1.779943f, 0.689514f, }, + { 0.323918f, 0.365752f, 0.360473f, 0.406899f, 0.521889f, }, + { 1.089529f, 1.049556f, 0.999532f, 0.947192f, 0.910775f, }, + { 0.778315f, 0.772521f, 0.770412f, 0.757735f, 0.766615f, }, + { 2.382149f, 1.389184f, 0.821738f, 0.560577f, 0.437522f, }, + { 0.422645f, 0.427987f, 3.028798f, 0.996559f, 0.548607f, }, + { 0.943902f, 0.991288f, 1.222348f, 1.287613f, 1.275699f, }, + { 0.976039f, 0.966009f, 0.952110f, 0.937347f, 0.925149f, }, + { 4.404412f, 2.299179f, 1.359051f, 0.845995f, 0.611213f, }, + { 0.527446f, 0.618156f, 0.706851f, 0.629108f, 0.566558f, }, + { 1.233373f, 1.169295f, 1.096161f, 1.026234f, 0.965180f, }, + { 0.825364f, 0.833740f, 0.844135f, 0.853512f, 0.863188f, }, + { 1.505253f, 1.418813f, 1.328096f, 1.229135f, 1.135295f, }, + { 0.693032f, 0.827423f, 1.234705f, 1.845313f, 2.542454f, }, + { 0.945943f, 1.081860f, 1.265427f, 1.540595f, 1.749407f, }, + { 1.052402f, 1.008307f, 0.871943f, 0.749492f, 2.088583f, }, + { 2.146194f, 2.016499f, 1.782081f, 1.524242f, 1.323508f, }, + { 0.290883f, 0.301913f, 0.334033f, 0.442895f, 2.885471f, }, + { 0.606905f, 1.398622f, 1.501382f, 1.030661f, 0.895216f, }, + { 0.980941f, 0.933889f, 0.878940f, 0.827155f, 0.794956f, }, + { 1.832121f, 1.420187f, 1.218118f, 0.992368f, 0.811142f, }, + { 0.349042f, 0.479090f, 1.353992f, 0.999951f, 1.142766f, }, + { 1.316650f, 1.312876f, 1.299885f, 1.276895f, 1.233464f, }, + { 0.986649f, 0.998506f, 1.008895f, 1.015456f, 1.020661f, }, + { 3.044209f, 2.251119f, 1.400128f, 0.883141f, 0.610713f, }, + { 0.606060f, 0.626282f, 0.675680f, 0.754010f, 0.845070f, }, + { 1.271739f, 1.240164f, 1.197404f, 1.148908f, 1.103891f, }, + { 0.766260f, 0.820830f, 0.890415f, 0.954560f, 1.014693f, }, + { 1.742866f, 1.608286f, 1.450560f, 1.281919f, 1.141203f, }, + { 0.419616f, 0.455676f, 1.951458f, 1.863714f, 0.973334f, }, + { 0.875636f, 1.291339f, 1.924261f, 3.300506f, 3.929508f, }, + { 0.588088f, 0.613937f, 0.671033f, 1.786119f, 1.131808f, }, + { 7.419703f, 4.514918f, 3.368681f, 1.171582f, 0.557291f, }, +}; + +const float UVG2CB2_WB[UVG2_CBSIZE][5] = +{ + { 0.382157f, 0.339570f, 0.399108f, 1.276274f, 0.654653f, }, + { 0.526317f, 0.624477f, 1.514850f, 1.357657f, 0.962890f, }, + { 0.497765f, 0.587492f, 0.755478f, 0.832206f, 0.968825f, }, + { 1.242760f, 1.236637f, 1.218059f, 1.186075f, 1.163104f, }, + { 0.350569f, 0.423863f, 0.687511f, 0.576640f, 0.586036f, }, + { 1.068227f, 1.080389f, 1.090163f, 1.093335f, 1.096811f, }, + { 1.134662f, 0.996393f, 0.866640f, 0.727742f, 0.651101f, }, + { 0.416366f, 0.476179f, 0.898235f, 1.911077f, 2.415833f, }, + { 0.693081f, 0.445820f, 0.352293f, 0.295523f, 0.303834f, }, + { 0.338564f, 0.344193f, 0.431633f, 2.166267f, 1.070002f, }, + { 0.981922f, 0.923891f, 0.870264f, 0.809574f, 0.755981f, }, + { 2.437343f, 1.744939f, 1.275522f, 0.913573f, 0.738923f, }, + { 1.652469f, 0.575451f, 0.373855f, 0.353600f, 0.379997f, }, + { 1.120803f, 1.140296f, 1.155888f, 1.163382f, 1.169191f, }, + { 1.051700f, 1.024805f, 0.989204f, 0.951249f, 0.920163f, }, + { 0.558571f, 0.622568f, 1.201735f, 2.024839f, 3.632277f, }, + { 0.332205f, 0.361342f, 0.368816f, 0.486187f, 2.551270f, }, + { 0.716016f, 0.764423f, 0.901925f, 1.144217f, 1.269692f, }, + { 0.972618f, 0.744037f, 0.605346f, 0.645594f, 1.346183f, }, + { 1.306825f, 1.337871f, 1.339887f, 1.326540f, 1.327383f, }, + { 0.810386f, 0.703444f, 0.617077f, 0.525349f, 0.470428f, }, + { 1.189609f, 1.159137f, 1.117761f, 1.075965f, 1.039311f, }, + { 1.509928f, 1.073290f, 0.915705f, 0.830047f, 0.707661f, }, + { 0.527199f, 1.969524f, 1.839455f, 1.250142f, 0.888607f, }, + { 0.553059f, 2.484691f, 0.928542f, 0.631924f, 0.595981f, }, + { 0.534157f, 0.538470f, 1.048001f, 3.098313f, 1.438832f, }, + { 0.875629f, 0.891265f, 0.918069f, 0.943470f, 0.966723f, }, + { 3.212350f, 2.380788f, 1.750784f, 1.325976f, 1.309454f, }, + { 1.393980f, 1.018875f, 0.714902f, 0.510150f, 0.433226f, }, + { 0.861995f, 0.935236f, 1.133018f, 1.412823f, 1.616763f, }, + { 1.073054f, 1.063390f, 1.045198f, 1.023854f, 1.003573f, }, + { 0.547694f, 0.604539f, 1.419472f, 0.968088f, 6.634663f, }, + { 0.384404f, 0.407015f, 1.841710f, 0.733522f, 0.484417f, }, + { 0.630723f, 0.612993f, 2.852480f, 1.407572f, 1.173696f, }, + { 0.886615f, 0.844153f, 0.800046f, 0.760230f, 0.725250f, }, + { 2.092080f, 1.654743f, 1.432156f, 1.346378f, 1.255149f, }, + { 0.797508f, 0.740916f, 0.717801f, 0.679101f, 0.657052f, }, + { 0.959244f, 1.037313f, 1.117438f, 1.190695f, 1.260351f, }, + { 1.084782f, 1.018723f, 0.943477f, 0.876418f, 0.814781f, }, + { 0.976114f, 1.153683f, 1.398515f, 1.677934f, 1.925023f, }, + { 1.066698f, 0.689574f, 0.546216f, 0.402266f, 0.342894f, }, + { 0.244053f, 0.249520f, 0.360608f, 0.654699f, 3.729612f, }, + { 0.955958f, 0.940178f, 0.919330f, 0.894537f, 0.876740f, }, + { 3.224046f, 1.094907f, 0.788658f, 0.951478f, 0.890611f, }, + { 2.441966f, 0.858237f, 0.584262f, 0.545170f, 0.539909f, }, + { 1.123818f, 1.180721f, 1.238015f, 1.283992f, 1.321097f, }, + { 0.956697f, 0.985042f, 1.019696f, 1.050902f, 1.078825f, }, + { 0.743688f, 2.034202f, 4.022331f, 2.727508f, 2.650772f, }, + { 0.250845f, 0.245822f, 0.291984f, 0.385336f, 1.449503f, }, + { 0.461815f, 0.591238f, 0.787875f, 0.956948f, 1.806615f, }, + { 0.875089f, 0.862359f, 0.856436f, 0.847061f, 0.839057f, }, + { 1.309442f, 1.502701f, 1.661279f, 1.673280f, 1.662961f, }, + { 0.985927f, 0.857309f, 0.739752f, 0.643488f, 0.569376f, }, + { 1.650427f, 1.495147f, 1.278185f, 1.049539f, 0.900202f, }, + { 1.006963f, 1.593657f, 0.993154f, 0.790603f, 0.850326f, }, + { 1.225572f, 1.441567f, 1.728901f, 2.088278f, 2.349483f, }, + { 0.341446f, 1.432559f, 0.749195f, 0.421280f, 0.404079f, }, + { 1.145314f, 1.033705f, 0.970105f, 0.917177f, 2.347552f, }, + { 0.971156f, 0.977194f, 0.977277f, 0.972506f, 0.966892f, }, + { 0.513513f, 4.115618f, 2.258778f, 1.186578f, 1.154071f, }, + { 1.963588f, 1.292572f, 0.969148f, 0.756260f, 0.630658f, }, + { 1.142688f, 1.247234f, 1.361439f, 1.456244f, 1.531956f, }, + { 1.188195f, 1.119173f, 1.043934f, 0.966349f, 0.898995f, }, + { 0.296171f, 0.760591f, 1.599661f, 5.561118f, 5.121441f, }, +}; + + +const float UVG2CB1_NB[UVG2_CBSIZE][5] = +{ + { 0.188739f, 0.191757f, 0.191531f, 0.191578f, 0.209839f, }, + { 0.869071f, 0.859505f, 0.832542f, 0.797074f, 0.773080f, }, + { 0.431109f, 0.727906f, 2.508026f, 0.925174f, 0.548901f, }, + { 1.217337f, 1.160289f, 1.097694f, 1.018471f, 0.957574f, }, + { 0.497102f, 0.495688f, 0.490534f, 0.481662f, 0.463058f, }, + { 0.803575f, 0.867673f, 0.944431f, 1.007241f, 1.060698f, }, + { 0.783034f, 0.762224f, 0.738827f, 0.711210f, 0.682893f, }, + { 3.227538f, 1.670940f, 0.968417f, 0.670516f, 0.602001f, }, + { 0.379041f, 0.397159f, 0.339889f, 0.431105f, 0.898154f, }, + { 1.313227f, 1.132838f, 0.938410f, 0.794448f, 0.643291f, }, + { 0.390638f, 0.395881f, 0.593166f, 2.306134f, 1.028762f, }, + { 1.248727f, 1.269418f, 1.296714f, 1.309796f, 1.304405f, }, + { 1.520874f, 0.734382f, 0.485483f, 0.396077f, 0.389855f, }, + { 0.421502f, 0.516180f, 1.720254f, 1.504402f, 1.050148f, }, + { 0.245081f, 0.257874f, 0.449391f, 1.466236f, 1.733604f, }, + { 1.559619f, 2.358229f, 1.100964f, 0.677191f, 0.515930f, }, + { 0.258870f, 0.281444f, 0.341911f, 0.423056f, 0.517793f, }, + { 0.841801f, 0.860159f, 0.881827f, 0.899050f, 0.920338f, }, + { 0.365189f, 0.499345f, 0.710492f, 0.869768f, 0.990808f, }, + { 1.078960f, 1.121199f, 1.170587f, 1.201313f, 1.215423f, }, + { 0.343519f, 1.297406f, 0.680773f, 0.408835f, 0.329668f, }, + { 1.027852f, 1.031491f, 1.031891f, 1.021937f, 1.017812f, }, + { 0.548592f, 2.012860f, 1.072282f, 0.615844f, 0.417353f, }, + { 1.760444f, 1.645651f, 1.491751f, 1.317721f, 1.142677f, }, + { 0.879361f, 0.558186f, 0.385066f, 0.300063f, 0.280186f, }, + { 1.629306f, 1.276033f, 0.873148f, 0.597645f, 0.464031f, }, + { 0.233010f, 0.252664f, 0.263381f, 0.410771f, 2.333462f, }, + { 0.979199f, 1.428996f, 2.192152f, 1.742747f, 1.094684f, }, + { 0.679754f, 0.659549f, 0.643852f, 0.621674f, 0.603191f, }, + { 1.077752f, 0.992367f, 1.129539f, 1.027383f, 2.264297f, }, + { 0.676422f, 0.735375f, 0.819505f, 0.911898f, 0.992613f, }, + { 4.819767f, 2.100243f, 0.962614f, 0.621495f, 0.509149f, }, + { 0.276365f, 0.274270f, 0.270315f, 0.266915f, 0.271854f, }, + { 0.955282f, 0.937005f, 0.911375f, 0.886292f, 0.866125f, }, + { 0.231384f, 0.382150f, 1.480144f, 0.647910f, 0.407074f, }, + { 1.503587f, 1.359087f, 1.192322f, 1.035379f, 0.920358f, }, + { 0.225897f, 0.284201f, 0.386850f, 1.479923f, 0.754288f, }, + { 0.932117f, 0.985694f, 1.055295f, 1.107535f, 1.153749f, }, + { 1.047555f, 0.950740f, 0.840054f, 0.733910f, 0.667261f, }, + { 2.085890f, 1.583746f, 1.211518f, 0.930697f, 0.725212f, }, + { 0.425680f, 0.429169f, 0.415950f, 0.398797f, 0.384700f, }, + { 1.078194f, 1.039819f, 0.987399f, 0.930104f, 0.885793f, }, + { 0.468506f, 0.527117f, 0.811323f, 3.412384f, 1.928112f, }, + { 1.453081f, 1.399223f, 1.322881f, 1.235534f, 1.155194f, }, + { 0.677564f, 0.686571f, 0.612173f, 0.620178f, 1.607781f, }, + { 0.838759f, 0.966836f, 1.138047f, 1.458807f, 1.531620f, }, + { 0.752352f, 0.769151f, 0.792542f, 0.814617f, 0.830990f, }, + { 0.998295f, 3.910764f, 2.022774f, 1.004988f, 0.660092f, }, + { 0.346421f, 0.347923f, 0.341870f, 0.334828f, 0.332826f, }, + { 0.933744f, 0.949722f, 0.965032f, 0.974951f, 0.980120f, }, + { 0.609754f, 0.656553f, 0.694920f, 0.735124f, 0.784513f, }, + { 1.250595f, 1.226482f, 1.191682f, 1.145255f, 1.104473f, }, + { 0.557881f, 0.567717f, 0.565744f, 0.564657f, 0.554475f, }, + { 1.096985f, 1.105627f, 1.102877f, 1.093358f, 1.084804f, }, + { 2.230968f, 0.968956f, 0.615720f, 0.542594f, 0.589697f, }, + { 2.443527f, 2.128707f, 1.780354f, 1.424964f, 1.106474f, }, + { 0.202766f, 0.221654f, 0.253737f, 0.404291f, 1.663403f, }, + { 0.505346f, 1.337503f, 1.263272f, 0.954743f, 0.901882f, }, + { 0.385023f, 0.382150f, 0.399218f, 0.630553f, 3.211494f, }, + { 1.364681f, 1.413025f, 1.445785f, 1.648508f, 1.724301f, }, + { 0.991474f, 0.853670f, 0.661673f, 0.512336f, 0.418893f, }, + { 0.671308f, 0.761259f, 4.046266f, 1.926581f, 0.891469f, }, + { 0.634219f, 0.750043f, 0.930049f, 1.197664f, 1.262605f, }, + { 3.747086f, 2.672835f, 1.889530f, 1.215477f, 0.841197f, }, +}; + +const float UVG2CB2_NB[UVG2_CBSIZE][5]= +{ + { 0.234676f, 0.211553f, 0.198300f, 0.188137f, 0.189102f, }, + { 0.621072f, 0.655881f, 0.734889f, 0.880212f, 1.232321f, }, + { 0.372062f, 0.443795f, 0.705281f, 0.739519f, 0.743747f, }, + { 1.024051f, 1.049997f, 1.079370f, 1.098001f, 1.118202f, }, + { 0.494519f, 0.485721f, 0.479727f, 0.474381f, 0.473326f, }, + { 1.059136f, 1.014755f, 0.967436f, 0.915428f, 0.876510f, }, + { 1.887753f, 0.709034f, 0.440367f, 0.343384f, 0.369381f, }, + { 0.393820f, 0.574466f, 2.762395f, 1.407229f, 1.047606f, }, + { 0.370772f, 0.356840f, 0.349999f, 0.327343f, 0.316005f, }, + { 0.397170f, 0.417453f, 0.528104f, 2.356989f, 1.370805f, }, + { 0.566954f, 1.780471f, 0.793633f, 0.493204f, 0.504320f, }, + { 1.212718f, 1.247958f, 1.263151f, 1.270187f, 1.276770f, }, + { 0.388100f, 0.353795f, 0.474245f, 1.451972f, 0.869892f, }, + { 1.891456f, 1.262146f, 0.797925f, 0.583916f, 0.508257f, }, + { 0.969344f, 0.868915f, 0.772349f, 0.677308f, 0.608680f, }, + { 0.486474f, 0.539484f, 0.782305f, 0.907366f, 5.745668f, }, + { 0.289328f, 0.301705f, 0.347406f, 0.516255f, 1.165024f, }, + { 0.960737f, 0.937409f, 0.906673f, 0.874736f, 0.848802f, }, + { 0.400429f, 0.378419f, 0.439385f, 0.636950f, 2.656142f, }, + { 0.992977f, 1.083218f, 1.174551f, 1.247095f, 1.351591f, }, + { 0.359381f, 0.333729f, 0.374249f, 0.520426f, 1.795028f, }, + { 1.052276f, 1.045824f, 1.029194f, 1.005147f, 0.990365f, }, + { 2.640896f, 1.119783f, 0.637471f, 0.504513f, 0.497219f, }, + { 0.510018f, 0.592500f, 1.147016f, 3.572948f, 1.835225f, }, + { 0.617425f, 0.380988f, 0.295255f, 0.238370f, 0.230673f, }, + { 0.709915f, 0.749521f, 0.990016f, 1.431043f, 1.574221f, }, + { 0.653333f, 0.698564f, 0.760571f, 0.804532f, 0.831992f, }, + { 0.715875f, 3.498556f, 1.594958f, 0.912733f, 0.845138f, }, + { 0.898701f, 0.751704f, 0.624648f, 0.525250f, 0.464610f, }, + { 1.375977f, 1.297850f, 1.215381f, 1.145089f, 1.080297f, }, + { 0.561123f, 1.764692f, 1.703012f, 1.037951f, 0.817155f, }, + { 0.611282f, 0.835322f, 1.656358f, 2.071091f, 3.677700f, }, + { 0.305955f, 0.288104f, 0.277282f, 0.266999f, 0.262681f, }, + { 0.842437f, 0.860463f, 0.878879f, 0.890085f, 0.905076f, }, + { 0.415168f, 0.495616f, 1.605015f, 1.158622f, 1.086554f, }, + { 1.144592f, 1.160015f, 1.162718f, 1.153999f, 1.152784f, }, + { 0.726849f, 0.577021f, 0.459744f, 0.381537f, 0.341456f, }, + { 1.240211f, 1.143782f, 1.043599f, 0.936329f, 0.857727f, }, + { 1.329362f, 0.934539f, 0.696166f, 0.547436f, 0.475481f, }, + { 0.470979f, 1.229760f, 4.335935f, 2.037582f, 1.538102f, }, + { 0.448859f, 0.435001f, 0.410153f, 0.387131f, 0.374390f, }, + { 0.753476f, 0.847563f, 0.984091f, 1.208422f, 2.367011f, }, + { 0.781083f, 0.745169f, 0.707134f, 0.671579f, 0.640062f, }, + { 1.421280f, 1.411590f, 1.398311f, 1.358993f, 1.337416f, }, + { 0.377859f, 0.545381f, 1.647399f, 0.625545f, 0.420396f, }, + { 1.635438f, 1.273369f, 1.092522f, 0.862149f, 0.739370f, }, + { 0.921246f, 0.885689f, 0.844748f, 0.800456f, 0.770371f, }, + { 0.385947f, 0.408195f, 0.715197f, 4.936704f, 4.011602f, }, + { 0.295343f, 0.296573f, 0.339012f, 0.409703f, 0.531531f, }, + { 0.943088f, 0.948849f, 0.961247f, 0.966943f, 0.973872f, }, + { 0.376239f, 0.425963f, 0.446486f, 0.849370f, 3.799501f, }, + { 1.085015f, 1.208963f, 1.360517f, 1.478597f, 1.597861f, }, + { 0.600520f, 0.585154f, 0.557646f, 0.520820f, 0.498211f, }, + { 1.173770f, 1.141539f, 1.096824f, 1.055073f, 1.028510f, }, + { 3.669747f, 1.622178f, 0.809242f, 0.707943f, 0.704413f, }, + { 0.977405f, 1.162230f, 1.695878f, 2.019914f, 2.051052f, }, + { 1.221003f, 0.609077f, 0.389066f, 0.326390f, 0.333196f, }, + { 0.836930f, 0.904878f, 0.994299f, 1.088050f, 1.140088f, }, + { 0.812087f, 0.799997f, 0.786734f, 0.767023f, 0.753822f, }, + { 1.504493f, 1.542127f, 1.585432f, 1.577024f, 1.594146f, }, + { 0.649261f, 0.634440f, 0.619454f, 0.606033f, 0.621463f, }, + { 2.088260f, 1.685051f, 1.277621f, 1.004769f, 0.891082f, }, + { 1.133569f, 1.000746f, 0.882781f, 0.781417f, 0.706843f, }, + { 2.340990f, 6.501577f, 3.762808f, 3.059604f, 2.127793f, }, +}; + +const float frac_4sf[NB_SUBFR+2] = {0.25f,0.5f,0.75f,1.0f,1.0f,1.0f}; + +/* ERB table for PPP-ampl-quant */ +const float erb_WB[NUM_ERB_WB+1] = {0.0f, 92.8061f, 185.6121f, 278.4182f, 371.2243f, 464.0304f, 556.8364f, 649.6425f, 746.4f, 853.6f, + 972.5f, 1104.0f, 1251.8f, 1415.8f, 1599.2f, 1804.6f, 2035.2f, 2294.9f, 2588.4f, 2921.2f, 3300.1f, + 3733.7f, 4400.0f, 5300.0f, 6400.0f+1 + }; + +/* ERB table for PPP-ampl-quant */ +const float erb_NB[NUM_ERB_NB+1] = {0.0f, 92.8061f, 185.6121f, 278.4182f, 371.2243f, 464.0304f, 556.8364f, 649.6425f, 746.4f, 853.6f, + 972.5f, 1104.0f, 1251.8f, 1415.8f, 1599.2f, 1804.6f, 2035.2f, 2294.9f, 2588.4f, 2921.2f, 3300.1f, + 3733.7f, 4000.0f+1.0f + }; + + + + +/*Amplitude and power tables for PPP*/ + + +const float AmpCB1_WB[64][10] = +{ + { 0.6903076f, 0.1939697f, -0.0797119f, 0.4355469f, -0.3873291f, -0.2260742f, -0.3911133f, -0.5643311f, -0.2563477f, -0.6229248f, }, + { -0.1126709f, -0.0081787f, -0.8730469f, -0.6052246f, -0.2464600f, -0.2209473f, -1.0415039f, -0.0791016f, 0.8033447f, 0.9818115f, }, + { 0.0195313f, 0.0949707f, -0.1873779f, 0.1053467f, 0.6691895f, 0.2043457f, -0.4365234f, 0.0150146f, -0.3861084f, -0.4388428f, }, + { -0.1040039f, -0.0064697f, -0.1318359f, -0.3275146f, -0.3905029f, -0.1159668f, -0.1651611f, 0.7639160f, -0.1746826f, 0.1524658f, }, + { 0.2513428f, 0.0826416f, 0.0178223f, 0.1234131f, 0.1166992f, -0.2468262f, -0.0030518f, 0.0366211f, 0.0513916f, -0.7152100f, }, + { 0.1253662f, -0.0551758f, -0.8963623f, -0.1284180f, 0.4660645f, 0.1341553f, -0.1226807f, 0.0804443f, -0.0623779f, -0.0803223f, }, + { 0.2552490f, 0.0878906f, -0.0732422f, 0.0177002f, -0.1835938f, -0.2094727f, -0.0539551f, -0.2651367f, -0.1837158f, 0.3298340f, }, + { 0.0892334f, 0.1798096f, -0.0260010f, -0.5029297f, -0.3632813f, 0.0839844f, 0.3912354f, 0.1480713f, 0.0828857f, 0.0283203f, }, + { 0.4482422f, 0.5822754f, -0.1462402f, -0.0363770f, -0.2092285f, -0.4478760f, -0.3458252f, -0.0810547f, -0.2269287f, -0.2905273f, }, + { -0.1427002f, -0.1944580f, -0.0552979f, 0.0360107f, -0.1495361f, -0.3796387f, -0.2167969f, 0.2578125f, 0.3308105f, 0.4068604f, }, + { 0.1247559f, 0.1523438f, 0.1331787f, 0.1420898f, 0.1464844f, 0.2175293f, -0.0987549f, -0.2814941f, -0.3813477f, -0.2678223f, }, + { -0.1912842f, 0.0567627f, 0.2713623f, -0.1588135f, -0.0565186f, -0.2633057f, 0.0889893f, 0.2781982f, -0.2365723f, 0.0744629f, }, + { 0.0533447f, -0.0980225f, -0.1251221f, 0.0946045f, -0.0208740f, -0.0777588f, 0.0198975f, 0.2747803f, 0.0385742f, -0.2030029f, }, + { -0.5032959f, -0.0024414f, -0.3450928f, -0.1866455f, -0.1752930f, 0.4207764f, 0.0096436f, -0.0334473f, 0.2014160f, 0.5001221f, }, + { 0.2891846f, 0.1131592f, 0.0546875f, -0.0548096f, 0.0357666f, -0.0291748f, -0.1254883f, -0.5865479f, 0.1652832f, 0.0526123f, }, + { -0.2708740f, -0.0598145f, -0.4698486f, 0.2000732f, -0.3570557f, 0.0997314f, 0.1812744f, 0.3084717f, 0.6645508f, -0.2434082f, }, + { 0.1801758f, 0.0617676f, -0.2005615f, 0.2445068f, -0.2045898f, -0.0961914f, -0.2052002f, -0.2454834f, 0.1695557f, 0.0551758f, }, + { 0.0723877f, 0.0003662f, -0.1464844f, -0.4866943f, -0.1994629f, -0.5261230f, -0.0837402f, 0.1076660f, 0.7611084f, 0.2954102f, }, + { -0.0239258f, -0.1534424f, -0.2487793f, -0.0607910f, 0.1701660f, 0.0819092f, -0.2810059f, -0.0987549f, -0.0544434f, 0.4448242f, }, + { -0.2005615f, -0.2812500f, -0.1010742f, 0.0128174f, -0.0394287f, -0.4768066f, -0.1171875f, 0.8940430f, 0.3778076f, -0.0959473f, }, + { 0.0115967f, 0.0772705f, 0.1545410f, 0.0915527f, 0.1842041f, -0.2481689f, -0.3825684f, 0.0527344f, 0.1254883f, -0.2227783f, }, + { 0.1535645f, 0.0312500f, -0.3966064f, -0.8383789f, -0.0638428f, -0.0396729f, -0.2171631f, 0.5264893f, 0.3081055f, 0.4190674f, }, + { -0.0732422f, -0.0500488f, -0.0107422f, 0.0500488f, -0.1442871f, -0.1391602f, -0.1767578f, -0.1640625f, -0.6193848f, 0.7390137f, }, + { 0.2678223f, 0.1837158f, -0.0831299f, -0.2939453f, 0.1679688f, 0.1695557f, 0.1475830f, 0.1279297f, -0.5125732f, -0.3587646f, }, + { 0.2264404f, 0.2128906f, -0.1640625f, -0.1746826f, -0.2386475f, -0.2203369f, -0.6093750f, 0.0625000f, 0.0761719f, 0.3355713f, }, + { -0.4206543f, -0.1483154f, -0.4594727f, -0.2647705f, -0.4395752f, -0.1612549f, 0.0081787f, 0.5280762f, 0.8085938f, 0.7099609f, }, + { -0.0407715f, -0.2131348f, -0.0538330f, -0.0920410f, 0.2261963f, 0.4747314f, -0.0726318f, -0.0601807f, 0.0538330f, -0.0989990f, }, + { -0.0058594f, -0.0932617f, -0.1798096f, -0.0833740f, 0.0736084f, -0.2141113f, 0.0952148f, 0.0852051f, 0.1323242f, 0.2091064f, }, + { 0.0683594f, -0.0986328f, -0.0920410f, -0.3527832f, -0.1470947f, -0.0388184f, -0.1246338f, 0.3900146f, 0.6949463f, -0.5618896f, }, + { 0.1639404f, -0.1295166f, -0.2979736f, -0.2177734f, 0.0880127f, 0.0325928f, 0.0277100f, -0.0759277f, 0.3677979f, -0.0937500f, }, + { -0.0576172f, 0.0109863f, 0.0015869f, 0.0354004f, 0.1287842f, 0.1157227f, 0.1973877f, -0.2890625f, -0.1326904f, 0.1346436f, }, + { -0.5839844f, -0.4726563f, 0.6256104f, -0.3073730f, -0.0262451f, 0.8498535f, 0.1336670f, -0.1856689f, 0.2552490f, -0.3615723f, }, + { 0.2789307f, 0.1363525f, 0.1433105f, 0.3216553f, -0.2327881f, -0.1235352f, 0.0993652f, -0.0509033f, -0.2639160f, -0.3424072f, }, + { -0.1450195f, -0.0863037f, -0.0986328f, -0.2144775f, 0.0317383f, -0.1334229f, -0.4830322f, -0.3986816f, 0.5043945f, 0.7299805f, }, + { 0.0216064f, -0.1804199f, 0.1171875f, 0.2476807f, 0.4869385f, 0.0728760f, -0.3737793f, -0.4809570f, -0.2060547f, 0.0288086f, }, + { -0.1903076f, 0.0183105f, 0.2968750f, 0.0424805f, -0.0295410f, -0.2458496f, -0.1253662f, 0.7687988f, -0.3609619f, -0.4833984f, }, + { 0.1330566f, 0.1237793f, -0.1539307f, -0.0908203f, -0.1164551f, -0.1145020f, -0.4532471f, -0.3994141f, 0.6538086f, -0.2875977f, }, + { -0.1756592f, 0.4648438f, -0.2844238f, -0.5416260f, 0.6319580f, -0.4401855f, -0.1687012f, 0.2226563f, 0.0496826f, 0.0396729f, }, + { 0.0792236f, 0.0402832f, 0.0103760f, 0.0251465f, -0.0506592f, 0.0223389f, -0.0788574f, 0.0734863f, -0.3242188f, 0.0986328f, }, + { 0.1268311f, 0.0035400f, -0.3908691f, -0.7529297f, -0.4443359f, 0.4560547f, 0.5106201f, 0.4832764f, 0.0402832f, 0.0413818f, }, + { 0.3297119f, 0.0418701f, 0.1832275f, 0.2293701f, -0.3898926f, -0.5673828f, -0.1989746f, 0.2021484f, -0.1926270f, -0.0102539f, }, + { -0.3741455f, -0.5036621f, 0.0029297f, -0.0317383f, 0.0321045f, -0.2081299f, -0.1573486f, 0.2968750f, 0.1500244f, 0.9132080f, }, + { 0.3156738f, 0.2070313f, 0.0788574f, -0.2164307f, -0.0966797f, 0.2358398f, -0.2329102f, -0.2315674f, -0.1378174f, 0.0136719f, }, + { -0.6917725f, -0.1943359f, 0.2750244f, -0.1196289f, 0.1929932f, 0.0257568f, 0.6441650f, 0.5915527f, -0.0351563f, -0.0194092f, }, + { 0.1166992f, 0.1459961f, 0.0941162f, -0.1187744f, -0.2178955f, -0.0629883f, -0.1239014f, 0.1033936f, 0.0749512f, -0.0965576f, }, + { -0.0539551f, -0.1945801f, -0.5654297f, -0.5361328f, -0.0507813f, 0.1706543f, 0.3137207f, 0.0917969f, 0.0322266f, 0.8020020f, }, + { 0.2020264f, 0.0666504f, 0.1511230f, -0.1662598f, -0.1623535f, -0.2447510f, 0.4382324f, -0.2630615f, -0.0224609f, -0.1494141f, }, + { -0.1772461f, -0.1871338f, -0.0651855f, 0.1232910f, -0.2083740f, 0.0977783f, 0.4428711f, -0.0352783f, 0.2946777f, 0.0161133f, }, + { 0.3226318f, -0.3433838f, -0.5522461f, 0.6215820f, -0.8986816f, 0.0903320f, 0.0522461f, -0.0622559f, 0.0098877f, -0.1475830f, }, + { 0.0751953f, 0.1774902f, 0.2271729f, -0.4831543f, -0.4985352f, 0.0230713f, -0.1488037f, -0.1068115f, 0.4594727f, 0.2546387f, }, + { -0.1896973f, -0.2528076f, 0.1849365f, 0.4140625f, 0.0014648f, -0.0837402f, -0.2946777f, -0.1687012f, 0.0214844f, 0.2056885f, }, + { 0.2508545f, -0.6955566f, 0.1931152f, 0.5025635f, -0.5915527f, -0.3566895f, 0.0744629f, 0.2541504f, 0.5715332f, -0.3035889f, }, + { 0.0424805f, 0.2756348f, -0.0412598f, -0.1683350f, 0.1796875f, 0.0754395f, -0.0246582f, -0.1369629f, -0.0092773f, -0.3012695f, }, + { -0.1484375f, -0.1203613f, -0.0399170f, -0.1759033f, 0.0124512f, 0.0491943f, -0.2569580f, 0.2943115f, 0.1843262f, 0.1572266f, }, + { -0.0872803f, -0.0704346f, 0.1311035f, 0.3092041f, -0.4298096f, -0.4210205f, 0.2612305f, -0.0916748f, -0.0374756f, 0.4644775f, }, + { 0.0192871f, -0.1690674f, -0.0493164f, -0.1682129f, -0.2377930f, 0.4620361f, 0.5146484f, 0.3255615f, -0.2312012f, -0.1903076f, }, + { 0.1265869f, 0.1673584f, 0.1207275f, -0.0250244f, -0.0406494f, -0.5839844f, -0.4185791f, -0.1566162f, 0.4027100f, 0.1048584f, }, + { -0.6008301f, -0.6690674f, -0.1459961f, -0.2133789f, -0.0878906f, 0.0629883f, 0.0137939f, 0.5603027f, 0.8631592f, 0.5303955f, }, + { -0.6993408f, -0.4714355f, 0.4382324f, 0.1785889f, 0.8659668f, 0.6092529f, 0.1042480f, -0.0080566f, -0.1989746f, -0.0837402f, }, + { -0.1126709f, -0.3986816f, -0.2426758f, 0.2862549f, 0.0958252f, -0.1733398f, 0.3666992f, 0.3581543f, -0.1519775f, -0.0079346f, }, + { -0.3291016f, -0.3769531f, -0.1755371f, 0.0749512f, 0.1933594f, -0.0291748f, -0.1894531f, 0.0708008f, 0.7672119f, -0.2042236f, }, + { -0.1950684f, -0.4904785f, -0.2330322f, 0.0911865f, 0.3895264f, 0.0446777f, 0.1790771f, -0.2359619f, 0.3367920f, 0.3422852f, }, + { 0.0632324f, 0.0235596f, -0.1402588f, -0.3793945f, 0.0538330f, 0.1779785f, 0.3406982f, -0.5042725f, 0.3288574f, 0.4116211f, }, + { -0.6131592f, -0.7923584f, 0.2189941f, 0.3343506f, 0.1785889f, 0.7132568f, 0.3502197f, 0.2432861f, -0.1719971f, 0.5898438f, }, +}; + +const float AmpCB2_WB[64][NUM_ERB_WB-11] = +{ + { -0.6440430f, -0.9412842f, -0.4294434f, -0.2949219f, -0.0466309f, 0.0389404f, -0.2319336f, -0.1098633f, 0.2105713f, 0.1079102f, 0.4969482f, }, + { -0.4946289f, -0.2966309f, -0.0410156f, 0.2607422f, 0.3669434f, 0.0721436f, -0.4752197f, -0.3333740f, 0.3204346f, 0.2917480f, -0.1278076f, }, + { -0.1077881f, -0.4111328f, -0.5169678f, -0.4548340f, 0.0230713f, -0.2200928f, 0.0957031f, 0.2851563f, 0.0251465f, -0.2612305f, 0.3663330f, }, + { -0.0891113f, -0.2781982f, 0.0103760f, -0.4144287f, 0.5330811f, 0.2702637f, -0.0310059f, -0.3801270f, -0.2866211f, 0.3372803f, 0.0837402f, }, + { -0.9149170f, -0.8078613f, 0.3862305f, -0.4830322f, -0.3272705f, -0.2501221f, 0.2025146f, 0.4436035f, 0.3615723f, 0.1921387f, 0.0462646f, }, + { -0.3024902f, 0.3492432f, 0.0751953f, 0.1372070f, 0.0250244f, -0.3753662f, -0.0424805f, -0.2448730f, -0.0109863f, 0.0928955f, 0.1412354f, }, + { -0.0139160f, -1.1547852f, -0.3400879f, -0.3972168f, -0.1367188f, -0.1831055f, -0.0544434f, 0.3460693f, -0.0383301f, 0.3912354f, 0.2581787f, }, + { -0.1021729f, -0.0318604f, 0.0043945f, 0.0097656f, -0.0592041f, 0.1383057f, 0.2592773f, -0.1258545f, -0.0489502f, -0.3864746f, 0.1397705f, }, + { -0.1972656f, -0.4180908f, -0.3748779f, -0.8411865f, -0.5124512f, 0.2797852f, 0.6298828f, -0.0056152f, 0.1745605f, 0.0341797f, 0.1682129f, }, + { 0.2075195f, -0.2042236f, -0.1374512f, 0.6433105f, 0.6220703f, -0.1190186f, -0.1306152f, 0.1604004f, -0.2916260f, -0.3640137f, 0.0024414f, }, + { -0.3928223f, -0.1088867f, -0.0776367f, -0.1069336f, -0.0368652f, -0.3568115f, -0.3955078f, 0.5030518f, 0.1983643f, -0.0679932f, 0.1213379f, }, + { 0.0664063f, 0.3243408f, 0.8707275f, -0.0333252f, -0.4309082f, -0.1732178f, 0.1746826f, -0.1142578f, -0.3200684f, 0.0369873f, 0.0091553f, }, + { -0.6645508f, -0.6773682f, 0.5106201f, 0.1523438f, 0.4240723f, -0.0963135f, 0.2899170f, -0.2170410f, 0.2026367f, 0.1855469f, -0.1749268f, }, + { -0.4940186f, 0.0648193f, 0.8546143f, 0.0848389f, 0.2305908f, 0.5201416f, -0.3406982f, -0.1900635f, -0.3637695f, -0.0385742f, 0.0506592f, }, + { 0.1384277f, 0.1832275f, -0.8450928f, 0.0635986f, -0.3825684f, -0.2211914f, 0.2255859f, 0.0825195f, -0.2115479f, 0.0895996f, 0.2694092f, }, + { 0.2476807f, -0.0581055f, -0.2412109f, -0.0196533f, 0.0035400f, 0.8724365f, -0.2165527f, 0.0878906f, -0.1306152f, -0.0454102f, -0.1984863f, }, + { -0.7901611f, -0.2988281f, -0.6390381f, -0.3236084f, -0.2197266f, -0.1802979f, -0.0936279f, 0.1629639f, 0.0574951f, 0.5928955f, 0.1083984f, }, + { 0.0723877f, -0.0451660f, 0.0239258f, 0.1107178f, 0.0212402f, 0.0679932f, -0.0878906f, -0.1634521f, 0.1940918f, 0.0045166f, -0.1522217f, }, + { -0.1595459f, 0.0336914f, -0.2122803f, -0.7363281f, -0.3769531f, -0.3050537f, -0.0606689f, -0.0479736f, -0.0694580f, 0.3665771f, 0.3288574f, }, + { 0.4578857f, 0.5678711f, -0.0314941f, -0.1593018f, 0.0213623f, 0.0230713f, -0.0419922f, -0.2906494f, -0.2431641f, 0.0565186f, 0.0645752f, }, + { -0.7781982f, 0.4841309f, -0.4343262f, -0.3663330f, -0.0781250f, 0.3804932f, 0.1367188f, 0.1179199f, 0.1606445f, -0.0684814f, 0.0032959f, }, + { 0.3410645f, 0.3455811f, 0.4287109f, 0.4215088f, -0.0510254f, -0.2830811f, -0.8228760f, -0.4202881f, 0.0097656f, 0.1563721f, 0.2064209f, }, + { 0.1831055f, -0.0721436f, -0.0902100f, 0.2911377f, -0.5708008f, -0.7106934f, -0.1754150f, 0.0891113f, 0.4385986f, -0.0533447f, 0.1330566f, }, + { 0.4268799f, -0.2358398f, 0.3483887f, 0.5930176f, 0.3239746f, 0.1156006f, 0.2293701f, -0.5023193f, 0.3295898f, -0.3774414f, -0.1860352f, }, + { 0.0274658f, -1.0097656f, -0.8222656f, -0.1558838f, 0.3651123f, 0.3641357f, 0.1378174f, -0.2027588f, 0.3438721f, 0.0571289f, 0.0599365f, }, + { -0.0908203f, 0.0476074f, 0.0826416f, 0.9923096f, -0.3820801f, -0.0838623f, -0.0528564f, 0.1816406f, -0.4593506f, -0.0216064f, -0.0709229f, }, + { -0.0932617f, 0.0047607f, 0.1876221f, -0.2689209f, -0.2048340f, 0.0321045f, -0.1481934f, 0.2655029f, -0.2266846f, 0.3780518f, -0.1091309f, }, + { 0.5135498f, -0.2371826f, -0.1018066f, 0.1846924f, -0.5032959f, 0.4859619f, 0.7374268f, 0.0797119f, -0.0924072f, -0.0382080f, -0.3691406f, }, + { -0.5632324f, -0.3831787f, -0.3620605f, 0.0217285f, 0.6049805f, -0.0521240f, -0.0050049f, 0.2900391f, 0.1230469f, -0.1649170f, -0.0112305f, }, + { 0.1193848f, 0.2438965f, 0.6281738f, 0.2525635f, 0.0142822f, -0.2141113f, -0.3364258f, 0.5401611f, 0.0205078f, -0.2205811f, -0.2149658f, }, + { -0.1483154f, 0.0217285f, -0.1906738f, -0.4112549f, -0.1121826f, -0.3144531f, 0.4411621f, 0.6064453f, -0.0036621f, -0.0483398f, -0.1405029f, }, + { -0.1398926f, 0.1059570f, 0.1309814f, -0.0438232f, 0.3334961f, 0.0666504f, 0.5408936f, -0.0391846f, -0.1319580f, 0.1721191f, -0.3923340f, }, + { -0.2827148f, -0.5968018f, -0.3002930f, -0.4692383f, -0.8939209f, -0.1755371f, -0.1816406f, 0.2257080f, 0.4927979f, 0.2955322f, 0.3292236f, }, + { -0.2895508f, -0.2291260f, 0.0817871f, 0.4484863f, -0.1107178f, 0.1083984f, -0.4520264f, 0.0457764f, -0.1560059f, -0.1802979f, 0.3052979f, }, + { -0.1142578f, -0.2053223f, -0.1651611f, -0.0408936f, -0.5419922f, 0.0467529f, -0.3332520f, -0.2600098f, -0.1348877f, 0.1938477f, 0.4077148f, }, + { 0.5878906f, -0.4910889f, 0.0612793f, -0.5061035f, 0.0288086f, 0.5469971f, 0.0718994f, -0.4511719f, 0.1008301f, -0.0118408f, 0.0270996f, }, + { -0.9810791f, -0.2739258f, 0.0173340f, 0.0988770f, -0.2679443f, 0.1605225f, 0.0800781f, 0.2320557f, -0.0592041f, 0.0386963f, 0.1845703f, }, + { 0.1788330f, -0.2473145f, 0.2261963f, 0.1134033f, 0.2038574f, -0.3339844f, -0.0565186f, -0.1020508f, -0.6037598f, -0.0163574f, 0.3380127f, }, + { 0.3627930f, -0.6284180f, -0.3841553f, 0.1114502f, -0.1810303f, 0.0325928f, -0.1904297f, 0.4764404f, 0.1839600f, 0.1348877f, -0.1826172f, }, + { 0.0256348f, -0.1459961f, 0.4594727f, 0.0733643f, 0.1989746f, 0.4689941f, 0.7780762f, -0.1578369f, -0.5560303f, -0.3768311f, 0.0242920f, }, + { -0.2340088f, -0.4066162f, -0.2828369f, -0.2165527f, 0.0584717f, 0.4531250f, 0.3331299f, 0.1597900f, -0.3719482f, -0.0627441f, 0.1051025f, }, + { -0.0260010f, 0.1607666f, -0.2484131f, 0.5333252f, 0.6381836f, 0.1149902f, -0.3725586f, -0.2827148f, -0.4122314f, 0.1370850f, -0.0079346f, }, + { 0.3060303f, 0.3309326f, -0.2558594f, -0.2641602f, -0.3215332f, -0.6365967f, -0.4783936f, 0.1893311f, -0.0057373f, 0.2429199f, 0.2893066f, }, + { 0.2471924f, -0.2930908f, 0.5899658f, -0.4735107f, -0.0197754f, -0.3760986f, 0.0611572f, -0.0622559f, 0.3349609f, -0.1107178f, 0.0308838f, }, + { -0.2131348f, -0.3076172f, 0.4172363f, -0.1783447f, 0.2612305f, 0.3060303f, 0.0164795f, 0.1778564f, 0.3900146f, -0.1558838f, -0.3122559f, }, + { -0.0080566f, 1.3244629f, -0.1993408f, -0.1282959f, -0.4194336f, -0.1973877f, 0.1755371f, -0.1502686f, -0.2128906f, 0.0849609f, -0.0424805f, }, + { 0.4191895f, 0.2589111f, -0.1988525f, -0.3002930f, -0.4962158f, 0.1414795f, -0.1572266f, 0.3470459f, 0.0850830f, -0.1052246f, 0.0004883f, }, + { 0.1179199f, -0.0541992f, -0.2270508f, 0.1770020f, 0.7844238f, 0.6767578f, 0.1777344f, -0.3449707f, -0.1590576f, -0.3391113f, -0.1560059f, }, + { -0.8125000f, -0.3956299f, -0.8646240f, 0.2727051f, 0.0249023f, 0.2139893f, 0.0980225f, 0.0609131f, 0.2003174f, 0.0106201f, 0.1795654f, }, + { -0.1617432f, 0.0485840f, 0.3641357f, 0.5297852f, -0.1687012f, 0.0897217f, -0.0732422f, -0.5701904f, -0.0310059f, 0.2840576f, -0.1230469f, }, + { -0.0175781f, -0.1773682f, -0.2204590f, -0.2037354f, 0.0482178f, -0.4010010f, -0.2200928f, -0.2586670f, 0.1503906f, 0.3557129f, 0.1806641f, }, + { 1.0510254f, 0.2182617f, 0.3227539f, 0.1658936f, 0.4617920f, -0.0134277f, -0.1634521f, -0.1632080f, -0.4183350f, -0.0769043f, -0.1451416f, }, + { -0.3125000f, 0.1191406f, 0.0589600f, -0.3349609f, -0.4459229f, -0.1573486f, 0.3552246f, -0.2974854f, 0.3870850f, 0.1805420f, 0.0191650f, }, + { 0.1004639f, 0.5653076f, -0.2331543f, 0.4560547f, -0.0517578f, -0.0189209f, -0.6677246f, -0.0904541f, 0.4674072f, -0.3410645f, -0.0067139f, }, + { -0.1766357f, -0.4234619f, -0.2376709f, 0.3557129f, -0.0074463f, -0.4187012f, 0.4326172f, -0.2279053f, 0.3645020f, 0.1231689f, -0.1282959f, }, + { 0.0885010f, 0.3580322f, 0.3571777f, 0.7139893f, 0.0313721f, -0.3254395f, 0.7673340f, -0.2785645f, -0.3659668f, -0.3144531f, -0.1190186f, }, + { -0.4461670f, -0.2279053f, -0.6152344f, -0.1757813f, 0.4323730f, -0.0736084f, 0.5866699f, -0.3427734f, -0.1993408f, 0.1694336f, 0.1402588f, }, + { -0.1972656f, -0.2259521f, 0.2590332f, 0.5465088f, 0.3033447f, 0.1679688f, 0.0880127f, 0.2653809f, -0.3750000f, 0.1682129f, -0.3142090f, }, + { -0.0045166f, 0.1613770f, -0.2009277f, -0.4409180f, 0.5423584f, 0.1967773f, -0.4154053f, 0.0867920f, 0.0161133f, 0.0145264f, -0.0277100f, }, + { 0.6175537f, 0.3530273f, 0.1025391f, 0.6667480f, -0.4237061f, -0.1635742f, 0.2559814f, 0.0174561f, 0.2136230f, -0.3725586f, -0.2358398f, }, + { -0.7753906f, -0.5085449f, -0.0787354f, 0.5269775f, 0.0772705f, 0.4493408f, 0.3431396f, 0.2863770f, 0.2897949f, -0.3660889f, -0.1544189f, }, + { -0.0256348f, 0.6243896f, 0.5678711f, 0.1593018f, 0.4521484f, -0.1777344f, -0.0374756f, -0.0557861f, -0.1776123f, -0.4370117f, 0.0822754f, }, + { 0.2703857f, 0.3000488f, -0.3687744f, -0.0080566f, 0.3094482f, -0.0795898f, 0.1496582f, 0.0836182f, 0.1068115f, -0.2139893f, -0.1420898f, }, + { -0.0743408f, 0.4204102f, 0.0687256f, 0.4670410f, 0.1961670f, 0.4636230f, 0.1690674f, 0.4763184f, -0.2429199f, -0.4978027f, -0.3062744f, }, +}; + +const float AmpCB1_NB[64][10] = +{ + { -0.1654053f, 0.0225830f, -0.0270996f, -0.0269775f, 0.2412109f, 0.3807373f, 0.0659180f, 0.1627197f, -0.4450684f, -0.3065186f, }, + { -0.1195068f, 0.2031250f, 0.2547607f, 0.1160889f, 0.0960693f, -0.2059326f, -0.1043701f, 0.1945801f, 0.1542969f, -0.6091309f, }, + { -0.2388916f, -0.0262451f, -0.1037598f, 0.1671143f, -0.0137939f, 0.3101807f, -0.3544922f, 0.0906982f, 0.0773926f, -0.0802002f, }, + { -0.4196777f, -0.2498779f, 0.0861816f, 0.0103760f, -0.0727539f, -0.0061035f, 0.0258789f, 0.1152344f, 0.0144043f, 0.1684570f, }, + { -0.1468506f, -0.0095215f, -0.0260010f, -0.2210693f, -0.0953369f, -0.2404785f, 0.8065186f, -0.3626709f, 0.0179443f, -0.1810303f, }, + { 0.0046387f, 0.6844482f, 0.6374512f, -0.5574951f, -0.4931641f, -0.2757568f, -0.3796387f, -0.2587891f, 0.1137695f, -0.0288086f, }, + { -0.1284180f, 0.1268311f, -0.1064453f, 0.0407715f, -0.1121826f, 0.3370361f, 0.4052734f, -0.7114258f, 0.0064697f, 0.1297607f, }, + { -0.1298828f, -0.0091553f, -0.1239014f, -0.2608643f, -0.0881348f, 0.0689697f, 0.0767822f, 0.2393799f, -0.0554199f, 0.1057129f, }, + { -0.1083984f, 0.3237305f, 0.2436523f, -0.2648926f, -0.1080322f, 0.4058838f, -0.0787354f, -0.2316895f, -0.1201172f, -0.0784912f, }, + { -0.1230469f, 0.3017578f, 0.2929688f, -0.4526367f, -0.2939453f, -0.1282959f, 0.2476807f, 0.1656494f, -0.0776367f, -0.0573730f, }, + { -0.1595459f, 0.0799561f, 0.0809326f, 0.0035400f, 0.1088867f, -0.0115967f, -0.0111084f, -0.3620605f, -0.1965332f, 0.3243408f, }, + { -0.2655029f, -0.3869629f, -0.4637451f, -0.3741455f, 0.1379395f, 0.1649170f, 0.4655762f, 0.3406982f, 0.1804199f, 0.1855469f, }, + { -0.1618652f, -0.0634766f, -0.0844727f, 0.1097412f, 0.2415771f, -0.0484619f, -0.0496826f, 0.0549316f, -0.0694580f, -0.0745850f, }, + { -0.1499023f, 0.1054688f, 0.3111572f, 0.3743896f, -0.3065186f, -0.5782471f, -0.3297119f, -0.0371094f, 0.0830078f, 0.1740723f, }, + { -0.1306152f, -0.0023193f, -0.1931152f, -0.3433838f, -0.2236328f, 0.3674316f, 0.0305176f, -0.0748291f, 0.4138184f, -0.0208740f, }, + { -0.1770020f, -0.0509033f, -0.0943604f, -0.0794678f, -0.0494385f, -0.2812500f, -0.0952148f, 0.8125000f, -0.3991699f, -0.1613770f, }, + { 0.0085449f, 0.6231689f, 0.3908691f, -0.0101318f, -0.1129150f, -0.0559082f, 0.1468506f, -0.1931152f, -0.5075684f, -0.4431152f, }, + { -0.2077637f, -0.1036377f, -0.0067139f, -0.1203613f, -0.2396240f, -0.1391602f, -0.2370605f, 0.4085693f, 0.4304199f, -0.0531006f, }, + { -0.1744385f, -0.2550049f, -0.1977539f, -0.1551514f, 0.3480225f, 0.2666016f, -0.3017578f, 0.3925781f, 0.3521729f, -0.3566895f, }, + { -0.1485596f, 0.0104980f, -0.0227051f, -0.0340576f, -0.0910645f, 0.1572266f, 0.3681641f, -0.0794678f, -0.3319092f, 0.0386963f, }, + { -0.1595459f, -0.0155029f, -0.1354980f, 0.1695557f, 0.0258789f, 0.2176514f, 0.3197021f, -0.2097168f, 0.2191162f, -0.4987793f, }, + { -0.1580811f, 0.0906982f, 0.0367432f, -0.2225342f, -0.0272217f, -0.0794678f, -0.2165527f, -0.0494385f, 0.2059326f, 0.2479248f, }, + { -0.1055908f, 0.1292725f, -0.0477295f, 0.0616455f, -0.3343506f, -0.3385010f, 0.0019531f, -0.3613281f, 0.3748779f, 0.4058838f, }, + { -0.0965576f, 0.2808838f, 0.0531006f, 0.0130615f, -0.4930420f, 0.0977783f, -0.1494141f, 0.2263184f, -0.1268311f, 0.0618896f, }, + { -0.0632324f, 0.1217041f, 0.1021729f, 0.4041748f, 0.0617676f, 0.1252441f, -0.0283203f, -0.2343750f, -0.4765625f, 0.0495605f, }, + { -0.2266846f, -0.0645752f, -0.0947266f, -0.0854492f, -0.0809326f, -0.1855469f, 0.2073975f, 0.0993652f, 0.2543945f, -0.0582275f, }, + { -0.1636963f, -0.1370850f, -0.3129883f, -0.3398438f, 0.2999268f, 0.3934326f, -0.1170654f, 0.0469971f, -0.2275391f, 0.4582520f, }, + { -0.1649170f, -0.1644287f, -0.2720947f, -0.3518066f, -0.1295166f, -0.1829834f, -0.3696289f, 0.4030762f, 0.2746582f, 0.6761475f, }, + { -0.1168213f, -0.0415039f, 0.0032959f, 0.1840820f, 0.0203857f, -0.4288330f, 0.2061768f, 0.3145752f, -0.2209473f, -0.0629883f, }, + { -0.1295166f, 0.2650146f, 0.2165527f, 0.2479248f, 0.1126709f, -0.2359619f, -0.2001953f, -0.3516846f, 0.1048584f, -0.1018066f, }, + { 0.0498047f, 0.3005371f, 0.2530518f, 0.2572021f, -0.3260498f, 0.1391602f, -0.4268799f, -0.3048096f, 0.3642578f, -0.3304443f, }, + { -0.2150879f, -0.3081055f, -0.2680664f, 0.0340576f, -0.3149414f, 0.0582275f, 0.2814941f, 0.5670166f, 0.0845947f, -0.1109619f, }, + { -0.1329346f, 0.2382813f, 0.3703613f, -0.2185059f, 0.0959473f, -0.1402588f, -0.3804932f, 0.4400635f, -0.2359619f, -0.2302246f, }, + { -0.1170654f, 0.1140137f, 0.0300293f, -0.2657471f, -0.2978516f, 0.1655273f, 0.1063232f, 0.4238281f, 0.3122559f, -0.5507813f, }, + { -0.0954590f, 0.1540527f, 0.1090088f, 0.2415771f, 0.2912598f, -0.2208252f, -0.5318604f, -0.0478516f, -0.2353516f, 0.1923828f, }, + { -0.2137451f, -0.0399170f, -0.1242676f, -0.0753174f, -0.2893066f, -0.3552246f, 0.5163574f, -0.0109863f, -0.1661377f, 0.4389648f, }, + { -0.1304932f, -0.0384521f, -0.0197754f, -0.0413818f, -0.0382080f, 0.0040283f, 0.5717773f, 0.3431396f, -0.3316650f, -0.4497070f, }, + { 0.0848389f, 0.5574951f, -0.0909424f, -0.2821045f, -0.0947266f, -0.3173828f, -0.1009521f, -0.1269531f, -0.1217041f, 0.3027344f, }, + { -0.1890869f, -0.0913086f, -0.0759277f, -0.0317383f, 0.1782227f, 0.1362305f, -0.0368652f, -0.3087158f, 0.2631836f, -0.0051270f, }, + { -0.1608887f, -0.0693359f, -0.0324707f, -0.0544434f, -0.2700195f, 0.3283691f, -0.5699463f, 0.6500244f, -0.2468262f, 0.1657715f, }, + { -0.1601563f, 0.2799072f, 0.1865234f, 0.0861816f, 0.1184082f, -0.0355225f, 0.0467529f, -0.0833740f, -0.1870117f, -0.2249756f, }, + { -0.1683350f, 0.1031494f, 0.1486816f, 0.0482178f, -0.2299805f, 0.0017090f, 0.0825195f, -0.2088623f, 0.0970459f, 0.0354004f, }, + { -0.0905762f, 0.0471191f, -0.0531006f, 0.0501709f, 0.1600342f, 0.0670166f, -0.5103760f, -0.6008301f, 0.1827393f, 0.5450439f, }, + { -0.2102051f, -0.0853271f, -0.2390137f, -0.5036621f, -0.4549561f, -0.0799561f, 0.1895752f, 0.2188721f, 0.6021729f, 0.3729248f, }, + { -0.1538086f, -0.0754395f, 0.0653076f, -0.2451172f, 0.4641113f, -0.4619141f, 0.3084717f, -0.1016846f, 0.0235596f, -0.1296387f, }, + { -0.1057129f, 0.1004639f, 0.1906738f, 0.0179443f, -0.0760498f, -0.2207031f, -0.1341553f, 0.0847168f, -0.0704346f, 0.0909424f, }, + { -0.2785645f, -0.5052490f, -0.3870850f, 0.0092773f, 0.0030518f, -0.1314697f, 0.0582275f, 0.0665283f, 0.7423096f, 0.3959961f, }, + { -0.1625977f, -0.0958252f, 0.0119629f, -0.2052002f, -0.4398193f, -0.4805908f, 0.0639648f, 0.5673828f, 0.1359863f, 0.3109131f, }, + { -0.1397705f, 0.0496826f, 0.2478027f, 0.3808594f, -0.2122803f, -0.0626221f, -0.0632324f, 0.1617432f, -0.2075195f, -0.3491211f, }, + { -0.1741943f, 0.0634766f, -0.1269531f, -0.0966797f, -0.0446777f, -0.2653809f, -0.0637207f, -0.0292969f, 0.6909180f, -0.3861084f, }, + { -0.1768799f, -0.2017822f, -0.1839600f, 0.0709229f, 0.1633301f, -0.3206787f, -0.2274170f, 0.2235107f, 0.1588135f, 0.2570801f, }, + { -0.1528320f, 0.1188965f, 0.0242920f, 0.0083008f, -0.0084229f, -0.1060791f, 0.1054688f, 0.2896729f, -0.7102051f, 0.3507080f, }, + { 0.0031738f, 0.1186523f, 0.0438232f, -0.0684814f, -0.0476074f, 0.0458984f, 0.0274658f, 0.0631104f, 0.0792236f, -0.2156982f, }, + { -0.0797119f, 0.2645264f, 0.1076660f, -0.0852051f, 0.0261230f, -0.4985352f, -0.5046387f, 0.2553711f, 0.3415527f, -0.0638428f, }, + { -0.1223145f, 0.0593262f, 0.0791016f, -0.1320801f, 0.0493164f, -0.1818848f, 0.1904297f, -0.6083984f, 0.6853027f, -0.1759033f, }, + { -0.1250000f, -0.0379639f, 0.0521240f, 0.0434570f, -0.2858887f, 0.0262451f, -0.2822266f, 0.0543213f, -0.2902832f, 0.6239014f, }, + { -0.0693359f, 0.0103760f, 0.1621094f, 0.2254639f, 0.4279785f, 0.1444092f, -0.3077393f, -0.2526855f, -0.0969238f, -0.2296143f, }, + { -0.0592041f, 0.1368408f, 0.1516113f, 0.1588135f, -0.5328369f, -0.2712402f, 0.3176270f, -0.0472412f, 0.1828613f, -0.1640625f, }, + { -0.1552734f, -0.1666260f, -0.2694092f, -0.0260010f, -0.2291260f, 0.3488770f, 0.1036377f, -0.1116943f, 0.0406494f, 0.3037109f, }, + { -0.2464600f, -0.2500000f, -0.1783447f, -0.2355957f, -0.1719971f, -0.0488281f, 0.0598145f, -0.2712402f, 0.1557617f, 0.8917236f, }, + { -0.1867676f, -0.2125244f, -0.3250732f, 0.3856201f, 0.1418457f, -0.1818848f, 0.1850586f, -0.1828613f, 0.1491699f, 0.1022949f, }, + { 0.1617432f, 0.6575928f, 0.4746094f, 0.2373047f, -0.2082520f, -0.3527832f, -0.2325439f, -0.4761963f, -0.3914795f, 0.0251465f, }, + { -0.1722412f, -0.1170654f, -0.0356445f, -0.0483398f, -0.1888428f, -0.0102539f, -0.5377197f, -0.1309814f, 0.6752930f, 0.2192383f, }, + { 0.3857422f, 0.0058594f, -0.2855225f, -0.7182617f, -0.0224609f, -0.0063477f, 0.0157471f, 0.6589355f, 0.0461426f, -0.0391846f, }, +}; + +const float AmpCB2_NB[64][NUM_ERB_NB-11] = +{ + { -0.3272705f, -0.5357666f, -0.5212402f, -0.5770264f, -0.0291748f, 0.2365723f, 0.2133789f, 0.2821045f, 0.5249023f, }, + { -0.4830322f, -0.1585693f, 0.4256592f, 0.1947021f, -0.0460205f, 0.0360107f, -0.1456299f, -0.1938477f, 0.2578125f, }, + { -0.1920166f, -0.7766113f, -0.0615234f, 0.2192383f, -0.3077393f, -0.0083008f, 0.1613770f, 0.1492920f, 0.2762451f, }, + { -0.0614014f, -0.4768066f, 0.4499512f, -0.4759521f, -0.0169678f, 0.2546387f, 0.0058594f, 0.0426025f, 0.0667725f, }, + { -0.7796631f, 0.1635742f, -0.1790771f, -0.1296387f, -0.0235596f, 0.1617432f, -0.1452637f, 0.2922363f, 0.2039795f, }, + { -0.2419434f, -0.3170166f, -0.0476074f, -0.1835938f, 0.2772217f, -0.0462646f, -0.2868652f, 0.4969482f, 0.0085449f, }, + { -0.1165771f, -0.1077881f, -0.2160645f, -0.1300049f, -0.2982178f, -0.2171631f, -0.1343994f, -0.0806885f, 0.7720947f, }, + { 0.2283936f, -0.3262939f, 0.4389648f, 0.4605713f, -0.0831299f, 0.4077148f, -0.1730957f, 0.0855713f, -0.5191650f, }, + { -0.4798584f, -0.2246094f, -0.2915039f, -0.3267822f, -0.4327393f, -0.0050049f, 0.4486084f, 0.4691162f, 0.2683105f, }, + { -0.2091064f, -0.0395508f, 0.0731201f, 0.1614990f, 0.2230225f, -0.5992432f, -0.2036133f, 0.0751953f, 0.3183594f, }, + { 0.0439453f, -0.2159424f, -0.6424561f, -0.1560059f, 0.4260254f, 0.2362061f, 0.1654053f, -0.1584473f, 0.1162109f, }, + { 0.2198486f, 0.0548096f, 0.0306396f, -0.1246338f, -0.4475098f, 0.0584717f, 0.4268799f, 0.1882324f, -0.2727051f, }, + { -0.4167480f, -0.5472412f, -0.7061768f, 0.1716309f, 0.1473389f, 0.3642578f, 0.2156982f, 0.3981934f, -0.0975342f, }, + { -0.3813477f, 0.6392822f, 0.0561523f, 0.2449951f, -0.1861572f, -0.2570801f, -0.0939941f, 0.0666504f, 0.0167236f, }, + { 0.0489502f, -0.1596680f, 0.1182861f, 0.0249023f, -0.1984863f, -0.0718994f, -0.5196533f, 0.2128906f, 0.3461914f, }, + { 0.2908936f, 0.3344727f, -0.0516357f, 0.3864746f, 0.2343750f, -0.0842285f, -0.3662109f, -0.5479736f, 0.3079834f, }, + { -0.8170166f, -0.6268311f, -0.0902100f, -0.2342529f, 0.1499023f, 0.2873535f, 0.4077148f, 0.2321777f, 0.1304932f, }, + { -0.3887939f, -0.3190918f, 0.3374023f, -0.0258789f, -0.2515869f, -0.1680908f, 0.0852051f, 0.4509277f, -0.0152588f, }, + { -0.1164551f, -0.5043945f, -0.0493164f, 0.5245361f, 0.1579590f, 0.2154541f, 0.2985840f, -0.2791748f, -0.1693115f, }, + { -0.0017090f, 0.0620117f, 0.1402588f, 0.0010986f, -0.0533447f, 0.0633545f, -0.0512695f, 0.0549316f, -0.0916748f, }, + { -0.1992188f, -0.1697998f, -0.2695313f, -0.2386475f, -0.1428223f, 0.5881348f, 0.1357422f, 0.1325684f, -0.0954590f, }, + { 0.1632080f, 0.1032715f, -0.4191895f, 0.0694580f, 0.2100830f, -0.0947266f, -0.3323975f, 0.1473389f, 0.1198730f, }, + { -0.1748047f, -0.1082764f, 0.0384521f, -0.3699951f, 0.4213867f, 0.0933838f, -0.1541748f, -0.2619629f, 0.3612061f, }, + { -0.3197021f, 0.1839600f, 0.1601563f, 0.4989014f, 0.3814697f, 0.1998291f, -0.1711426f, -0.0054932f, -0.3897705f, }, + { 0.1705322f, -0.3187256f, -0.4444580f, -0.3024902f, -0.2082520f, 0.0717773f, 0.0242920f, 0.4542236f, 0.1485596f, }, + { -0.1524658f, -0.1459961f, 0.8823242f, 0.1215820f, 0.1072998f, -0.1634521f, 0.0013428f, -0.1185303f, -0.2050781f, }, + { 0.0874023f, -0.0047607f, 0.0284424f, 0.2374268f, 0.1889648f, -0.1801758f, 0.0671387f, -0.2779541f, 0.0374756f, }, + { 0.9049072f, 0.2556152f, -0.1990967f, -0.0694580f, -0.1649170f, -0.0241699f, -0.0589600f, -0.0628662f, -0.1644287f, }, + { -0.0258789f, -0.3233643f, -0.0633545f, 0.0238037f, 0.3593750f, -0.0970459f, 0.1794434f, 0.0798340f, -0.1767578f, }, + { 0.3852539f, 0.1671143f, 0.4841309f, 0.4128418f, -0.3395996f, -0.5194092f, -0.1412354f, -0.0258789f, 0.0478516f, }, + { 0.1051025f, 0.6181641f, 0.5786133f, -0.3067627f, -0.4166260f, -0.0673828f, -0.2805176f, -0.0701904f, 0.1379395f, }, + { 0.1437988f, 0.1914063f, 0.5604248f, 0.1511230f, 0.0447998f, 0.1984863f, 0.0732422f, -0.7188721f, 0.0198975f, }, + { -0.4567871f, -0.4455566f, -0.4774170f, 0.0874023f, 0.1121826f, -0.1832275f, 0.0067139f, 0.2205811f, 0.4639893f, }, + { -0.6800537f, -0.5657959f, 0.1495361f, 0.3919678f, 0.4643555f, 0.1820068f, -0.1105957f, 0.0122070f, 0.0493164f, }, + { -0.2126465f, -0.2292480f, -0.2612305f, 0.2015381f, 0.2001953f, 0.4853516f, -0.4189453f, -0.1402588f, 0.1666260f, }, + { 0.2492676f, 0.0478516f, 0.0937500f, -0.1872559f, 0.1337891f, 0.4652100f, -0.0257568f, -0.2523193f, -0.1605225f, }, + { -0.5086670f, 0.1397705f, -0.3353271f, -0.0181885f, 0.6464844f, -0.0897217f, 0.0534668f, 0.0068359f, -0.0493164f, }, + { -0.0194092f, -0.2641602f, -0.1170654f, 0.4262695f, -0.0842285f, -0.0839844f, -0.1319580f, 0.3371582f, -0.1453857f, }, + { 0.0798340f, 0.2503662f, -0.2617188f, -0.3918457f, -0.2225342f, 0.0906982f, 0.0837402f, -0.0916748f, 0.3031006f, }, + { 0.0195313f, 0.1561279f, 0.3962402f, 0.2287598f, 0.3037109f, 0.1455078f, -0.7296143f, -0.0583496f, 0.0146484f, }, + { -0.0426025f, -0.0079346f, -0.2868652f, -0.0270996f, -0.2048340f, -0.4375000f, 0.1359863f, 0.3990479f, 0.1784668f, }, + { -0.1359863f, -0.0168457f, 0.2880859f, -0.3371582f, 0.0878906f, -0.4665527f, 0.3079834f, 0.0263672f, 0.1428223f, }, + { 0.5368652f, -0.5162354f, -0.2258301f, 0.1552734f, 0.0467529f, 0.2119141f, -0.0467529f, -0.1580811f, 0.0103760f, }, + { -0.0161133f, 0.1383057f, 0.1837158f, 0.1790771f, -0.2916260f, -0.2655029f, 0.4916992f, -0.3359375f, 0.0294189f, }, + { -0.5313721f, -0.2567139f, -0.0686035f, 0.0997314f, 0.4832764f, 0.6678467f, 0.2369385f, -0.1950684f, -0.2867432f, }, + { 0.0245361f, 0.1723633f, -0.0971680f, 0.3406982f, -0.5158691f, 0.3939209f, -0.2431641f, -0.0194092f, -0.0194092f, }, + { 0.4986572f, -0.1890869f, 0.1245117f, -0.2659912f, -0.0947266f, -0.2548828f, -0.0179443f, -0.0051270f, 0.2294922f, }, + { -0.1256104f, 0.6081543f, -0.2509766f, 0.0135498f, 0.1733398f, 0.2613525f, 0.0368652f, -0.3142090f, -0.1203613f, }, + { -0.0582275f, -0.4512939f, -0.2867432f, -0.2519531f, -0.0408936f, -0.0268555f, 0.7149658f, 0.0069580f, -0.0008545f, }, + { -0.6600342f, -0.0666504f, -0.0430908f, 0.3498535f, 0.0167236f, -0.0166016f, 0.4282227f, 0.1210938f, -0.2513428f, }, + { -0.2482910f, -0.1375732f, -0.0230713f, -0.0366211f, -0.2628174f, 0.4401855f, 0.3079834f, -0.4549561f, 0.1862793f, }, + { -0.4635010f, 0.2604980f, 0.5312500f, -0.1123047f, -0.0560303f, 0.3322754f, 0.2177734f, -0.0086670f, -0.3698730f, }, + { -0.1070557f, 0.2401123f, -0.2008057f, -0.5410156f, 0.0625000f, 0.0047607f, 0.2144775f, 0.3509521f, -0.1156006f, }, + { 0.2248535f, 0.1666260f, 0.1831055f, 0.1038818f, 0.0725098f, -0.3530273f, -0.0493164f, 0.4061279f, -0.3757324f, }, + { -0.1922607f, -0.1535645f, -0.1187744f, -0.0233154f, -0.0476074f, 0.0054932f, 0.0765381f, -0.0277100f, 0.1982422f, }, + { -0.0174561f, 0.0262451f, 0.2633057f, 0.5915527f, 0.6512451f, 0.4146729f, -0.0242920f, -0.5423584f, -0.3773193f, }, + { -0.0345459f, -0.0263672f, 0.1510010f, -0.1804199f, -0.6883545f, -0.0946045f, 0.0640869f, 0.2572021f, 0.3013916f, }, + { 0.3581543f, -0.0311279f, 0.2976074f, 0.1005859f, 0.7291260f, -0.2221680f, -0.1623535f, -0.1467285f, -0.2969971f, }, + { 0.1098633f, 0.0793457f, -0.6901855f, 0.3529053f, -0.1878662f, -0.0552979f, 0.2028809f, 0.0281982f, -0.0177002f, }, + { 0.2027588f, 0.0904541f, -0.0405273f, 0.1490479f, 0.2208252f, 0.1151123f, 0.5897217f, -0.1938477f, -0.5638428f, }, + { 0.0079346f, -0.0964355f, -0.1202393f, -0.1090088f, 0.4118652f, 0.3842773f, 0.0352783f, 0.3597412f, -0.6079102f, }, + { -0.0806885f, -0.0521240f, 0.1759033f, 0.9394531f, 0.0192871f, -0.2336426f, -0.2525635f, -0.2095947f, -0.0510254f, }, + { 0.3243408f, 0.5150146f, 0.1837158f, -0.1337891f, 0.0733643f, -0.1789551f, -0.2141113f, -0.0584717f, -0.0194092f, }, + { 0.4123535f, 0.6411133f, 0.6176758f, 0.4884033f, 0.1588135f, 0.0512695f, -0.1547852f, -0.3433838f, -0.5122070f, }, +}; + + + +const float PowerCB_WB[64][2] = +{ + { -1.6459961f, -0.8359375f, }, + { -0.083007813f, 0.17089844f, }, + { -0.31152344f, -0.45849609f, }, + { 0.02734375f, 0.52441406f, }, + { -0.76123047f, -0.30566406f, }, + { 0.09765625f, 0.16796875f, }, + { -0.19384766f, 0.11621094f, }, + { 0.13867188f, 0.69091797f, }, + { -0.64599609f, -0.91796875f, }, + { -0.265625f, 0.57128906f, }, + { -0.30224609f, -0.12451172f, }, + { 0.28662109f, 0.47558594f, }, + { -0.61621094f, -0.047851563f, }, + { 0.15966797f, 0.073730469f, }, + { 0.020019531f, -0.14746094f, }, + { 0.45947266f, 0.91601563f, }, + { -1.1020508f, -0.60205078f, }, + { 0.013671875f, 0.098632813f, }, + { -0.25390625f, -0.27392578f, }, + { 0.16503906f, 0.51171875f, }, + { -0.52734375f, -0.24169922f, }, + { 0.092773438f, 0.28417969f, }, + { -0.13867188f, -0.01171875f, }, + { 0.28222656f, 0.77392578f, }, + { -0.64648438f, -0.53173828f, }, + { -0.034667969f, 0.27734375f, }, + { -0.22998047f, -0.012695313f, }, + { 0.55664063f, 0.44384766f, }, + { -0.41796875f, -0.0625f, }, + { 0.20751953f, 0.36132813f, }, + { 0.068359375f, 0.005859375f, }, + { 0.77880859f, 0.92333984f, }, + { -1.0625f, -1.1279297f, }, + { -0.15039063f, 0.26416016f, }, + { -0.15380859f, -0.41943359f, }, + { -0.0390625f, 0.64160156f, }, + { -0.87011719f, 0.24902344f, }, + { 0.19677734f, 0.21972656f, }, + { -0.29638672f, 0.28417969f, }, + { 0.070800781f, 0.89697266f, }, + { -0.44921875f, -0.67675781f, }, + { -0.10986328f, 0.42578125f, }, + { -0.19287109f, -0.12597656f, }, + { 0.40478516f, 0.47900391f, }, + { -0.46142578f, 0.16845703f, }, + { 0.31396484f, 0.11767578f, }, + { -0.02734375f, -0.011230469f, }, + { 0.59130859f, 0.72363281f, }, + { -0.87548828f, -0.71240234f, }, + { 0.01953125f, 0.1953125f, }, + { -0.11669922f, -0.22998047f, }, + { 0.25976563f, 0.60449219f, }, + { -0.37792969f, -0.25195313f, }, + { 0.11914063f, 0.40576172f, }, + { -0.076660156f, 0.07421875f, }, + { 0.28125f, 1.1166992f, }, + { -0.453125f, -0.41210938f, }, + { 0.020019531f, 0.37060547f, }, + { -0.078613281f, -0.096679688f, }, + { 0.42626953f, 0.66064453f, }, + { -0.3125f, 0.051269531f, }, + { 0.33935547f, 0.30419922f, }, + { 0.17773438f, -0.08984375f, }, + { 0.60449219f, 1.1943359f, }, +}; + + +const float PowerCB_NB[64][2] = +{ + { -1.6352539f, -1.359375f, }, + { -0.3828125f, 0.18798828f, }, + { -0.43505859f, -0.27441406f, }, + { 0.061523438f, 0.44677734f, }, + { -0.74121094f, -0.70214844f, }, + { 0.1484375f, 0.025878906f, }, + { -0.15332031f, -0.21826172f, }, + { 0.33544922f, 0.59521484f, }, + { -1.262207f, -0.88232422f, }, + { -0.031738281f, 0.074707031f, }, + { -0.59521484f, -0.16455078f, }, + { 0.24267578f, 0.34179688f, }, + { -0.43652344f, -0.51318359f, }, + { 0.078613281f, 0.22021484f, }, + { -0.022460938f, -0.25195313f, }, + { 0.48193359f, 0.74169922f, }, + { -1.1118164f, -1.1245117f, }, + { -0.17285156f, 0.21728516f, }, + { -0.25976563f, -0.26367188f, }, + { 0.0024414063f, 0.62060547f, }, + { -0.51123047f, -0.69970703f, }, + { 0.328125f, -0.10986328f, }, + { -0.16357422f, -0.036621094f, }, + { 0.49169922f, 0.515625f, }, + { -0.66503906f, -0.91748047f, }, + { -0.045410156f, 0.17919922f, }, + { -0.22851563f, -0.12646484f, }, + { 0.87890625f, -0.14160156f, }, + { -0.54589844f, -0.38720703f, }, + { 0.20117188f, 0.23046875f, }, + { -0.0043945313f, -0.096191406f, }, + { 0.71826172f, 0.79785156f, }, + { -1.2827148f, -1.3901367f, }, + { -0.13134766f, 0.080078125f, }, + { -0.33642578f, -0.18212891f, }, + { 0.2109375f, 0.45898438f, }, + { -0.78173828f, -0.40966797f, }, + { 0.15185547f, 0.13232422f, }, + { -0.10351563f, -0.12255859f, }, + { 0.26513672f, 0.83691406f, }, + { -0.98339844f, -0.65234375f, }, + { 0.053222656f, 0.11767578f, }, + { -0.38525391f, -0.053710938f, }, + { 0.35595703f, 0.43359375f, }, + { -0.20410156f, -0.62353516f, }, + { 0.125f, 0.32910156f, }, + { 0.10644531f, -0.10595703f, }, + { 0.50146484f, 1.0083008f, }, + { -0.86376953f, -1.1196289f, }, + { -0.13476563f, 0.41650391f, }, + { -0.17578125f, -0.37304688f, }, + { 0.18359375f, 0.60888672f, }, + { -0.62207031f, -0.54785156f, }, + { 0.29394531f, 0.1328125f, }, + { -0.064941406f, -0.015625f, }, + { 0.67089844f, 0.54589844f, }, + { -0.90820313f, -0.87646484f, }, + { -0.011230469f, 0.30273438f, }, + { -0.25634766f, 0.029296875f, }, + { 0.52246094f, 0.26757813f, }, + { -0.33740234f, -0.39013672f, }, + { 0.34228516f, 0.27929688f, }, + { 0.039550781f, 0.0087890625f, }, + { 0.95166016f, 1.0351563f, }, +}; + +/* sinc for warp/extrapolate./16384., in Q14 */ +const float sinc[8][12] = +{ + {0.0f/16384.0f,0.0f/16384.0f,0.0f/16384.0f,0.0f/16384.0f,0.0f/16384.0f,16384.0f/16384.0f,0.0f/16384.0f,0.0f/16384.0f,0.0f/16384.0f,0.0f/16384.0f,0.0f/16384.0f,0.0f/16384.0f,}, + {-388.0f/16384.0f,484.0f/16384.0f,-638.0f/16384.0f,939.0f/16384.0f,-1773.0f/16384.0f,15966.0f/16384.0f,2281.0f/16384.0f,-1063.0f/16384.0f,694.0f/16384.0f,-514.0f/16384.0f,409.0f/16384.0f,-339.0f/16384.0f,}, + {-701.0f/16384.0f,868.0f/16384.0f,-1134.0f/16384.0f,1639.0f/16384.0f,-2949.0f/16384.0f,14751.0f/16384.0f,4917.0f/16384.0f,-2106.0f/16384.0f,1341.0f/16384.0f,-982.0f/16384.0f,776.0f/16384.0f,-640.0f/16384.0f,}, + {-895.0f/16384.0f,1101.0f/16384.0f,-1427.0f/16384.0f,2029.0f/16384.0f,-3503.0f/16384.0f,12849.0f/16384.0f,7709.0f/16384.0f,-2964.0f/16384.0f,1835.0f/16384.0f,-1328.0f/16384.0f,1042.0f/16384.0f,-856.0f/16384.0f,}, + {-947.0f/16384.0f,1159.0f/16384.0f,-1489.0f/16384.0f,2086.0f/16384.0f,-3476.0f/16384.0f,10430.0f/16384.0f,10430.0f/16384.0f,-3476.0f/16384.0f,2086.0f/16384.0f,-1489.0f/16384.0f,1159.0f/16384.0f,-947.0f/16384.0f,}, + {-856.0f/16384.0f,1042.0f/16384.0f,-1328.0f/16384.0f,1835.0f/16384.0f,-2964.0f/16384.0f,7709.0f/16384.0f,12849.0f/16384.0f,-3503.0f/16384.0f,2029.0f/16384.0f,-1427.0f/16384.0f,1101.0f/16384.0f,-895.0f/16384.0f,}, + {-640.0f/16384.0f,776.0f/16384.0f,-982.0f/16384.0f,1341.0f/16384.0f,-2106.0f/16384.0f,4917.0f/16384.0f,14751.0f/16384.0f,-2949.0f/16384.0f,1639.0f/16384.0f,-1134.0f/16384.0f,868.0f/16384.0f,-701.0f/16384.0f,}, + {-339.0f/16384.0f,409.0f/16384.0f,-514.0f/16384.0f,694.0f/16384.0f,-1063.0f/16384.0f,2281.0f/16384.0f,15966.0f/16384.0f,-1773.0f/16384.0f,939.0f/16384.0f,-638.0f/16384.0f,484.0f/16384.0f,-388.0f/16384.0f,}, +}; + +/*----------------------------------------------------------------------------------* + * Highrate SWB BWE tables + *----------------------------------------------------------------------------------*/ + +const float overlap_coefs_48kHz[NSV_OVERLAP*WIDTH_BAND] = +{ 0.30f, 0.34f, 0.36f, 0.39f, 0.42f, 0.44f, 0.46f, 0.475f, 0.49f, 0.51f, 0.54f, 0.57f, 0.62f, 0.72f, 0.83f, 0.95f }; + +const float overlap_coefs[NSV_OVERLAP*WIDTH_BAND] = +{ 0.2700f, 0.3060f, 0.3240f, 0.3510f, 0.3780f, 0.3960f, 0.4140f, 0.4275f, 0.4410f, 0.4590f, 0.4860f, 0.5130f, 0.5580f, 0.6480f, 0.7470f, 0.855f }; + +const float swb_hr_env_code1[NUM_ENVLOPE_CODE_HR1*2] = +{ + 0.044983f, 0.041700f, + 0.524276f, 0.469365f, + 0.671757f, 0.605513f, + 0.983501f, 0.855093f, + 1.227874f, 1.132200f, + 1.672212f, 1.432704f, + 2.548211f, 2.361091f, + 3.196961f, 3.306999f, + 2.580753f, 5.217478f, + 4.207751f, 7.243802f, + 3.517157f, 1.738487f, + 4.381567f, 2.753657f, + 4.758266f, 4.696094f, + 6.827988f, 6.106459f, + 4.450459f, 10.131211f, + 7.256045f, 12.488036f, + 6.708720f, 1.953339f, + 6.604030f, 3.699560f, + 10.612728f, 2.537916f, + 9.387467f, 4.241173f, + 7.119045f, 8.281485f, + 9.062854f, 7.086526f, + 8.919388f, 9.762914f, + 11.299319f, 11.763904f, + 11.782217f, 5.879754f, + 14.050457f, 9.665228f, + 11.201525f, 9.001128f, + 14.434753f, 13.236565f, + 14.337260f, 3.904411f, + 20.071049f, 4.335061f, + 18.105812f, 8.223599f, + 22.352287f, 9.603263f, + 7.242756f, 16.564487f, + 11.777528f, 19.167645f, + 11.121798f, 15.455982f, + 14.563579f, 17.359568f, + 17.821218f, 11.894719f, + 17.466026f, 15.296063f, + 21.336960f, 13.455175f, + 20.544336f, 17.125366f, + 9.056358f, 22.338306f, + 11.238424f, 28.832520f, + 13.262732f, 25.143383f, + 16.243559f, 28.256853f, + 15.269305f, 21.539135f, + 16.983515f, 24.699589f, + 19.591730f, 22.689682f, + 20.146198f, 25.888466f, + 17.797417f, 19.453121f, + 21.290621f, 20.186579f, + 24.097319f, 19.086721f, + 23.613092f, 22.545858f, + 23.682005f, 16.328239f, + 26.886553f, 19.402439f, + 26.009769f, 15.632211f, + 28.939930f, 16.240620f, + 25.094482f, 12.366419f, + 27.713383f, 13.263280f, + 28.330946f, 10.329259f, + 30.632830f, 12.851279f, + 25.273802f, 6.138124f, + 29.195339f, 7.222413f, + 32.171322f, 5.019567f, + 31.979000f, 9.473855f, +}; + +const float swb_hr_env_code2[NUM_ENVLOPE_CODE_HR2*2] = +{ + 0.512539f, 0.472507f, + 1.338963f, 1.108591f, + 2.544041f, 1.759765f, + 3.124053f, 3.045299f, + 4.892713f, 3.721097f, + 4.010297f, 5.750862f, + 5.111215f, 2.164709f, + 6.667518f, 3.893404f, + 8.454117f, 2.751430f, + 11.123573f, 3.518174f, + 6.622948f, 5.960704f, + 8.562429f, 5.003579f, + 8.919363f, 7.784057f, + 10.759037f, 5.959438f, + 12.449193f, 8.359519f, + 13.677005f, 11.230577f, + 13.672631f, 5.457414f, + 16.471989f, 3.917684f, + 20.910328f, 6.432810f, + 25.457325f, 8.617220f, + 16.410700f, 7.574456f, + 18.574385f, 10.291498f, + 22.088757f, 12.512156f, + 21.170530f, 17.208714f, + 5.276107f, 9.622470f, + 9.093585f, 11.274686f, + 11.945659f, 15.538144f, + 16.550409f, 15.046564f, + 6.358148f, 17.547396f, + 13.316619f, 21.765524f, + 7.646096f, 26.106720f, + 2.451297f, 31.933104f +}; + +const float swb_hr_env_code3[NUM_ENVLOPE_CODE_HR_TR*N_BANDS_TRANS_BWE_HR] = +{ + 0.799219f, 0.677609f, + 1.754571f, 1.215689f, + 2.846222f, 2.017775f, + 4.379336f, 1.975914f, + 5.935472f, 2.945818f, + 3.938621f, 4.220399f, + 8.080808f, 2.632276f, + 7.579771f, 4.986835f, + 4.956485f, 10.363663f, + 7.739148f, 8.652471f, + 9.238397f, 7.051655f, + 10.205707f, 5.619638f, + 10.645117f, 4.374648f, + 11.660180f, 3.474015f, + 10.845836f, 2.664596f, + 11.724073f, 1.637023f +}; + +/* Searching thresholds for quantization of norms */ +const float thren_HQ[39] = +{ + 110217.974940f, 77935.877489f, + 55108.987470f, 38967.938744f, + 27554.493735f, 19483.969372f, + 13777.246868f, 9741.984686f, + 6888.623434f, 4870.992343f, + 3444.311717f, 2435.496172f, + 1722.155858f, 1217.748086f, + 861.077929f, 608.874043f, + 430.538965f, 304.437021f, + 215.269482f, 152.218511f, + 107.634741f, 76.109255f, + 53.817371f, 38.054628f, + 26.908685f, 19.027314f, + 13.454343f, 9.513657f, + 6.727171f, 4.756828f, + 3.363586f, 2.378414f, + 1.681793f, 1.189207f, + 0.840896f, 0.594604f, + 0.420448f, 0.297302f, + 0.210224f +}; + +/*----------------------------------------------------------------------------------* + * ACELP/HQ core switching + *----------------------------------------------------------------------------------*/ + +/* short filters for BWE of ACELP->HQ switching frame */ +const float hp12800_16000[21] = +{ + -0.00000000f, 0.00212227f, -0.00632535f, 0.01161181f, -0.01235466f, 0.00000000f, 0.03177450f, -0.08143591f, + 0.13749378f, -0.18212549f, 0.19916883f, -0.18212549f, 0.13749378f, -0.08143591f, 0.03177450f, 0.00000000f, + -0.01235466f, 0.01161181f, -0.00632535f, 0.00212227f, -0.00000000f +}; + +const float hp12800_32000[41] = +{ + -0.00000000f, 0.00136608f, 0.00106650f, -0.00143351f, -0.00317865f, 0.00000000f, 0.00583523f, 0.00477033f, + -0.00620853f, -0.01289218f, -0.00000000f, 0.02060233f, 0.01596749f, -0.02003257f, -0.04092361f, 0.00000000f, + 0.06909412f, 0.05929089f, -0.09152269f, -0.30127931f, 0.60052441f, -0.30127931f, -0.09152269f, 0.05929089f, + 0.06909412f, 0.00000000f, -0.04092361f, -0.02003257f, 0.01596749f, 0.02060233f, -0.00000000f, -0.01289218f, + -0.00620853f, 0.00477033f, 0.00583523f, 0.00000000f, -0.00317865f, -0.00143351f, 0.00106650f, 0.00136608f, + -0.00000000f +}; + +const float hp12800_48000[61] = +{ + -0.00000000f, 0.00067336f, 0.00101850f, 0.00071064f, -0.00030497f, -0.00156225f, -0.00211804f, -0.00111583f, + 0.00136699f, 0.00388820f, 0.00427438f, 0.00122967f, -0.00413694f, -0.00827775f, -0.00727539f, 0.00000000f, + 0.00994020f, 0.01548435f, 0.01063964f, -0.00437614f, -0.02123403f, -0.02726869f, -0.01372549f, 0.01631621f, + 0.04603958f, 0.05175432f, 0.01589299f, -0.06098444f, -0.15675008f, -0.23604172f, 0.73360516f, -0.23604172f, + -0.15675008f, -0.06098444f, 0.01589299f, 0.05175432f, 0.04603958f, 0.01631621f, -0.01372549f, -0.02726869f, + -0.02123403f, -0.00437614f, 0.01063964f, 0.01548435f, 0.00994020f, 0.00000000f, -0.00727539f, -0.00827775f, + -0.00413694f, 0.00122967f, 0.00427438f, 0.00388820f, 0.00136699f, -0.00111583f, -0.00211804f, -0.00156225f, + -0.00030497f, 0.00071064f, 0.00101850f, 0.00067336f, -0.00000000f +}; + + +const float hp16000_32000[33] = +{ + -0.00000000f, 0.00188788f, -0.00000000f, -0.00386248f, -0.00000000f, 0.00824247f, -0.00000000f, -0.01594711f, + -0.00000000f, 0.02867656f, -0.00000000f, -0.05071856f, -0.00000000f, 0.09801591f, -0.00000000f, -0.31594176f, + 0.50070579f, -0.31594176f, -0.00000000f, 0.09801591f, -0.00000000f, -0.05071856f, -0.00000000f, 0.02867656f, + -0.00000000f, -0.01594711f, -0.00000000f, 0.00824247f, -0.00000000f, -0.00386248f, -0.00000000f, 0.00188788f, + -0.00000000f +}; + +const float hp16000_48000[49] = +{ + -0.00000000f, 0.00100660f, 0.00119953f, -0.00000000f, -0.00195325f, -0.00254135f, -0.00000000f, 0.00421805f, + 0.00534416f, 0.00000000f, -0.00829341f, -0.01018351f, -0.00000000f, 0.01504620f, 0.01817861f, 0.00000000f, + -0.02654841f, -0.03231243f, -0.00000000f, 0.04992164f, 0.06470722f, 0.00000000f, -0.13575216f, -0.27474220f, + 0.66706142f, -0.27474220f, -0.13575216f, 0.00000000f, 0.06470722f, 0.04992164f, -0.00000000f, -0.03231243f, + -0.02654841f, 0.00000000f, 0.01817861f, 0.01504620f, -0.00000000f, -0.01018351f, -0.00829341f, 0.00000000f, + 0.00534416f, 0.00421805f, -0.00000000f, -0.00254135f, -0.00195325f, -0.00000000f, 0.00119953f, 0.00100660f, + -0.00000000f +}; + +const double cu15[28][3] = +{ + /* xx/3, xx*xx/3, xx*xx*xx/3 xx v */ + /* 0:*/ { 0.0222222222, 0.0014814815, 0.0000987654 }, /* 1/15 */ + /* 1:*/ { 0.0444444444, 0.0059259259, 0.0007901235 }, /* 2/15 */ + /* 2:*/ { 0.0666666667, 0.0133333333, 0.0026666667 }, + /* 3:*/ { 0.0888888889, 0.0237037037, 0.0063209877 }, + /* 4:*/ { 0.1111111111, 0.0370370370, 0.0123456790 }, + /* 5:*/ { 0.1333333333, 0.0533333333, 0.0213333333 }, + /* 6:*/ { 0.1555555556, 0.0725925926, 0.0338765432 }, + /* 7:*/ { 0.1777777778, 0.0948148148, 0.0505679012 }, + /* 8:*/ { 0.2000000000, 0.1200000000, 0.0720000000 }, /* 9/15 */ + /* 9:*/ { 0.2222222222, 0.1481481481, 0.0987654321 }, /* 10/15 */ + /*10:*/ { 0.2444444444, 0.1792592593, 0.1314567901 }, + /*11:*/ { 0.2666666667, 0.2133333333, 0.1706666667 }, + /*12:*/ { 0.2888888889, 0.2503703704, 0.2169876543 }, + /*13:*/ { 0.3111111111, 0.2903703704, 0.2710123457 }, /* 14/15 */ + /*14:*/ { 0.3555555556, 0.3792592593, 0.4045432099 }, /* 16/15 */ + /*15:*/ { 0.3777777778, 0.4281481481, 0.4852345679 }, + /*16:*/ { 0.4000000000, 0.4800000000, 0.5760000000 }, /* 18/15 */ + /*17:*/ { 0.4222222222, 0.5348148148, 0.6774320988 }, + /*18:*/ { 0.4444444444, 0.5925925926, 0.7901234568 }, /* 20/15 */ + /*19:*/ { 0.4666666667, 0.6533333333, 0.9146666667 }, + /*20:*/ { 0.4888888889, 0.7170370370, 1.0516543210 }, + /*21:*/ { 0.5111111111, 0.7837037037, 1.2016790123 }, + /*22:*/ { 0.5333333333, 0.8533333333, 1.3653333333 }, + /*23:*/ { 0.5555555556, 0.9259259259, 1.5432098765 }, + /*24:*/ { 0.5777777778, 1.0014814815, 1.7359012346 }, + /*25:*/ { 0.6000000000, 1.0800000000, 1.9440000000 }, /* 27/15 */ + /*26:*/ { 0.6222222222, 1.1614814815, 2.1680987654 }, + /*27:*/ { 0.6444444444, 1.2459259259, 2.4087901235 }, /* 29/15 */ +}; + +const double cu4[6][3] = +{ + /* xx/3, xx*xx/3, xx*xx*xx/3 */ + /* 0:*/ { 0.0833333333, 0.0208333333, 0.0052083333 }, /*0.25*/ + /* 1:*/ { 0.1666666667, 0.0833333333, 0.0416666667 }, /*0.5*/ + /* 2:*/ { 0.2500000000, 0.1875000000, 0.1406250000 }, /*0.75*/ + /* 3:*/ { 0.4166666667, 0.5208333333, 0.6510416667 }, /*1.25*/ + /* 4:*/ { 0.5000000000, 0.7500000000, 1.1250000000 }, /*1.5*/ + /* 5:*/ { 0.5833333333, 1.0208333333, 1.7864583333 } /*1.75*/ +}; + +const short ct2[7][13] = +{ + /* accepted configurations */ + /*input 12.8, output :*/ + /*8*/ {30, 22, 30, 16, 25, 30, 19, 30, 30, 0, 8, 4, 15}, + /*16*/ {25, 22, 19, 16, 16, 0, 0, 0, 12, 1, 4, 4, 15}, + /*32*/ {19, 16, 19, 16, 16, 0, 0, 0, 6, 2, 2, 4, 15}, + /*48*/ {17, 14, 15, 16, 16, 0, 0, 0, 4, 3, 4, 4, 15}, + + /*input 16, output :*/ + /*12*/ { 9, 3, 4, 5, 9, 0, 0, 0, 5, 0, 5, 5, 4}, + /*32*/ { 4, 4, 4, 4, 4, 0, 0, 0, 2, 1, 1, 4, 4}, + /*48*/ {18, 18, 18, 18, 18, 0, 0, 0, 5, 2, 1, 4, 15}, +}; + + +/*----------------------------------------------------------------------------------* + * hp filter for filtering random part of excitation in frame error concealment + * Used in lib_dec\syn_bfi.c + *----------------------------------------------------------------------------------*/ + +const float h_high[5] = { -0.0125f, -0.1090f, 0.7813f, -0.1090f, -0.0125f }; + +const float sincos_t_rad3[T_SIN_PI_2+1] = +{ + 0.000000000000000f, 0.004090604026235f, 0.008181139603937f, 0.012271538285720f, 0.016361731626487f, 0.020451651184577f, 0.024541228522912f, 0.028630395210139f, + 0.032719082821776f, 0.036807222941359f, 0.040894747161583f, 0.044981587085452f, 0.049067674327418f, 0.053152940514528f, 0.057237317287569f, 0.061320736302209f, + 0.065403129230143f, 0.069484427760237f, 0.073564563599667f, 0.077643468475068f, 0.081721074133668f, 0.085797312344440f, 0.089872114899235f, 0.093945413613929f, + 0.098017140329561f, 0.102087226913474f, 0.106155605260457f, 0.110222207293883f, 0.114286964966846f, 0.118349810263305f, 0.122410675199216f, 0.126469491823675f, + 0.130526192220052f, 0.134580708507126f, 0.138632972840227f, 0.142682917412363f, 0.146730474455362f, 0.150775576241001f, 0.154818155082141f, 0.158858143333861f, + 0.162895473394589f, 0.166930077707230f, 0.170961888760301f, 0.174990839089060f, 0.179016861276633f, 0.183039887955141f, 0.187059851806832f, 0.191076685565203f, + 0.195090322016128f, 0.199100693998982f, 0.203107734407763f, 0.207111376192219f, 0.211111552358965f, 0.215108195972610f, 0.219101240156870f, 0.223090618095693f, + 0.227076263034373f, 0.231058108280671f, 0.235036087205927f, 0.239010133246176f, 0.242980179903264f, 0.246946160745958f, 0.250908009411060f, 0.254865659604515f, + 0.258819045102521f, 0.262768099752639f, 0.266712757474898f, 0.270652952262902f, 0.274588618184932f, 0.278519689385053f, 0.282446100084213f, 0.286367784581343f, + 0.290284677254462f, 0.294196712561769f, 0.298103825042740f, 0.302005949319228f, 0.305903020096553f, 0.309794972164597f, 0.313681740398891f, 0.317563259761712f, + 0.321439465303162f, 0.325310292162263f, 0.329175675568039f, 0.333035550840599f, 0.336889853392220f, 0.340738518728429f, 0.344581482449080f, 0.348418680249435f, + 0.352250047921233f, 0.356075521353776f, 0.359895036534988f, 0.363708529552498f, 0.367515936594704f, 0.371317193951837f, 0.375112238017038f, 0.378901005287410f, + 0.382683432365090f, 0.386459455958303f, 0.390229012882428f, 0.393992040061048f, 0.397748474527011f, 0.401498253423481f, 0.405241314004990f, 0.408977593638489f, + 0.412707029804395f, 0.416429560097637f, 0.420145122228702f, 0.423853654024676f, 0.427555093430282f, 0.431249378508924f, 0.434936447443717f, 0.438616238538528f, + 0.442288690219001f, 0.445953741033595f, 0.449611329654607f, 0.453261394879198f, 0.456903875630421f, 0.460538710958240f, 0.464165840040552f, 0.467785202184201f, + 0.471396736825998f, 0.475000383533732f, 0.478596082007181f, 0.482183772079123f, 0.485763393716340f, 0.489334887020625f, 0.492898192229784f, 0.496453249718633f, + 0.500000000000000f, 0.503538383725718f, 0.507068341687617f, 0.510589814818519f, 0.514102744193222f, 0.517607071029487f, 0.521102736689023f, 0.524589682678469f, + 0.528067850650368f, 0.531537182404149f, 0.534997619887097f, 0.538449105195327f, 0.541891580574752f, 0.545324988422046f, 0.548749271285616f, 0.552164371866554f, + 0.555570233019602f, 0.558966797754107f, 0.562354009234973f, 0.565731810783613f, 0.569100145878898f, 0.572458958158102f, 0.575808191417845f, 0.579147789615035f, + 0.582477696867802f, 0.585797857456439f, 0.589108215824328f, 0.592408716578875f, 0.595699304492433f, 0.598979924503229f, 0.602250521716282f, 0.605511041404326f, + 0.608761429008721f, 0.612001630140370f, 0.615231590580627f, 0.618451256282204f, 0.621660573370077f, 0.624859488142386f, 0.628047947071334f, 0.631225896804083f, + 0.634393284163645f, 0.637550056149777f, 0.640696159939861f, 0.643831542889791f, 0.646956152534857f, 0.650069936590618f, 0.653172842953777f, 0.656264819703058f, + 0.659345815100069f, 0.662415777590172f, 0.665474655803342f, 0.668522398555031f, 0.671558954847018f, 0.674584273868271f, 0.677598304995789f, 0.680600997795453f, + 0.683592302022871f, 0.686572167624217f, 0.689540544737067f, 0.692497383691237f, 0.695442635009612f, 0.698376249408973f, 0.701298177800824f, 0.704208371292213f, + 0.707106781186547f, 0.709993358984412f, 0.712868056384380f, 0.715730825283819f, 0.718581617779698f, 0.721420386169390f, 0.724247082951467f, 0.727061660826497f, + 0.729864072697836f, 0.732654271672413f, 0.735432211061519f, 0.738197844381584f, 0.740951125354959f, 0.743692007910687f, 0.746420446185274f, 0.749136394523459f, + 0.751839807478977f, 0.754530639815318f, 0.757208846506485f, 0.759874382737746f, 0.762527203906388f, 0.765167265622459f, 0.767794523709512f, 0.770408934205345f, + 0.773010453362737f, 0.775599037650177f, 0.778174643752598f, 0.780737228572094f, 0.783286749228650f, 0.785823163060853f, 0.788346427626606f, 0.790856500703845f, + 0.793353340291235f, 0.795836904608884f, 0.798307152099031f, 0.800764041426753f, 0.803207531480645f, 0.805637581373517f, 0.808054150443073f, 0.810457198252595f, + 0.812846684591615f, 0.815222569476594f, 0.817584813151584f, 0.819933376088899f, 0.822268218989775f, 0.824589302785025f, 0.826896588635696f, 0.829190037933717f, + 0.831469612302545f, 0.833735273597809f, 0.835986983907947f, 0.838224705554838f, 0.840448401094438f, 0.842658033317402f, 0.844853565249707f, 0.847034960153274f, + 0.849202181526579f, 0.851355193105265f, 0.853493958862750f, 0.855618443010829f, 0.857728610000272f, 0.859824424521420f, 0.861905851504774f, 0.863972856121587f, + 0.866025403784439f, 0.868063460147822f, 0.870086991108711f, 0.872095962807139f, 0.874090341626759f, 0.876070094195407f, 0.878035187385663f, 0.879985588315404f, + 0.881921264348355f, 0.883842183094633f, 0.885748312411290f, 0.887639620402854f, 0.889516075421856f, 0.891377646069366f, 0.893224301195515f, 0.895056009900018f, + 0.896872741532688f, 0.898674465693954f, 0.900461152235364f, 0.902232771260093f, 0.903989293123443f, 0.905730688433339f, 0.907456928050819f, 0.909167983090522f, + 0.910863824921176f, 0.912544425166069f, 0.914209755703531f, 0.915859788667400f, 0.917494496447491f, 0.919113851690058f, 0.920717827298248f, 0.922306396432559f, + 0.923879532511287f, 0.925437209210971f, 0.926979400466833f, 0.928506080473216f, 0.930017223684012f, 0.931512804813095f, 0.932992798834739f, 0.934457180984039f, + 0.935905926757326f, 0.937339011912575f, 0.938756412469813f, 0.940158104711519f, 0.941544065183021f, 0.942914270692887f, 0.944268698313317f, 0.945607325380521f, + 0.946930129495106f, 0.948237088522441f, 0.949528180593037f, 0.950803384102905f, 0.952062677713924f, 0.953306040354194f, 0.954533451218389f, 0.955744889768105f, + 0.956940335732209f, 0.958119769107168f, 0.959283170157394f, 0.960430519415566f, 0.961561797682962f, 0.962676986029777f, 0.963776065795440f, 0.964859018588927f, + 0.965925826289068f, 0.966976471044852f, 0.968010935275723f, 0.969029201671875f, 0.970031253194544f, 0.971017073076290f, 0.971986644821279f, 0.972939952205560f, + 0.973876979277334f, 0.974797710357222f, 0.975702130038528f, 0.976590223187499f, 0.977461974943572f, 0.978317370719628f, 0.979156396202234f, 0.979979037351883f, + 0.980785280403230f, 0.981575111865320f, 0.982348518521816f, 0.983105487431216f, 0.983846005927077f, 0.984570061618220f, 0.985277642388941f, 0.985968736399212f, + 0.986643332084879f, 0.987301418157858f, 0.987942983606322f, 0.988568017694885f, 0.989176509964781f, 0.989768450234042f, 0.990343828597665f, 0.990902635427780f, + 0.991444861373810f, 0.991970497362629f, 0.992479534598710f, 0.992971964564277f, 0.993447779019444f, 0.993906970002356f, 0.994349529829318f, 0.994775451094928f, + 0.995184726672197f, 0.995577349712672f, 0.995953313646548f, 0.996312612182778f, 0.996655239309180f, 0.996981189292537f, 0.997290456678690f, 0.997583036292635f, + 0.997858923238603f, 0.998118112900149f, 0.998360600940223f, 0.998586383301244f, 0.998795456205172f, 0.998987816153567f, 0.999163459927649f, 0.999322384588350f, + 0.999464587476366f, 0.999590066212200f, 0.999698818696204f, 0.999790843108610f, 0.999866137909562f, 0.999924701839145f, 0.999966533917401f, 0.999991633444351f, + 1.000000000000000f +}; + +/*----------------------------------------------------------------------------------* + * TCX + *----------------------------------------------------------------------------------*/ + +const float gain_corr_fac[3] = {1.0208f,1.0103f,1.0052f}; /*pow(10,2^(-n-2)/28)*/ +const float gain_corr_inv_fac[3] = {0.9797f,0.9898f,0.9949f};/*pow(10,-2^(-n-2)/28)*/ + +const float inter4_2tcx2[4][4] = +{ + { 0.2325402f, 0.5349195f, 0.2325402f, 0.0000000f }, + { 0.1353017f, 0.5094465f, 0.3400065f, 0.0152453f }, + { 0.0608774f, 0.4391226f, 0.4391226f, 0.0608774f }, + { 0.0152453f, 0.3400065f, 0.5094465f, 0.1353017f } +}; + +const float inter6_2tcx2[6][4] = +{ + { 0.2241379f, 0.5517241f, 0.2241379f, 0.0000000f }, + { 0.1562044f, 0.5388595f, 0.2990011f, 0.0059349f }, + { 0.0991379f, 0.5018346f, 0.3750000f, 0.0240275f }, + { 0.0549361f, 0.4450639f, 0.4450639f, 0.0549361f }, + { 0.0240275f, 0.3750000f, 0.5018346f, 0.0991379f }, + { 0.0059349f, 0.2990011f, 0.5388595f, 0.1562044f } +}; +const float inter_core_12_8kHz_output_8kHz[] = +{ + 0.5349196f, 0.5094466f, 0.4391227f, 0.3400065f, + 0.2325402f, 0.1353016f, 0.0608773f, 0.0152453f, + 0.0000000f +}; +const float inter_core_12_8kHz_output_16kHz[] = +{ + 0.4279357f, 0.4147958f, 0.3774199f, 0.3214508f, + 0.2548195f, 0.1860321f, 0.1225801f, 0.0699165f, + 0.0312127f, 0.0078047f, 0.0000000f, 0.0000000f, + 0.0000000f +}; +const float inter_core_12_8kHz_output_32kHz[] = +{ + 0.2139679f, 0.2123089f, 0.2073979f, 0.1994284f, + 0.1887100f, 0.1756491f, 0.1607254f, 0.1444646f, + 0.1274097f, 0.1100939f, 0.0930161f, 0.0766219f, + 0.0612900f, 0.0473253f, 0.0349583f, 0.0243509f, + 0.0156063f, 0.0087817f, 0.0039024f, 0.0009753f, + 0.0000000f +}; +const float inter_core_12_8kHz_output_48kHz[] = +{ + 0.1426452f, 0.1421528f, 0.1406841f, 0.1382653f, + 0.1349386f, 0.1307618f, 0.1258066f, 0.1201564f, + 0.1139041f, 0.1071503f, 0.1000000f, 0.0925607f, + 0.0849398f, 0.0772420f, 0.0695677f, 0.0620107f, + 0.0546572f, 0.0475844f, 0.0408600f, 0.0345417f, + 0.0286774f, 0.0233055f, 0.0184558f, 0.0141503f, + 0.0104042f, 0.0072274f, 0.0046257f, 0.0026016f, + 0.0011560f, 0.0002890f, 0.0000000f, 0.0000000f, + 0.0000000f +}; +const float inter_core_16kHz_output_8kHz[] = +{ + 0.5517241f, 0.5388595f, 0.5018346f, 0.4450639f, 0.3750000f, 0.2990011f, + 0.2241379f, 0.1562044f, 0.0991379f, 0.0549361f, 0.0240275f, 0.0059349f, + 0.0000000f +}; +const float inter_core_16kHz_output_16kHz[] = +{ + 0.5517241f, 0.5388595f, 0.5018346f, 0.4450639f, 0.3750000f, 0.2990011f, + 0.2241379f, 0.1562044f, 0.0991379f, 0.0549361f, 0.0240275f, 0.0059349f, + 0.0000000f +}; +const float inter_core_16kHz_output_32kHz[] = +{ + 0.2758621f, 0.2742414f, 0.2694298f, 0.2615753f, 0.2509173f, 0.2377748f, + 0.2225320f, 0.2056203f, 0.1875000f, 0.1686403f, 0.1495006f, 0.1305132f, + 0.1120690f, 0.0945060f, 0.0781022f, 0.0630725f, 0.0495690f, 0.0376861f, + 0.0274680f, 0.0189188f, 0.0120137f, 0.0067120f, 0.0029675f, 0.0007394f, + 0.0000000f +}; +const float inter_core_16kHz_output_48kHz[] = +{ + 0.1839080f, 0.1834272f, 0.1819912f, 0.1796198f, 0.1763457f, 0.1722133f, + 0.1672782f, 0.1616061f, 0.1552712f, 0.1483546f, 0.1409433f, 0.1331275f, + 0.1250000f, 0.1166535f, 0.1081796f, 0.0996670f, 0.0912002f, 0.0828579f, + 0.0747126f, 0.0668293f, 0.0592649f, 0.0520681f, 0.0452794f, 0.0389306f, + 0.0330460f, 0.0276422f, 0.0227295f, 0.0183120f, 0.0143894f, 0.0109575f, + 0.0080092f, 0.0055360f, 0.0035286f, 0.0019783f, 0.0008771f, 0.0002189f, + 0.0000000f +}; +const float inter_core_25_6kHz_output_8kHz[] = +{ + 0.5349196f, 0.5094466f, 0.4391227f, 0.3400065f, + 0.2325402f, 0.1353016f, 0.0608773f, 0.0152453f, + 0.0000000f +}; +const float inter_core_25_6kHz_output_16kHz[] = +{ + 0.5349196f, 0.5094466f, 0.4391227f, 0.3400065f, + 0.2325402f, 0.1353016f, 0.0608773f, 0.0152453f, + 0.0000000f +}; +const float inter_core_25_6kHz_output_32kHz[] = +{ + 0.4279357f, 0.4147958f, 0.3774199f, 0.3214508f, + 0.2548195f, 0.1860321f, 0.1225801f, 0.0699165f, + 0.0312127f, 0.0078047f, 0.0000000f, 0.0000000f, + 0.0000000f +}; +const float inter_core_25_6kHz_output_48kHz[] = +{ + 0.2852965f, 0.2813740f, 0.2698819f, 0.2516166f, + 0.2278099f, 0.2000000f, 0.1698781f, 0.1391327f, + 0.1093111f, 0.0817166f, 0.0573517f, 0.0369093f, + 0.0208069f, 0.0092505f, 0.0023118f, 0.0000000f, + 0.0000000f +}; + +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, 0.67f }, + { 0, 8000, 9600, 0.70f }, + { 0, 9600, 13200, 0.76f }, + { 0, 13200, 16400, 0.86f }, + { 0, 16400, 24400, 0.90f }, + { 0, 24400, 64000, 0.96f }, + + { 1, 0, 8000, 1.f }, + { 1, 8000, 9600, 1.f }, + { 1, 9600, 13200, 1.f }, + { 1, 13200, 16400, 0.85f /*0.85f*/ }, + { 1, 16400, 24400, 0.88f /*0.90*/}, + { 1, 24400, 32000, 0.90f /*0.90*/}, + { 1, 32000, 32400, 0.95f /*0.91f*/}, +}; + + +/*----------------------------------------------------------------------------------* + * Arithmetic coder + *----------------------------------------------------------------------------------*/ + +const unsigned char 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 +}; + +const unsigned short 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 int 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 + } +}; + +const float Ratios_WB_2[32] = + /* 2 */ { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 60, 64, 72 }; + +const float Ratios_WB_3[32] = + /* 3 */ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 44, 48, 54, 60, 68, 78, 80 }; + +const float Ratios_WB_4[32] = + /* 4 */ { 1.5f, 2, 2.5f, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 48, 52, 54, 68 }; + +const float Ratios_WB_5[32] = + /* 5 */ { 1, 1.5f, 2, 2.5f, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 40, 44, 48, 54 }; + +const float Ratios_WB_6[32] = + /* 6 */ { 1, 1.5f, 2, 2.5f, 3, 3.5f, 4, 4.5f, 5, 5.5f, 6, 6.5f, 7, 7.5f, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24, 26, 28, 34, 40, 41 }; + +const float Ratios_WB_7[32] = + /* 7 */ { 1, 1.5f, 2, 2.5f, 3, 3.5f, 4, 4.5f, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22.5f, 24, 25, 27, 28, 30, 35 }; + +const float Ratios_WB_8[16] = + /* 8 */ { 0.5f, 1, 1.5f, 2, 2.5f, 3, 3.5f, 4, 4.5f, 5, 5.5f, 6, 7, 8, 9, 10 }; + +const float Ratios_WB_9[16] = + /* 9 */ { 1, 2, 2.5f, 3, 4, 5, 6, 7, 8, 9, 10, 12, 15, 16, 18, 27 }; + +const float Ratios_WB_10[16] = + /* 10 */ { 1, 1.5f, 2, 2.5f, 3, 3.5f, 4, 5, 6, 8, 10, 15, 18, 22, 24, 26 }; + +const float Ratios_WB_11[16] = + /* 11 */ { 1, 1.5f, 2, 2.5f, 3, 3.5f, 4, 5, 6, 8, 10, 12, 13, 14, 18, 21 }; + +const float Ratios_WB_12[16] = + /* 12 */ { 0.5f, 1, 1.5f, 2, 2.5f, 3, 4, 5, 6, 8, 9, 11, 12, 13.5f, 16, 20 }; + +const float Ratios_WB_13[16] = + /* 13 */ { 0.5f, 1, 1.5f, 2, 2.5f, 3, 4, 5, 6, 7, 8, 10, 11, 12, 14, 20 }; + +const float Ratios_WB_14[16] = + /* 14 */ { 0.5f, 1, 1.5f, 2, 2.5f, 3, 4, 4.5f, 6, 7.5f, 9, 10, 12, 14, 15, 18 }; + +const float Ratios_WB_15[16] = + /* 15 */ { 0.5f, 1, 1.25f, 1.5f, 1.75f, 2, 2.5f, 3, 3.5f, 4, 4.5f, 5, 6, 8, 9, 14 }; + +const float Ratios_WB_16[4] = + /* 16 */ { 0.5f, 1, 2, 4 }; + +const float Ratios_WB_17[4] = + /* 17 */ { 1, 1.5f, 2, 4 }; + +const float Ratios_WB_18[4] = + /* 18 */ { 1, 2, 3, 4 }; + +const float Ratios_NB_2[32] = + /* 2 */ { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 30, 32, 34, 36, 38, 40 }; + +const float Ratios_NB_3[16] = + /* 3 */ { 0.5f, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 16, 20, 24, 30 }; + +const float Ratios_NB_4[16] = + /* 4 */ { 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20, 24, 30 }; + +const float Ratios_NB_5[16] = + /* 5 */ { 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20, 24, 30 }; + +const float Ratios_NB_6[16] = + /* 6 */ { 2, 2.5f, 3, 3.5f, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20 }; + +const float Ratios_NB_7[16] = + /* 7 */ { 1, 2, 2.5f, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20 }; + +const float Ratios_NB_8[16] = + /* 8 */ { 1, 1.5f, 2, 2.5f, 3, 3.5f, 4, 4.5f, 5, 6, 7, 8, 9, 10, 12, 16 }; + +const float Ratios_NB_9[8] = + /* 9 */ { 1, 2, 3, 4, 5, 6, 8, 10 }; + +const float Ratios_NB_10[8] = + /* 10 */ { 1, 2, 3, 4, 5, 6, 8, 10 }; + +const float Ratios_NB_11[8] = + /* 11 */ { 1, 1.5f, 2, 3, 4, 5, 6, 8 }; + +const float Ratios_NB_12[8] = + /* 12 */ { 1, 2, 2.5f, 3, 4, 5, 6, 8 }; + +const float Ratios_NB_13[4] = + /* 13 */ { 1, 2, 3, 4 }; + +const float Ratios_NB_14[4] = + /* 14 */ { 1, 2, 4, 6 }; + +const float Ratios_NB_15[4] = + /* 15 */ { 1, 2, 3, 4 }; + +const float Ratios_NB_16[4] = + /* 16 */ { 1, 1.5f, 2, 4 }; + +const float Ratios_NB_17[4] = + /* 17 */ { 1, 1.5f, 2, 3 }; + +const float Ratios_NB_18[4] = + /* 18 */ { 0.5f, 1, 2, 3 }; + +const float *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 + } +}; + +#define QGC(x) FL2WORD16_SCALE(x, 4) +const Word16 qGains[2][1 << kTcxHmNumGainBits] = +{ + /* GC */ { QGC(0.75f) }, + /* VC */ { QGC(0.6f), QGC(1.4f), QGC(4.5f), QGC(10.0f) } +}; + +/*----------------------------------------------------------------------------------* + * TNS + *----------------------------------------------------------------------------------*/ + +struct TnsParameters const tnsParametersIGF32kHz_LowBR[1] = +{ + { 600, 3, 1.85f, 0.075f } +}; + +struct TnsParameters const tnsParameters32kHz[2] = +{ + { 4500, 3, 1.35f, 0.0300f }, + { 600, 1, 1.75f, 0.0625f } +}; + +struct TnsParameters const tnsParameters32kHz_grouped[2] = +{ + { 8400, 3, 1.375f, 0.03125f }, + { 800, 3, 1.375f, 0.03125f } +}; + +struct TnsParameters const tnsParameters16kHz[1] = +{ + { 600, 3, 1.5f, 0.05f } +}; + + +struct TnsParameters const tnsParameters16kHz_grouped[2] = +{ + { 4400, 3, 1.5f, 0.05f }, + { 800, 3, 1.5f, 0.05f } +}; + +struct TnsParameters const tnsParameters48kHz_grouped[2] = +{ + { 10400, 3, 1.375f, 0.03125f }, + { 800, 3, 1.375f, 0.03125f } +}; + +float const tnsAcfWindow[TNS_MAX_FILTER_ORDER] = +{ + 0.997803f, 0.991211f, 0.980225f, 0.964844f, 0.945068f, 0.920898f, 0.892334f, 0.859375f +}; + +/* 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 */ +}; + +int const nTnsCoeffCodes = sizeof(codesTnsCoeff0TCX20)/sizeof(codesTnsCoeff0TCX20[0]); + +const Coding * const codesTnsCoeffSWBTCX20[] = { codesTnsCoeff0TCX20, codesTnsCoeff1TCX20, codesTnsCoeff2TCX20, codesTnsCoeff3TCX20, codesTnsCoeff4TCX20, codesTnsCoeff5, codesTnsCoeff6, codesTnsCoeff7 }; +const Coding * const codesTnsCoeffSWBTCX10[] = { codesTnsCoeff0TCX10, codesTnsCoeff1TCX10, codesTnsCoeff2TCX10, codesTnsCoeff3TCX10, codesTnsCoeff4TCX10, codesTnsCoeff5, codesTnsCoeff6, codesTnsCoeff7 }; +const Coding * const codesTnsCoeffWBTCX20[] = { codesTnsCoeff0WBTCX20, codesTnsCoeff1WBTCX20, codesTnsCoeff2WB, codesTnsCoeff3WB, codesTnsCoeff456, codesTnsCoeff456, codesTnsCoeff456, codesTnsCoeff7 }; + +int 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 */ +}; + +int const nTnsOrderCodes = sizeof(codesTnsOrder)/sizeof(codesTnsOrder[0]); + +ParamsBitMap const tnsSWBTCX20FilterCoeffBitMap = +{ + 1, + { + { 0, GetSWBTCX20TnsFilterCoeffBits, TRUE, GetTnsFilterCoeff, SetTnsFilterCoeff, EncodeSWBTCX20TnsFilterCoeff, DecodeSWBTCX20TnsFilterCoeff, NULL } /* TNS filter coefficients */ + } +}; + +ParamsBitMap const tnsSWBTCX10FilterCoeffBitMap = +{ + 1, + { + { 0, GetSWBTCX10TnsFilterCoeffBits, TRUE, GetTnsFilterCoeff, SetTnsFilterCoeff, EncodeSWBTCX10TnsFilterCoeff, DecodeSWBTCX10TnsFilterCoeff, NULL } /* TNS filter coefficients */ + } +}; + +ParamsBitMap const tnsSWBTCX20FilterBitMap = +{ + 1, + { + { 0, GetTnsFilterOrderBitsSWBTCX20, FALSE, GetTnsFilterOrder, SetTnsFilterOrder, EncodeTnsFilterOrderSWBTCX20, DecodeTnsFilterOrderSWBTCX20, &tnsSWBTCX20FilterCoeffBitMap } /* TNS filter order */ + } +}; + +ParamsBitMap const tnsSWBTCX10FilterBitMap = +{ + 1, + { + { 0, GetTnsFilterOrderBitsSWBTCX10, FALSE, GetTnsFilterOrder, SetTnsFilterOrder, EncodeTnsFilterOrderSWBTCX10, DecodeTnsFilterOrderSWBTCX10, &tnsSWBTCX10FilterCoeffBitMap } /* TNS filter order */ + } +}; + +ParamsBitMap const tnsSWBTCX20BitMap = +{ + 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, NULL, TRUE, GetTnsEnabled, SetTnsEnabled, NULL, NULL, &tnsSWBTCX20BitMap } /* TNS Enabled/Disable */ + } +}; + +ParamsBitMap const tnsSWBTCX10BitMap = +{ + 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, NULL, TRUE, GetTnsEnabled, SetTnsEnabled, NULL, NULL, &tnsSWBTCX10BitMap } /* TNS Enabled/Disable */ + } +}; + +ParamsBitMap const tnsWBTCX20FilterCoeffBitMap = +{ + 1, + { + { 0, GetWBTCX20TnsFilterCoeffBits, TRUE, GetTnsFilterCoeff, SetTnsFilterCoeff, EncodeWBTCX20TnsFilterCoeff, DecodeWBTCX20TnsFilterCoeff, NULL } /* TNS filter coefficients */ + } +}; + + +ParamsBitMap const tnsWBTCX20FilterBitMap = +{ + 1, + { + { 0, GetTnsFilterOrderBits, FALSE, GetTnsFilterOrder, SetTnsFilterOrder, EncodeTnsFilterOrder, DecodeTnsFilterOrder, &tnsWBTCX20FilterCoeffBitMap } /* TNS filter order */ + } +}; + + +/* For storing/reading bits in WB mode */ +ParamsBitMap const tnsEnabledWBTCX20BitMap = +{ + 1, + { + { 1, NULL, TRUE, GetTnsEnabledSingleFilter, SetTnsEnabledSingleFilter, NULL, NULL, &tnsWBTCX20FilterBitMap } /* TNS Enabled/Disable */ + } +}; + + +/** + * 4 bit resolution TNS coefficients. + */ +float const tnsCoeff4[16]= +{ + -0.99573418F, /* = sin(-8*(EVS_PI/2.0)/(8 + 0.5)) */ + -0.96182564F, /* = sin(-7*(EVS_PI/2.0)/(8 + 0.5)) */ + -0.89516329F, + -0.79801723F, + -0.67369564F, + -0.52643216F, + -0.36124167F, + -0.18374952F, /* = sin(-1*(EVS_PI/2.0)/(8 + 0.5)) */ + 0.00000000F, /* = sin(0*(EVS_PI/2.0)/(8 + 0.5)) */ + 0.20791169F, /* = sin(1*(EVS_PI/2.0)/(8 - 0.5)) */ + 0.40673664F, + 0.58778525F, + 0.74314483F, + 0.86602540F, + 0.95105652F, /* = sin(6*(EVS_PI/2.0)/(8 - 0.5)) */ + 0.99452190F /* = sin(7*(EVS_PI/2.0)/(8 - 0.5)) */ +}; + +/**********************************************************************/ /** +igf settings structure for each bitrate mode +**************************************************************************/ +const int 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 + }, + /* 14: 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 float igf_whitening_TH[15][2][IGF_MAX_TILES] = +{ + /* 0: for 9600 kbs WB */ + { + /* medium */ {0.36f, 0.36f, 0.f, 0.f}, + /* strong */ {1.41f, 1.41f, 0.f, 0.f} + }, + /* 1: for 13200 kbs WB RF */ + { + /* medium */ {0.36f, 0.36f, 0.f, 0.f}, + /* strong */ {1.41f, 1.41f, 0.f, 0.f} + }, + /* 2: for 9600 kbs SWB */ + { + /* medium */ {0.84f, 0.89f, 0.f, 0.f}, + /* strong */ {1.30f, 1.25f, 0.f, 0.f} + }, + /* 3: for 13200 kbs SWB */ + { + /* medium */ {0.84f, 0.89f, 0.f, 0.f}, + /* strong */ {1.30f, 1.25f, 0.f, 0.f} + }, + /* 4: for 13200 kbs SWB RF */ + { + /* medium */ {0.84f, 0.89f, 0.f, 0.f}, + /* strong */ {1.30f, 1.25f, 0.f, 0.f} + }, + /* 5: for 16400 kbs SWB */ + { + /* medium */ {0.83f, 0.89f, 0.89f, 0.f}, + /* strong */ {1.31f, 1.19f, 1.19f, 0.f} + }, + /* 6: for 24400 kbs SWB*/ + { + /* medium */ {0.81f, 0.85f, 0.85f, 0.f}, + /* strong */ {1.35f, 1.23f, 1.23f, 0.f} + }, + /* 7: for 32000 kbs SWB */ + { + /* medium */ {0.91f, 0.85f, 0.85f, 0.f}, + /* strong */ {1.34f, 1.35f, 1.35f, 0.f} + }, + /* 8: for 48000 kbs SWB */ + { + /* medium */ {1.15f, 0.f, 0.f, 0.f}, + /* strong */ {1.19f, 0.f, 0.f, 0.f} + }, + /* 10: for 16400 kbs FB */ + { + /* medium */ {0.63f, 0.27f, 0.36f, 0.f}, + /* strong */ {1.53f, 1.32f, 0.67f, 0.f} + }, + /* 10: for 24400 kbs FB */ + { + /* medium */ {0.78f, 0.31f, 0.34f, 0.34f}, + /* strong */ {1.49f, 1.38f, 0.65f, 0.65f} + }, + /* 11: for 32000 kbs FB */ + { + /* medium */ {0.78f, 0.31f, 0.34f, 0.34f}, + /* strong */ {1.49f, 1.38f, 0.65f, 0.65f} + }, + /* 12: for 48000 kbs FB */ + { + /* medium */ {0.80f, 0.f, 0.f, 0.f}, + /* strong */ {1.00f, 0.f, 0.f, 0.f} + }, + /* 13: for 96000 kbs FB */ + { + /* medium */ {0.f, 0.f, 0.f, 0.f}, + /* strong */ {2.82f, 0.f, 0.f, 0.f} + }, + /* 14: for 128000 kbs FB */ + { + /* medium */ {0.f, 0.f, 0.f, 0.f}, + /* strong */ {2.82f, 0.f, 0.f, 0.f} + } +}; + +/* IGF SCF arithmetic coder cumulative frequency tables and offsets */ +const short 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 short 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 short cf_off_se10_tab = -7; + +const short 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 unsigned short 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 unsigned short 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 unsigned short cf_se02_tab[9][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} + }, + { /* 13.2 kbs WB RF 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} + }, + { /* 13.2 kbs A */ + { 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} + }, + { /* 13.2 kbs SWB RF 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} + }, + { /* 16.4 kbs 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} + }, + { /* 32.0 kbs A */ + { 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 unsigned short 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 unsigned short 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 +**************************************************************************/ +/* possible ROMOPTIM: transFac not needed any more, can be deleted */ +const IGF_MODE igfMode[15] = +{ + /* sampleRate, frameLength, bitRate, igfMinFq, transFac, maxHopsize */ + { 16000, 320, 9600, 774, 1.25f, 4 }, /* 9.6kbs WB 0 */ + { 16000, 320, 13200, 774, 1.25f, 4 }, /* 13.2kbs WB RF 1 */ + { 32000, 640, 9600, 800, 1.25f, 2 }, /* 9.6kbs SWB 2 */ + { 32000, 640, 13200, 800, 1.25f, 4 }, /* 13.2kbs SWB 3 */ + { 32000, 640, 13200, 800, 1.25f, 2 }, /* 13.2kbs SWB RF 4 */ + { 32000, 640, 16400, 800, 1.25f, 4 }, /* 16.4kbs SWB 5 */ + { 32000, 640, 24400, 800, 1.25f, 4 }, /* 24.4kbs SWB 6 */ + { 32000, 640, 32000, 800, 1.25f, 4 }, /* 32.0kbs SWB 7 */ + { 32000, 640, 48000, 1600, 1.25f, 4 }, /* 48.0kbs SWB 8 */ + { 48000, 960, 16400, 800, 1.25f, 4 }, /* 16.4kbs FB 9 */ + { 48000, 960, 24400, 800, 1.25f, 2 }, /* 24.4kbs FB 10 */ + { 48000, 960, 32000, 800, 1.25f, 2 }, /* 32.0kbs FB 11 */ + { 48000, 960, 48000, 1600, 1.25f, 2 }, /* 48.0kbs FB 12 */ + { 48000, 960, 96000, 1600, 0.50f, 1 }, /* 96.0kbs FB 13 */ + { 48000, 960, 128000, 1600, 0.50f, 1 } /*128.0kbs FB 14 */ +}; + + +const int bwMode2fs[4] = { 8000, 16000, 32000, 48000 }; + + +const float normReciprocal[CHEAP_NORM_SIZE] = +{ + 0.0f, 1.0000000000f, 0.5000000000f, 0.3333333333f, 0.2500000000f, 0.2000000000f, 0.1666666667f, 0.1428571429f, 0.1250000000f, 0.1111111111f, 0.1000000000f, 0.0909090909f, 0.0833333333f, 0.0769230769f, 0.0714285714f, 0.0666666667f, 0.0625000000f, 0.0588235294f, 0.0555555556f, 0.0526315789f, 0.0500000000f, 0.0476190476f, 0.0454545455f, 0.0434782609f, 0.0416666667f, 0.0400000000f, 0.0384615385f, 0.0370370370f, 0.0357142857f, 0.0344827586f, 0.0333333333f, 0.0322580645f, 0.0312500000f, 0.0303030303f, 0.0294117647f, 0.0285714286f, 0.0277777778f, 0.0270270270f, 0.0263157895f, 0.0256410256f, 0.0250000000f, 0.0243902439f, 0.0238095238f, 0.0232558140f, 0.0227272727f, 0.0222222222f, 0.0217391304f, 0.0212765957f, 0.0208333333f, 0.0204081633f, 0.0200000000f, 0.0196078431f, 0.0192307692f, 0.0188679245f, 0.0185185185f, 0.0181818182f, 0.0178571429f, 0.0175438596f, 0.0172413793f, 0.0169491525f, 0.0166666667f, 0.0163934426f, 0.0161290323f, 0.0158730159f, 0.0156250000f, 0.0153846154f, 0.0151515152f, 0.0149253731f, 0.0147058824f, 0.0144927536f, 0.0142857143f, 0.0140845070f, 0.0138888889f, 0.0136986301f, 0.0135135135f, 0.0133333333f, 0.0131578947f, 0.0129870130f, 0.0128205128f, 0.0126582278f, 0.0125000000f, 0.0123456790f, 0.0121951220f, 0.0120481928f, 0.0119047619f, 0.0117647059f, 0.0116279070f, 0.0114942529f, 0.0113636364f, 0.0112359551f, 0.0111111111f, 0.0109890110f, 0.0108695652f, 0.0107526882f, 0.0106382979f, 0.0105263158f, 0.0104166667f, 0.0103092784f, 0.0102040816f, 0.0101010101f, 0.0100000000f, 0.0099009901f, 0.0098039216f, 0.0097087379f, 0.0096153846f, 0.0095238095f, 0.0094339623f, 0.0093457944f, 0.0092592593f, 0.0091743119f, 0.0090909091f, 0.0090090090f, 0.0089285714f, 0.0088495575f, 0.0087719298f, 0.0086956522f, 0.0086206897f, 0.0085470085f, 0.0084745763f, 0.0084033613f, 0.0083333333f, 0.0082644628f, 0.0081967213f, 0.0081300813f, 0.0080645161f, 0.0080000000f, 0.0079365079f, 0.0078740157f, 0.0078125000f, 0.0077519380f, 0.0076923077f, 0.0076335878f, 0.0075757576f, 0.0075187970f, 0.0074626866f, 0.0074074074f, 0.0073529412f, 0.0072992701f, 0.0072463768f, 0.0071942446f, 0.0071428571f, 0.0070921986f, 0.0070422535f, 0.0069930070f, 0.0069444444f, 0.0068965517f, 0.0068493151f, 0.0068027211f, 0.0067567568f, 0.0067114094f, 0.0066666667f, 0.0066225166f, 0.0065789474f, 0.0065359477f, 0.0064935065f, 0.0064516129f, 0.0064102564f, 0.0063694268f, 0.0063291139f, 0.0062893082f, 0.0062500000f +}; + +const float w1N8[30] = {0.998795f, -0.049068f, 0.995185f, -0.098017f, 0.989177f, -0.146730f, 0.980785f, -0.195090f, 0.970031f, -0.242980f, 0.956940f, -0.290285f, 0.941544f, -0.336890f, 0.923880f, -0.382683f, 0.903989f, -0.427555f, 0.881921f, -0.471397f, 0.857729f, -0.514103f, 0.831470f, -0.555570f, 0.803208f, -0.595699f, 0.773010f, -0.634393f, 0.740951f, -0.671559f}; +const float w2N8[30] = {0.995185f, -0.098017f, 0.980785f, -0.195090f, 0.956940f, -0.290285f, 0.923880f, -0.382683f, 0.881921f, -0.471397f, 0.831470f, -0.555570f, 0.773010f, -0.634393f, 0.707107f, -0.707107f, 0.634393f, -0.773010f, 0.555570f, -0.831470f, 0.471397f, -0.881921f, 0.382683f, -0.923880f, 0.290285f, -0.956940f, 0.195090f, -0.980785f, 0.098017f, -0.995185f}; +const float w3N8[30] = {0.989177f, -0.146730f, 0.956940f, -0.290285f, 0.903989f, -0.427555f, 0.831470f, -0.555570f, 0.740951f, -0.671559f, 0.634393f, -0.773010f, 0.514103f, -0.857729f, 0.382683f, -0.923880f, 0.242980f, -0.970031f, 0.098017f, -0.995185f, -0.049068f, -0.998795f, -0.195090f, -0.980785f, -0.336890f, -0.941544f, -0.471397f, -0.881921f, -0.595699f, -0.803208f}; +const float w4N8[30] = {0.980785f, -0.195090f, 0.923880f, -0.382683f, 0.831470f, -0.555570f, 0.707107f, -0.707107f, 0.555570f, -0.831470f, 0.382683f, -0.923880f, 0.195090f, -0.980785f, 0.000000f, -1.000000f, -0.195090f, -0.980785f, -0.382683f, -0.923880f, -0.555570f, -0.831470f, -0.707107f, -0.707107f, -0.831470f, -0.555570f, -0.923880f, -0.382683f, -0.980785f, -0.195090f}; +const float w5N8[30] = {0.970031f, -0.242980f, 0.881921f, -0.471397f, 0.740951f, -0.671559f, 0.555570f, -0.831470f, 0.336890f, -0.941544f, 0.098017f, -0.995185f, -0.146730f, -0.989177f, -0.382683f, -0.923880f, -0.595699f, -0.803208f, -0.773010f, -0.634393f, -0.903989f, -0.427555f, -0.980785f, -0.195090f, -0.998795f, 0.049068f, -0.956940f, 0.290285f, -0.857729f, 0.514103f}; +const float w6N8[30] = {0.956940f, -0.290285f, 0.831470f, -0.555570f, 0.634393f, -0.773010f, 0.382683f, -0.923880f, 0.098017f, -0.995185f, -0.195090f, -0.980785f, -0.471397f, -0.881921f, -0.707107f, -0.707107f, -0.881921f, -0.471397f, -0.980785f, -0.195090f, -0.995185f, 0.098017f, -0.923880f, 0.382683f, -0.773010f, 0.634393f, -0.555570f, 0.831470f, -0.290285f, 0.956940f}; +const float w7N8[30] = {0.941544f, -0.336890f, 0.773010f, -0.634393f, 0.514103f, -0.857729f, 0.195090f, -0.980785f, -0.146730f, -0.989177f, -0.471397f, -0.881921f, -0.740951f, -0.671559f, -0.923880f, -0.382683f, -0.998795f, -0.049068f, -0.956940f, 0.290285f, -0.803208f, 0.595699f, -0.555570f, 0.831470f, -0.242980f, 0.970031f, 0.098017f, 0.995185f, 0.427555f, 0.903989f}; +const float *w_a[7] = {w1N8, w2N8, w3N8, w4N8, w5N8, w6N8, w7N8}; + + +#define STC(x) WORD322WORD16(x) +#define STCP(a,b) { { STC(a), STC(b) } } + +const PWord16 SineTable512_fx[] = +{ + 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) +}; + +/** + * \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 +}; + +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 +}; + +/* ACELP pulse coding */ +const int low_len[10] = { 0, 0, 8, 5, 7,11,13,15,16,16}; +const int low_mask[10] = { 0, 0, 255,31,127,2047,8191,32767,65535,65535}; +const int indx_fact[10] = { 0, 0,2,172,345,140,190,223,463,1732}; +const int index_len[3] = { 0, 5, 9 }; +const int index_mask_ACELP[3] = { 0, 31, 511 }; diff --git a/lib_com/rom_com.h b/lib_com/rom_com.h new file mode 100644 index 000000000..3e2f30eae --- /dev/null +++ b/lib_com/rom_com.h @@ -0,0 +1,1230 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#ifndef ROM_COM_H +#define ROM_COM_H + +#include +#include "options.h" +#include "stat_enc.h" +#include "stat_dec.h" +#include "stl.h" +#include "basop_util.h" + +typedef struct +{ + int fin; /* input frequency */ + int fout; /* output frequency */ + short fac_num; /* numerator of resampling factor */ + const float *filter; /* resampling filter coefficients */ + short filt_len; /* number of filter coeff. */ + unsigned short flags; /* flags from config. table */ +} Resampling_cfg; + +typedef struct +{ + short bands; + short bw; + const short *band_width; + Word32 L_qint; + Word16 eref_fx; + Word16 bit_alloc_weight_fx; + short gqlevs; + short Ngq; + short p2a_bands; + float p2a_th; + float pd_thresh; + float ld_slope; + float ni_coef; + float ni_pd_th; +} Xcore_Config; + +/*-----------------------------------------------------------------* + * Table of bitrates + *-----------------------------------------------------------------*/ + +extern const long brate_tbl[SIZE_BRATE_TBL]; +extern const long acelp_sig_tbl[MAX_ACELP_SIG]; + +/*-----------------------------------------------------------------* + * Bit-allocation tables + *-----------------------------------------------------------------*/ + +extern const short LSF_bits_tbl[]; /* Bit allocation table for end-frame ISF quantizer */ +extern const short mid_LSF_bits_tbl[]; /* Bit allocation table for mid-frame ISF quantizer */ +extern const short Es_pred_bits_tbl[]; /* Bit allocation table for scaled innovation energy prediction */ +extern const short gain_bits_tbl[]; /* Bit allocation table for gain quantizer */ +extern const short ACB_bits_tbl[]; /* Bit allocation table for adaptive codebook (pitch) */ +extern const short FCB_bits_tbl[]; /* Bit allocation table for algebraic (fixed) codebook (innovation) */ +extern const short reserved_bits_tbl[]; /* Bit allocation table for reseved bits */ + +extern const short ACB_bits_16kHz_tbl[]; /* Bit allocation table for adaptive codebook (pitch) @16kHz */ +extern const short FCB_bits_16kHz_tbl[]; /* Bit allocation table for algebraic (fixed) codebook (innovation) @16kHz */ +extern const short gain_bits_16kHz_tbl[]; /* Bit allocation table for gain quantizer @16kHz */ +extern const short AVQ_bits_16kHz_tbl[]; /* Bit allocation table for AVQ bits @16kHz ACELP, active segments */ + +extern const long unsigned pulsestostates[17][9]; /* Number of states for any combination of pulses in any combination of vector length */ + +extern const unsigned char ACELP_NRG_MODE[RATE_MODE_MAX][BANDWIDTH_MODE_MAX][ACELP_MODE_MAX+RF_MODE_MAX]; +extern const unsigned char ACELP_NRG_BITS[3]; + +extern const unsigned char ACELP_LTP_MODE[RATE_MODE_MAX][BANDWIDTH_MODE_MAX][ACELP_MODE_MAX+RF_MODE_MAX]; +extern const unsigned char ACELP_LTP_BITS[RATE_MODE_MAX][BANDWIDTH_MODE_MAX][ACELP_MODE_MAX+RF_MODE_MAX]; +extern const unsigned char ACELP_LTP_BITS_SFR[8+RF_MODE_MAX][5]; + +extern const unsigned char ACELP_LTF_MODE[RATE_MODE_MAX][BANDWIDTH_MODE_MAX][ACELP_MODE_MAX+RF_MODE_MAX]; +extern const unsigned char ACELP_LTF_BITS[4]; + +extern const unsigned char ACELP_GAINS_MODE[RATE_MODE_MAX][BANDWIDTH_MODE_MAX][ACELP_MODE_MAX+RF_MODE_MAX]; +extern const unsigned char ACELP_GAINS_BITS[10]; + +extern const unsigned char ACELP_BPF_MODE[RATE_MODE_MAX][BANDWIDTH_MODE_MAX][ACELP_MODE_MAX+RF_MODE_MAX]; +extern const unsigned char ACELP_BPF_BITS[3]; + + +/*----------------------------------------------------------------------------------* + * Pre-processing + *----------------------------------------------------------------------------------*/ + +extern const float inv_tbl[]; /* Table of 1/x values */ + +extern const Resampling_cfg resampling_cfg_tbl[]; /* table of resampling configurations */ +extern const FrameSizeParams FrameSizeConfig[FRAME_SIZE_NB]; + +extern const float h_high[]; /* HP filter for filtering random part of excitation in FEC */ +extern const float crit_bands[]; /* Table of critical bands */ +extern const int pow2[]; /* Table with power of 2 values */ +extern const float sincos_t[]; /* FFT - sinus and cosinus tables */ +extern const float sincos_t_ext[]; +extern const float sincos_t_rad3[]; +extern const short fft256_read_indexes[]; /* FFT */ +extern const float inter4_2[]; /* 1/4 resolution interpolation filter */ +extern const float LP_assym_window[]; /* Assymetric window for LP analysis @12.8kHz */ +extern const float LP_assym_window_16k[]; /* Assymetric window for LP analysis @16kHz */ +extern const float hamcos_window[]; /* Hamming-Cosinus window */ +extern const float grid50[]; /* Table of grid points for evaluating Chebyshev polynomials */ +extern const float grid40[]; /* Table of grid points for evaluating Chebyshev polynomials */ +extern const float grid100[]; /* Table of 100 grid points for evaluating Chebyshev polynomials */ + +extern const float wind_sss[LEN_WIN_SSS]; /* window for modify_sf ana */ +extern const float filter5_39s320_120[]; /* LP FIR filter for 8kHz signal resampling */ + +extern const float lag_window_8k[17]; +extern const float lag_window_12k8[][17]; +extern const float lag_window_16k[][17]; +extern const float lag_window_25k6[][17]; +extern const float lag_window_32k[][17]; +extern const float lag_window_48k[17]; + +extern const float interpol_frac_12k8[]; /* LPC interpolation coefficients */ +extern const float interpol_isp_amr_wb[]; /* LPC interpolation coefficients for AMR-WB interoperable mode */ +extern const float interpol_frac_16k[]; /* LPC interpolation coefficients @ 16kHz */ +extern const float interpol_frac_mid[]; /* LPC interpolation coefficients with mid-ISFs */ +extern const float interpol_frac_mid_16k[]; /* LPC interpolation coefficients with mid-ISFs @ 16kHz */ +extern const float interpol_frac_mid_relaxprev_12k8[]; /* LPC interpolation coefficients with mid-ISFs @ 16kHz - relaxed prev frame interp */ +extern const float interpol_frac_mid_FEC[]; /* LPC interpolation coefficients with mid-ISFs - FEC */ +extern const float interpol_frac_mid_relaxprev_16k[]; /* LPC interpolation coefficients with mid-ISFs @ 16kHz - relaxed prev frame interp */ +extern const float interpol_frac_mid_16k_FEC[]; /* LPC interpolation coefficients with mid-ISFs @ 16kHz - FEC */ +extern const float interpol_frac_mid_relaxprev_pred_12k8[]; +extern const float interpol_frac_mid_relaxprev_pred_16k[]; + +extern const float inter6_2[PIT_FIR_SIZE6_2]; +extern const Float32 inter4_2tcx2[4][4]; +extern const Float32 inter6_2tcx2[6][4]; +typedef struct TCX_LTP_FILTER +{ + const float *filt; + int length; +} TCX_LTP_FILTER; +extern const TCX_LTP_FILTER tcxLtpFilters[12]; + +extern const float gain_qua_mless_7b[]; /* Gain quantization - gain quantization table */ +extern const float gain_qua_mless_6b[]; /* Gain quantization - gain quantization table */ +extern const float gain_qua_mless_5b[]; /* Gain quantization - gain quantization table */ +extern const float pred_gain[]; /* Gain quantization - MA predicition coefficients for gain quantizer */ +extern const float t_qua_gain6b[]; /* Gain quantization - gain quantization table for AMR-WB interoperable mode */ +extern const float t_qua_gain7b[]; /* Gain quantization - gain quantization table for AMR-WB interoperable mode */ +extern const float Es_pred_qua_5b[]; /* Gain quantization - quantization table for scaled innovation energy prediciton */ +extern const float Es_pred_qua_4b[]; /* Gain quantization - quantization table for scaled innovation energy prediciton */ +extern const float Es_pred_qua_3b[]; /* Gain quantization - quantization table for scaled innovation energy prediciton */ +extern const float Es_pred_qua_4b_no_ltp[]; /* Gain quantization - quantization table for scaled innovation energy prediciton */ + +extern const float b_1sfr[]; /* Gain quantization - gain estimation constants for gain quantizer at 7.2 and 8.0 kbps */ +extern const float b_2sfr[]; /* Gain quantization - gain estimation constants for gain quantizer at 7.2 and 8.0 kbps */ +extern const float b_3sfr[]; /* Gain quantization - gain estimation constants for gain quantizer at 7.2 and 8.0 kbps */ +extern const float b_4sfr[]; /* Gain quantization - gain estimation constants for gain quantizer at 7.2 and 8.0 kbps */ + +extern const float gp_gamma_1sfr_8b[]; /* Gain quantization - gain quantization table for gain quantizer at 7.2 and 8.0 kbps */ +extern const float gp_gamma_2sfr_8b[]; /* Gain quantization - gain quantization table for gain quantizer at 7.2 and 8.0 kbps */ +extern const float gp_gamma_3sfr_8b[]; /* Gain quantization - gain quantization table for gain quantizer at 7.2 and 8.0 kbps */ +extern const float gp_gamma_4sfr_8b[]; /* Gain quantization - gain quantization table for gain quantizer at 7.2 and 8.0 kbps */ + +extern const float gp_gamma_1sfr_7b[]; /* Gain quantization - gain quantization table for gain quantizer at 7.2 and 8.0 kbps */ +extern const float gp_gamma_2sfr_7b[]; /* Gain quantization - gain quantization table for gain quantizer at 7.2 and 8.0 kbps */ +extern const float gp_gamma_3sfr_7b[]; /* Gain quantization - gain quantization table for gain quantizer at 7.2 and 8.0 kbps */ +extern const float gp_gamma_4sfr_7b[]; /* Gain quantization - gain quantization table for gain quantizer at 7.2 and 8.0 kbps */ + +extern const float gp_gamma_1sfr_7b[]; /* Gain quantization - gain quantization table for gain quantizer at 7.2 and 8.0 kbps */ +extern const float gp_gamma_2sfr_7b[]; /* Gain quantization - gain quantization table for gain quantizer at 7.2 and 8.0 kbps */ +extern const float gp_gamma_3sfr_7b[]; /* Gain quantization - gain quantization table for gain quantizer at 7.2 and 8.0 kbps */ +extern const float gp_gamma_4sfr_7b[]; /* Gain quantization - gain quantization table for gain quantizer at 7.2 and 8.0 kbps */ + +extern const float gp_gamma_1sfr_6b[]; /* Gain quantization - gain quantization table for gain quantizer at 7.2 and 8.0 kbps */ +extern const float gp_gamma_2sfr_6b[]; /* Gain quantization - gain quantization table for gain quantizer at 7.2 and 8.0 kbps */ +extern const float gp_gamma_3sfr_6b[]; /* Gain quantization - gain quantization table for gain quantizer at 7.2 and 8.0 kbps */ +extern const float gp_gamma_4sfr_6b[]; /* Gain quantization - gain quantization table for gain quantizer at 7.2 and 8.0 kbps */ + +extern const short E_ROM_qua_gain5b_const[]; +extern const short E_ROM_qua_gain6b_const[]; +extern const short E_ROM_qua_gain7b_const[]; + +extern const float gain_qua_mless[]; + +extern const float tbl_gain_code_tc[]; /* TC - code gain quantization table */ +extern const float tbl_gain_trans_tc[]; /* TC - gain quantization table for g_trans */ +extern const float glottal_cdbk[]; /* TC - table of prototype glottal impulses */ + +extern const int PI_select_table[23][8]; /* selection table for Pulse indexing */ +extern const int PI_offset[8][8]; /* offset table for Pulse indexing */ +extern const short PI_factor[]; /* EVS_PI factor table for Pulse indexing */ + +extern const float deem_tab[]; /* HF BWE - de-emphasis coefficients */ +extern const float filt_hp[]; +extern const float exp_tab_p[]; /* HF BWE - Table of values exp(-j*w*i) */ +extern const float exp_tab_q[]; /* HF BWE - Table of values exp(-j*w*i) */ +extern const float HP_gain[]; /* HF BWE - quantization table for 23.85 */ +extern const float fir_6k_8k[]; /* HF BWE - band-pass filter coefficients */ + +extern const float b_hp400[]; /* HF (6-7kHz) BWE - 400Hz HP filter coefficients */ +extern const float a_hp400[]; /* HF (6-7kHz) BWE - 400Hz HP filter coefficients */ +extern const float fir_6k_7k[]; /* HF (6-7kHz) BWE - 6.0 - 7.0 kHz BP filter coefficients */ + +extern const float low_H[]; /* Enhacer - 2.0 - 6.4 kHz impulse response with phase dispersion */ +extern const float mid_H[]; /* Enhancer - 3.2 - 6.4 kHz impulse response with phase dispersion */ + +extern const float filt_lp[1 + L_FILT]; +extern const float filt_lp_16kHz[1+L_FILT16k]; + +extern const float tab_hup_l[SIZ_TAB_HUP_L]; /* NB post-filter */ +extern const float tab_hup_s[SIZ_TAB_HUP_S]; /* NB post-filter */ + +extern const float edct_table_80[]; /* EDCT */ +extern const float edct_table_120[]; /* EDCT */ +extern const float edct_table_320[]; /* EDCT */ +extern const float edct_table_480[]; /* EDCT */ +extern const float edct_table_128[]; /* EDCT */ +extern const float edct_table_160[]; /* EDCT */ +extern const float edct_table_40[]; /* EDCT */ +extern const float edct_table_20[]; /* EDCT */ +extern const float edct_table_64[]; +extern const float edct_table_100[]; /* EDCT */ +extern const float edct_table_200[]; +extern const float edct_table_240[]; +extern const float edct_table_256[]; +extern const float edct_table_400[]; +extern const float edct_table_600[]; /* EDCT */ + +extern const short crit_bins[]; /* (used only in AMR-WB IO mode) */ +extern const float crit_bins_corr[CRIT_NOIS_BAND]; +extern const float crit_bands_loc[]; /* (used only in AMR-WB IO mode) */ +extern const float mfreq_loc_LD[]; /* LD music post-filter */ +extern const short mfreq_bindiv_LD[]; +extern const float post_dct_wind[OFFSET2]; +extern const float MAX_SNR_SNR1_tab[]; +extern const float INV_MAX_SNR_tab[]; +extern const float sc_qnoise[]; + +extern const float W_DTX_HO[HO_HIST_SIZE]; +extern const float ENR_ATT[5]; +extern const float HO_ATT[5]; + +extern const short hq_swb_bwe_nb_bits[]; + +/*----------------------------------------------------------------------------------* + * ISF quantization (AMR-WB IO mode) + *----------------------------------------------------------------------------------*/ + +extern const float mean_isf_amr_wb[M]; /* Mean ISF vector (only in AMR-WB IO mode) */ +extern const float mean_isf_noise_amr_wb[]; /* Mean ISF vector for SID frame (only in AMR-WB IO mode) */ +extern const float gaus_dico[]; /* Gaussian codebook */ +extern const float gaus_dico_swb[]; /* Gaussian codebook for SWB TBE */ + +extern const float dico1_isf[]; /* ISF codebook - common 1st stage, 1st split (only in AMR-WB IO mode) */ +extern const float dico2_isf[]; /* ISF codebook - common 1st stage, 2nd split (only in AMR-WB IO mode) */ + +extern const float dico21_isf_46b[]; /* ISF codebook - 46b, 2nd stage, 1st split (only in AMR-WB IO mode) */ +extern const float dico22_isf_46b[]; /* ISF codebook - 46b, 2nd stage, 2st split (only in AMR-WB IO mode) */ +extern const float dico23_isf_46b[]; /* ISF codebook - 46b, 2nd stage, 3rd split (only in AMR-WB IO mode) */ +extern const float dico24_isf_46b[]; /* ISF codebook - 46b, 2nd stage, 4th split (only in AMR-WB IO mode) */ +extern const float dico25_isf_46b[]; /* ISF codebook - 46b, 2nd stage, 5th split (only in AMR-WB IO mode) */ + +extern const float dico21_isf_36b[]; /* ISF codebook - 36b, 2nd stage, 1st split (only in AMR-WB IO mode) */ +extern const float dico22_isf_36b[]; /* ISF codebook - 36b, 2nd stage, 2nd split (only in AMR-WB IO mode) */ +extern const float dico23_isf_36b[]; /* ISF codebook - 36b, 2nd stage, 3rd split (only in AMR-WB IO mode) */ + +extern const float dico1_ns_28b[]; /* ISF codebook for SID frames - 28b, 1st split */ +extern const float dico2_ns_28b[]; /* ISF codebook for SID frames - 28b, 2nd spilt */ +extern const float dico3_ns_28b[]; /* ISF codebook for SID frames - 28b, 3rd spilt */ +extern const float dico4_ns_28b[]; /* ISF codebook for SID frames - 28b, 4th spilt */ +extern const float dico5_ns_28b[]; /* ISF codebook for SID frames - 28b, 5th spilt */ + +extern const float dico1_cng_ev[]; +extern const float dico2_cng_ev[]; +extern const float dico3_cng_ev[]; +extern const float dico4_cng_ev[]; +extern const float dico5_cng_ev[]; + +/*----------------------------------------------------------------------------------* + * LSF quantization - MSVQ tables + *----------------------------------------------------------------------------------*/ + +extern const float stable_ISP[]; +extern const float stable_LSP[]; +extern const float stable_ISF[]; + +extern const float UVWB_Ave[]; +extern const float UVNB_Ave[]; +extern const float SVWB_Ave[]; +extern const float SVNB_Ave[]; +extern const float IAWB_Ave[]; +extern const float IANB_Ave[]; +extern const float GENB_Ave[]; +extern const float GEWB_Ave[]; +extern const float GEWB2_Ave[]; +extern const float TRWB_Ave[]; +extern const float TRWB2_Ave[]; +extern const float means_wb_cleanspeech_lsf16k0[]; +extern const float means_swb_cleanspeech_lsf25k6[]; +extern const float means_swb_cleanspeech_lsf32k0[]; +extern const float ModeMean12[]; + +extern const float Predictor0[]; +extern const float Predictor1[]; +extern const float Predictor2[]; +extern const float Predictor3[]; +extern const float Predictor4[]; +extern const float Predictor5[]; +extern const float Predictor6[]; +extern const float Predictor7[]; +extern const float Predictor8[]; +extern const float CNG_SN1[]; + +extern const short CB_lsf[]; +extern const short CB_p_lsf[]; +extern const float *const ModeMeans[]; +extern const float *const Predictors[]; +extern const short CBsizes[]; +extern const short CBbits[]; + +extern const short CBbits_p[]; +extern const float vals[NO_LEADERS][MAX_NO_VALS]; +extern const int no_vals[NO_LEADERS]; +extern const int no_vals_ind[NO_LEADERS][MAX_NO_VALS]; +extern const int C_VQ[LATTICE_DIM+1][LATTICE_DIM+1]; +extern const short BitsVQ[]; +extern const short BitsVQ_p[]; +extern const int no_lead[][MAX_NO_SCALES*2]; +extern const int no_lead_p[][MAX_NO_SCALES*2]; +extern const float sigma_MSLVQ[][16]; +extern const float sigma_p[][16]; +extern const float inv_sigma_MSLVQ[][16]; +extern const float inv_sigma_p[][16]; +extern const float scales[][MAX_NO_SCALES*2]; +extern const float scales_p[][MAX_NO_SCALES*2]; +extern const short predmode_tab[][6]; +extern const float pl_HQ[]; +extern const int pi0[]; +extern const unsigned int table_no_cv[]; +extern const int pl_par[]; +extern const float *const Quantizers[]; +extern const float *const Quantizers_p[]; +extern const short cng_sort[]; +extern const short perm_MSLVQ[][4]; +extern const short min_lat_bits_SN[]; +extern const short min_lat_bits_pred[]; +extern const short offset_in_lvq_mode_SN[][21]; +extern const short offset_in_lvq_mode_pred[][32]; +extern const short offset_lvq_modes_SN[]; +extern const short offset_lvq_modes_pred[]; + +/*-----------------------------------------------------------------* + * LSF quantization - BC-TCVQ tables + *-----------------------------------------------------------------*/ + +extern const short FixBranch_tbl[4][4][N_STAGE_VQ - 4]; + +extern const short BC_TCVQ_BIT_ALLOC_40B[]; + +extern const int NTRANS[4][16]; +extern const int NTRANS2[4][16]; + +extern const float AR_IntraCoeff[N_STAGE_VQ-1][2][2]; +extern const float SN_IntraCoeff[N_STAGE_VQ-1][2][2]; + +extern const float scale_ARSN[]; +extern const float scale_inv_ARSN[]; + +extern const float AR_TCVQ_CB_SUB1[2][128][2]; +extern const float AR_TCVQ_CB_SUB2[2][64][2]; +extern const float AR_TCVQ_CB_SUB3[4][32][2]; + +extern const float SN_TCVQ_CB_SUB1[2][128][2]; +extern const float SN_TCVQ_CB_SUB2[2][64][2]; +extern const float SN_TCVQ_CB_SUB3[4][32][2]; + +extern const float AR_SVQ_CB1[32][8]; +extern const float AR_SVQ_CB2[16][8]; + + +extern const short uniform_model[]; + +/*-----------------------------------------------------------------* + * LSF quantization - mid-frame quantization tables + *-----------------------------------------------------------------*/ + +extern const float tbl_mid_gen_wb_2b[]; +extern const float tbl_mid_gen_wb_5b[]; + +extern const float tbl_mid_unv_wb_4b[]; +extern const float tbl_mid_unv_wb_5b[]; + +extern const float tbl_mid_voi_wb_1b[]; +extern const float tbl_mid_voi_wb_4b[]; +extern const float tbl_mid_voi_wb_5b[]; + +/*-----------------------------------------------------------------* + * LSF quantization - Mode 2 quantization tables + *-----------------------------------------------------------------*/ + +extern const float lsf_init[16]; +extern const Float32 means_wb_31bits_ma_lsf[16]; +extern const Float32 means_nb_31bits_ma_lsf[16]; +extern const float *lsf_means[2]; +extern const float *const lsf_codebook[2][2][TCXLPC_NUMSTAGES]; +extern const int lsf_numbits[TCXLPC_NUMSTAGES]; +extern const int lsf_dims[TCXLPC_NUMSTAGES]; +extern const int lsf_offs[TCXLPC_NUMSTAGES]; +extern const float lsf_q_diff_cb_8b_rf[]; +extern const float lsf_cdk_nb_gc_stg1[]; +extern const float lsf_cdk_nb_gc_stg2[]; +extern const float lsf_cdk_nb_gc_stg3[]; +extern const float lsf_ind_cdk_nb_gc_stg4[]; +extern const float lsf_cdk_nb_vc_stg1[]; +extern const float lsf_cdk_nb_vc_stg2[]; +extern const float lsf_cdk_nb_vc_stg3[]; +extern const float lsf_ind_cdk_nb_vc_stg4[]; +extern const float lsf_cdk_wb_gc_stg1[]; +extern const float lsf_cdk_wb_gc_stg2[]; +extern const float lsf_cdk_wb_gc_stg3[]; +extern const float lsf_ind_cdk_wb_gc_stg4[]; +extern const float lsf_cdk_wb_vc_stg1[]; +extern const float lsf_cdk_wb_vc_stg2[]; +extern const float lsf_cdk_wb_vc_stg3[]; +extern const float lsf_ind_cdk_wb_vc_stg4[]; + +extern const float *const lsf_ind_codebook[2][2][TCXLPC_IND_NUMSTAGES]; +extern const int lsf_ind_numbits[TCXLPC_IND_NUMSTAGES]; +extern const int lsf_ind_dims[TCXLPC_IND_NUMSTAGES]; +extern const int lsf_ind_offs[TCXLPC_IND_NUMSTAGES]; +extern const Word16 min_distance_thr[2][2]; + +typedef float lsp_unw_triplet[3]; +extern const lsp_unw_triplet p16_gamma0_92to1[16]; +extern const lsp_unw_triplet p16_gamma0_94to1[16]; + + +/*------------------------------------------------------------------------------* + * AVQ - RE8 tables + *------------------------------------------------------------------------------*/ + +extern const int select_table22[][9]; +extern const int vals_a[][4]; /* value of leader element */ +extern const int vals_q[][4]; /* code parameter for every leader */ +extern const unsigned int Is[]; /* codebook start address for every leader */ +extern const int AA3[]; /* A3 - Number of the absolute leaders in codebook Q3 */ +extern const int AA4[]; /* A4 - Number of the absolute leaders in codebook Q4 */ +extern const unsigned int II3[]; /* I3 - Cardinality offsets for absolute leaders in Q3 */ +extern const unsigned int II4[]; /* I4 - Cardinality offset for absolute leaders in Q4 */ +extern const int Da_pos[]; /* Position of the first absolute leader on a spherical shell (or sphere) */ +extern const int Da_nb[]; /* Number of absolute leaders on a spherical shell */ +extern const int Da_id[]; /* identification code of an absolute leader */ +extern const int Da_nq[]; /* Codebook number for each absolute leader */ + +/*------------------------------------------------------------------------------* + * SWB TBE tables + *------------------------------------------------------------------------------*/ + +extern const short skip_bands_SWB_TBE[]; /* bands for SWB TBE quantisation */ +extern const short skip_bands_WB_TBE[]; /* bands for WB TBE quantisation */ + +extern const float interpol_frac_shb[]; + +extern const float AP1_STEEP[]; /* All pass filter coeffs for interpolation and decimation by a factor of 2 */ +extern const float AP2_STEEP[]; /* All pass filter coeffs for interpolation and decimation by a factor of 2 */ +extern const float STEPS[]; /* Granuality in conversion from lpc to lsp */ + +extern const float cos_fb_exc[]; +extern const float recip_order[]; + +extern const float win_lpc_shb[]; /* Window for calculating SHB LPC coeffs */ +extern const float win_lpc_hb_wb[]; +extern const float ola_win_shb_switch_fold[]; +extern const float win_flatten[]; /* Window for calculating whitening filter for SHB excitation */ +extern const float win_flatten_4k[]; /* Window for calculating whitening filter for WB excitation */ +extern const float window_shb[]; /* Overlap add window for SHB excitation used in anal and synth */ +extern const float window_shb_32k[]; /* Upsampled overlap add window for SHB excitation used transition generation */ +extern const float subwin_shb[]; /* Short overlap add window for SHB excitation used in anal and synth */ +extern const float window_wb[]; +extern const float subwin_wb[]; /* Short overlap add window for SHB excitation used in anal and synth */ + +extern const float Hilbert_coeffs[4*NUM_HILBERTS][HILBERT_ORDER1+1]; + +extern const float wac[]; +extern const float wac_swb[]; + +extern const float wb_bwe_lsfvq_cbook_8bit[]; +extern const float lbr_wb_bwe_lsfvq_cbook_2bit[]; +extern const float swb_tbe_lsfvq_cbook_8b[]; +extern const float SHBCB_SubGain5bit[]; /* 5 bit Quantizer table for SHB gain shapes */ +extern const float HBCB_SubGain5bit[]; /* 5-bit TD WB BWE temporal shaping codebook */ +extern const float SHBCB_FrameGain64[]; /* 6 bit Quantizer table for SHB overall gain */ +extern const float SHBCB_FrameGain16[]; + +extern const float full_band_bpf_1[][5]; +extern const float full_band_bpf_2[][5]; +extern const float full_band_bpf_3[][5]; + +extern const float lsf_q_cb_4b[]; /* 4 bit differential scalar quantizer table for TD SWB BWE LSFs 1 and 2*/ +extern const float lsf_q_cb_3b[]; /* 3 bit differential scalar quantizer table for TD SWB BWE LSFs 3, 4 and 5*/ +extern const float *const lsf_q_cb[]; /* Codebook array for each LSF */ +extern const short lsf_q_cb_size[]; /* Size of each element of the above */ +extern const short lsf_q_num_bits[]; /* Size of each element of the above, in bits */ +extern const float mirror_point_q_cb[]; /* LSF mirroring point codebook */ +extern const float lsf_grid[4][5]; /* LSF mirroring adjustment grid */ +extern const float grid_smoothing[]; /* LSF mirroring smoothing table */ + +extern const float overlap_coefs[]; /* HR SWB BWE - overlap coefficients */ +extern const float overlap_coefs_48kHz[]; /* HR SWB BWE - overlap coefficients @48kHz */ +extern const float swb_hr_env_code1[]; /* HR SWB BWE - envelope Q table - first two subabnds in non-transient frames */ +extern const float swb_hr_env_code2[]; /* HR SWB BWE - envelope Q table - second two subabnds in non-transient frames*/ +extern const float swb_hr_env_code3[]; /* HR SWB BWE - envelope Q table - two subabnds in transient frames */ + +extern const float allpass_poles_3_ov_2[9]; +extern const float decimate_3_ov_2_lowpass_num[3]; +extern const float decimate_3_ov_2_lowpass_den[3]; + + +/*------------------------------------------------------------------------------* + * WB BWE tables + *------------------------------------------------------------------------------*/ + +extern const float F_2_5[64]; + +/*------------------------------------------------------------------------------* + * SWB BWE tables + *------------------------------------------------------------------------------*/ + +extern const short swb_bwe_trans_subband[]; +extern const short swb_bwe_trans_subband_width[]; +extern const short swb_bwe_subband[]; +extern const float swb_inv_bwe_subband_width[]; +extern const short swb_bwe_sm_subband[]; +extern const float smooth_factor[]; +extern const short fb_bwe_subband[]; +extern const float fb_inv_bwe_subband_width[]; +extern const short fb_bwe_sm_subband[]; +extern const float fb_smooth_factor[]; +extern const float EnvCdbk11 []; +extern const float EnvCdbk1st []; +extern const float EnvCdbk2nd []; +extern const float EnvCdbk3rd []; +extern const float EnvCdbk4th []; +extern const float EnvCdbkFB[]; +extern const float Env_TR_Cdbk1 []; +extern const float Env_TR_Cdbk2 []; +extern const float w_NOR[]; +extern const float Mean_env[]; +extern const float Mean_env_fb[]; +extern const float Mean_env_tr[]; + +/*------------------------------------------------------------------------------* + * ACEPL/HQ core switching tables + *------------------------------------------------------------------------------*/ + +extern const float hp12800_32000[]; +extern const float hp16000_32000[]; +extern const float hp12800_48000[]; +extern const float hp16000_48000[]; +extern const float hp12800_16000[]; + + +extern const double cu15[28][3]; +extern const double cu4[6][3]; +extern const short ct2[7][13]; + +/*------------------------------------------------------------------------------* + * HQ core tables + *------------------------------------------------------------------------------*/ + +extern const float window_48kHz[]; +extern const float window_256kHz[]; +extern const float half_overlap_25[]; +extern const float half_overlap_48[]; +extern const float half_overlap_int[]; +extern const float small_overlap_25[]; +extern const float small_overlap_48[]; +extern const float small_overlap_int[]; +extern const float window_8_16_32kHz[]; + +extern const float short_window_48kHz[]; +extern const float short_window_32kHz[]; +extern const float short_window_16kHz[]; +extern const float short_window_8kHz[]; + +extern const float wscw16q15[]; +extern const float wscw16q15_8[]; +extern const float wscw16q15_16[]; +extern const float wscw16q15_32[]; + +/* Band structure */ +extern const short band_len_HQ[]; +extern const short band_start_HQ[]; +extern const short band_end_HQ[]; +extern const short band_len_wb[]; +extern const short band_start_wb[]; +extern const short band_end_wb[]; +extern const short band_len_harm[]; +extern const short band_start_harm[]; +extern const short band_end_harm[]; +extern const float rat[SFM_N_WB]; + +extern const short intl_bw_16[N_INTL_GRP_16]; +extern const short intl_bw_32[N_INTL_GRP_32]; +extern const short intl_bw_48[N_INTL_GRP_48]; +extern const short intl_cnt_16[N_INTL_GRP_16]; +extern const short intl_cnt_32[N_INTL_GRP_32]; +extern const short intl_cnt_48[N_INTL_GRP_48]; +extern const short norm_order_48[NB_SFM]; +extern const short norm_order_32[SFM_N_SWB]; +extern const short norm_order_16[SFM_N_WB]; + +extern const float dicn_pg[45]; +extern const short expPkEnrg_tbl[45]; +extern const int manPkEnrg_tbl[45]; +extern const int E_max5_tbl[40]; + +extern const float thren_pg[44]; + +extern const float dicn[40]; +extern const float dicn_inv[40]; +extern const float thren_HQ[39]; +extern const short dicnlg2[40]; +extern const short huffnorm[32]; +extern const short huffsizn[32]; +extern const short huffcoef[60]; +extern const short pgain_huffnorm[32]; +extern const short pgain_huffsizn[32]; + +extern const short resize_huffnorm[32]; +extern const short resize_huffsizn[32]; + +extern const short huffnorm_tran[32]; +extern const short huffsizn_tran[32]; + +extern const short sfm_width[20]; +extern const short a_map[20]; +extern const short subf_norm_groups[4][11]; + +extern const Word32 SQRT_DIM_fx[]; + +/* HQ inner_frame signallisation table */ +extern const short inner_frame_tbl[]; + +/* NB short win: 7200/8000/9600, 13200/16400 */ +extern const short band_width_40_4_6_0_0_0[4]; +extern const short band_width_40_5_6_0_0_0[5]; + +/* NB long win: 7200, 8000, 9600, 13200, 16400 */ +extern const short band_width_160_18_6_4_0_0[18]; +extern const short band_width_160_17_6_3_0_0[17]; +extern const short band_width_160_14_6_3_0_0[14]; +extern const short band_width_160_13_6_2_0_0[13]; + +/* WB short win: 13200/16400 */ +extern const short band_width_80_7_6_0_0_0[7]; + +/* WB long win: 13200, 16400 */ +extern const short band_width_320_18_6_3_0_0[18]; +extern const short band_width_320_20_6_3_0_0[20]; + +/* SWB short win: 13200, 16400 */ +extern const short band_width_142_8_8_0_0_0[8]; +extern const short band_width_160_8_8_0_0_0[8]; + +/* SWB long win: 13200, 16400 */ +extern const short band_width_568_22_6_2_0_0[22]; +extern const short band_width_640_24_6_4_0_0[24]; + +/* LR-MDCT configuration tables */ +extern const Xcore_Config xcore_config_8kHz_007200bps_long; +extern const Xcore_Config xcore_config_8kHz_008000bps_long; +extern const Xcore_Config xcore_config_8kHz_013200bps_long; +extern const Xcore_Config xcore_config_8kHz_016400bps_long; + +extern const Xcore_Config xcore_config_8kHz_007200bps_short; +extern const Xcore_Config xcore_config_8kHz_008000bps_short; +extern const Xcore_Config xcore_config_8kHz_013200bps_short; +extern const Xcore_Config xcore_config_8kHz_016400bps_short; + +extern const Xcore_Config xcore_config_16kHz_013200bps_long; +extern const Xcore_Config xcore_config_16kHz_016400bps_long; + +extern const Xcore_Config xcore_config_16kHz_013200bps_short; +extern const Xcore_Config xcore_config_16kHz_016400bps_short; + +extern const Xcore_Config xcore_config_32kHz_013200bps_long; +extern const Xcore_Config xcore_config_32kHz_016400bps_long; + +extern const Xcore_Config xcore_config_32kHz_013200bps_short; +extern const Xcore_Config xcore_config_32kHz_016400bps_short; + + +extern const short Nb[NB_SFM]; +extern const short LNb[ NB_SFM]; + +extern const Word32 pow_getbitsfrompulses_fx[16]; +extern const Word32 table_logcum_fx[563]; +extern const Word16 DDP_fx[4]; +extern const float DDP[4]; + + +extern const short step_tcq[8][STATES]; +extern const short denc[8][STATES]; +extern const short ddec[8][STATES]; + +extern const short step_LSB[STATES_LSB][2]; +extern const short denc_LSB[STATES_LSB][2]; +extern const short dqnt_LSB[STATES_LSB][4]; +extern const short dstep_LSB[4][2]; +extern const short ddec_LSB[4][2]; + +extern const short nextstate[STATES][2]; + +extern const short fine_gain_bits[]; +extern const float *const finegain[]; + +extern const unsigned char hBitsMinus1_N01[2]; +extern const unsigned char hBitsMinus1_N02[65]; +extern const unsigned char hBitsMinus1_N03[65]; +extern const unsigned char hBitsMinus1_N04[65]; +extern const unsigned char hBitsMinus1_N05[54]; +extern const unsigned char hBitsMinus1_N06[42]; +extern const unsigned char hBitsMinus1_N07[34]; +extern const unsigned char hBitsMinus1_N08[29]; +extern const unsigned char hBitsMinus1_N09[25]; +extern const unsigned char hBitsMinus1_N10[22]; +extern const unsigned char hBitsMinus1_N11[19]; +extern const unsigned char hBitsMinus1_N12[17]; +extern const unsigned char hBitsMinus1_N13[16]; +extern const unsigned char hBitsMinus1_N14[14]; +extern const unsigned char hBitsMinus1_N15[13]; +extern const unsigned char hBitsMinus1_N16[13]; +extern const unsigned char hBitsMinus1_N17[12]; +extern const unsigned char hBitsMinus1_N18[12]; +extern const unsigned char hBitsMinus1_N19[11]; +extern const unsigned char hBitsMinus1_N20[11]; +extern const unsigned char hBitsMinus1_N21[10]; +extern const unsigned char hBitsMinus1_N22[10]; +extern const unsigned char hBitsMinus1_N23[10]; +extern const unsigned char hBitsMinus1_N24[10]; +extern const unsigned char hBitsMinus1_N25[9]; +extern const unsigned char hBitsMinus1_N26[9]; +extern const unsigned char hBitsMinus1_N27[9]; +extern const unsigned char hBitsMinus1_N28[9]; +extern const unsigned char hBitsMinus1_N29[9]; +extern const unsigned char hBitsMinus1_N30[8]; +extern const unsigned char hBitsMinus1_N31[8]; +extern const unsigned char hBitsMinus1_N32[8]; +extern const unsigned char hBitsMinus1_N33[8]; +extern const unsigned char hBitsMinus1_N34[8]; +extern const unsigned char hBitsMinus1_N35[8]; +extern const unsigned char hBitsMinus1_N36[8]; +extern const unsigned char hBitsMinus1_N37[8]; +extern const unsigned char hBitsMinus1_N38[8]; +extern const unsigned char hBitsMinus1_N39[8]; +extern const unsigned char hBitsMinus1_N40[8]; +extern const unsigned char hBitsMinus1_N41[7]; +extern const unsigned char hBitsMinus1_N42[7]; +extern const unsigned char hBitsMinus1_N43[7]; +extern const unsigned char hBitsMinus1_N44[7]; +extern const unsigned char hBitsMinus1_N45[7]; +extern const unsigned char hBitsMinus1_N46[7]; +extern const unsigned char hBitsMinus1_N47[7]; +extern const unsigned char hBitsMinus1_N48[7]; +extern const unsigned char hBitsMinus1_N49[7]; +extern const unsigned char hBitsMinus1_N50[7]; +extern const unsigned char hBitsMinus1_N51[7]; +extern const unsigned char hBitsMinus1_N52[7]; +extern const unsigned char hBitsMinus1_N53[7]; +extern const unsigned char hBitsMinus1_N54[7]; +extern const unsigned char hBitsMinus1_N55[7]; +extern const unsigned char hBitsMinus1_N56[7]; +extern const unsigned char hBitsMinus1_N57[7]; +extern const unsigned char hBitsMinus1_N58[7]; +extern const unsigned char hBitsMinus1_N59[7]; +extern const unsigned char hBitsMinus1_N60[7]; +extern const unsigned char hBitsMinus1_N61[6]; +extern const unsigned char hBitsMinus1_N62[6]; +extern const unsigned char hBitsMinus1_N63[6]; +extern const unsigned char hBitsMinus1_N64[6]; +extern const unsigned char* const hBitsN[65]; +extern const short dsHighDiracsTab[43]; +extern const unsigned int intLimCDivInvDQ31[68]; +extern const unsigned char obtainEnergyQuantizerDensity_f[57]; +extern const short lim_neg_inv_tbl_fx[11]; +extern const short fg_inv_tbl_fx[13] ; +/* functions and tables for pvq_indexing */ +extern const unsigned int exactdivodd[ODD_DIV_SIZE] ; + +extern const float gain_att[]; +extern const float att_step[]; +extern const float gain_qlow[]; +extern const short gain_cb_size[]; +extern const float stab_trans[]; +extern const Word16 stab_trans_fx[]; +extern const float env_stab_tp[2][2]; +/*----------------------------------------------------------------------------------* + * SWB BWE for LR MDCT core + *----------------------------------------------------------------------------------*/ +extern const float gain_table_SWB_BWE[NB_SWB_SUBBANDS]; +/* HQ_NORMAL mode */ +extern const short bits_lagIndices_modeNormal[NB_SWB_SUBBANDS]; +extern const short subband_offsets_12KBPS[NB_SWB_SUBBANDS]; +extern const short subband_offsets_16KBPS[NB_SWB_SUBBANDS]; +extern const short subband_search_offsets[NB_SWB_SUBBANDS]; +extern const short bw_SPT_tbl[2][SPT_SHORTEN_SBNUM]; + +/* HQ_HARMONIC mode */ +extern const short bits_lagIndices_mode0_Har[NB_SWB_SUBBANDS_HAR_SEARCH_SB]; +extern const short subband_offsets_sub5_13p2kbps_Har[NB_SWB_SUBBANDS_HAR]; +extern const short subband_search_offsets_13p2kbps_Har[NB_SWB_SUBBANDS_HAR_SEARCH_SB]; +extern const short subband_offsets_sub5_16p4kbps_Har[NB_SWB_SUBBANDS_HAR]; +extern const short subband_search_offsets_16p4kbps_Har[NB_SWB_SUBBANDS_HAR_SEARCH_SB] ; + +/*----------------------------------------------------------------------------------* + * SC-VBR + *----------------------------------------------------------------------------------*/ + +/* NELP filter coefficients */ +extern const float bp1_num_coef_wb[5]; +extern const float bp1_den_coef_wb[5]; +extern const float shape1_num_coef[11]; +extern const float shape1_den_coef[11]; +extern const float shape2_num_coef[11]; +extern const float shape2_den_coef[11]; +extern const float shape3_num_coef[11]; +extern const float shape3_den_coef[11]; +extern const float txlpf1_num_coef[11]; +extern const float txlpf1_den_coef[11]; +extern const float txhpf1_num_coef[11]; +extern const float txhpf1_den_coef[11]; +extern const float bp1_num_coef_nb_fx_order7[8]; +extern const float bp1_den_coef_nb_fx_order7[8]; +extern const float num_nelp_lp[NELP_LP_ORDER+1]; +extern const float den_nelp_lp[NELP_LP_ORDER+1]; + +extern const float UVG1CB_WB[UVG1_CBSIZE][2]; +extern const float UVG2CB1_WB[UVG2_CBSIZE][5]; +extern const float UVG2CB2_WB[UVG2_CBSIZE][5]; + +extern const float UVG1CB_NB[UVG1_CBSIZE][2]; +extern const float UVG2CB1_NB[UVG2_CBSIZE][5]; +extern const float UVG2CB2_NB[UVG2_CBSIZE][5]; + +extern const float frac_4sf[NB_SUBFR + 2]; + +extern const float erb_WB[NUM_ERB_WB + 1]; +extern const float erb_NB[NUM_ERB_NB + 1]; + +extern const float AmpCB1_WB[64][10]; +extern const float AmpCB2_WB[64][NUM_ERB_WB - 11]; + +extern const float AmpCB1_NB[64][10]; +extern const float AmpCB2_NB[64][NUM_ERB_NB - 11]; + +extern const float PowerCB_WB[64][2]; +extern const float PowerCB_NB[64][2]; +extern const float sinc[8][12]; + +extern const float hvq_thr_adj[5]; +extern const float hvq_peak_cb[1024]; +extern const float hvq_class_c[16]; +extern const short hvq_cb_search_overlap24k[17]; +extern const short hvq_cb_search_overlap32k[21]; + +extern const short hvq_pg_huff_offset[NUM_PG_HUFFLEN]; +extern const short hvq_pg_huff_thres[NUM_PG_HUFFLEN]; +extern const short hvq_pg_huff_tab[32]; + +extern const short hvq_cp_huff_len[52]; +extern const short hvq_cp_huff_val[52]; +extern const short hvq_cp_layer1_map5[HVQ_CP_MAP_LEN]; + +extern const short hvq_cp_huff_thres[HVQ_CP_HUFF_NUM_LEN]; +extern const short hvq_cp_huff_offset[HVQ_CP_HUFF_NUM_LEN]; +extern const short hvq_cp_huff_tab[52]; + +extern const short pow2_angle_res[8]; + +/*------------------------------------------------------------------------------* + * GSC mode + *------------------------------------------------------------------------------*/ + +extern const float sin_table256[]; + +extern const short gsc_sfm_start[]; +extern const short gsc_sfm_end[]; +extern const short gsc_sfm_size[]; + +extern const float sm_table[]; + +extern const float mfreq_loc[]; +extern const short mfreq_bindiv_loc[]; + +extern const float mean_gp[]; +extern const float dic_gp[]; + +extern const float Gain_mean[]; +extern const float Gain_meanHR[]; +extern const float Gain_mean_dic[]; +extern const float Gain_mean_dicHR[]; + +extern const float YG_mean16[]; +extern const float YG_dicMR_1[]; +extern const float YG_dicMR_2[]; +extern const float YG_dicMR_3[]; +extern const float YG_dicMR_4[]; + +extern const float mean_m[]; +extern const float mean_gain_dic[]; + +extern const float YGain_mean_LR[]; +extern const float YGain_dic1_LR[]; +extern const float YGain_dic2_LR[]; +extern const float YGain_dic3_LR[]; +extern const float Gain_dic2_NBHR[]; +extern const float Gain_dic3_NBHR[]; + +extern const short GSC_freq_bits[]; +extern const short GSC_freq_DL0_bits[]; + +extern const float Gain_meanNB[]; +extern const float Gain_mean_dicNB[]; +extern const float Mean_dic_NB[]; +extern const float Gain_dic1_NB[]; +extern const float Gain_dic2_NB[]; +extern const float Gain_dic3_NB[]; + + +/*------------------------------------------------------------------------------* + * FFT transform + *------------------------------------------------------------------------------*/ + +extern const short Odx_fft64[64]; +extern const float w_fft64[32]; +extern const short Ip_fft64[6]; +extern const short Odx_fft32_15[32]; +extern const float w_fft32[16]; +extern const short Ip_fft32[6]; +extern const short Odx_fft32_5[32]; +extern const short Odx_fft16[16]; +extern const float w_fft16[8]; +extern const short Ip_fft16[6]; +extern const float w_fft8[8]; +extern const short Ip_fft8[6]; +extern const short Idx_dortft80[80]; +extern const short Idx_dortft120[120]; +extern const short Idx_dortft160[160]; +extern const short Idx_dortft320[320]; +extern const short Idx_dortft480[480]; +extern const short Ip_fft128[10]; +extern const float w_fft128[64]; +extern const short Ip_fft256[10]; +extern const float w_fft256[128]; +extern const short Ip_fft512[18]; +extern const float w_fft512[256]; +extern const short Idx_dortft40[40]; +extern const short Odx_fft8_5[8]; +extern const short ip_edct2_64[6]; +extern const float w_edct2_64[80]; +extern const short Idx_dortft20[20]; +extern const short Odx_fft4_5[4]; +extern const float w_fft4[2]; +extern const short Ip_fft4[6]; + +/*----------------------------------------------------------------------------------* + * FEC for HQ core + *----------------------------------------------------------------------------------*/ + +extern const float Asr_LP32[41]; +extern const float Asr_LP16[21]; +extern const float Asr_LP48[61]; + +extern const short Num_bands_NB[]; +extern const float SmoothingWin_NB875[]; +extern const float SmoothingWin_NB2[]; + +/*----------------------------------------------------------------------------------* + * CLDFB + *----------------------------------------------------------------------------------*/ + +extern const int freqTable[2]; + +extern const float CLDFB80_10[100]; +extern const float CLDFB80_16[160]; +extern const float CLDFB80_20[200]; +extern const float CLDFB80_30[300]; +extern const float CLDFB80_32[320]; +extern const float CLDFB80_40[400]; +extern const float CLDFB80_60[600]; + +extern const float *const CLDFB80_COEF[]; + +extern const float rot_vec_ana_re_L10[5]; +extern const float rot_vec_ana_im_L10[5]; +extern const float rot_vec_ana_re_L16[8]; +extern const float rot_vec_ana_im_L16[8]; +extern const float rot_vec_ana_re_L20[10]; +extern const float rot_vec_ana_im_L20[10]; +extern const float rot_vec_ana_re_L30[15]; +extern const float rot_vec_ana_im_L30[15]; +extern const float rot_vec_ana_re_L32[16]; +extern const float rot_vec_ana_im_L32[16]; +extern const float rot_vec_ana_re_L40[20]; +extern const float rot_vec_ana_im_L40[20]; +extern const float rot_vec_ana_re_L60[30]; +extern const float rot_vec_ana_im_L60[30]; + +extern const float rot_vec_syn_re_L10[5]; +extern const float rot_vec_syn_im_L10[5]; +extern const float rot_vec_syn_re_L16[8]; +extern const float rot_vec_syn_im_L16[8]; +extern const float rot_vec_syn_re_L20[10]; +extern const float rot_vec_syn_im_L20[10]; +extern const float rot_vec_syn_re_L30[15]; +extern const float rot_vec_syn_im_L30[15]; +extern const float rot_vec_syn_re_L32[16]; +extern const float rot_vec_syn_im_L32[16]; +extern const float rot_vec_syn_re_L40[20]; +extern const float rot_vec_syn_im_L40[20]; +extern const float rot_vec_syn_re_L60[30]; +extern const float rot_vec_syn_im_L60[30]; + +extern const float bpf_weights_16[CLDFB_NO_COL_MAX]; + +extern const float CNG_details_codebook[64][NUM_ENV_CNG]; +/*----------------------------------------------------------------------------------* + * FD CNG + *----------------------------------------------------------------------------------*/ + +extern const int d_array[18]; +extern const float m_array[18]; +extern const float msQeqInvAv_thresh[3]; +extern const float msNoiseSlopeMax[4]; + +extern const SCALE_SETUP scaleTable[20]; +extern const SCALE_SETUP scaleTable_cn_only[18]; +extern const float scaleTable_cn_only_amrwbio[3][2]; + +extern const int 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 short maxN_37bits; +extern const short maxC_37bits; +extern const short stages_37bits; +extern const int levels_37bits[6]; +extern const short bits_37bits[6]; +extern const float * const cdk_37bits[]; + +extern const float fftSineTab640[321]; + +extern const float olapWinAna512[512]; +extern const float olapWinAna640[640]; + +extern const float olapWinSyn256[256]; +extern const float olapWinSyn320[320]; + + +/*----------------------------------------------------------------------------------* + * TCX + *----------------------------------------------------------------------------------*/ + +extern float const gain_corr_fac[]; +extern float const gain_corr_inv_fac[]; + +extern const SCALE_TCX_SETUP scaleTcxTable[13]; + + +/*----------------------------------------------------------------------------------* + * Arithmetic coder + *----------------------------------------------------------------------------------*/ + +extern const unsigned char ari_lookup_s17_LC[4096]; +extern const unsigned short ari_pk_s17_LC_ext[64][18]; + +extern const int NumRatioBits[2][17]; +extern const float Ratios_WB_2[32]; +extern const float Ratios_WB_3[32]; +extern const float Ratios_WB_4[32]; +extern const float Ratios_WB_5[32]; +extern const float Ratios_WB_6[32]; +extern const float Ratios_WB_7[32]; +extern const float Ratios_WB_8[16]; +extern const float Ratios_WB_9[16]; +extern const float Ratios_WB_10[16]; +extern const float Ratios_WB_11[16]; +extern const float Ratios_WB_12[16]; +extern const float Ratios_WB_13[16]; +extern const float Ratios_WB_14[16]; +extern const float Ratios_WB_15[16]; +extern const float Ratios_WB_16[4]; +extern const float Ratios_WB_17[4]; +extern const float Ratios_WB_18[4]; +extern const float Ratios_NB_2[32]; +extern const float Ratios_NB_3[16]; +extern const float Ratios_NB_4[16]; +extern const float Ratios_NB_5[16]; +extern const float Ratios_NB_6[16]; +extern const float Ratios_NB_7[16]; +extern const float Ratios_NB_8[16]; +extern const float Ratios_NB_9[8]; +extern const float Ratios_NB_10[8]; +extern const float Ratios_NB_11[8]; +extern const float Ratios_NB_12[8]; +extern const float Ratios_NB_13[4]; +extern const float Ratios_NB_14[4]; +extern const float Ratios_NB_15[4]; +extern const float Ratios_NB_16[4]; +extern const float Ratios_NB_17[4]; +extern const float Ratios_NB_18[4]; +extern const float *const Ratios[2][17]; + +extern const Word16 qGains[2][1 << kTcxHmNumGainBits]; + +/*----------------------------------------------------------------------------------* + * Innovative codebook + *----------------------------------------------------------------------------------*/ + +extern const PulseConfig PulseConfTable[]; + +/*----------------------------------------------------------------------------------* + * TNS + *----------------------------------------------------------------------------------*/ + +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 float const tnsAcfWindow[TNS_MAX_FILTER_ORDER]; + +extern ParamsBitMap const tnsEnabledSWBTCX20BitMap; +extern ParamsBitMap const tnsEnabledSWBTCX10BitMap; +extern ParamsBitMap const tnsEnabledWBTCX20BitMap; + +extern const Coding codesTnsAllCoeffs[]; + +extern const Coding codesTnsCoeff0SWBTCX20[]; +extern const Coding codesTnsCoeff0SWBTCX10[]; +extern const Coding codesTnsCoeff1SWBTCX20[]; +extern const Coding codesTnsCoeff1SWBTCX10[]; +extern const Coding codesTnsCoeff2SWBTCX20[]; +extern const Coding codesTnsCoeff2SWBTCX10[]; +extern const Coding codesTnsCoeff3SWBTCX20[]; +extern const Coding codesTnsCoeff3SWBTCX10[]; +extern const Coding codesTnsCoeff4SWBTCX20[]; +extern const Coding codesTnsCoeff4SWBTCX10[]; +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 int const nTnsCoeffCodes; + +extern const Coding * const codesTnsCoeffSWBTCX20[]; +extern const Coding * const codesTnsCoeffSWBTCX10[]; +extern const Coding * const codesTnsCoeffWBTCX20[]; +extern int const nTnsCoeffTables; + +extern const Coding codesTnsOrderTCX20[]; +extern const Coding codesTnsOrderTCX10[]; +extern const Coding codesTnsOrder[]; +extern int const nTnsOrderCodes; + +extern float const tnsCoeff4[16]; + +/**********************************************************************/ /** +igf settings structure for each bitrate mode +**************************************************************************/ +typedef struct igf_mode_type +{ + int sampleRate; + int frameLength; + int bitRate; + int igfMinFq; + float transFac; + int maxHopsize; +} IGF_MODE,*H_IGF_MODE; + +extern const IGF_MODE igfMode[15]; +extern const int swb_offset_LB_new[15][IGF_MAX_SFB]; +extern const float igf_whitening_TH[15][2][IGF_MAX_TILES]; +extern const short cf_off_se01_tab[9]; +extern const short cf_off_se10_tab; +extern const short cf_off_se02_tab[9][IGF_CTX_COUNT]; +extern const short cf_off_se11_tab[IGF_CTX_COUNT][IGF_CTX_COUNT]; +extern const unsigned short cf_se00_tab[IGF_SYMBOLS_IN_TABLE + 1]; +extern const unsigned short cf_se01_tab[9][IGF_SYMBOLS_IN_TABLE + 1]; +extern const unsigned short cf_se02_tab[9][IGF_CTX_COUNT][IGF_SYMBOLS_IN_TABLE + 1]; +extern const unsigned short cf_se10_tab[IGF_SYMBOLS_IN_TABLE + 1]; +extern const unsigned short cf_se11_tab[IGF_CTX_COUNT][IGF_CTX_COUNT][IGF_SYMBOLS_IN_TABLE + 1]; + +extern const int bwMode2fs[4]; + +extern const float normReciprocal[CHEAP_NORM_SIZE]; +extern const float *w_a[7]; + +extern const PWord16 SineTable512_fx[]; +extern const Word16 ldCoeff[7]; +extern const UWord32 exp2_tab_long[32]; +extern const UWord32 exp2w_tab_long[32]; +extern const UWord32 exp2x_tab_long[32]; +extern const Word16 invTable[INV_TABLE_SIZE+1]; +extern const Word16 sqrtTable[SQRT_TABLE_SIZE+1]; +extern const Word16 invSqrtTable[SQRT_TABLE_SIZE+1]; + +/* ACELP pulse coding */ +extern const int low_len[10]; +extern const int low_mask[10]; +extern const int indx_fact[10]; +extern const int index_len[3]; +extern const int index_mask_ACELP[3]; + +#endif + diff --git a/lib_com/stab_est.c b/lib_com/stab_est.c new file mode 100644 index 000000000..958da3004 --- /dev/null +++ b/lib_com/stab_est.c @@ -0,0 +1,198 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define BIN_4000 80 /* The frequency bin corresponding to 4kHz */ +#define MAX_SNR1 45.0f +#define INV_MAX_SNR (1.0f / (MAX_SNR1-1.0f)) /* Max. SNR considered for noise subtraction in voiced segments */ +#define MAX_SNR_SNR1 (MAX_SNR1 * INV_MAX_SNR) /* 45 * (1 / (MAX_SNR1-1)) */ +#define MAX_BANDEXC 20 +#define TH_0_MAX (1.5f*3.125f) +#define TH_1_MAX (1.5f*2.8125f) +#define TH_2_MAX (1.5f*2.1875f) +#define TH_3_MAX (1.5f*1.875f) + +#define TH_UP 0.15625f +#define TH_DW 0.15625f +#define NB_TH3_MIN 30 +#define NB_TH1_MIN 30 + +#define MAX_THR 0.92f + +/*------------------------------------------------------------------------* + * stab_est() + * + * Signal stability estimation based on energy variation + *------------------------------------------------------------------------*/ + +short stab_est( + float etot, /* i : Total energy of the current frame */ + float *lt_diff_etot, /* i/o : Long term total energy variation */ + float *mem_etot, /* i/o : Total energy memory */ + short *nb_thr_3, /* i/o : Number of consecutives frames of level 3 */ + short *nb_thr_1, /* i/o : Number of consecutives frames of level 1 */ + float *thresh, /* i/o : Detection thresold */ + short *last_music_flag, /* i/o : Previous music detection ouptut */ + short vad_flag +) +{ + short i, music_flag2; + float mean_diff; + float ftmp_c, fcorr, dev; + + /*------------------------------------------------------------------------* + * Find mean of the past MAX_LT frames energy variation + *------------------------------------------------------------------------*/ + + mean_diff = 0.0f; + for (i = 1; i= 3 + * (last category was "tonal" and the new one is "very tonal") + *--------------------------------------------------------------------*/ + + if ( dev < thresh[3] && *last_music_flag >= 3 ) + { + music_flag2 = 4; + *nb_thr_3 += 1; + *nb_thr_1 = 0; + } + + /*--------------------------------------------------------------------* + * statistical deviation < Thresh2 and last signal category type >= 2 + * (last category was "moderatly tonal" and the new one is a "tonal" ) + *--------------------------------------------------------------------*/ + + else if ( dev < thresh[2] && *last_music_flag >= 2 ) + { + music_flag2 = 3; + *nb_thr_3 += 1; + *nb_thr_1 = 0; + } + + /*--------------------------------------------------------------------* + * statistical deviation < Thresh1 and last signal category type >= 1 + * (last category was "slightly tonal" and the new one is a "moderatly tonal") + *--------------------------------------------------------------------*/ + + else if ( dev < thresh[1] && *last_music_flag >= 1 ) + { + music_flag2 = 2; + } + + /*--------------------------------------------------------------------* + * statistical deviation < Thresh0 + * (last category was "not tonal" and the new one is "slightly tonal") + *--------------------------------------------------------------------*/ + + else if ( dev < thresh[0] ) + { + music_flag2 = 1; + } + + /*--------------------------------------------------------------------* + * statistical deviation > Thresh0 + * (Statistical deviation is high: the new tonal category is not tonal) + *--------------------------------------------------------------------*/ + + else + { + *nb_thr_1 += 1; + *nb_thr_3 = 0; + } + + /*------------------------------------------------------------------------* + * Update the thresholds + *------------------------------------------------------------------------*/ + + if (*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] += TH_UP; + thresh[1] += TH_UP; + thresh[2] += TH_UP; + thresh[3] += TH_UP; + } + else if (*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] -= TH_DW; + thresh[1] -= TH_DW; + thresh[2] -= TH_DW; + thresh[3] -= TH_DW; + } + + /* limitation of the threshold (this local macro stores the highest of the two and it also counts the # of operations) */ + set_max( &thresh[0], TH_0_MIN2 ); + set_max( &thresh[1], TH_1_MIN2 ); + set_max( &thresh[2], TH_2_MIN2 ); + + set_min( &thresh[0], TH_0_MAX ); + set_min( &thresh[1], TH_1_MAX ); + set_min( &thresh[2], TH_2_MAX ); + + set_max( &thresh[3], TH_3_MIN2 ); + set_min( &thresh[3], TH_3_MAX ); + /*------------------------------------------------------------------------* + * Final updates + *------------------------------------------------------------------------*/ + + *last_music_flag = music_flag2; + if ( vad_flag == 0 ) + { + /* overwrite decision in unvoiced frames */ + music_flag2 = 0; + } + + return music_flag2; +} diff --git a/lib_com/stat_com.h b/lib_com/stat_com.h new file mode 100644 index 000000000..468515941 --- /dev/null +++ b/lib_com/stat_com.h @@ -0,0 +1,643 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + + +#ifndef STAT_COM_H +#define STAT_COM_H + +#include +#include +#include +#include "options.h" +#include "typedef.h" +#include "cnst.h" + + +/*----------------------------------------------------------------------------------* + * Declaration of structures + *----------------------------------------------------------------------------------*/ + +/* Forward declaration of Decoder_State */ +struct Decoder_State; + +/* NB postfilter static variables */ +typedef struct +{ + int on; /* On/off flag */ + short reset; /* reset flag */ + float mem_pf_in[L_SUBFR]; /* Input memory */ + float mem_stp[L_SUBFR]; /* 1/A(gamma1) memory */ + float mem_res2[DECMEM_RES2]; /* A(gamma2) residual */ + float mem_zero[M]; /* null memory to compute i.r. of A(gamma2)/A(gamma1) */ + float gain_prec; /* for gain adjustment */ +} PFSTAT; + +typedef struct +{ + float a[MAXLAG_WI]; + float b[MAXLAG_WI]; + int lag; + int nH; + int nH_4kHz; + float upper_cut_off_freq_of_interest; + float upper_cut_off_freq; + float Fs; +} DTFS_STRUCTURE; + +typedef struct +{ + short lead_sign_ind; + unsigned int index, size; + short dim, k_val; +} PvqEntry; + +typedef struct +{ + unsigned char buf[MAX_SIZEBUF_PBITSTREAM]; + signed char curPos; + unsigned int numByte; + unsigned int numbits; + unsigned int maxBytes; +} BITSTREAM, *PBITSTREAM; + +typedef struct +{ + PBITSTREAM bsInst; + + unsigned int low; + unsigned int high; + + unsigned int value; + int bits_to_follow; + + int num_bits; + int max_bits; + +} ARCODEC, *PARCODEC; + +/*---------------------------------------------------------------* + * Encoder/Decoder Static RAM * + *---------------------------------------------------------------*/ +typedef struct +{ + /*Coding mode info*/ + short mode_index; + + /*LPC info*/ + short midLpc; /*Flag for using or not mid LPC for the current frame*/ + short midLpc_enable; /*Flag enabling or not the mid LPC for the current mode*/ + + /*ICB flags*/ + short pre_emphasis; /*Flag for triggering pre-emphasis*/ + short pitch_sharpening; /*Flag for triggering pitch sharpening*/ + short phase_scrambling; /*Flag for triggering phase scrambling*/ + short formant_enh; /*Flag for triggering formant enhancement*/ + short formant_tilt; /*Flag for triggering formant tile*/ + + short voice_tilt; /*Flag for triggering new voice factor tilt*/ + + float formant_enh_num; + float formant_enh_den; + + short bpf_mode; + + short nrg_mode; + short nrg_bits; + + short ltp_mode; + short ltp_bits; + + short ltf_mode; + short ltf_bits; + + short gains_mode[NB_SUBFR16k]; + + int fixed_cdk_index[NB_SUBFR16k]; + + +} ACELP_config; + +/* tns_base.h */ +/** TNS configuration. + * Use InitTnsConfiguration to initialize it. + */ +typedef struct +{ + unsigned char maxOrder; + + /** Maximum number of filters. */ + unsigned char 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. + */ + short 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. */ + int spectrumLength; + /** Filter order. */ + int order; + /** Quantized filter coefficients. */ + int coefIndex[TNS_MAX_FILTER_ORDER]; + /** Prediction gain. The ratio of a signal and TNS residual energy. */ + float predictionGain; + /** Average squared filter coefficient. */ + float avgSqrCoef; +} STnsFilter; + +/** TNS data. + * TNS data describing all active filters. + */ +typedef struct +{ + /** Number of active filters. */ + int 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 */ + float tcx_mdct_window[L_MDCT_OVLP_MAX]; /* Sine window for OL decision and DTX transitions*/ + float tcx_aldo_window_1[L_FRAME_MAX]; /* ALDO window long slope */ + float tcx_aldo_window_2[L_MDCT_OVLP_MAX]; /* ALDO window short slope */ + float *tcx_aldo_window_1_trunc; /* ALDO window truncated long slope */ + + short last_aldo; + float tcx_mdct_window_half[L_MDCT_HALF_OVLP_MAX]; + float tcx_mdct_window_minimum[L_MDCT_MIN_OVLP_MAX]; + float tcx_mdct_window_trans[L_MDCT_TRANS_OVLP_MAX]; /* transition window for ACELP->TCX */ + + int tcx5Size; /* Size of the TCX5 spectrum. Always 5ms. */ + + short tcx_curr_overlap_mode; /* window overlap of current frame (0: full, 2: none, or 3: half) */ + short tcx_last_overlap_mode; /* previous window overlap, i.e. left-side overlap of current frame */ + + int tcx_mdct_window_length; /* length of overlap-add region*/ + int tcx_mdct_window_half_length; /* length of the "half" overlap */ + int tcx_mdct_window_min_length; /* length of the "minimum" overlap */ + int tcx_mdct_window_trans_length; /* length of the ACELP->TCX overlap */ + + int tcx_mdct_window_delay; /*length of window delay*/ + int tcx_offset; /* Offset of the folding point relative to the end of the previous synthetised frame */ + int tcx_mdct_window_length_old; /*for keeping old value for sample rate switching */ + float tcx_mdct_windowFB[L_MDCT_OVLP_MAX]; + float tcx_aldo_window_1_FB[L_FRAME_MAX]; /* ALDO window long slope */ + float tcx_aldo_window_2_FB[L_MDCT_OVLP_MAX]; /* ALDO window short slope */ + float *tcx_aldo_window_1_FB_trunc; /* ALDO window truncated long slope */ + + float tcx_mdct_window_halfFB[L_MDCT_HALF_OVLP_MAX]; + float tcx_mdct_window_minimumFB[L_MDCT_MIN_OVLP_MAX]; + float tcx_mdct_window_transFB[L_MDCT_TRANS_OVLP_MAX]; /* transition window for ACELP->TCX */ + + int tcx5SizeFB; /* Size of the TCX5 spectrum. Always 5ms. */ + + int tcx_mdct_window_lengthFB; /*length of window, length of overlap-add region*/ + int tcx_mdct_window_half_lengthFB; /*length of the "half" overlap window*/ + int tcx_mdct_window_min_lengthFB; /*length of the "minimum" overlap window*/ + int tcx_mdct_window_trans_lengthFB; /* length of the ACELP->TCX overlap */ + + int tcx_mdct_window_delayFB; /*length of window delay*/ + int tcx_offsetFB; + + int tcx_coded_lines; /* max number of coded lines, depending on bandwidth mode */ + + /* FAC window */ + int lfacNext; + int lfacNextFB; + + /* TNS */ + int fIsTNSAllowed; + STnsConfig tnsConfig[2][2]; + STnsConfig const * pCurrentTnsConfig; + + /*Quantization*/ + float sq_rounding; /*set the sq deadzone (no deadzone=0.5f)*/ + short tcxRateLoopOpt; + + /*Bandwidth*/ + float preemph_fac; /*preemphasis factor*/ + float bandwidth; + + /* Context HM - Residual Quantization*/ + short ctx_hm; /*Flag for enabling Context HM*/ + short resq; /*Flag for enabling Residual Quantization*/ + int coder_type; /*GC,VC,UC*/ + + float na_scale; + + float SFM2; + +} TCX_config; + +/* prot.h */ +typedef struct +{ + int bits; /* bits per subframe */ + int nbiter; /* number of iterations */ + float alp; /* initial energy of all fixed pulses */ + int nb_pulse; /* number of pulses */ + int fixedpulses; /* number of pulses whose position is determined from correlation and not by iteration */ + int nbpos[13]; /* number of positions tried in the pair-wise search */ + enum TRACKPOS codetrackpos; /* ordering of tracks -mode */ +} PulseConfig; + +/* ari.h */ +typedef struct +{ + int low,high,vobf; +} Tastat; + +/* FD-based CNG setup */ +typedef struct +{ + int fftlen; /* FFT length */ + int stopFFTbin; /* Number of FFT bins to be actually processed */ + int numPartitions; /* Number of partitions */ + const int* sidPartitions; /* Upper boundaries for grouping the (sub)bands into partitions when transmitting SID frames (define as NULL pointer to avoid grouping) */ + + int numShapingPartitions; /* Number of partitions */ + const int* 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 +{ + int bwmode; + + int bitrateFrom; + int bitrateTo; + + float scale; + +} SCALE_SETUP; + + +/* Arrays and variables common to encoder and decoder */ +typedef struct +{ + FD_CNG_SETUP FdCngSetup; + + int numSlots; /* Number of time slots in CLDFB matrix */ + int regularStopBand;/* Number of CLDFB bands to be considered */ + + int numCoreBands; /* Number of core bands to be decomposed into FFT subbands */ + int stopBand; /* Total number of (sub)bands to be considered */ + int startBand; /* First (sub)band to be considered */ + int stopFFTbin; /* Total number of FFT subbands */ + int frameSize; /* Frame size in samples */ + int fftlen; /* FFT length used for the decomposition */ + + float timeDomainBuffer[L_FRAME16k]; + float fftBuffer[FFTLEN]; + float olapBufferAna[FFTLEN]; + float olapBufferSynth[FFTLEN]; + float olapBufferSynth2[FFTLEN]; + const float * olapWinAna; + const float * olapWinSyn; + const float * fftSineTab; + + float msM_win; + float msM_subwin; + + short msFrCnt_init_counter; /* Frame counter at initialization */ + short msFrCnt_init_thresh; + float init_old; + int msFrCnt; /* Frame counter */ + float msAlphaCor[2]; /* Correction factor (smoothed) */ + float msSlope[2]; + float msQeqInvAv[2]; + int msMinBufferPtr; + + float msPsdSum[2]; + float msPeriodogSum[2]; + + short offsetflag; + + float periodog[PERIODOGLEN]; /* Periodogram */ + float cngNoiseLevel[FFTCLDFBLEN]; /* Noise level applied for the CNG in each (sub)band */ + short seed; /* Seed memory (for random function) */ + + int npart; /* Number of partitions */ + int midband[NPART]; /* Central band of each partition */ + int nFFTpart; /* Number of hybrid spectral partitions */ + int part[NPART]; /* Partition upper boundaries (band indices starting from 0) */ + float psize[NPART]; /* Partition sizes */ + float psize_inv[NPART]; /* Inverse of partition sizes */ + float FFTscalingFactor; /* Squared ratio between core signal analysis FFT and noise estimator FFT */ + float scalingFactor; + int nCLDFBpart; /* Number of CLDFB spectral partitions */ + int CLDFBpart[NPARTCLDFB]; /* CLDFB Partition upper boundaries (band indices starting from 0 above the core coder bands) */ + float CLDFBpsize_inv[NPARTCLDFB];/* Inverse of CLDFB partition sizes */ + + short inactive_frame_counter; + short sid_frame_counter; + short active_frame_counter; + + float sidNoiseEst[NPART]; /* Transmitted noise level */ + + int frame_type_previous; + + float A_cng[17]; + float exc_cng[L_FRAME16k]; + + int CngBitrate; + short CngBandwidth; + + short flag_noisy_speech; + float likelihood_noisy_speech; + +} +FD_CNG_COM; +typedef FD_CNG_COM *HANDLE_FD_CNG_COM; + +/* parameter_bitmapping.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, int index, int * 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, int index, int 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 int (* TGetNumberOfBits)(int value, int 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 int (* TEncodeValue)(int value, int index); + +/** Function that decodes a value. + * @param bitstream Bitstream containing a coded value. + * @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 int (* TDecodeValue)(struct Decoder_State *st, int index, int * 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. + */ + int 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. + */ + int 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. */ + int nParams; + /** Definition of the mapping for each parameter. */ + ParamBitMap params[10]; +} ParamsBitMap; + +/* tns_tables.h */ +struct TnsParameters +{ + /* Parameters for each TNS filter */ + int startLineFrequency; /* Starting lower frequency of the TNS filter [20..16000] */ + int nSubdivisions; /* Number of spectrum subdivisions in which the filter operates [1..8) */ + float minPredictionGain; /* Minimum prediction gain required to turn on the TNS filter */ + float minAvgSqrCoef; /* Minimum average square of coefficients required to turn on the TNS filter */ +}; + +/**********************************************/ +/* Helper structures for hufmann table coding */ +/**********************************************/ + +typedef struct +{ + unsigned char value; + unsigned short int code; + unsigned char nBits; +} Coding; + + +/* Scale TCX setup */ +typedef struct +{ + int bwmode; + + int bitrateFrom; + int bitrateTo; + + float scale; + +} SCALE_TCX_SETUP; + + +/* glob_con.h */ +typedef struct +{ + unsigned short frame_bits; /*Bits per frame*/ + unsigned short frame_net_bits; /*Net Bits per frame*/ + unsigned char transmission_bits; /*max=1*/ + unsigned char transmission_mode[2]; /*SID,VBR/CBR*/ + unsigned char bandwidth_bits; /*max=2*/ + unsigned char bandwidth_min; /*first valid bandwidth (NB,WB,SWB,FB)*/ + unsigned char bandwidth_max; /*last valid bandwidth (NB,WB,SWB,FB)*/ + unsigned char reserved_bits; /*max=1*/ +} FrameSizeParams; + +typedef struct +{ + int no_channels; + int no_col; + int p_filter_length; + CLDFB_TYPE type; + + const float *p_filter; + + /* rotation vectors */ + const float *rot_vec_ana_re; + const float *rot_vec_ana_im; + const float *rot_vec_syn_re; + const float *rot_vec_syn_im; + + /* memory helper states */ + float *memory; + unsigned int memory_length; + + /* main filter state */ + float *cldfb_state; + + /* other parameters */ + int bandsToZero; /* bands not synthesized */ + int nab; /* number of active bands */ + float scale; /* scaling of frequency domain */ +} +CLDFB_FILTER_BANK; + +typedef CLDFB_FILTER_BANK *HANDLE_CLDFB_FILTER_BANK; + +typedef struct +{ + float pGainTemp[CLDFB_NO_COL_MAX]; + float loBuffer[CLDFB_NO_COL_MAX + MAX_TEC_SMOOTHING_DEG]; + +} TEMPORAL_ENVELOPE_CODING_DECODER; +typedef TEMPORAL_ENVELOPE_CODING_DECODER* HANDLE_TEC_DEC; + +typedef struct +{ + float loBuffer[CLDFB_NO_COL_MAX + MAX_TEC_SMOOTHING_DEG + DELAY_TEMP_ENV_BUFF_TEC]; + float loTempEnv[CLDFB_NO_COL_MAX]; + float loTempEnv_ns[CLDFB_NO_COL_MAX]; + float hiTempEnv[CLDFB_NO_COL_MAX + DELAY_TEMP_ENV_BUFF_TEC + EXT_DELAY_HI_TEMP_ENV]; + int tranFlag; + int corrFlag; +} TEMPORAL_ENVELOPE_CODING_ENCODER; +typedef TEMPORAL_ENVELOPE_CODING_ENCODER* HANDLE_TEC_ENC; + + +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 +{ + int swb_offset[IGF_MAX_SFB]; + int swb_offset_len; + int startFrequency; + int stopFrequency; + int startLine; + int stopLine; + int startSfb; + int stopSfb; + int sfbWrap[IGF_MAX_TILES+1]; + int sbWrap[IGF_MAX_TILES]; + int nTiles; + int minSrcSubband; + int minSrcFrequency; + int tile[IGF_MAX_TILES]; + int infoIsRefined; + int infoGranuleLen; + float infoTransFac; + float whiteningThreshold[2][IGF_MAX_TILES]; + float gFactor; + float fFactor; + float lFactor; +} IGF_GRID, *H_IGF_GRID; + +typedef struct IGF_INFO_struct +{ + short nfSeed; + int sampleRate; + int frameLength; + int maxHopsize; + IGF_GRID grid[IGF_NOF_GRIDS]; + short bitRateIndex; +} IGF_INFO, *H_IGF_INFO; + + +typedef struct +{ + int *indexBuffer; + int *peakIndices, *holeIndices; + int numPeakIndices, numHoleIndices; +} CONTEXT_HM_CONFIG; + +#endif diff --git a/lib_com/stat_noise_uv_mod.c b/lib_com/stat_noise_uv_mod.c new file mode 100644 index 000000000..90dbb3bb7 --- /dev/null +++ b/lib_com/stat_noise_uv_mod.c @@ -0,0 +1,206 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "prot.h" + + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ + +#define TILT_COMP_LIM 0.75f + +/*---------------------------------------------------------* + * Local functions + *---------------------------------------------------------*/ + +static float calc_tilt(const float *x, const short len); + +/*--------------------------------------------------------------------* + * stat_noise_uv_mod() + * + * Modifies excitation signal in stationary noise segments + *--------------------------------------------------------------------*/ + +void stat_noise_uv_mod( + const short coder_type, /* i : coder type */ + float noisiness, /* i : noisiness parameter */ + const float *lsp_old, /* i : old LSP vector at 4th sfr */ + const float *lsp_new, /* i : LSP vector at 4th sfr */ + const float *lsp_mid, /* i : LSP vector at 2nd sfr */ + float *Aq, /* o : A(z) quantized for the 4 subframes */ + float *exc2, /* o : excitation buffer */ + const short bfi, /* i : bad frame indicator */ + float *ge_sm, /* i/o: smoothed excitation gain */ + short *uv_count, /* i/o: unvoiced counter */ + short *act_count, /* i/o: activation counter */ + float lspold_s[], /* i/o: old LSP */ + short *noimix_seed, /* i/o: mixture seed */ + float *st_min_alpha, /* i/o: minimum alpha */ + float *exc_pe, /* i/o: memory of the preemphasis filter */ + const long bitrate, /* i : core bitrate */ + const short bwidth /* i : Sampling rate */ +) +{ + short i, k; + short i_subfr; + float exctilt; + float vare, ge, randval; + float alpha, min_alpha; + float lspnew_s[M], oldlsp_mix[M], midlsp_mix[M], newlsp_mix[M]; + float beta; + float noimix_fac; + + alpha = 1.0f; + min_alpha = 0.5f; + + /*---------------------------------------------------------* + * Update minimum mixing factor alpha + *---------------------------------------------------------*/ + + /* Activate modifications for WB/SWB <= 9.6kbps for NB only at 9.6kbps */ + if ( coder_type == INACTIVE && ( bitrate == ACELP_9k60 || (bitrate < ACELP_9k60 && bwidth > NB) ) ) + { + if ( !bfi ) + { + min_alpha = max( noisiness/31.0f * 0.5f + 0.5f, *st_min_alpha - 0.05f ); + *st_min_alpha = min_alpha; + } + else + { + min_alpha = *st_min_alpha; + } + } + + /*---------------------------------------------------------* + * Mix excitation signal with random noise + *---------------------------------------------------------*/ + + /* Activate modifications for WB/SWB <= 9.6kbps for NB only at 9.6kbps */ + if ( coder_type == INACTIVE && (bitrate == ACELP_9k60 || (bitrate < ACELP_9k60 && bwidth > NB ) ) ) + { + /* preemphasize the excitation signal with its tilt */ + if( min_alpha < TILT_COMP_LIM ) + { + for (i_subfr=0; i_subfr FULL_NG) + { + *uv_count = FULL_NG; + } + + alpha = 1 + ((float)*uv_count - START_NG)/((float)FULL_NG - START_NG) * (min_alpha - 1.0f); + } + + /* calculate lowpass-filtered excitation gain */ + vare = 0.01f; + for (i=0; i 3) + { + *act_count = 3; + *uv_count = 0; + } + } + + return; +} + +/*---------------------------------------------------------------------------* + * calc_tilt() + * + * Calculate spectral tilt by means of 1st-order LP analysis + *---------------------------------------------------------------------------*/ + +static float calc_tilt( + const float *x, /* i : Signal input */ + const short len /* i : lenght */ +) +{ + int i; + float r0, r1; + + r0 = 0; + r1 = 0; + + for ( i=0; i +#include "wmc_auto.h" +#include +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*-------------------------------------------------------------------* + * WB_BWE_gain_pred() + * + * predict WB frequency envelopes for 0b WB BWE + *-------------------------------------------------------------------*/ + +short WB_BWE_gain_pred( + float *WB_fenv, /* o : WB frequency envelopes */ + const float *core_dec_freq, /* i : Frequency domain core decoded signal */ + const short coder_type, /* i : coding type */ + short prev_coder_type, /* i : coding type of last frame */ + float prev_WB_fenv, /* i : envelope for last frame */ + float *voice_factors, /* i : voicing factors */ + const float pitch_buf[], /* i : pitch buffer */ + long last_core_brate, /* i : previous frame core bitrate */ + float last_wb_bwe_ener /* i : previous frame wb bwe signal energy */ + ,short last_extl /* i : extl. layer for last frame */ + ,float tilt +) +{ + float enerL, alfa = 1.0f; + short n_freq, mode; + short ener_var_flag = 0; + float voice_factor, pitch; + short env_var_flag = 0; + + mode = NORMAL; + + enerL = EPSILON; + for (n_freq = 128; n_freq<192; n_freq++) + { + enerL += core_dec_freq[n_freq] * core_dec_freq[n_freq]; + } + WB_fenv[0] = EPSILON; + for (n_freq = 192; n_freq<224; n_freq++) + { + WB_fenv[0] += core_dec_freq[n_freq] * core_dec_freq[n_freq]; + } + + WB_fenv[1] = EPSILON; + for (n_freq = 224; n_freq<256; n_freq++) + { + WB_fenv[1] += core_dec_freq[n_freq] * core_dec_freq[n_freq]; + } + + voice_factor = sum_f( voice_factors, 4 ); + pitch = sum_f( pitch_buf, 4 ) + EPSILON; + + if(enerL < 16.0f*max(WB_fenv[0], WB_fenv[1]) && pitch < 308) + { + ener_var_flag = 1; + } + + if(WB_fenv[0] > 2.0f*WB_fenv[1]) + { + alfa = max(2.0f*WB_fenv[1]/WB_fenv[0], 0.1f); + WB_fenv[0] *= alfa; + } + else if (2.0f*WB_fenv[0] < WB_fenv[1] && coder_type != UNVOICED) + { + alfa = max(2.0f*WB_fenv[0]/WB_fenv[1], 0.1f); + WB_fenv[1] *= alfa; + } + + WB_fenv[0] = (float)sqrt((WB_fenv[0]+WB_fenv[1])/64); + + if(coder_type != AUDIO && coder_type != UNVOICED && ener_var_flag == 0) + { + WB_fenv[0] *= 1.5f; + } + + if( coder_type != TRANSITION && coder_type != AUDIO && coder_type != UNVOICED && sqrt(enerL) > 40.0f*WB_fenv[0] && alfa > 0.9f && + !(coder_type == prev_coder_type && WB_fenv[0] > prev_WB_fenv) ) + { + WB_fenv[0] *= min((float)(0.025f*sqrt(enerL)/WB_fenv[0]), 4.0f); + + if( WB_fenv[0] > prev_WB_fenv ) + { + WB_fenv[0] = 0.3f*WB_fenv[0] + 0.7f*prev_WB_fenv; + } + } + + alfa = min(1.5f, max(0.5f, 77.0f*voice_factor/pitch)); + if( sqrt(enerL) > 64.0f*alfa*WB_fenv[0] && 3.0f*WB_fenv[0]*WB_fenv[0] < sqrt(enerL) && prev_coder_type != UNVOICED ) + { + env_var_flag = 1; + WB_fenv[0] *= min((float)(0.015625f*sqrt(enerL)/WB_fenv[0]), 4.0f); + + if( WB_fenv[0] > prev_WB_fenv ) + { + WB_fenv[0] = 0.3f*WB_fenv[0] + 0.7f*prev_WB_fenv; + } + } + + if( coder_type == UNVOICED || prev_coder_type == UNVOICED ) + { + WB_fenv[0] *= 0.5f; + } + + if( coder_type != AUDIO ) + { + WB_fenv[0] /= max(1.2f * voice_factor, 1.0f); + WB_fenv[0] *= min(2.0f, max(0.125f, pitch/400.0f)); + } + + if( last_core_brate > ACELP_8k00 && WB_fenv[0] > last_wb_bwe_ener ) + { + WB_fenv[0] = 0.9f*last_wb_bwe_ener + 0.1f*WB_fenv[0]; + } + + if(last_extl != WB_BWE && (tilt < 8.f)) + { + WB_fenv[0] *= min(0.5, 16.0f*tilt); + } + + if(env_var_flag == 1) + { + WB_fenv[1] = 1.5f*WB_fenv[0]; + WB_fenv[0] *= 0.75f; + } + else + { + WB_fenv[1] = WB_fenv[0]; + } + + if(coder_type == UNVOICED || prev_coder_type == UNVOICED) + { + WB_fenv[1] *= 0.5f; + } + + return (mode); +} + +/*-------------------------------------------------------------------* + * calc_normal_length() + * + *-------------------------------------------------------------------*/ + +void calc_normal_length( + const short core, /* i : core */ + const float *sp, /* i : input signal */ + const short mode, /* i : input mode */ + const short extl, /* i : extension layer */ + short *L_swb_norm, /* o : normalize length */ + short *prev_L_swb_norm /*i/o : last normalize length */ +) +{ + short i, n_freq, n_band, THRES; + const float *pit; + float peak, mean, mag; + short L_swb_norm_trans, L_swb_norm_norm, L_swb_norm_harm, L_swb_norm_cur; + short N; + + if( core == HQ_CORE || extl == SWB_BWE || extl == FB_BWE ) + { + THRES = 8; + } + else + { + THRES = 4; + } + + if( core == HQ_CORE && (mode == HQ_HARMONIC || mode == HQ_HVQ) ) + { + N = 13; + } + else + { + N = 16; + } + + n_band = 0; + pit = sp; + for(i = 0; i < N; i ++) + { + peak = 0.0f; + mean = 0; + + for(n_freq = 0; n_freq < 16; n_freq ++) + { + mag = (float) fabs(*pit); + if (mag > peak) + { + peak = mag; + } + mean += mag; + pit ++; + } + + if((15+THRES)*peak > THRES*mean && peak>10) + { + n_band += 1; + } + } + + if( core == ACELP_CORE ) + { + L_swb_norm_trans = (short)(4 + 0.25f*n_band); + L_swb_norm_norm = (short)(8 + 0.5f*n_band); + L_swb_norm_harm = max((short)(32 + 2.0f*n_band), 24); + + if( mode == HARMONIC ) + { + L_swb_norm_cur = L_swb_norm_harm; + } + else if( mode == NORMAL ) + { + L_swb_norm_cur = L_swb_norm_norm; + } + else + { + L_swb_norm_cur = L_swb_norm_trans; + } + + *L_swb_norm = (short)(0.5f*L_swb_norm_cur + 0.5f* (*prev_L_swb_norm)); + *prev_L_swb_norm = L_swb_norm_cur; + } + else + { + if( mode == HQ_HARMONIC || mode == HQ_HVQ ) + { + L_swb_norm_cur = (short)( 32 + 2.5f*n_band); + } + else + { + L_swb_norm_cur = (short)(8 + 0.5f*n_band); + } + + *L_swb_norm = (short)(0.1f*L_swb_norm_cur + 0.9f* (*prev_L_swb_norm) + 0.5f); + *prev_L_swb_norm = L_swb_norm_cur; + } + + return; +} +/*-------------------------------------------------------------------* +* calc_tilt_bwe() +* +* calculate tilt parameter +*-------------------------------------------------------------------*/ + +void calc_tilt_bwe( + const float *sp, /* i : input signal */ + float *tilt, /* o : signal tilt */ + const short N /* i : signal length */ +) +{ + short i; + float r0, r1; + + r0 = EPSILON; + for(i=0; i 0) + { + WB_signal[n_freq] *= (0.55f - weight); + } + WB_signal[n_freq] *= signum[n_freq]; + } + } + + /* Normalize with envelope */ + for (n_freq = swb_bwe_subband[0]; n_freq prev_WB_fenv[0] ) + { + alfa = 0.4f; + beta = 2.5f; + } + else + { + alfa = 0.6f; + beta = 1.67f; + } + + if( coder_type == GENERIC || ((EnergyL > 0.5f*(*prev_Energy) && EnergyL < 2.0f*(*prev_Energy) && *prev_flag == 1)) ) + { + WB_fenv[0] *= 0.5f; + WB_fenv[1] *= 0.5f; + flag = 1; + } + } + if( (mode == HARMONIC && WB_fenv[1] < 0.25f*WB_fenv[0]) || mode == NORMAL ) + { + if( last_extl == WB_BWE && ( (prev_coder_type == AUDIO && coder_type != AUDIO) || (prev_coder_type != AUDIO && coder_type == AUDIO)) && total_brate <= ACELP_8k00 ) + { + if( WB_fenv[0] > prev_WB_fenv[0] ) + { + wfenv[0] = 0.3f*WB_fenv[0] + 0.7f*prev_WB_fenv[0]; + wfenv[1] = 0.3f*WB_fenv[1] + 0.7f*prev_WB_fenv[1]; + } + else + { + wfenv[0] = 0.5f*WB_fenv[0] + 0.5f*prev_WB_fenv[0]; + wfenv[1] = 0.4f*WB_fenv[1] + 0.4f*prev_WB_fenv[1]; + } + } + else if ( last_extl == WB_BWE && prev_WB_fenv[0]*EnergyL < WB_fenv[0]*(*prev_Energy) && WB_fenv[0] > prev_WB_fenv[0] && coder_type != AUDIO && coder_type != UNVOICED && total_brate <= ACELP_8k00) + { + wfenv[0] = 0.3f*WB_fenv[0] + 0.7f*prev_WB_fenv[0]; + wfenv[1] = 0.3f*WB_fenv[1] + 0.7f*prev_WB_fenv[1]; + } + else if ( last_extl == WB_BWE && EnergyL > alfa*(*prev_Energy) && EnergyL < beta*(*prev_Energy) && prev_coder_type != UNVOICED ) + { + wfenv[0] = 0.5f*(WB_fenv[0] + prev_WB_fenv[0]); + wfenv[1] = 0.5f*(WB_fenv[1] + prev_WB_fenv[1]); + } + else + { + wfenv[0] = WB_fenv[0]; + wfenv[1] = WB_fenv[1]; + } + for (n_freq = swb_bwe_subband[0]; n_freq 0.5f*(*prev_Energy) && EnergyL < 2.0f*(*prev_Energy)) + { + wfenv[0] = 0.25f*wfenv[0] + 0.375f*(prev_WB_fenv[0] + prev_WB_fenv[1]); + } + for (n_freq = swb_bwe_subband[0]; n_freq 8.0f*SWB_fenv[0]) + { + fenvL = SWB_fenv[0]; + } + calc_normal_length( ACELP_CORE, core_dec_freq, mode, extl, &L_swb_norm, prev_L_swb_norm ); + + if( mode == TRANSIENT ) + { + Energy = 0.0f; + for(n_band = 0; n_band < SWB_FENV_TRANS; n_band++) + { + Energy += SWB_fenv[n_band]*SWB_fenv[n_band]; + } + Energy /= SWB_FENV_TRANS; + + /* Reconstruct excitation from LF signal */ + mvr2r(&core_dec_freq[112], &SWB_signal[240+st_offset], 128); + mvr2r(&core_dec_freq[112], &SWB_signal[368+st_offset], 128); + mvr2r(&core_dec_freq[176], &SWB_signal[496+st_offset], 64); + + /* calculate envelope */ + calc_norm_envelop(SWB_signal, envelope, L_swb_norm, SWB_flength, st_offset); + + /* Normalize with envelope */ + for (n_freq = swb_bwe_trans_subband[0]+st_offset; n_freq EnergyL || (tilt_nb > 7 && Energy > 0.5f*EnergyL) || tilt_nb > 12) && Energy > 75 && fenvL > 25)) + { + for (n_freq=swb_bwe_subband[0]+st_offset; n_freq SWB_fenv[n_band+1] ) + { + SWB_fenv[n_band+1] *= (0.8f+0.015f*n_band); + } + else if( SWB_fenv[n_band+1] * 0.9f > SWB_fenv[n_band] ) + { + SWB_fenv[n_band] *= (0.8f+0.015f*n_band); + } + } + + mvr2r(&core_dec_freq[112], &SWB_signal[240+st_offset], 128); + mvr2r(&core_dec_freq[112], &SWB_signal[368+st_offset], 128); + mvr2r(&core_dec_freq[176], &SWB_signal[496+st_offset], 64); + + tmp1 = (float)(fabs(SWB_signal[368+st_offset]) + fabs(SWB_signal[369+st_offset])) + EPSILON; + tmp2 = (float)(fabs(SWB_signal[365+st_offset]) + fabs(SWB_signal[366+st_offset])) + EPSILON; + pit1 = &SWB_signal[368+st_offset]; + + tmp3 = tmp2/tmp1; + if(tmp3 < 0.3) + { + tmp3 = 0.3f; + } + + while(tmp3 < 1) + { + *pit1++ *= tmp3; + tmp3 += 0.1f; + } + + pit1 = &SWB_signal[367+st_offset]; + tmp3 = tmp1/tmp2; + + if( tmp3 > 5 ) + { + tmp3 = 5; + while( tmp3 > 1 ) + { + *pit1-- *= tmp3; + tmp3 -= 0.5f; + } + } + + tmp1 = (float)(fabs(SWB_signal[496+st_offset]) + fabs(SWB_signal[497+st_offset])) + EPSILON; + tmp2 = (float)(fabs(SWB_signal[492+st_offset]) + fabs(SWB_signal[493+st_offset]) + fabs(SWB_signal[494+st_offset]) + fabs(SWB_signal[495+st_offset])) + EPSILON; + pit1 = &SWB_signal[496+st_offset]; + + tmp3 = tmp2/tmp1; + if( tmp3 < 0.3 ) + { + tmp3 = 0.3f; + } + + while(tmp3 < 1) + { + *pit1++ *= tmp3; + tmp3 += 0.1f; + } + + pit1 = &SWB_signal[495+st_offset]; + + tmp3 = tmp1/tmp2; + tmp3 = 0.5f*tmp3; + tmp4 = 0.05f*tmp3; + + while( tmp3 > 1 ) + { + *pit1-- *= tmp3; + tmp3 -= tmp4; + } + + /* calculate envelope */ + calc_norm_envelop(SWB_signal, envelope, L_swb_norm, SWB_flength, st_offset); + } + } + + /* Normalize with envelope */ + if( *frica_flag == 0 && mode != NOISE ) + { + L = swb_bwe_subband[0]+st_offset; + inv_L_swb_norm = 1.0f/L_swb_norm; + weight = (mode != HARMONIC) ? max(min(3.0f*inv_L_swb_norm, 0.5f), 0.2f) : 0.2f; + weight = 0.4f*weight + 0.6f*(*prev_weight); + for(n_freq = L; n_freq 0) + { + SWB_signal[n_freq] *= (1.2f - weight); + } + SWB_signal[n_freq] *= signum[n_freq]; + } + + for (n_freq = L; n_freq 1.25f*Energy && Energy > 0 ) + { + weight = 0.5f*Energy/(*prev_Energy); + } + else + { + weight = 0.5f; + } + + wfenv = weight*prev_SWB_fenv[0] + (1-weight)*SWB_fenv[0]; + factor = fenvL; + factor1 = (wfenv - fenvL) * 0.125f; + for (n_freq = swb_bwe_subband[0]+st_offset; n_freq < swb_bwe_subband[0]+8+st_offset; n_freq++) + { + SWB_signal[n_freq] *= factor; + factor += factor1; + } + + for(n_band = 0; n_band < 12; n_band++) + { + wfenv = weight*prev_SWB_fenv[n_band+1] + (1-weight)*SWB_fenv[n_band+1]; + factor = SWB_fenv[n_band]; + factor1 = (wfenv - SWB_fenv[n_band]) * smooth_factor[n_band]; + for (; n_freq < swb_bwe_sm_subband[n_band+1]+st_offset; n_freq++) + { + SWB_signal[n_freq] *= factor; + factor += factor1; + } + } + + wfenv = weight*prev_SWB_fenv[13] + (1-weight)*SWB_fenv[13]; + factor = SWB_fenv[12]; + factor1 = (wfenv - SWB_fenv[12]) * smooth_factor[12]; + for ( ; n_freq < swb_bwe_sm_subband[13]+st_offset; n_freq++) + { + SWB_signal[n_freq] *= factor; + factor += factor1; + } + + for(n_band=13; n_band 1.8f*energyL[i] && energyL[i+1] > 50) + { + pos = i+1; + break; + } + } + + if (pos > 0) + { + if(pos < 3) + { + pos ++; + } + + energy = EPSILON; + j = L*pos; + for(i=0; i0 ? 1.0f: -1.0f); + } + } + else + { + for ( n_freq = sfidx; n_freq < efidx; n_freq++ ) + { + coeff_out1[n_freq] =coeff_out1[n_freq]*signum[n_freq]; + } + } + + /* normalizing modified low frequency spectrum */ + for( k =0 ; k < nband_lf; ++k ) + { + energy = EPSILON; + for ( i = k*blen+sfidx; i < (k+1)*blen+sfidx; ++i ) + { + energy += coeff_out1[i] * coeff_out1[i]; + } + energy = (float)sqrt(energy/blen); + + for ( i = k*blen+sfidx; i < (k+1)*blen+sfidx; ++i ) + { + coeff_out1[i] /= energy; + } + } + mvr2r(coeff_out1+HQ_GENERIC_OFFSET, &coeff_out[HQ_GENERIC_HIGH0+hq_generic_offset], HQ_GENERIC_LEN0); + mvr2r(coeff_out1+HQ_GENERIC_OFFSET, &coeff_out[HQ_GENERIC_HIGH1+hq_generic_offset], HQ_GENERIC_LEN0); + + if ( hq_generic_offset <= HQ_GENERIC_FOFFSET_24K4 ) + { + mvr2r( &coeff_out1[HQ_GENERIC_LOW0], &coeff_out[HQ_GENERIC_HIGH2+hq_generic_offset], HQ_GENERIC_END_FREQ - HQ_GENERIC_HIGH2 ); + } + + if ( HQ_mode == HQ_GEN_FB ) + { + if ( hq_generic_offset <= HQ_GENERIC_FOFFSET_24K4 ) + { + mvr2r(coeff_out1+HQ_GENERIC_LOW0 + HQ_GENERIC_END_FREQ - HQ_GENERIC_HIGH2, &coeff_out[fb_bwe_subband[0]], 160); + } + else + { + mvr2r(coeff_out1+HQ_GENERIC_OFFSET + HQ_GENERIC_LEN0, &coeff_out[fb_bwe_subband[0]], 160); + } + } + tmp1 = EPSILON; + tmp2 = EPSILON; + for(i=0; i<5; ++i) + { + tmp1 += (float)fabs(coeff_out[HQ_GENERIC_HIGH1+hq_generic_offset+i]); + tmp2 += (float)fabs(coeff_out[HQ_GENERIC_HIGH1-2+hq_generic_offset-i]); + } + + pit1 = &coeff_out[HQ_GENERIC_HIGH1+hq_generic_offset]; + tmp3 = tmp2/tmp1; + if( tmp3 < 0.3f ) + { + tmp3 = 0.3f; + } + + while( tmp3 < 1 ) + { + *pit1++ *= tmp3; + tmp3 += 0.1f; + } + + pit1 = &coeff_out[HQ_GENERIC_HIGH1-1+hq_generic_offset]; + tmp3 = tmp1/tmp2; + if( tmp3 > 5 ) + { + tmp3 = 5; + while( tmp3 > 1 ) + { + *pit1-- *= tmp3; + tmp3 -= 0.5f; + } + } + + if ( hq_generic_offset <= HQ_GENERIC_FOFFSET_24K4 ) + { + tmp1 = (float)(fabs(coeff_out[HQ_GENERIC_HIGH2+hq_generic_offset]) + fabs(coeff_out[HQ_GENERIC_HIGH2+1+hq_generic_offset])) + EPSILON; + tmp2 = (float)(fabs(coeff_out[HQ_GENERIC_HIGH2-4+hq_generic_offset]) + fabs(coeff_out[HQ_GENERIC_HIGH2-3+hq_generic_offset]) + + fabs(coeff_out[HQ_GENERIC_HIGH2-2+hq_generic_offset]) + fabs(coeff_out[HQ_GENERIC_HIGH2-1+hq_generic_offset])) + EPSILON; + + pit1 = &coeff_out[HQ_GENERIC_HIGH2+hq_generic_offset]; + tmp3 = tmp2/tmp1; + if( tmp3 < 0.3f ) + { + tmp3 = 0.3f; + } + + while( tmp3 < 1 ) + { + *pit1++ *= tmp3; + tmp3 += 0.1f; + } + + pit1 = &coeff_out[HQ_GENERIC_HIGH2-1+hq_generic_offset]; + tmp3 = tmp1/tmp2; + tmp3 = 0.5f*tmp3; + tmp4 = 0.05f*tmp3; + while(tmp3 > 1) + { + *pit1-- *= tmp3; + tmp3 -= tmp4; + } + } + + wfenv = hq_generic_fenv[0]; + for (n_freq = swb_bwe_subband[0]+hq_generic_offset,i=0; n_freq 15.f || hq_generic_fenv[nenv] < 5.f) + { + wfenv = hq_generic_fenv[nenv-1]; + for ( i=0; n_freq +#include "wmc_auto.h" +#include "options.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * swb_hr_nonzero_subband_noise_fill() + * + * SWB BWE HR noise filling of zero subbands + *-------------------------------------------------------------------*/ + +static void swb_hr_nonzero_subband_noise_fill( + const float tilt_wb, /* i : tilt of wideband signal */ + float *t_audio, /* i/o: mdct spectrum */ + short *bwe_highrate_seed, /* i/o: seed of random noise */ + const short N, /* i : length of subband */ + const short Nsv /* i : number of subband */ +) +{ + short i, j; + float *ptr; + float min_bwe, max_bwe, tmpF; + + if( tilt_wb > 5.0f ) + { + for( i=0; i 0 ) + { + min_bwe = min(tmpF, min_bwe); + max_bwe = max(tmpF, max_bwe); + } + } + + if( max_bwe == min_bwe && min_bwe > 1.0f ) + { + min_bwe *= 0.5f; + } + + ptr = &t_audio[i*N]; + for( j=0; j 0 ) + { + *ptr = 0.5f*min_bwe; + } + else + { + *ptr = -0.5f*min_bwe; + } + } + ptr++; + } + } + } + + return; +} + +/*-------------------------------------------------------------------* + * swb_hr_noise_fill() + * + * SWB BWE HR noise filling + *-------------------------------------------------------------------*/ + +void swb_hr_noise_fill( + const short is_transient, /* i : transient flag */ + const short spect_start, /* i : spectrum start point */ + const short spect_end, /* i : spectrum end point */ + const float tilt_wb, /* i : tilt of wideband signal */ + const float pitch, /* i : pitch value */ + const short nq[], /* i : AVQ nq index */ + short Nsv, /* i : number of subband */ + short *bwe_highrate_seed, /* i/o: seed of random noise */ + float *t_audio /* i/o: mdct spectrum */ +) +{ + short i, j, k; + float alpha, beta; + short pos_start, pos_end, incr; + + if( is_transient ) + { + for( i=0; i 5.0f ) + { + beta = 0.25f; + } + else + { + if( 100 > 0.25f*pitch ) + { + beta = 0.25f; + } + else + { + beta = 100/pitch; + } + } + + i = 0; + if( nq[i] == 0 ) + { + i = 1; + while( i < Nsv && nq[i] == 0 ) + { + i++; + } + + pos_start = i; + + + while( i< Nsv && nq[i] != 0 ) + { + i++; + } + + pos_end = i - 1; + + if( pos_end - pos_start > pos_start ) + { + pos_end = 2*pos_start - 1; + } + + incr = pos_end; + + for( j = pos_start-1; j >= 0; j-- ) + { + for( k=0; k= pos_start; j-- ) + { + for( k=0; k max_samp ) + { + max_samp = (float)fabs(hb_synth[i]); + pos = i; + } + } + + if( pos < 160 ) + { + gain = sum2_f( hb_synth + input_frame - 80, 80 ) + EPSILON; + } + else + { + gain = sum2_f( hb_synth, 80 ) + EPSILON; + } + + gain = (float)sqrt(gain/80); + + ind1 = max(0, pos-40); + ind2 = min( input_frame, pos+40 ); + tmpF = sum2_f( hb_synth + ind1, ind2 - ind1 ) + EPSILON; + tmpF = (float)sqrt( tmpF/(ind2-ind1) ); + + gain = min( 1.0f, gain/tmpF ); + + if( last_extl == SWB_BWE || last_extl == FB_BWE ) + { + for( i = ind1; i < input_frame; i++ ) + { + hb_synth[i] *= gain; + } + } + else + { + for( i = ind1; i < ind2; i++ ) + { + hb_synth[i] *= gain; + } + + if( ind2 != input_frame ) + { + step = 0.0f; + alpha = (gain > 0.5f) ? 1.0f : 0.5f; + beta = (alpha - gain)/(input_frame - ind2); + + for( i = ind2; i < input_frame; i++ ) + { + hb_synth[i] *= (gain + step); + step += beta; + } + } + } + + return( gain ); +} diff --git a/lib_com/swb_bwe_com_lr.c b/lib_com/swb_bwe_com_lr.c new file mode 100644 index 000000000..1942a73a4 --- /dev/null +++ b/lib_com/swb_bwe_com_lr.c @@ -0,0 +1,2048 @@ + /*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + + #include + #include "wmc_auto.h" + #include + #include "options.h" + #include "cnst.h" + #include "prot.h" + #include "rom_com.h" + + + /*-------------------------------------------------------------------* + * hf_parinitiz() + * + * + *-------------------------------------------------------------------*/ + + void hf_parinitiz( + const long total_brate, + const short hqswb_clas, + short lowlength, + short highlength, + short wBands[], + const short **subband_search_offset, + const short **subband_offsets, + short *nBands, + short *nBands_search, + short *swb_lowband, + short *swb_highband + ) + { + *swb_lowband = lowlength; + *swb_highband = highlength; + + if( hqswb_clas == HQ_HARMONIC ) + { + /* Mode dependent initializations (performed every frame in case mode-switching implemented) */ + *nBands = NB_SWB_SUBBANDS_HAR; + *nBands_search = NB_SWB_SUBBANDS_HAR_SEARCH_SB; + + if ( total_brate == HQ_13k20 ) + { + wBands[0] = SWB_SB_BW_LEN0_12KBPS_HAR; + wBands[1] = SWB_SB_BW_LEN1_12KBPS_HAR; + wBands[2] = SWB_SB_BW_LEN2_12KBPS_HAR; + wBands[3] = SWB_SB_BW_LEN3_12KBPS_HAR; + *subband_offsets = subband_offsets_sub5_13p2kbps_Har; + *subband_search_offset = subband_search_offsets_13p2kbps_Har; + } + else + { + wBands[0] = SWB_SB_BW_LEN0_16KBPS_HAR; + wBands[1] = SWB_SB_BW_LEN1_16KBPS_HAR; + wBands[2] = SWB_SB_BW_LEN2_16KBPS_HAR; + wBands[3] = SWB_SB_BW_LEN3_16KBPS_HAR; + *subband_offsets = subband_offsets_sub5_16p4kbps_Har; + *subband_search_offset = subband_search_offsets_16p4kbps_Har; + } + } + else + { + /* Mode-dependent initializations (performed every frame in case mode-switching implemented) */ + *nBands = NB_SWB_SUBBANDS; + *nBands_search = NB_SWB_SUBBANDS; + + if ( total_brate == HQ_13k20 ) + { + wBands[0] = SWB_SB_LEN0_12KBPS; + wBands[1] = SWB_SB_LEN1_12KBPS; + wBands[2] = SWB_SB_LEN2_12KBPS; + wBands[3] = SWB_SB_LEN3_12KBPS; + *subband_offsets = subband_offsets_12KBPS; + } + else + { + wBands[0] = SWB_SB_LEN0_16KBPS; + wBands[1] = SWB_SB_LEN1_16KBPS; + wBands[2] = SWB_SB_LEN2_16KBPS; + wBands[3] = SWB_SB_LEN3_16KBPS; + *subband_offsets = subband_offsets_16KBPS; + } + } + return; + } + + /*-------------------------------------------------------------------* + * GetPredictedSignal() + * + * Routine for calculating the predicted signal + *-------------------------------------------------------------------*/ + void GetPredictedSignal( + const float *predBuf, /* i : prediction buffer */ + float *outBuf, /* o : output buffer */ + const short lag, /* i : prediction buffer offset */ + const short fLen, /* i : length of loop (output) */ + const float gain /* i : gain to be applied */ + ) + { + short i; + + predBuf += lag; + + for(i = 0; i < fLen; i++) + { + *outBuf++ = *predBuf++ * gain; + } + + return; + } + /*-------------------------------------------------------------------* + * est_freq_har_decis() + * + * Harmonic frequency decision matrix + *-------------------------------------------------------------------*/ + static + void est_freq_har_decis( + short *har_freq_est1, /* o: harmonic analysis 1*/ + short *har_freq_est2, /* o: harmonic analysis 2*/ + short sharp, /* i: pka-avg for group 1 */ + short sharp1, /* i: pka-avg for group 2 */ + short hfe_est_countk1, /* i: group pks count 1*/ + short hfe_est_countk2, /* i: group pks count 2*/ + short k, /* i: group count */ + short k1, + short k2, + short *prev_frm_hfe2 /* i: harmonic estimation */ + ) + { + short temp_hfe2 = 0; + + if( k != 0) + { + *har_freq_est1 = (int) sharp /k; + } + if(k1 > 1) + { + *har_freq_est2 = (int) sharp1 /k1; + } + else if( (k1 < 2 && (k2 != 0 || k>1))) + { + *har_freq_est2 = (int) *har_freq_est1; + } + else + { + if((hfe_est_countk1 != 0 || hfe_est_countk2 != 0) && (k1 == 0 && k2 == 0)) + { + *har_freq_est2 = (*har_freq_est1); + } + else + { + *har_freq_est2 = 2*(*har_freq_est1); + } + } + + /* Consider Estimation Error upto 200Hz */ + if( *prev_frm_hfe2 != 0 && ( (short)abs(*prev_frm_hfe2 - *har_freq_est2) < 10 || abs(*prev_frm_hfe2-2*(*har_freq_est2))<10)) + { + *har_freq_est2 = *prev_frm_hfe2; + } + else if(*prev_frm_hfe2 != 0 && abs(*har_freq_est2-2*(*prev_frm_hfe2))<10) + { + *har_freq_est2 =2*( *prev_frm_hfe2); + } + else + { + temp_hfe2 = (short)(*prev_frm_hfe2+*har_freq_est2)/2; + + if(abs(temp_hfe2 -*prev_frm_hfe2) < 2) + { + temp_hfe2 =*prev_frm_hfe2; + *har_freq_est2 = temp_hfe2; + } + } + if( *har_freq_est2 <*har_freq_est1 && (k>1 && k1<2)) + { + *har_freq_est2 = *har_freq_est1; + } + return; + } + + /*--------------------------------------------------------------------------* + * har_est() + * + * Harmonic Structure analysis using LF spectrum + *--------------------------------------------------------------------------*/ + + short har_est( + float spectra[], /* i : coded spectrum */ + short N, /* i : length of the desired spectrum */ + short *har_freq_est1, /* i/o: Estimation harmonics 1 */ + short *har_freq_est2, /* o : Estimation harmonics 2 */ + short *flag_dis, /* i/o: flag for BWE reconstruction */ + short *prev_frm_hfe2, /* i/o: Estimated harmonic update */ + const short subband_search_offset[],/* i : Subband Search range */ + const short sbWidth[], /* i : Subband Search range */ + short *prev_stab_hfe2 /* i/o: Estimated harmonic position */ + ) + { + float peak; + short i, j, q, k , k1, k2; + float input_abs[L_FRAME32k],blk_peak[30]; + short blk_end,blk_st; + short peak_pos,blk_peak_pos[30],diff_peak_pos[30], sharp, sharp1, sharp2; + int min_har_pos; + short blk_peak_pos_te[30]; + float blk_peak_te[30]; + short temp; + short hfe_est_countk,hfe_est_countk1,hfe_est_countk2; + short r1, r2, r3; + short start_pos; + float blk_peak_max; + short blk_peak_pos_max; + + short nlags, ct_hfsb2,sum_diff=0; + short blk_peak_pos_hfsb2[30],diff_peak_pos_hfsb2[30]; + short rem_hfe2 ,q_diffpos_hfe2 = 0,diff_posmax_hfe2, q_diffpos_prevhfe2; + short blk_peak_max_idx,blk_peak_pos_max_diff,diff_peak_pos_te[30]; + rem_hfe2 = 0; + q_diffpos_hfe2 = 0; + diff_posmax_hfe2 = 0; + q_diffpos_prevhfe2 = 0; + + set_s(blk_peak_pos_te,0,30); + set_s(diff_peak_pos,0,30); + + r1 = SWB_HAR_RAN1; + r2 = SWB_HAR_RAN2; + r3 = SWB_HAR_RAN3; + start_pos =r1; + + /* Copy the abs values of LF spectrum*/ + for ( i = start_pos; i < N; i++) + { + input_abs[i] = (float) fabs(spectra[i]); + } + + blk_end = (short) N/LR_BLK_LEN; + blk_st = (short) start_pos/LR_BLK_LEN; + + if( (float)N/(LR_BLK_LEN) - blk_end > 0.0f) + { + blk_end++; + } + + /* initialization of over buffer for fractional point */ + for(i=N; i<(blk_end*LR_BLK_LEN); i++) + { + input_abs[i] = 0.0f; + } + + q = start_pos; + + /* Block Processing, to detect the spectral peaks*/ + for(i = blk_st; i < blk_end; i++) + { + peak = 0.0f; + peak_pos = 0; + + for(j = 0; j < LR_BLK_LEN; j ++, q ++) + { + if (input_abs[q] > peak) + { + peak = input_abs[q]; + peak_pos = q; + } + + if( i > blk_st && input_abs[q] != 0 && input_abs[q] == peak && (peak_pos - blk_peak_pos[i-1]) < LR_HLF_PK_BLK_LEN ) + { + peak = input_abs[q]; + peak_pos = q; + } + } + + blk_peak[i] = peak; + blk_peak_pos[i] = peak_pos; + } + + for(i = blk_st; i < blk_end; i++) + { + if(i > blk_st) + { + if(blk_peak_pos[i] != 0 && blk_peak_pos[i-1] != 0) + { + if((blk_peak_pos[i] - blk_peak_pos[i-1]) < LR_LOWBAND_DIF_PK_LEN) + { + if(blk_peak[i] > blk_peak[i-1]) + { + blk_peak[i-1] = 0.0f; + blk_peak_pos[i-1] = 0; + } + else + { + blk_peak[i] = blk_peak[i-1]; + blk_peak_pos[i] = blk_peak_pos[i-1]; + blk_peak[i-1] = 0.0f; + blk_peak_pos[i-1] = 0; + } + } + } + } + } + + /* peak counts in each group */ + j = 0; + hfe_est_countk = 0; + hfe_est_countk1 = 0; + hfe_est_countk2 = 0; + for(i = blk_st; i < blk_end; i++) + { + if(blk_peak_pos[i] != 0 ) + { + blk_peak_pos_te[j] = blk_peak_pos[i]; + if( blk_peak_pos[i] blk_peak_max) + { + blk_peak_max = blk_peak_te[i-1]; + blk_peak_pos_max = blk_peak_pos_te[i-1] ; + blk_peak_max_idx = i-1; + } + + temp++; + } + blk_peak_pos_max_diff = diff_peak_pos[blk_peak_max_idx]; + + /* Decision for BWE reconstruction */ + if((hfe_est_countk < 2 && hfe_est_countk1 <2 && hfe_est_countk2 <2 ) || min_har_pos >= SWB_HAR_RAN1) + { + *flag_dis = 0; + if((hfe_est_countk == 1 && hfe_est_countk1 == 1)&& (hfe_est_countk2 == 1 || hfe_est_countk2 == 0)) + { + *flag_dis = 1; + } + } + for(i=0; i 0) + { + sharp += diff_peak_pos[i]; + k++; + } + else if((diff_peak_pos[i] <= (min_har_pos+2*LR_LOWBAND_DIF_PK_LEN)) && diff_peak_pos[i] > 0) + { + sharp1 += diff_peak_pos[i]; + k1++; + } + else if(diff_peak_pos[i] > 0) + { + sharp2 += diff_peak_pos[i]; + k2++; + } + } + + est_freq_har_decis(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[temp-1]; + + if((*prev_stab_hfe2) > 0 && (*prev_frm_hfe2) > 0 && *prev_stab_hfe2 < N) + { + rem_hfe2 = *har_freq_est2%(*prev_frm_hfe2); + diff_posmax_hfe2 = (short) abs(blk_peak_pos_max-*prev_stab_hfe2); + if(rem_hfe2 == 0) + { + if(diff_posmax_hfe2 < 9 || *har_freq_est2 == 0) + { + blk_peak_pos_max = *prev_stab_hfe2; + } + else + { + q_diffpos_hfe2 = diff_posmax_hfe2/(*har_freq_est2); + q_diffpos_prevhfe2 = diff_posmax_hfe2/(*prev_frm_hfe2); + if(q_diffpos_hfe2 < 10 || q_diffpos_prevhfe2 < 10) + { + blk_peak_pos_max = *prev_stab_hfe2; + } + else + { + *prev_stab_hfe2 = blk_peak_pos_max; + } + } + } + else + { + *prev_stab_hfe2 = blk_peak_pos_max; + } + } + else + { + *prev_stab_hfe2 = blk_peak_pos_max; + } + + if(*har_freq_est1==0 || *har_freq_est2 ==0) + { + *flag_dis =0; + } + } + + if(*flag_dis == 0) + { + if(*prev_frm_hfe2 != 0) + { + *har_freq_est2 = *prev_frm_hfe2; + } + else + { + nlags = (short)pow(2, bits_lagIndices_mode0_Har[0]); + ct_hfsb2 = 0; + for(i = 0; i < j; i++) + { + if(blk_peak_pos_te[i] >=(subband_search_offset[0]- nlags/2) + && blk_peak_pos_te[i] <(subband_search_offset[0] + sbWidth[0]+ nlags/2)) + { + blk_peak_pos_hfsb2[ct_hfsb2] = blk_peak_pos_te[i]; + ct_hfsb2++; + } + } + + if(ct_hfsb2 >1) + { + for(i=1; i(dst_pos) && ii<(sbWidth[k]+sbWidth[k-1]); j--) + { + xSynth_har[ii] = noise_flr[j]; + tmpbuf[ii] = xSynth_har[ii]; + if(predBuf[j] != 0.0f) + { + hf_pulse_peaks[l] = predBuf[j]; + l++; + } + ii++; + } + } + pos =0; + for(j = 0; j< l; j++) + { + st_last_peakpos+=har_freq_est2; + if(st_last_peakpos< hfband_end[k]) + { + pk_sf[k*8+pos].nmrValue = hf_pulse_peaks[j]; + pk_sf[k*8+pos].gainIndex = st_last_peakpos-fLenLow; + pul_res[k]++; + pulse_peak_sb[i] = hf_pulse_peaks[j]; + i++; + pos++; + } + } + st_last_peakpos = temp_last_peakpos; + } + res=i-1; + l=1; + ii = hfband_end[k-1]-fLenLow-1; + for(; k<(bands-harmonic_band); k++) + { + for(j=hfband_end[k-1]-fLenLow; j<(hfband_end[k]-fLenLow); j++) + { + xSynth_har[j] = tmpbuf[ii]; + tmpbuf[j] = xSynth_har[j]; + ii--; + } + pos=0; + while(st_last_peakpos < hfband_end[k-1]) + { + st_last_peakpos +=har_freq_est2; + } + while(st_last_peakpos < hfband_end[k] && pul_res[k] fLen ) + { + mvr2r( inBuf, outBuf, fLen ); + return; + } + + /* span must be odd */ + if( (span & 0x1) == 0 ) + { + span--; + } + + span1 = span >> 1; + + /* first sample */ + sum = *inBuf; + *outBuf++ = sum; + + oldPtr = inBuf; + newPtr = inBuf + 2; + + /* handle start */ + inBuf++; + sum += *inBuf; + + for( i = 1, nItems = 3; i < span1; i++, inBuf++ ) + { + sum += *newPtr++; + *outBuf++ = sum / nItems; + + sum += *newPtr++; + nItems += 2; + } + + ispan = 1.0f / span; + inBuf++; + i++; + sum += *newPtr++; + *outBuf++ = sum * ispan; + + /* moving average */ + for( ; i < fLen - span1; i++, inBuf++ ) + { + sum += *newPtr++; + sum -= *oldPtr++; + *outBuf++ = sum * ispan; + } + + /* handle end */ + nItems = span - 2; + sum -= *oldPtr++; + + for( ; i < fLen - 1; i++, inBuf++ ) + { + sum -= *oldPtr++; + *outBuf++ = sum / nItems; + nItems -= 2; + sum -= *oldPtr++; + } + + /* last sample */ + *outBuf = *inBuf; + + return; + } + + /*-------------------------------------------------------------------* + * SpectrumSmoothing() + * + * Smoothing of the low-frequency envelope + *-------------------------------------------------------------------*/ + + void SpectrumSmoothing( + float *inBuf, /* i : input */ + float *outBuf, /* o : output */ + const short fLen, /* i : length */ + const float th_cut /* i : threshold of cut */ + ) + { + short i, k; + float inBuf_pss[L_FRAME32k]; + float outBuf_pss[L_FRAME32k]; + float max_val[L_FRAME32k/L_SB]; + float max_val_norm; + float inBuf_abs; + short j; + short num_subband_smooth; + short m, n; + short cnt_zero_cont; + short n_list[BANDS_MAX]; + short reset_flag; + + num_subband_smooth = (short) fLen/L_SB; + if( (float)fLen / L_SB - num_subband_smooth > 0.0f ) + { + num_subband_smooth++; + } + + for( i=0; i subband_search_offsets[0]/L_SB && reset_flag == 0) + { + n = 0; + reset_flag = 1; + } + n_list[n] = j; + n++; + } + + if(reset_flag == 1 && n == 1) + { + m = 0; + } + + if(cnt_zero_cont > 3*L_SB/4) + { + for(i=0; i th_cut) + { + outBuf[i] = outBuf_pss[i]; + } + } + + return; + } + + /*-------------------------------------------------------------------* + * Get20Log10Spec() + * + * Calculates 20*log10() for the specified samples. Input and output buffers can be the same. + *-------------------------------------------------------------------*/ + static + void Get20Log10Spec( + const float *inBuf, /* i : input */ + float *outBuf, /* o : output */ + const short fLen /* i : loop length */ + ) + { + short i; + + for( i = 0; i < fLen; i++, inBuf++ ) + { + *outBuf++ = (float) (20.0f * log10(fabs(*inBuf + 1.0))); + } + + return; + } + + void convert_lagIndices_pls2smp( + short lagIndices_in[], + short nBands_search, + short lagIndices_out[], + const float sspectra[], + const short sbWidth[], + const short fLenLow + ) + { + int sb; + int i, cnt; + + for( sb = 0; sb < nBands_search; sb++ ) + { + cnt = 0; + i = 0; + while( cnt <= lagIndices_in[sb] ) + { + if( sspectra[subband_search_offsets[sb]+i] != 0.0f ) + { + cnt++; + } + + i++; + + if( subband_search_offsets[sb] + i + sbWidth[sb] >= fLenLow ) + { + /* over fLenLow, no need for more search */ + break; + } + } + + lagIndices_out[sb] = (short)i-1+subband_search_offsets[sb]; + } + + return; + } + + int get_usebit_npswb( + short hqswb_clas + ) + { + short i; + short bits; + short up_lmt; + const short *bits_req; + + up_lmt = 0; + bits_req = bits_lagIndices_modeNormal; + bits =0; + if(hqswb_clas == HQ_NORMAL) + { + up_lmt = NB_SWB_SUBBANDS; + bits_req = bits_lagIndices_modeNormal; + } + else if ( hqswb_clas == HQ_HARMONIC ) + { + up_lmt = NB_SWB_SUBBANDS_HAR_SEARCH_SB; + bits_req =bits_lagIndices_mode0_Har; + bits = 2; /*noise gain*/ + } + for( i = 0; i < up_lmt; i++ ) + { + bits += bits_req[i]; + } + + return bits; + } + + void SpectrumSmoothing_nss( + float *inBuf, + float *outBuf, + int fLen + ) + { + int i, k; + float inBufw[L_FRAME32k+L_SB_NSS]; + float outBufw[L_FRAME32k+L_SB_NSS]; + float temp_sum_1[NUM_SUBBAND_SMOOTH_MAX]; + float temp_sum_2[NUM_SUBBAND_SMOOTH_MAX]; + float temp_sum_3[NUM_SUBBAND_SMOOTH_MAX]; + float temp_sum_log[NUM_SUBBAND_SMOOTH_MAX]; + float temp_sum_smooth[NUM_SUBBAND_SMOOTH_MAX]; + float temp_sum_div[NUM_SUBBAND_SMOOTH_MAX]; + short num_subband_smooth; + float smr, avg_val, r0; + float clip_cof, avg_val2, thre; + float thre_min; + float max_peak; + + /* calculate subband number */ + num_subband_smooth = (short)(fLen/L_SB_NSS); + if( fLen/(L_SB_NSS + 0.0f) - num_subband_smooth > 0.0f ) + { + num_subband_smooth++; + } + + /* buffer copy for fractional point */ + for( i = 0; i < fLen; i++ ) + { + inBufw[i] = inBuf[i]; + outBufw[i] = 0.0f; + } + + /* initialization of over buffer for fractional point */ + for( i = fLen; i < fLen + L_SB_NSS; i++ ) + { + inBufw[i] = 0.0f; + outBufw[i] = 0.0f; + } + + avg_val = 0.0f; + for( i = 0; i < fLen; i++ ) + { + r0 = (float)fabs(inBufw[i]); + avg_val += r0; + } + avg_val /= (float)fLen; + + max_peak = 0.0f; + for( i = 0; i < fLen; i++ ) + { + r0 = (float)fabs(inBufw[i]); + if( max_peak < r0 ) + { + max_peak = r0; + } + } + + smr = 10.0f * (float)log10( max_peak/(avg_val + 1.0e-20) + 1.0e-20 ); + + for( i = 0; i < num_subband_smooth; i++ ) + { + temp_sum_1[i] = 0.0; + temp_sum_2[i] = 0.0; + + for( k = 0; k < L_SB_NSS_HALF; k++ ) + { + temp_sum_1[i] += (float)(fabs(inBufw[k + L_SB_NSS * i])); + } + + for( k = L_SB_NSS_HALF; k < L_SB_NSS; k++ ) + { + temp_sum_2[i] += (float)(fabs(inBufw[k + L_SB_NSS * i])); + } + + temp_sum_1[i] *= 0.25f; + temp_sum_2[i] *= 0.25f; + temp_sum_3[i] = temp_sum_1[i] * temp_sum_2[i]; + + if( temp_sum_3[i] == 0.0f ) + { + temp_sum_3[i] = temp_sum_1[i] + temp_sum_2[i]; + } + } + + Get20Log10Spec( temp_sum_3, temp_sum_log, num_subband_smooth ); + + for( i = 0; i < num_subband_smooth; i++ ) + { + temp_sum_log[i] *= 0.5f; + } + + SmoothSpec( temp_sum_log, temp_sum_smooth, num_subband_smooth, MA_LEN ); + + for (i = 0; i < num_subband_smooth; i++) + { + temp_sum_div[i] = (float)pow(10, -1.0f * temp_sum_smooth[i]/20); + } + + for (i = 0; i < num_subband_smooth; i++) + { + for (k = 0; k < L_SB_NSS; k++) + { + outBufw[k + L_SB_NSS * i] = inBufw[k + L_SB_NSS * i] * temp_sum_div[i]; + } + } + + avg_val2 = 0.0f; + for( i = 0; i < fLen; i++ ) + { + r0 = (float)fabs(outBufw[i]); + avg_val2 += r0; + } + avg_val2 /= (float)fLen; + + clip_cof = smr - 16.0f; + if( clip_cof < 0.0f ) + { + clip_cof = 0.0f; + } + clip_cof += 2.5f; + + thre = avg_val2 * clip_cof; + thre_min = avg_val2 * 0.25f; + for(i = 0; i < fLen; i++) + { + if( fabs(outBufw[i]) > thre ) + { + if( outBufw[i] < 0.0f ) + { + outBufw[i] = -1.0f*thre; + } + else + { + outBufw[i] = thre; + } + } + + if( fabs(outBufw[i]) < thre_min ) + { + outBufw[i] = 0.0f; + } + } + + for(i = 0; i < fLen; i++) + { + outBuf[i] = outBufw[i]; + } + + return; + } + + static float get_sigma( + float x_abs[], + float avg, + int length + ) + { + int i; + float d; + float sigma; + + d = 0; + for( i=0; i thr ) + { + g[peak_cnt].nmrValue = abs_in[j]; + g[peak_cnt].gainIndex = j; + abs_in[j] = 0.0f; + peak_cnt++; + } + + if( peak_cnt == N_NBIGGESTSEARCH ) + { + break; + } + } + } + + thr *= (0.3f / N_NBIGGESTSEARCH) * peak_cnt + 0.7f; + + if( peak_cnt < N_NBIGGESTSEARCH ) + { + for (j = 0; j < nIdx; j++) + { + if( abs_in[j] > thr ) + { + g[peak_cnt].nmrValue = abs_in[j]; + g[peak_cnt].gainIndex = j; + abs_in[j] = 0.0f; + peak_cnt++; + } + + if( peak_cnt == N_NBIGGESTSEARCH ) + { + break; + } + } + } + + thr *= (0.6f / N_NBIGGESTSEARCH) * peak_cnt + 0.3f; + if( peak_cnt < N_NBIGGESTSEARCH ) + { + for (j = 0; j < nIdx; j++) + { + if( abs_in[j] > thr ) + { + g[peak_cnt].nmrValue = abs_in[j]; + g[peak_cnt].gainIndex = j; + abs_in[j] = 0.0f; + peak_cnt++; + } + + if( peak_cnt == N_NBIGGESTSEARCH ) + { + break; + } + } + } + + *n = peak_cnt; + + return; + } + + /*--------------------------------------------------------------------------* + * spectrumsmooth_noiseton() + * Spectrum normalization for the the core coder + *--------------------------------------------------------------------------*/ + float spectrumsmooth_noiseton( + float spectra[], /* i : core coder */ + const float spectra_ni[], /* i : core coder with sparse filling */ + float sspectra[], /* o : Smoothed tonal information from core coder */ + float sspectra_diff[], /* o : non tonal infomration for gap filling */ + float sspectra_ni[], /* o : smoothed core coder */ + const short fLenLow, /* i : low frequency boundaries */ + short *ni_seed /* io : random seed */ + ) + { + float spectra_diff[L_FRAME32k]; + float ni_ratio,ss_min,cut_sig_th,cut_ni_th; + short i,pcnt,sign; + float spectra_rm[L_FRAME32k]; + float cut_input=0.1f; + float rand_a[L_FRAME32k]; + + /* pre-prepare random array for float-fix interoperability */ + for(i=0; i cut_input ) + { + spectra_rm[i] = spectra[i]; + } + } + SpectrumSmoothing( spectra_rm, sspectra, fLenLow, cut_sig_th); + /*Extract noise informaton from the core coder*/ + mvr2r(sspectra, sspectra_ni, fLenLow); + for(i=0; i cut_input ) + { + spectra_rm[i] = spectra_diff[i]; + } + } + SpectrumSmoothing( spectra_rm, sspectra_diff, fLenLow, cut_ni_th); + /*Normalized corecoder for Gap filling */ + for(i=0; i ss_min ) + { + sspectra[i] =sign*((10-ss_min)/10.0f*(float)fabs(sspectra[i])+ss_min); + } + if(sspectra[i] != 0.0) + { + sspectra_ni[i] = sspectra[i]; + } + else + { + sspectra_ni[i] = sspectra_diff[i]*ni_ratio; + } + if( sspectra_ni[i] == 0.0f) + { + sspectra_ni[i] = 0.5f*10.0f*ni_ratio* rand_a[i]; + } + } + return(ss_min); + } + + /*--------------------------------------------------------------------------* + * noiseinj_hf() + * level adjustments for the missing bands in the core coder + *--------------------------------------------------------------------------*/ + + void noiseinj_hf( + float xSynth_har[], /* o : gap filled information */ + float th_g[], /* i : level adjustment information */ + float band_energy[], /* i : subband energies */ + float *prev_En_sb, /* i/o: band Energies */ + const short p2a_flags[], /* i : Missing bands in the core coder */ + short BANDS, /* i : total bands */ + short band_start[], /* i : band start indices */ + short band_end[], /* i : band end indices */ + const short fLenLow /* i : low frequency bandwidth */ + ) + { + + float *p_En,ni_scale,*p_Enn_sm_sb,En[NB_SWB_SUBBANDS],Enn_sm_sb[NB_SWB_SUBBANDS]; + short k,i; + + short map_pulse_t[L_FRAME32k]; + short map_pulse[L_FRAME32k]; + + set_s(map_pulse_t, 0, band_end[BANDS-1]+1); + set_s(map_pulse, 0, band_end[BANDS-1]+1); + /*level adjust the missing bands in the core coder */ + p_En = En; + for(k=BANDS-NB_SWB_SUBBANDS; k(*prev_ni_ratio)) + { + ni_ratio = 0.8f*ni_ratio_cur +(*prev_ni_ratio)*0.2f; + } + else + { + ni_ratio = 0.6f*ni_ratio_cur +(*prev_ni_ratio)*0.4f; + } + } + else + { + ni_ratio = 0.7f*ni_ratio_cur; + } + *prev_ni_ratio =ni_ratio; + + for(i=0; i=0 ) + { + pos++; + } + count_pos_end = pos; + pul_res_bnd[k] = count_pos_end-count_pos_st; + if(pul_res_bnd[k] >0) + { + peak[k]=(float) fabs(sb_ton[count_pos_st]); + } + k++; + {} {} } + while(k= 0.12f) ? 0.05f*ni_gain[k] : 1.0f*ni_gain[k], 1.4f); + + for(j=band_start[i]; j<=band_end[i]; j++) + { + xSynth_har[j-fLenLow] *=ni_gain[k]; + } + E = sum2_f(&xSynth_har[band_start[i]-fLenLow],band_width[i]); /*noise energy*/ + } + k++; + be_tonal[i] = (float) pow (2.0f, band_energy[i])- E; /*tonal energy*/ + + if(be_tonal[i] <0.0f) + { + E=0; + for(j=(band_start[i]-fLenLow); j<=(band_end[i]-fLenLow); j++) + { + xSynth_har[j]*=0.25f; + E+=xSynth_har[j]*xSynth_har[j]; + } + be_tonal[i] = (float) pow (2.0f, band_energy[i])- E; /*tonal energy*/ + } + } + return; + } + + /*--------------------------------------------------------------------------* + * Gettonl_scalfact() + * Gap filling for the core coder + *--------------------------------------------------------------------------*/ + void Gettonl_scalfact ( + float *outBuf, /* o : synthesized spectrum */ + const float *codbuf, /* i : core coder */ + const short fLenLow, /* i : lowband length */ + const short fLenHigh, /* i : highband length */ + short harmonic_band, /* i : total number of Low frequency bands */ + short bands, /* i : total number of subbands in a frame */ + float *band_energy, /* i : band energy of each subband */ + short *band_start, /* i : subband start indices */ + short *band_end, /* i : subband end indices */ + const short p2aflags[], /* i : missing bands in the core coder */ + float be_tonal[], /* i : tonal energy */ + GainItem *pk_sf, /* i : toanl information for Sparse filling */ + short *pul_res_pk /* i : pulse resolution information */ + ) + { + short k,i,band_pos; + short sb_ton_loc[SWB_HAR_RAN1]; + short pos_tmp; + float sb_ton[SWB_HAR_RAN1],est_ton_ene[NB_SWB_SUBBANDS],ton_sf; + float step,enrd_r = 0.9f; + float band_sf[SWB_HAR_RAN1]; + short pos,count_pos_st,count_pos_end,j; + + set_f(est_ton_ene,0.0f,NB_SWB_SUBBANDS); + set_s(sb_ton_loc, -1,SWB_HAR_RAN1); + /* Get the tonal information for sparse filling */ + pos=0; + for(k=0; k=0 ) + { + pos++; + } + count_pos_end = pos; + for(i=count_pos_st; i 0.0f) + { + ton_sf= (float) sqrt(be_tonal[band_pos]/est_ton_ene[k]); + } + for(i=count_pos_st; i 0.0f ) + { + enrd_r *= (float)sqrt(be_tonal[band_pos]/pow(2.0f,band_energy[band_pos])); + } + else + { + enrd_r = 0.0f; + } + enrd_r -=step; + if(p2aflags[band_pos] == 1) + { + for(i= band_start[band_pos]; i<=band_end[band_pos]; i++) + { + outBuf[i-fLenLow] = codbuf[i]; + } + } + else + { + pos =0; + pos+=pos_tmp; + for(j=0; j predBufLen ) + { + /* should never happen */ + lag = predBufLen - fLen; + } + + GetPredictedSignal( predBuf, outBuf, lag, fLen, lagGains[sb]); + outBuf += fLen; + } + + outBuf = ptr_in_outBuf; + + return; + } + + + /*--------------------------------------------------------------------------* + * GetlagGains() + * + * + *--------------------------------------------------------------------------*/ + + void GetlagGains( + const float *predBuf, /* i: predictve buffer */ + const float *band_energy, /* i: band Energies */ + const short nBands, /* i: high frequency bands */ + const short *sbWidth, /* i: high frequency band resolution */ + const short *lagIndices, /* i: correlation indices */ + const short predBufLen, /* i: predictive buffer length */ + float *lagGains /* o: lag gains */ + ) + { + short i; + short sb, fLen, lag; + float outBuf[L_FRAME32k]; + float lagEnergy; + + /* Get the gain information for the missing bands*/ + for( sb = 0; sb < nBands; sb++ ) + { + fLen = sbWidth[sb]; + lag = lagIndices[sb]; + + if(lag + fLen > predBufLen) + { + /* should never happen */ + lag = predBufLen - fLen; + } + + GetPredictedSignal( predBuf, outBuf, lag, fLen, 1.0 ); + + lagEnergy = 0.0f; + for( i=0; i length ) + { + set_f( t_audio + length, 0.0f, inner_frame - length ); + } + } + else /* transient frame */ + { + if( inner_frame == length || bws_cnt > 0) + { + /* Copy the scratch buffer to the output */ + mvr2r( y2, t_audio, length ); + } + else + { + /* 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; + + mvr2r( y2 + k1, t_audio + k2, length/NUM_TIME_SWITCHING_BLOCKS ); + set_f( t_audio + k2 + length/NUM_TIME_SWITCHING_BLOCKS, 0.0f, (inner_frame-length)/NUM_TIME_SWITCHING_BLOCKS ); + } + } + } + + /* update */ + if( (bwe_br == HQ_16k40 || bwe_br == HQ_13k20) && bwidth == SWB ) + { + *prev_hqswb_clas = hqswb_clas; + if( hqswb_clas != HQ_HARMONIC ) + { + *prev_frm_hfe2 = 0; + *prev_stab_hfe2 = 0; + } + } + else + { + *prev_hqswb_clas = is_transient; + } + + if((bwe_br == HQ_16k40 || bwe_br == HQ_13k20) && bwidth == SWB && hqswb_clas == HQ_NORMAL ) + { + j = 0; + for(k=bands-SPT_SHORTEN_SBNUM; k +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*-----------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------*/ + +static void create_random_vector( float output[], const short length, short seed[] ); +static void flip_spectrum( const float input[], float output[], const short length ); +static void Hilbert_transform( float tmp_R[], float tmp_I[], float *tmpi_R, float *tmpi_I, const short length, const short HB_stage_id ); +static void Estimate_mix_factors( const float *shb_res, const float *exc16kWhtnd, const float *White_exc16k, const float pow1, + const float pow22, float *vf_modified, short *vf_ind ); +/*-------------------------------------------------------------------* + * swb_tbe_reset() + * + * Reset the SWB TBE encoder + *-------------------------------------------------------------------*/ + +void swb_tbe_reset( + float mem_csfilt[], + float mem_genSHBexc_filt_down_shb[], + float state_lpc_syn[], + float syn_overlap[], + float state_syn_shbexc[], + float *tbe_demph, + float *tbe_premph, + float mem_stp_swb[], + float *gain_prec_swb +) +{ + set_f( mem_csfilt, 0, 2); + set_f( mem_genSHBexc_filt_down_shb, 0.0f, (2*ALLPASSSECTIONS_STEEP+1) ); + set_f( state_lpc_syn, 0.0f, LPC_SHB_ORDER ); + set_f( syn_overlap, 0.0f, L_SHB_LAHEAD ); + set_f( state_syn_shbexc, 0.0f, L_SHB_LAHEAD ); + *tbe_demph = 0.0f; + *tbe_premph = 0.0f; + set_f(mem_stp_swb, 0, LPC_SHB_ORDER); + *gain_prec_swb = 1.0f; + + return; +} + +/*-------------------------------------------------------------------* + * swb_tbe_reset_synth() + * + * Reset the extra parameters needed for synthesis of the SWB TBE output + *-------------------------------------------------------------------*/ + +void swb_tbe_reset_synth( + float genSHBsynth_Hilbert_Mem[], + float genSHBsynth_state_lsyn_filt_shb_local[] +) +{ + set_f( genSHBsynth_Hilbert_Mem, 0.0f, HILBERT_MEM_SIZE ); + set_f( genSHBsynth_state_lsyn_filt_shb_local, 0.0f, 2 * ALLPASSSECTIONS_STEEP ); + + return; +} + +/*-------------------------------------------------------------------* + * tbe_celp_exc_offset() + * + * Compute tbe bwe celp excitation offset + *-------------------------------------------------------------------*/ +short tbe_celp_exc_offset( + const short T0, /* i : Integer pitch */ + const short T0_frac /* i : Fractional part of the pitch */ +) +{ + short offset; + 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; + + return offset; +} +/*-------------------------------------------------------------------* + * flip_and_downmix_generic() + * + * flips the spectrum and downmixes the signals, lpf if needed + *-------------------------------------------------------------------*/ + +void flip_and_downmix_generic( + float input[], /* i : input spectrum */ + float output[], /* o : output spectrum */ + const short length, /* i : length of spectra */ + float mem1_ext[], /* i/o: Hilbert filter memory */ + float mem2_ext[], /* i/o: memory */ + float mem3_ext[], /* i/o: memory */ + short *phase_state /* i/o: Phase state in case frequency isn't multiple of 50 Hz */ +) +{ + short i, j; + float tmp[L_FRAME32k + HILBERT_ORDER1]; + float tmpi_R[L_FRAME32k]; + float tmpi_I[L_FRAME32k]; + float tmpi2_R[L_FRAME32k + HILBERT_ORDER2]; + float tmpi2_I[L_FRAME32k + HILBERT_ORDER2]; + float tmp_R[L_FRAME32k + HILBERT_ORDER2]; + float tmp_I[L_FRAME32k + HILBERT_ORDER2]; + short k, period; + float recip_period; + float local_negsin_table[L_FRAME16k]; + float local_cos_table[L_FRAME16k]; + + period = 17; /* == (short) (32000.0f / 1850.0f + 0.5f); */ + + recip_period = 256.0f / (float) period; + for( i=0; i= period ) + { + *phase_state = 0; + } + + for( i=0, j=*phase_state; i < length; ) + { + for( ; (j < period) && (i < length); j++, i++ ) + { + output[i] = tmp_R[i + HILBERT_ORDER2] * local_cos_table[j] + tmp_I[i + HILBERT_ORDER2] * local_negsin_table[j]; + } + + if( j >= period ) + { + j = 0; + } + } + + *phase_state = j; + + return; +} + +/*---------------------------------------------- + * Hilbert_transform() + * + * Hilbert transform + *------------------------------------------------*/ + +static void Hilbert_transform( + float tmp_R[], /* i: Real component of HB */ + float tmp_I[], /* i: Real component of HB */ + float tmpi_R[], /* o: Real component of HB */ + float tmpi_I[], /* o: Imag. component of HB */ + const short length, /* i: input length */ + const short HB_stage_id /* i: HB transform stage */ +) +{ + short i, hb_filter_stage, offset; + + hb_filter_stage = 2*HB_stage_id; + offset = (HB_stage_id == 0) ? 1 : 0; + + if (HB_stage_id == 0 || HB_stage_id == 2) + { + for( i=0; i 0.35f) ) + { + csfilt_num2[0] = 0.2f; + csfilt_den2[1] = -0.8f; + } + else if( igf_flag && (coder_type == UNVOICED || avg_voice_fac < 0.2f) ) + { + csfilt_num2[0] = 0.01f; + csfilt_den2[1] = -0.99f; + } + set_f( wht_fil_mem, 0, LPC_WHTN_ORDER_WB ); + + Decimate_allpass_steep( bwe_exc_extended, mem_genSHBexc_filt_down1, L_FRAME32k, excTmp ); + + flip_spectrum_and_decimby4( excTmp, exc4k, L_FRAME16k, mem_genSHBexc_filt_down2, mem_genSHBexc_filt_down3, 0 ); + + if( uv_flag ) + { + /* unvoiced signal */ + create_random_vector( exc4kWhtnd, L_FRAME16k/4, bwe_seed ); + } + else + { + autocorr(exc4k, R, LPC_WHTN_ORDER_WB+1, L_FRAME16k/4, win_flatten_4k, 0, 1, 1); + + /* Ensure R[0] isn't zero when entering Levinson Durbin */ + R[0] = max(R[0], 1.0e-8f); + for( i = 0; i <= LPC_WHTN_ORDER_WB; i++ ) + { + R[i] = R[i] * wac[i]; + } + lev_dur( lpc_whtn, R, LPC_WHTN_ORDER_WB, ervec ); + + fir( exc4k, lpc_whtn, exc4kWhtnd, wht_fil_mem, L_FRAME16k/4, LPC_WHTN_ORDER_WB, 0); + + /* Ensure pow1 is greater than zero when computing normalization */ + for( i=0, pow1=0.00001f; i 1.0f) + { + formant_fac = 1.0f; + } + else if (formant_fac < 0.0f) + { + formant_fac = 0.0f; + } + + formant_fac = 1.0f - 0.5f*formant_fac; + + return formant_fac; +} + +/*-------------------------------------------------------------------* + * GenShapedSHBExcitation() + * + * Synthesize spectrally shaped highband excitation signal + *-------------------------------------------------------------------*/ + +void GenShapedSHBExcitation( + float *excSHB, /* o : synthesized shaped shb excitation */ + const float *lpc_shb, /* i : lpc coefficients */ + float *White_exc16k_FB, /* o : white excitation for the Fullband extension */ + float *mem_csfilt, /* i/o: memory */ + float *mem_genSHBexc_filt_down_shb,/* i/o: memory */ + float *state_lpc_syn, /* i/o: memory */ + const short coder_type, /* i : coding type */ + const float *bwe_exc_extended, /* i : bandwidth extended excitation */ + short bwe_seed[], /* i/o: random number generator seed */ + float voice_factors[], /* i : voicing factor*/ + const short extl, /* i : extension layer */ + float *tbe_demph, /* i/o: de-emphasis memory */ + float *tbe_premph, /* i/o: pre-emphasis memory */ + float *lpc_shb_sf, /* i: LP coefficients */ + float *shb_ener_sf, + float *shb_res_gshape, + float *shb_res, + short *vf_ind, + const float formant_fac, /* i : Formant sharpening factor [0..1] */ + float fb_state_lpc_syn[], /* i/o: memory */ + float *fb_tbe_demph, /* i/o: fb de-emphasis memory */ + const long bitrate, /* i : bitrate */ + const short prev_bfi /* i : previous frame was concealed */ +) +{ + short i, j, k; + float wht_fil_mem[LPC_WHTN_ORDER]; + float lpc_whtn[LPC_WHTN_ORDER + 1]; + float R[LPC_WHTN_ORDER + 2]; + float exc32k[L_FRAME32k], exc16k[L_FRAME16k]; + float pow1, pow22, scale, temp1, temp2; + float excTmp2[L_FRAME16k]; + short nbSubFr; + float excNoisyEnv[ L_FRAME16k]; + float csfilt_num2[1] = {0.2f}; + float csfilt_den2[2] = {1.0f, -0.8f}; + float varEnvShape; + float ervec[LPC_WHTN_ORDER+2]; + float exc16kWhtnd[L_FRAME16k]; + float temp = 0.0f; + float *White_exc16k; + float voiceFacEst[NB_SUBFR16k]; + float syn_shb_ener_sf[4], tempSHB[80]; + float zero_mem[LPC_SHB_ORDER]; + float vf_tmp; + float White_exc16k_FB_temp[L_FRAME16k]; + float fb_deemph_fac = 0.48f; + + set_f( zero_mem, 0, LPC_SHB_ORDER); + set_f( wht_fil_mem, 0, LPC_WHTN_ORDER ); + + for(i = 0; i < L_FRAME32k; i++) + { + exc32k[i] = ((i%2)==0)?(-bwe_exc_extended[i]):(bwe_exc_extended[i]); + } + + /* Decimate by 2 */ + Decimate_allpass_steep( exc32k, mem_genSHBexc_filt_down_shb, 2*L_FRAME16k, exc16k ); + + autocorr( exc16k, R, LPC_WHTN_ORDER+1, L_FRAME16k, win_flatten, 0, 1, 1 ); + + /* Ensure R[0] isn't zero when entering Levinson-Durbin */ + R[0] = max(R[0], 1.0e-8f); + for( i = 0; i <= LPC_WHTN_ORDER; i++ ) + { + R[i] = R[i] * wac[i]; + } + + /* Ensure R[0] isn't zero when entering Levinson-Durbin */ + R[0] += 1.0e-8f; + lev_dur( lpc_whtn, R, LPC_WHTN_ORDER, ervec ); + + fir( exc16k, lpc_whtn, exc16kWhtnd, wht_fil_mem, L_FRAME16k, LPC_WHTN_ORDER, 0 ); + + if( bitrate >= ACELP_24k40 ) + { + for(i = 0; i < L_FRAME16k; i++) + { + exc16kWhtnd[i] *= shb_res_gshape[(short)(i/80)]; + } + } + + for( k=0, pow1=0.00001f; k= ACELP_7k20) + { + varEnvShape = mean(voice_factors, 4); + } + else + { + varEnvShape = mean(voice_factors, 5); + } + + if ( extl == FB_TBE) + { + fb_deemph_fac = max((0.68f - (float)pow(varEnvShape, 3)), 0.48f); + } + + varEnvShape = 1.09875f - 0.49875f * varEnvShape; + varEnvShape = min( max(varEnvShape, 0.6f), 0.999f); + csfilt_num2[0] = 1.0f - varEnvShape; + csfilt_den2[1] = - varEnvShape; + + if (*mem_csfilt == 0 && ( bitrate == ACELP_9k60 || bitrate == ACELP_16k40 || bitrate == ACELP_24k40 ) ) + { + /* pre-init smoothing avoid energy drop outs */ + float tmp_scale = 0; + for (i=0; i= ACELP_24k40 ) + { + if( *vf_ind == 20 ) /* encoder side */ + { + Estimate_mix_factors( shb_res, exc16kWhtnd, White_exc16k, pow1, pow22, voiceFacEst, vf_ind ); + temp = (voiceFacEst[0] > 0.7f)? 1.0f : 0.8f; + } + else /* decoder side */ + { + temp = ((*vf_ind * 0.125f) > 0.7f)? 1.0f : 0.8f; + } + for(i = 0; i < NB_SUBFR16k; i++) + { + voice_factors[i] *= temp; + } + } + + mvr2r( White_exc16k, White_exc16k_FB, L_FRAME16k ); + deemph( White_exc16k, PREEMPH_FAC, L_FRAME16k, tbe_demph ); + + if( coder_type == UNVOICED ) + { + scale = sqrt( pow1/pow22 ); + if (pow22 == 0.f) + { + scale = 0; + } + for( k=0; k ths ) + { + en_abs = 1; + } + + + + + + p_out = output + NL_BUFF_OFFSET; /* NL_BUFF_OFFSET = 12 */ + /* update buffer memory */ + mvr2r( old_bwe_exc_extended, output, NL_BUFF_OFFSET ); + + for (i=j=0; i max) + { + max = temp; + j = i; + } + } + + if (max > 1.0f) + { + scale = 0.67f / max; + } + else + { + scale = 0.67f; + } + + + if ( *prev_scale <= 0.0 || *prev_scale > 1024.0f * scale ) + { + scale_step = 1.0; + *prev_scale = scale; + } + else + { + scale_step = 1.0f; + if(j != 0) + { + scale_step = (float) exp(1.0f / (float) j * (float) log(scale / *prev_scale)); + } + } + + for (i=0; i= 0.0) + { + *p_out++ = (input[i] * input[i]) **prev_scale; + } + else + { + if (en_abs) + { + *p_out++ = 1.0f * (input[i] * input[i]) **prev_scale; + } + else + { + *p_out++ = -1.0f * (input[i] * input[i]) **prev_scale; + } + + } + + if (i < j) + { + *prev_scale *= scale_step; + } + } + + max = 0.0f; + for (i=j=length/2; i max) + { + max = temp; + j = i; + } + } + + if (max > 1.0f) + { + scale = 0.67f / max; + } + else + { + scale = 0.67f; + } + + + if ( *prev_scale <= 0.0 || *prev_scale > 1024.0f * scale ) + { + scale_step = 1.0; + *prev_scale = scale; + } + else + { + scale_step = 1.0f; + if(j != length/2) + { + scale_step = (float) exp(1.0f / (float) (j - length/2) * (float) log(scale / *prev_scale)); + } + } + + for (i=length/2; i= 0.0) + { + *p_out++ = (input[i] * input[i]) **prev_scale; + } + else + { + if (en_abs) + { + *p_out++ = 1.0f * (input[i] * input[i]) **prev_scale; + } + else + { + *p_out++ = -1.0f * (input[i] * input[i]) **prev_scale; + } + } + + if (i < j) + { + *prev_scale *= scale_step; + } + } + + /* update buffer memory */ + mvr2r( output + L_FRAME32k, old_bwe_exc_extended, NL_BUFF_OFFSET ); + + return; +} + + +/*-------------------------------------------------------------------* + * create_random_vector() + * + * creates random number vector + * -------------------------------------------------------------------*/ + +void create_random_vector( + float output[], /* o : output random vector */ + const short length, /* i : length of random vector */ + short seed[] /* i/o: start seed */ +) +{ + short i, j, k; + float scale1, scale2; + + j = (short) (own_random(&seed[0]) * 0.0078f); + j = abs(j) & 0xff; + k = (short) (own_random(&seed[1]) * 0.0078f); + k = abs(k) & 0xff; + + while( k==j ) + { + k = (short)(own_random(&seed[1]) * 0.0078f); + k = abs(k) & 0xff; + } + + if( own_random(&seed[0]) < 0 ) + { + scale1 = -563.154f; /* -200.00f * 0.35f/0.1243f; */ + } + else + { + scale1 = 563.154f; /* 200.00f * 0.35f/0.1243f; */ + } + + if( own_random(&seed[1]) < 0 ) + { + scale2 = -225.261f; /* -80.00f * 0.35f/0.1243f; */ + } + else + { + scale2 = 225.261f; /* 80.00f * 0.35f/0.1243f; */ + } + + for( i=0; i 115.5f) && core_brate > ACELP_8k00 ) + { + tmp = 1.0f; + *voice_factors *= tmp; + } + + *voice_factors = min( max(0.000001f, *voice_factors), 0.999999f); + + if( L_frame == L_FRAME ) + { + interp_code_5over2( code, tmp_code, L_SUBFR ); + + for( i = 0; i < L_SUBFR * HIBND_ACB_L_FAC; i++ ) + { + bwe_exc[i + i_subfr * HIBND_ACB_L_FAC] = gain_pit * bwe_exc[i + i_subfr * HIBND_ACB_L_FAC] + + gain_code * tmp_code[i]; + } + } + else + { + for( i = 0; i < L_SUBFR; i++ ) + { + tmp_code_preInt[i] = gain_code * code[i] + 2 * gain_preQ * code_preQ[i]; + } + + interp_code_4over2( tmp_code_preInt, tmp_code, L_SUBFR ); + + for( i = 0; i < L_SUBFR * 2; i++ ) + { + bwe_exc[i + i_subfr * 2] = gain_pit * bwe_exc[i + i_subfr * 2] + tmp_code[i]; + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * get_tbe_bits() * + * * + * Determine TBE bit consumption per frame from bit rate * + *-------------------------------------------------------------------*/ + +short get_tbe_bits( + short bitrate, + short bandwidth, + short rf_mode +) +{ + short i, bits = 0; + + if( rf_mode ) + { + /* TBE bits for core, primary frame */ + if( bandwidth == WB && bitrate == ACELP_13k20 ) + { + /* Gain frame: 4, Gain shapes: 0, and LSFs: 2 */ + bits = NUM_BITS_SHB_FrameGain_LBR_WB + NUM_BITS_LBR_WB_LSF; + } + else if( bandwidth == SWB && bitrate == ACELP_13k20 ) + { + /* Gain frame: 5, Gain shapes: 5, and lowrate LSFs: 8 */ + bits = NUM_BITS_SHB_FRAMEGAIN + NUM_BITS_SHB_SUBGAINS + 8; + } + } + else + { + if( bandwidth == WB && bitrate == ACELP_9k60 ) + { + bits = NUM_BITS_LBR_WB_LSF + NUM_BITS_SHB_FrameGain_LBR_WB; + } + else if( bandwidth == SWB || bandwidth == FB ) + { + if( bitrate == ACELP_9k60 ) + { + bits = NUM_BITS_SHB_FRAMEGAIN + NUM_BITS_SHB_SUBGAINS + 8; + } + else if( bitrate >= ACELP_13k20 && bitrate <= ACELP_32k ) + { + bits = NUM_BITS_SHB_SUBGAINS + NUM_BITS_SHB_FRAMEGAIN + NUM_LSF_GRID_BITS + MIRROR_POINT_BITS; + + for( i=0; i= ACELP_24k40 ) + { + bits += NUM_BITS_SHB_ENER_SF + NUM_BITS_SHB_VF + NUM_BITS_SHB_RES_GS*NB_SUBFR16k; + } + + if( bandwidth == SWB && (bitrate == ACELP_16k40 || bitrate == ACELP_24k40) ) + { + bits += BITS_TEC + BITS_TFA; + } + + if( bandwidth == FB ) + { + /* fullband slope */ + bits += 4; + } + } + } + + return bits; +} diff --git a/lib_com/syn_12k8.c b/lib_com/syn_12k8.c new file mode 100644 index 000000000..cf3fe4ec6 --- /dev/null +++ b/lib_com/syn_12k8.c @@ -0,0 +1,36 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" + +/*------------------------------------------------------------------ + * syn_12k8() + * + * perform the synthesis filtering 1/A(z) + *------------------------------------------------------------------*/ + +void syn_12k8( + const short L_frame, /* i : length of the frame */ + const float *Aq, /* i : LP filter coefficients */ + const float *exc, /* i : input signal */ + float *synth, /* o : output signal */ + float *mem, /* i/o: initial filter states */ + const short update_m /* i : update memory flag: 0 --> no memory update */ +) /* 1 --> update of memory */ +{ + const float *p_Aq; + short i_subfr; + + p_Aq = Aq; /* pointer to interpolated LPC parameters */ + for ( i_subfr=0; i_subfr +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*------------------------------------------------------------------* + * syn_filt() + * + * perform the synthesis filtering 1/A(z) + *------------------------------------------------------------------*/ + +void syn_filt( + const float a[], /* i : LP filter coefficients */ + const short m, /* i : order of LP filter */ + const float x[], /* i : input signal */ + float y[], /* o : output signal */ + const short l, /* i : size of filtering */ + float mem[], /* i/o: initial filter states */ + const short update_m /* i : update memory flag: 0 --> no memory update */ +) /* 1 --> update of memory */ +{ + short i, j; +#if !defined(TCXLTP_LTP_ORDER) + float buf[L_FRAME48k + L_FRAME48k/2 + M]; /* temporary synthesis buffer */ +#else + float buf[L_FRAME48k + L_FRAME48k/2 + TCXLTP_LTP_ORDER]; /* temporary synthesis buffer */ +#endif + float s, *yy; + + yy = &buf[0]; + + /*------------------------------------------------------------------* + * copy initial filter states into synthesis buffer and do synthesis + *------------------------------------------------------------------*/ + + for (i = 0; i < m; i++) + { + *yy++ = mem[i]; + } + + /*-----------------------------------------------------------------------* + * Do the filtering + *-----------------------------------------------------------------------*/ + + for (i = 0; i < l; i++) + { + s = x[i]; + for (j = 1; j <= m; j++) + { + s -= a[j]*yy[i-j]; + } + + yy[i] = s; + y[i] = s; + } + + /*------------------------------------------------------------------* + * Update memory if required + *------------------------------------------------------------------*/ + + if (update_m) + { + for (i = 0; i < m; i++) + { + mem[i] = yy[l-m+i]; + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * synth_mem_updt2() + * + * Update of synthesis filter memories in case of ACELP@12k8 <-> ACELP@16k switching + *--------------------------------------------------------------------*/ + +void synth_mem_updt2( + const short L_frame, /* i : frame length */ + const short last_L_frame, /* i : frame length */ + float old_exc[], /* i/o: excitation buffer */ + float mem_syn_r[], /* i/o: synthesis filter memory */ + float mem_syn2[], /* o : synthesis filter memory for find_target */ + float mem_syn[], /* o : synthesis filter memory for find_target */ + const short dec /* i : flag for decoder indication */ +) +{ + short mem_syn_r_size_old, mem_syn_r_size_new; + + /* Residual and update old_exc */ + if( 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*/ + mem_syn_r_size_old = (short)(1.25*last_L_frame/20.f); + mem_syn_r_size_new = (short)(1.25*L_frame/20.f); + + 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 ); + + mvr2r( mem_syn_r+L_SYN_MEM-M, mem_syn2, M ); + + if( mem_syn != NULL ) + { + mvr2r( mem_syn2, mem_syn, M ); + } + + return; +} diff --git a/lib_com/tcq_position_arith.c b/lib_com/tcq_position_arith.c new file mode 100644 index 000000000..cc69501e8 --- /dev/null +++ b/lib_com/tcq_position_arith.c @@ -0,0 +1,2022 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "options.h" +#include "prot.h" +#include "rom_com.h" +#include "basop_util.h" +#include "basop_proto_func.h" + +void bitstream_save_bit(PBITSTREAM pBS, int bit); +unsigned int bitstream_load_bit(PBITSTREAM pBS); +void bitstream_rollback(PBITSTREAM pBS, int numBits); + + +static int ar_make_model( const short *freq, short *model, int len ); +static int ar_decode( PARCODEC arInst, const short *model ); +static void ar_encode( PARCODEC arInst, const short *model, int symbol ); +static void ar_encode_uniform( PARCODEC arInst, unsigned int data, int bits ); + + +/* 32x16 multiply: */ +Word32 Mult_32_16(Word32 a, Word16 b) +{ + Word32 result; + UWord16 lo; + /* use Mpy_32_16_ss(): */ + Mpy_32_16_ss(a, b, &result, &lo); + return result; +} + +/* 32x32 multiply: */ +Word32 Mult_32_32(Word32 a, Word32 b) +{ + Word32 result; + UWord32 lo; + /* use Mpy_32_32_ss(): */ + Mpy_32_32_ss(a, b, &result, &lo); + return result; +} + +static +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) + { + 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; +} + +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; + Word16 idxMem; + Word32 valMem; + + /*initilize */ + for (pos = 0; pos < length; pos++) + { + I[pos] = pos; + } + + for( pos = 0; pos < length; pos++ ) + { + srt[pos] = linear[pos]; + } + + /* now iterate */ + for (pos = 0; pos < (length - 1); pos++) + { + for (npos = (pos + 1); npos < length; npos++) + { + if (L_sub(srt[npos], srt[pos]) < 0) + { + idxMem = I[pos]; + I[pos] = I[npos]; + I[npos] = idxMem; + + valMem = srt[pos]; + srt[pos] = srt[npos]; + srt[npos] = valMem; + } + } + } + + return; +} + +static Word32 GetBitsFromPulses_fx(Word16 m, Word16 n) +{ + Word16 i, integer_fx, temp_fx1, temp_fx2, exp1, exp2; + Word32 temp32; + Word32 frac_fx32; + Word32 logCoeff_fx; + Word16 exp = 0; + Word32 mantissa_fx = 0; + + if (m == 0) + { + return 0; + } + + for (i = 0; i < min(m, n); 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_add(L_mult(temp_fx2, 22708), Mult_32_16(L_mult0(temp_fx2, temp_fx2), 7864));/*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 (sub(exp, integer_fx) < 0) + { + mantissa_fx = L_shr(mantissa_fx, sub(integer_fx, exp)); + mantissa_fx = L_add(mantissa_fx, frac_fx32); + + exp = integer_fx; + } + else + { + mantissa_fx = L_add(mantissa_fx, L_shr(frac_fx32, sub(exp, integer_fx))); + } + if (L_sub(mantissa_fx, 0x200000) >= 0) + { + exp++; + + mantissa_fx = L_shr(mantissa_fx, 1); + } + } + + mantissa_fx = L_shl(mantissa_fx, 2);/*22 */ + temp_fx1 = extract_h(mantissa_fx); + 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)); +} + +void decode_position_ari_fx(PARCODEC pardec, Word16 size, Word16 npulses, Word16* nz, Word32* position) +{ + Word16 i, 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, temppos, storepos; + + fxone = 32768; + fxp1 = 512*32768; + temppos = 0; + storepos = 0; + ovrflag = 0; + + + 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; + } + + if (L_sub(npulses, 1) > 0) + { + btcq_fx = GetBitsFromPulses_fx(npulses, size); + for (i = 0; i < L_min(npulses, size); 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( L_sub( pnzp_fx, 0) > 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; + } + } + else + { + prob[i] = 1; + } + } + + ar_make_model(prob, mode_num_nz, min(npulses, size)); + *nz = add(1, ar_decode(pardec, mode_num_nz));/*get #nz */ + nzp = *nz; + + if( nzp == 1 ) + { + mode_num_nz[0] = MAX_AR_FREQ; + 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(pardec, mode_num_nz) ] = 1; + } + else + { + mode_num_nz[0] = MAX_AR_FREQ; + + for( ; nzp > 0; nzp-- ) + { + scp = fxp1; + temppos = 0; + storepos = 0; + + for( i = stpos; i < size; i++) + { + ovrflag = 0; + + if( nzp == (size - i) ) + { + cp = 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) ); + + if( (mode_num_nz[i+1-storepos-stpos] == 0 && scp > 0) || mode_num_nz[i-storepos-stpos] == mode_num_nz[i+1-storepos-stpos] ) + { + ovrflag = 1; + temppos = ar_decode(pardec, mode_num_nz); + storepos += temppos; + scp = fxp1; + + if( temppos == i-stpos) /* esc transmitted */ + { + i--; + } + else + { + break; + } + } + } + if( !ovrflag ) + { + pos = ar_decode(pardec, mode_num_nz) + storepos; + } + else + { + pos = storepos; + } + + position[ stpos + pos] = 1; + stpos += pos + 1; + } + } + + } + else if (L_sub(npulses, 1) == 0) + { + *nz = npulses; + nzp = *nz; + mode_num_nz[0] = MAX_AR_FREQ; + 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(pardec, mode_num_nz) ] = 1; + } + else + { + *nz = 0; + } + + return; +} +void decode_magnitude_usq_fx(ARCODEC* pardec, Word16 size, Word16 npulses, Word16 nzpos, Word32* positions, Word32* out) +{ + Word16 i, magnp, magnzp; + Word16 magns[TCQ_MAX_BAND_SIZE], magncout = 0; + + Word16 storemagn, ovrflag, pos, tempmagn = 0, mmodel[MAX_PULSES+2]; + Word32 cp, scp, fxone, fxp1; + + fxone = 32768; + fxp1 = 512*32768; + ovrflag = 0; + + + set16_fx( magns, 1, TCQ_MAX_BAND_SIZE ); + if (sub(nzpos, npulses) == 0) + { + for (i = 0; i < size; i++) + { + out[i] = positions[i]; + } + return; + } + else if (sub(nzpos, 1) == 0) + { + for (i = 0; i < size; i++) + { + if ( positions[i] != 0 ) + { + out[i] = npulses; + return; + } + } + } + + magnzp = sub(nzpos, 1); + magnp = sub(npulses, 1); + + magncout = 0; + + set32_fx( out, 0, size ); + set16_fx( mmodel, 0, MAX_PULSES+2 ); + + mmodel[0] = MAX_AR_FREQ; + magncout = 0; + for( pos = 0; pos < size; pos++) + { + scp = fxp1; + if( positions[pos] != 0) + { + storemagn = 0; + + for( i = 0; i < magnp; i++) + { + ovrflag = 0; + + if( magnzp == (magnp-i) ) + { + cp = 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) ); + + if( (mmodel[i+1- storemagn] == 0 && scp > 0) || mmodel[i- storemagn] == mmodel[i+1- storemagn] ) + { + mmodel[i+1-storemagn] = 0; + /* read data */ + tempmagn = ar_decode( pardec, mmodel ); + storemagn += tempmagn; + + if( tempmagn < i ) + { + /* just magnitude */ + ovrflag = 1; + break; + } + else + { + /* esc code */ + scp = fxp1; + i--; + } + } + } + + if( ovrflag ) + { + out[magncout] = storemagn + 1; + } + else + { + out[magncout] = ar_decode( pardec, mmodel ) + storemagn + 1; + } + magnp -= out[magncout]; + magnzp--; + magncout++; + + if (magnzp == 0) /* last magnitude generation */ + { + for( pos = pos+1; pos < size; pos++) + { + if( positions[pos] != 0) + { + out[magncout] = magnp + 1; + return; + } + else + { + out[magncout] = 0; + magncout++; + } + } + } + else if(magnzp == magnp) /* rest magnitudes generation */ + { + for( pos = pos+1; pos < size; pos++) + { + out[magncout] = positions[pos]; + magncout++; + } + return; + } + } + else + { + out[magncout] = 0; + magncout++; + } + } + + return; +} + +static Word16 quantize_fx( Word16 val, Word16 D) +{ + Word16 qval4_fx; + Word16 retval_fx; + + 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 (sub(abs_s(sub(shl(abs_s(retval_fx), 10), abs_s(val))), abs_s(val)) > 0) + { + retval_fx = 0; + } + } + return retval_fx; +} + +void decode_mangitude_tcq_fx(ARCODEC* pardec, Word16 size, Word16 npulses, Word16 nzpos, Word32* positions, Word32* 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 = 0; + tcq_bits_fx = L_sub(table_logcum_fx[npulses], L_add(table_logcum_fx[nzpos], table_logcum_fx[npulses - (nzpos - 1)])); + + if (sub(nzpos, npulses) == 0) + { + for (i = 0; i < size; i++) + { + out[i] = positions[i]; + } + + return; + } + else if (sub(nzpos, 1) == 0) + { + for (i = 0; i < size; i++) + { + if ( positions[i] != 0 ) + { + out[i] = npulses; + return; + } + } + } + st = 0; + for (i = 0; i < size && leftnz > 1; i++) + { + out[i] = positions[i]; + if (positions[i] != 0) + { + /*generate the trellis path */ + symbol = 0; + for (j = 0; j < leftp; j++) + { + num = sub(leftnz, 1); + denum = sub(leftp, add(j, 1)); + if (sub(num, denum) >= 0) + { + prob1_fx = MAX_16; + prob0_fx = 0; + } + 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 (L_sub(sub(leftp, j), leftnz) == 0) + { + symbol = add(j, 1); + break; + } + + quantum1_fx = quantize_fx(shl(add(j, 1), 10), ddec[st][0]); + quantum2_fx = quantize_fx(shl(add(j, 1), 10), ddec[st][1]); + + if (sub(quantum1_fx, add(j, 1)) != 0 && sub(quantum2_fx, add(j, 1)) != 0) + { + prob0_fx = MAX_16; + move16(); + prob1_fx = 0; + move16(); + } + if (sub(prob0_fx, MAX_16) == 0 || sub(prob1_fx, MAX_16) == 0) + { + 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(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; + /*leftp -= symbol; */ + leftp = sub(leftp, symbol); + leftnz--; + } + + quantum1_fx = quantize_fx(out[i], ddec[st][0]); + quantum2_fx = quantize_fx(out[i], ddec[st][1]); + + /*generate the next state */ + if (sub(quantum1_fx, out[i]) == 0) + { + st = nextstate[st][0]; + } + else + { + st = nextstate[st][1]; + } + } + + /*generate the magnitudes */ + for (; i < size; i++) + { + out[i] = 0; + if (positions[i] != 0) + { + out[i] = add(sub(leftp, leftnz), 1); + } + + } + + if (sub(nzpos, npulses) != 0 && sub(nzpos, 1) > 0) + { + /*update the surplus */ + *surplus_fx = L_add(*surplus_fx, L_sub(tcq_bits_fx, L_shl(bits_fx, 1))); + } + + 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; /*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 saturation of pow2 result */ + + pulses = min( p_est, MAX_PULSES ); + + for( ; pulses >= 0; pulses--) + { + estbits_fx = GetBitsFromPulses_fx( pulses, blen); + if( L_sub( bits_fx, estbits_fx) >= 0) + { + break; + } + } + + if ( surplus_fx != 0 ) + { + *surplus_fx = L_add(*surplus_fx, L_sub(bits_fx, estbits_fx)); + } + + return pulses; +} + +void decode_signs_fx(ARCODEC* pardec, Word16 size, Word32* out) +{ + Word16 i; + + for ( i = 0; i < size; i++) + { + if ( out[i] != 0 ) + { + out[i] = ( ar_decode( pardec, uniform_model ) > 0) ? out[i] : -out[i]; + } + } + + return; +} + +Word32 encode_position_ari_fx(PARCODEC parenc, float* quants, Word16 size, Word32* est_bits_frame_fx) +{ + Word16 i; + Word16 nz = 0, pulses = 0; + Word16 prob[TCQ_MAX_BAND_SIZE]; + Word16 model_num_nz[TCQ_MAX_BAND_SIZE]; + float *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; + fxp1 = 512*32768; + + 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((short)cur_quants[i])); + if (cur_quants[i] != 0) + { + nz++; + } + } + + 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 */ + for (i = 0; i < min(pulses, size); 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( L_sub( pnzp_fx, 0) > 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; + } + } + else + { + prob[i] = 1; + } + } + + ar_make_model(prob, model_num_nz, min(pulses, size)); + + if (sub(nz, 1) > 0) + { + ar_encode( parenc, model_num_nz, nz - 1);/*encode #nz */ + + scp = fxp1; + pos = 0; + for( i = 0; i < size && nz > 0; i++) + { + if( nz == (size - i) ) + { + cp = 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) ); + + if( (model_num_nz[pos+1] == 0 && scp > 0) || model_num_nz[pos] == model_num_nz[pos+1] ) + { + model_num_nz[pos+1] = 0; + ar_encode( parenc, model_num_nz, pos ); + i--; + scp = fxp1; + pos = 0; + continue; + } + + if( cur_quants[i] != 0 ) + { + ar_encode( parenc, model_num_nz, pos ); + pos = 0; + scp = fxp1; + nz--; + } + else + { + pos++; + } + } + } + else if (sub(nz, 1) == 0) + { + if (sub(pulses, 1) > 0) + { + /*temp -= log2_f((float)(model_num_nz[nz-1] - model_num_nz[nz]) / MAX_AR_FREQ); */ + ar_encode(parenc, model_num_nz, 0);/*encode #nz */ + } + + pos = 0; + 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; + } + } + ar_encode( parenc, model_num_nz, pos ); /* encode pos */ + } + return bits_fx; +} + +Word32 encode_magnitude_tcq_fx(ARCODEC* parenc, float* 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; */ + + bits_fx = 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); + + if (sub(nzpos, npulses) == 0 || sub(nzpos, 1) == 0) + { + return bits_fx; + } + + st = 0; + for ( i = 0; i < size && leftnz > 1; i++) + { + st = savedstates[i]; + 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 (sub(num, denum) >= 0) + { + prob1_fx = MAX_16; + prob0_fx = 0; + } + 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); + } + + quantum1_fx = quantize_fx(shl(add(j, 1), 10), ddec[st][0]); + quantum2_fx = quantize_fx(shl(add(j, 1), 10), ddec[st][1]); + + if (sub(quantum1_fx, add(j, 1)) != 0 && sub(quantum2_fx, add(j, 1)) != 0) + { + prob0_fx = MAX_16; + prob1_fx = 0; + } + if (sub(prob0_fx, MAX_16) == 0 || sub(prob1_fx, MAX_16) == 0) + { + continue; + } + + magn_mode[1] = mult(prob1_fx, MAX_AR_FREQ); + if (sub(j, sub(abs_s( (short)magn_fx[i] ), 1)) < 0) + { + ar_encode(parenc, magn_mode, 0); + } + else + { + if (sub(leftp, j) > leftnz) + { + ar_encode(parenc, magn_mode, 1); + } + break; + } + } + + leftnz--; + leftp = sub(leftp, abs_s( (short)magn_fx[i] )); + } + } + + return bits_fx; +} + +Word32 encode_signs_fx(ARCODEC* parenc, float* 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 = (magn[i] > 0) ? 1 : 0; + ar_encode_uniform(parenc, sign, 1); + } + } + + return L_deposit_h(npos); +} + +Word32 encode_magnitude_usq_fx(ARCODEC* parenc, float* magn_fx, Word16 size, Word16 npulses, Word16 nzpos, Word32* est_frame_bits_fx) +{ + Word16 i, j, k, 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; + fxp1 = 512*32768; + + /*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); + + if (sub(npulses, nzpos) == 0 || sub(nzpos, 1) == 0) + { + return bits_fx; + } + magnp = sub(npulses, 1); + magnzp = sub(nzpos, 1); + + /*generate the binary sequences of magnitudes */ + k = 0; + for (i = 0; i < size; i++) + { + if (magn_fx[i] != 0) + { + for (j = 0; j < abs_s((short)magn_fx[i]) - 1; j++) + { + magn_position[k++] = 0; + } + magn_position[k++] = 1; + } + } + + set16_fx( model_m, 0, MAX_PULSES + 2); + scp = fxp1; + model_m[0] = MAX_AR_FREQ; + pos = 0; + for( i = 0; i < npulses-1 && magnzp > 0; i++ ) + { + if( magnzp == magnp ) + { + cp = 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) ); + + if( (model_m[pos+1] == 0 && scp > 0) || model_m[pos] == model_m[pos+1] ) + { + model_m[pos+1] = 0; + + ar_encode( parenc, model_m, pos ); + pos = 0; + i--; + scp = fxp1; + continue; + } + + if( magn_position[i] != 0 ) + { + ar_encode( parenc, model_m, pos ); + pos = 0; + magnzp--; + scp = fxp1; + } + else + { + pos++; + } + + magnp--; + } + return bits_fx; +} + + +static void transmission_bits( PARCODEC arInst, int bit ) +{ + bitstream_save_bit( arInst->bsInst, bit ); + arInst->num_bits++; + bit = !bit; + + 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++; + } + + return; +} + +void ar_encoder_start( PARCODEC arInst, PBITSTREAM bsInst, int max_bits + ) +{ + arInst->bsInst = bsInst; + + arInst->low = 0; + arInst->high = AR_TOP; + arInst->bits_to_follow = 0; + + arInst->num_bits = 0; + arInst->max_bits = max_bits; +} + + +static void ar_encode( PARCODEC arInst, const short *model, int symbol ) +{ + unsigned int range, high, low; + + high = arInst->high; + low = arInst->low; + + symbol ++; + range = high - low + 1; + + high = low + ( range * model[symbol - 1]) / model[0] - 1; + low = low + ( range * model[symbol] ) / model[0]; + + for( ; ; ) + { + if( high < AR_HALF ) + { + transmission_bits( arInst, 0 ); + } + else + { + if( low >= AR_HALF ) + { + transmission_bits( arInst, 1 ); + + low -= AR_HALF; + high -= AR_HALF; + } + else + { + if( low >= AR_FIRST && high < AR_THIRD ) + { + arInst->bits_to_follow ++; + + low -= AR_FIRST; + high -= AR_FIRST; + } + else + { + break; + } + } + } + + low = low << 1; + high = ( high << 1 ) + 1; + } + + arInst->high = high; + arInst->low = low; + + return; +} + + +static void ar_encode_uniform( PARCODEC arInst, unsigned int data, int bits ) +{ + int i; + + for( i = 0 ; i < bits ; i ++ ) + { + ar_encode( arInst, uniform_model, data & 0x1 ); + data >>= 1; + } + + return; +} + + +void ar_encoder_done( PARCODEC arInst ) +{ + arInst->bits_to_follow ++; + transmission_bits( arInst, arInst->low >= AR_FIRST ); + + return; +} + + +void ar_decoder_start( PARCODEC arInst, PBITSTREAM bsInst ) +{ + int i; + + arInst->bsInst = bsInst; + + arInst->low = 0; + arInst->high = AR_TOP; + arInst->value = 0; + + for( i = 0; i < AR_BITS ; i ++ ) + { + arInst->value = ( arInst->value << 1 ) + bitstream_load_bit( arInst->bsInst ); + } + + return; +} + + +static int ar_decode( PARCODEC arInst, const short *model ) +{ + unsigned int range; + short cum; + int symbol; + + range = (unsigned int)( arInst->high - arInst->low ) + 1; + cum = (short)( ( ( (unsigned int)( arInst->value - arInst->low ) + 1 ) * model[0] - 1 ) / range ); + + for (symbol = 1; model[symbol] > cum; symbol++) + { + ; + } + + arInst->high = arInst->low + ( range * model[symbol - 1] ) / model[0] - 1; + arInst->low = arInst->low + ( range * model[symbol] ) / model[0]; + + for( ; ; ) + { + if( arInst->high >= AR_HALF ) + { + if( arInst->low >= AR_HALF) + { + arInst->value -= AR_HALF; + arInst->low -= AR_HALF; + arInst->high -= AR_HALF; + } + else + { + if( arInst->low >= AR_FIRST && arInst->high < AR_THIRD ) + { + arInst->value -= AR_FIRST; + arInst->low -= AR_FIRST; + arInst->high -= AR_FIRST; + } + else + { + break; + } + } + } + arInst->low <<= 1; + arInst->high = ( arInst->high << 1 ) + 1; + arInst->value = ( arInst->value << 1 ) + bitstream_load_bit( arInst->bsInst ); + } + + return (symbol - 1); +} + +void ar_decoder_done( PARCODEC arInst ) +{ + bitstream_rollback( arInst->bsInst, AR_BITS - 2 ); + + return; +} + + +static int ar_make_model( const short *freq, short *model, int len ) +{ + short dist; + unsigned int sum = 0; + unsigned int cum = 0; + int i; + + for( i = 0 ; i < len ; i ++ ) + { + sum += freq[i]; + } + + if( sum == 0 ) + { + return 0; + } + + for( i = len ; ; i -- ) + { + model[i] = (short)( ( cum * MAX_AR_FREQ ) / sum ); + + if( !i ) + { + break; + } + + cum += freq[i - 1]; + } + + + for( i = 0 ; i < len - 1 ; i ++ ) + { + dist = model[i] - model[i + 1]; + + if( dist <= 0 ) + { + model[i + 1] += dist - 1; + } + } + + for( i = len ; i ; i -- ) + { + dist = model[i - 1] - model[i]; + + if( dist <= 0 ) + { + model[i - 1] -= dist - 1; + } + } + + return (model[0] > model[1]); +} + +void bitstream_save_bit(PBITSTREAM pBS, int bit) +{ + unsigned char cur; + + cur = pBS->buf[pBS->numByte]; + + + cur = (unsigned char)(cur | (bit << pBS->curPos--)); + pBS->buf[pBS->numByte] = cur; + pBS->numbits++; + + if (pBS->curPos < 0) + { + pBS->curPos = 7; + pBS->numByte++; + } + + return; +} + + +unsigned int bitstream_load_bit(PBITSTREAM pBS) +{ + unsigned int bit; + signed char * curPos; + + /* safety check in case of bit errors */ + if( pBS->numByte >= pBS->maxBytes ) + { + return 0; + } + + curPos = &pBS->curPos; + bit = (( pBS->buf[pBS->numByte] >> (*curPos)--) & 0x00000001); + + if (*curPos < 0) + { + pBS->numByte++; + *curPos = 7; + } + + return bit; +} + + +void bitstream_rollback(PBITSTREAM pBS, int numBits) +{ + + while (numBits > 0) + { + pBS->curPos++; + pBS->numbits--; + if (pBS->curPos == 8) + { + pBS->curPos = 0; + pBS->numByte--; + } + numBits--; + } + + return; +} + + +static float quantize( float val, int D) +{ + int qval4; + float retval;/* = qval4*4.0f + DD[D]; */ + + qval4 = (int)fabs( (val + 0.5)/4.0 ); + retval = qval4*4.0f + DDP[D]; + + /* 2nd zero check */ + if( D == 0 ) + { + if( fabs( fabs(retval) - fabs( val ) ) > fabs( val ) ) + { + retval = 0; + } + } + + return retval; +} + + +static void TCQnew( float *v, float scale, int length, float *vout, int pulses, int *pulsesout, int* nzposout, int *savedstates, int * lasttrellislevel, int terminate) +{ + short i, st, dminpos, position, pulsesnum, nzpos = 0; + float dmin, quantum1, quantum2, curdist1, curdist2, newdist1, newdist2, signq; + + float metric[STATES][TCQ_MAX_BAND_SIZE]; + short path[STATES][TCQ_MAX_BAND_SIZE]; + short quant[STATES][TCQ_MAX_BAND_SIZE]; + short pused[STATES][TCQ_MAX_BAND_SIZE]; + + set_f( *metric, 0.0f, STATES*TCQ_MAX_BAND_SIZE ); + set_s( *path, 0, STATES*TCQ_MAX_BAND_SIZE ); + set_s( *quant, 0, STATES*TCQ_MAX_BAND_SIZE ); + set_s( *pused, 0, STATES*TCQ_MAX_BAND_SIZE ); + + /* Initialize metric */ + for( st = 1; st < STATES; st++) + { + metric[st][0] = 1000; + } + for( st = 2; st < STATES; st++) + { + metric[st][1] = 1000; + } + for( st = 4; st < STATES; st++) + { + metric[st][2] = 1000; + } + + /* Viterbi for input sequence */ + for( i = 0; i < length; i++) /* cycle over symbols */ + { + for( st = 0; st < STATES; st++) /* cycle over conditions */ + { + curdist1 = metric[ step_tcq[st][0]][i]; + curdist2 = metric[ step_tcq[st][1]][i]; + + /* step 1 */ + quantum1 = quantize( v[i]*scale, denc[st][0]); + newdist1 = (float)( quantum1 - fabs(v[i])*scale ); + newdist1 *= newdist1; + + if( quantum1 + pused[ step_tcq[st][0]][i] > pulses && terminate) + { + newdist1 = 10000.0f; /* pulses check */ + } + + /* step 2 */ + quantum2 = quantize( v[i]*scale, denc[st][1]); + newdist2 = (float)( quantum2 - fabs(v[i])*scale ); + newdist2 *= newdist2; + + if( quantum2 + pused[ step_tcq[st][1]][i] > pulses && terminate) + { + newdist2 = 10000.0f; /* pulses check */ + } + + /* decision */ + if( curdist1 + newdist1 < curdist2 + newdist2 ) + { + path[st][i+1] = step_tcq[st][0]; + metric[st][i+1] = curdist1 + newdist1; + quant[st][i+1] = (int)quantize( v[i]*scale, denc[st][0]); + pused[st][i+1] = (int)(pused[ step_tcq[st][0]][i] + abs( quant[st][i+1] )); + } + else + { + path[st][i+1] = step_tcq[st][1]; + metric[st][i+1] = curdist2 + newdist2; + quant[st][i+1] = (int)quantize( v[i]*scale, denc[st][1]); + pused[st][i+1] = (int)(pused[ step_tcq[st][1]][i] + abs( quant[st][i+1] )); + } + } + } + + /* Find path with minimal metric */ + dminpos = 0; + dmin = metric[ dminpos][ length]; + for( i = 1; i < STATES; i++) + { + if( (dmin > metric[ i][ length] && pused[i][ length] == pulses) || + ( pused[dminpos][ length] != pulses && pused[i][ length] == pulses) ) + { + dmin = metric[ i][ length]; + dminpos = i; + } + } + + /* Trace back to get output */ + pulsesnum = 0; + position = dminpos; + + for( i = length; i > 0; i--) + { + signq = ( v[i-1] > 0.0f )?(1.0f):(-1.0f); + vout[i-1] = signq*quant[position][i]; + + position = path[position][i]; + savedstates[i-1] = position; + + /* calculate output pulses number & nz */ + pulsesnum += (int)fabs(vout[i-1]);/*quant[position][i]; */ + if( fabs(vout[i-1]) > 0.0f ) + { + if (nzpos == 0) + { + *lasttrellislevel = i; + } + + nzpos++; + } + } + + if( pulsesout != 0 ) + { + *pulsesout = pulsesnum; + } + if( nzposout != 0 ) + { + *nzposout = nzpos; + } + + return; +} + + +float GetISCScale( float *quants, int size, Word32 bits_fx, float *magn, float *qscale, Word32 *surplus_fx, float *pulses, int* savedstates, + int noTCQ, int *nzpout, short *bcount, float *abuffer, float *mbuffer, float *sbuffer) +{ + float scale, m, t, actualt, magnbits = 0.0f; + int pulsesnum, pos, terminate, leftp, leftnz, trellislevel, st; + int i, j, nzpos, direction, pulsescurr, nzposcurr, lasttrellislevel; + float dist[TCQ_MAX_BAND_SIZE]; + float aquants[TCQ_MAX_BAND_SIZE]; + float dmin, prob0, prob1, quantum1, quantum2; + float sx2 = 0, sy2 = 0, sxy = 0, g; + int pn = 0; + float pt = 0.f; + int diff; + int sign, m_int; + int flag_g1; + + set_f( dist, 0.0f, TCQ_MAX_BAND_SIZE ); + set_f( aquants, 0.0f, TCQ_MAX_BAND_SIZE ); + + if( bits_fx < 0 ) + { + pulsesnum = 0; + + if( surplus_fx != 0 ) + { + *surplus_fx = L_add( *surplus_fx, bits_fx); + } + } + else + { + pulsesnum = GetScale_fx( size, bits_fx, surplus_fx); + } + *nzpout = 0; + + if( pulses != 0 ) + { + *pulses = (float)pulsesnum; + } + + if( pulsesnum > 0 ) + { + /* Initial quantization */ + for( i = 0, m = 0; i < size; i++) + { + aquants[ i] = (float)fabs( quants[i] ); + m += aquants[i]; + } + + scale = (pulsesnum + EPSILON) / (m + EPSILON); + + for( i = 0, t = 0.0f; i < size; i++) + { + magn[i] = (float)((int)( 0.5f + aquants[ i] * scale)); + + t += magn[i]; + } + + /* Pulses redistribution */ + while( t != pulsesnum ) + { + pn = 0; + pt = 0.f; + + + for( i = 0, nzpos = 0; i < size; i++) + { + if( magn[i] > 0.0f ) + { + pn += (int)magn[i]; + pt += aquants[i]; + } + } + + direction = ( pulsesnum - t > 0 )?(1):(-1); + + /* new alg */ + { + for( i = 0; i < size; i++) + { + sxy += aquants[ i]*magn[ i]; + sx2 += aquants[ i]*aquants[ i]; + sy2 += magn[ i]*magn[ i]; + } + for( i = 0; i < size; i++) + { + if( magn[i] > 0.0f ) + { + g = (pt)/(pn + direction + EPSILON); + } + else + { + g = (pt + aquants[ i])/(pn + direction + EPSILON); + } + + dist[i] = sx2 - 2.0f*(sxy + direction*aquants[i])*g + g*g*(sy2 + 2.0f*magn[i]*direction + 1.0f); + } + } + + { + pos = 0; + dmin = dist[0]; + + /* find min */ + for( i = 1; i < size; i++) + { + if( dmin > dist[i] ) + { + pos = i; + dmin = dist[i]; + } + } + + magn[pos] += direction; + t += direction; + } + } + + /* calculate actual nz positions */ + actualt = 0.0f; + for( i = 0, nzpos = 0; i < size; i++) + { + if( magn[i] > 0.0f ) + { + if (quants[i] < 0) + { + magn[i] *= -1; + } + + actualt += aquants[i]; + nzpos++; + } + } + + /* calculate scale */ + if( actualt > 0) + { + scale = pulsesnum / actualt; + } + else + { + scale = FLT_MAX; + } + *qscale = scale; + *nzpout = nzpos; + + if( (nzpos != pulsesnum && nzpos > 1) && noTCQ == 0 ) + { + terminate = 1; + TCQnew( quants, scale, size, magn, pulsesnum, &pulsescurr, &nzposcurr, savedstates, &lasttrellislevel, terminate); + + if( pulsesnum > pulsescurr ) + { + scale *= 1.1f; + } + + if( pulsesnum < pulsescurr ) + { + scale *= 0.9f; + } + if( pulsesnum > pulsescurr ) + { + diff = pulsesnum - pulsescurr; + + for( i = size-1; i >=0; i--) + { + if( fabs(magn[i]) > 0 ) + { + sign = (magn[i]>0)?(1) : (-1); + magn[i] = (float)(sign*( fabs(magn[i]) + diff)); + + break; + } + } + } + else if( pulsesnum < pulsescurr ) + { + diff = pulsescurr - pulsesnum; + + for( i = size-1; i >=0 && diff > 0; i--) + { + if( fabs(magn[i]) > 0 ) + { + sign = (magn[i]>0)?(1) : (-1); + m_int = (int)fabs(magn[i]); + + if( diff < m_int ) + { + magn[i] = (float)(sign*( fabs(magn[i]) - diff)); + break; + } + else + { + diff = diff - m_int; + magn[i] = 0; + nzposcurr--; + } + } + } + } + + pulsescurr = pulsesnum; + + /* Magnitudes coding */ + { + leftp = pulsescurr;/*pulsesnum; */ + leftnz = nzposcurr; /*nzpos; */ + trellislevel = 0; + + for( i = 0; i < size && leftnz > 1; i++) + { + if( magn[i] != 0.0f ) + { + for( j = 0; j < leftp; j++) + { + prob1 = (leftnz - 1.0f) / (leftp - j - 1.0f); + prob0 = 1.0f - prob1; + + st = savedstates[ trellislevel ]; + quantum1 = (float)quantize( (float)(j + 1), ddec[st][ 0 ]); + quantum2 = (float)quantize( (float)(j + 1), ddec[st][ 1 ]); + + if( quantum1 != (j+1) && quantum2 != (j+1) ) + { + /* this magnitude is not possible so set probabilities */ + prob0 = 1.0f; + prob1 = 0.0f; + } + + if( j < fabs(magn[i]) - 1 ) + { + magnbits -= log2_f( prob0 ); + } + else + { + magnbits -= log2_f( prob1 ); + break; + } + } + + leftnz--; + leftp -= (int)fabs( magn[i] ); + } + + trellislevel++; + } + + /* Update actual occured surplus */ + *nzpout = nzposcurr; + } + } + + if( *nzpout > 1 && bcount != 0 ) + { + flag_g1 = 0; + + for( i = 0; i < size; i++) + { + if( fabs(magn[i]) > 1.0f ) + { + flag_g1 = 1; + } + } + /* prepare vector for TCQ */ + for( i = 0; i < size && flag_g1 && *bcount < 2*TCQ_AMP; i++) + { + if( fabs(magn[i]) > 0.0f ) + { + abuffer[*bcount] = quants[i]; + mbuffer[*bcount] = magn[i]; + sbuffer[*bcount] = scale; + + (*bcount)++; + + } + } + } + + if( actualt > 0) + { + *qscale = pulsesnum / actualt; + } + else + { + *qscale = FLT_MAX; + } + } + + return magnbits; +} + + +void InitLSBTCQ(short *bcount) +{ + *bcount = 0; + + return; +} + + +void TCQLSB(short bcount, float *abuffer, float *mbuffer, float *sbuffer, short *dpath) + +{ + short i, st, dminpos, position; + float q = QTCQ; + float dmin, curdist1, curdist2, newdist1, newdist2; + float metric[STATES_LSB][TCQ_LSB_SIZE]; + short path[STATES_LSB][TCQ_LSB_SIZE]; + short quant[STATES_LSB][TCQ_LSB_SIZE]; + short dquant[STATES_LSB][TCQ_LSB_SIZE]; + short qout[TCQ_LSB_SIZE]; + float q1, q2, s1, s2, a1, a2, sign1, sign2; + float dbuffer[MAX_PULSES]; + + set_f( *metric, 0.0f, STATES_LSB*TCQ_LSB_SIZE ); + set_s( *path, 0, STATES_LSB*TCQ_LSB_SIZE ); + set_s( *quant, 0, STATES_LSB*TCQ_LSB_SIZE ); + set_s( *dquant, 0, STATES_LSB*TCQ_LSB_SIZE ); + set_s( qout, 0, TCQ_LSB_SIZE ); + set_f( dbuffer, 0.0f, MAX_PULSES ); + + metric[1][0] = 16777216.0f; + metric[2][0] = 16777216.0f; + metric[3][0] = 16777216.0f; + + for( i = 0; i < 2*TCQ_AMP; i+=2 ) + { + q1 = mbuffer[i]; + q2 = mbuffer[i + 1]; + + s1 = sbuffer[i]; + s2 = sbuffer[i + 1]; + + a1 = abuffer[i]; + a2 = abuffer[i + 1]; + + /* cycle over conditions */ + for( st = 0; st < 4; st++) + { + curdist1 = metric[ step_LSB[st][0] ][i/2]; + curdist2 = metric[ step_LSB[st][1] ][i/2]; + + /* step 1 */ + sign1 = (denc_LSB[st][0] & 0x1)?(q):(-q); + sign2 = (denc_LSB[st][0] & 0x2)?(q):(-q); + newdist1 = (a1 - (q1+sign1)/s1)*(a1 - (q1+sign1)/s1) + (a2 - (q2+sign2)/s2)*(a2 - (q2+sign2)/s2); + + /* step 2 */ + sign1 = (denc_LSB[st][1] & 0x1)?(q):(-q); + sign2 = (denc_LSB[st][1] & 0x2)?(q):(-q); + newdist2 = (a1 - (q1+sign1)/s1)*(a1 - (q1+sign1)/s1) + (a2 - (q2+sign2)/s2)*(a2 - (q2+sign2)/s2); + + /* decision */ + if( curdist1 + newdist1 < curdist2 + newdist2 ) + { + path[st][i/2+1] = step_LSB[st][0]; + metric[st][i/2+1] = curdist1 + newdist1; + quant[st][i/2+1] = 0; + dquant[st][i/2+1] = dqnt_LSB[ step_LSB[st][0] ][st]; + } + else + { + path[st][i/2+1] = step_LSB[st][1]; + metric[st][i/2+1] = curdist2 + newdist2; + quant[st][i/2+1] = 1; + dquant[st][i/2+1] = dqnt_LSB[ step_LSB[st][0] ][st]; + } + } + + } + + /* Find path with minimal metric */ + dminpos = 0; + dmin = metric[ dminpos][ i/2]; + for( st = 1; st < 4; st++) + { + if( dmin > metric[ st][ i/2] ) + { + dmin = metric[ st][ i/2]; + dminpos = st; + } + } + + /* Trace back to get output */ + position = dminpos; + + for( ; i >= 0; i-=2) + { + qout[i/2] = quant[position][ i/2+1 ]; + dpath[i/2] = dquant[position][ i/2+1 ]; + + dbuffer[i] = (denc_LSB[position][qout[i/2]] & 0x1)?(q):(-q); + dbuffer[i + 1] = (denc_LSB[position][qout[i/2]] & 0x2)?(q):(-q); + + position = path[position][i/2+1]; + } + + /* add decoded sequence to quanta */ + for( i = 0; i < bcount; i++ ) + { + mbuffer[i] += dbuffer[i]; + } + + return; +} + +void TCQLSBdec( short *dpath, float *mbuffer, short bcount ) +{ + float q = QTCQ; + int i, state = 0; + + for( i = 0; i < bcount/2; i++) + { + mbuffer[2*i] = ( ddec_LSB[state][dpath[i]] & 0x1)?(q):(-q); + mbuffer[2*i + 1] = ( ddec_LSB[state][dpath[i]] & 0x2)?(q):(-q); + + state = dstep_LSB[state][dpath[i]]; + } + + return; +} + +void SaveTCQdata( PARCODEC arInst, short *dpath, short bcount) +{ + int i; + for( i = 0; i < bcount; i++) + { + ar_encode_uniform( arInst, dpath[i], 1); + } + + return; +} + +void LoadTCQdata( PARCODEC arInst, short *dpath, short bcount) +{ + int i; + for( i = 0; i < bcount; i++) + { + dpath[i] = ar_decode( arInst, uniform_model ); + } + + return; +} + +void RestoreTCQdec( int * magn, int size, short *bcount, float *mbuffer) +{ + int i, nzpos = 0, flag_g1 = 0; + + /* calculate actual nz positions */ + for( i = 0, nzpos = 0; i < size; i++) + { + if( magn[i] != 0 ) + { + nzpos++; + if( abs(magn[i]) > 1 ) + { + flag_g1 = 1; + } + magn[i] *= (1.0f/QTCQ); + } + } + + if( nzpos > 1) + { + for( i = 0; i < size && flag_g1 && *bcount < 2*TCQ_AMP; i++) + { + if( magn[i] != 0 ) + { + mbuffer[*bcount] = magn[i] + (1.0f/QTCQ)*mbuffer[*bcount]; + magn[i] = round_f( mbuffer[*bcount] ); + (*bcount)++; + } + } + } + + return; +} + + +void RestoreTCQ( float * magn, int size, short *bcount, float *mbuffer) +{ + int i, nzpos = 0, flag_g1 = 0; + + /* calculate actual nz positions */ + for( i = 0, nzpos = 0; i < size; i++) + { + if( magn[i] != 0.0f ) + { + nzpos++; + if( fabs(magn[i]) > 1.0f ) + { + flag_g1 = 1; + } + } + } + + if( nzpos > 1) + { + for( i = 0; i < size && flag_g1 && *bcount < 2*TCQ_AMP; i++) + { + if( fabs(magn[i]) > 0.0f ) + { + magn[i] = mbuffer[*bcount]; + (*bcount)++; + } + } + } + + return; +} diff --git a/lib_com/tcx_ltp.c b/lib_com/tcx_ltp.c new file mode 100644 index 000000000..22b62fac1 --- /dev/null +++ b/lib_com/tcx_ltp.c @@ -0,0 +1,757 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "prot.h" +#include "rom_com.h" +#include "assert.h" + + +/*------------------------------------------------------------------- + * Local constants + *-------------------------------------------------------------------*/ + +#define ALPHA 0.85f + + +/*------------------------------------------------------------------- + * tcx_ltp_get_lpc() + * + * + *-------------------------------------------------------------------*/ + +static void tcx_ltp_get_lpc( + float *input, + int length, + float *A, + int lpcorder +) +{ + int i, j; + float s, r[TCXLTP_LTP_ORDER+1]; + + for (i = 0; i <= lpcorder; i++) + { + s = 0.0; + + for (j = 0; j < length-i; j++) + { + s += input[j]*input[j+i]; + } + r[i] = s; + } + + if (r[0] < 100.0f) + { + r[0] = 100.0f; + } + r[0] *= 1.0001f; + + lev_dur( A, r, lpcorder, NULL ); + + return; +} + + +/*------------------------------------------------------------------- + * tcx_ltp_get_zir() + * + * + *-------------------------------------------------------------------*/ + +static void tcx_ltp_get_zir( + float *zir, + int length, + float *synth_ltp, + float *synth, + float *A, + int lpcorder, + float gain, + int pitch_int, + int pitch_fr, + int pitres, + int filtIdx +) +{ + float buf[TCXLTP_LTP_ORDER], alpha, step; + float *x0, *x1, s; + float *y0, *y1, s2; + const float *w0, *w1, *v0, *v1; + int 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[pitres - pitch_fr]; + v0 = &tcxLtpFilters[filtIdx].filt[0]; + v1 = &tcxLtpFilters[filtIdx].filt[pitres]; + L = tcxLtpFilters[filtIdx].length; + + for (j = 0; j < lpcorder; j++) + { + s = 0; + s2 = 0; + for (i = 0, k = 0; i < L; i++, k += pitres) + { + s += w0[k] * x0[i] + w1[k] * x1[-i]; + s2 += v0[k] * y0[i] + v1[k] * y1[-i]; + } + s2 *= ALPHA; + + buf[j] = ( synth[j] - gain * s2 ) - ( synth_ltp[j] - gain * s ); + + x0++; + x1++; + y0++; + y1++; + } + + set_f( zir, 0.0f, length ); + + syn_filt( A, lpcorder, zir, zir, length, buf, 0); + + alpha = 1.f; + step = 1.f/(float)(length/2); + + for ( j=length/2; j 0.f ) + { + 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[pitch_res - pitch_fr]; + v0 = &tcxLtpFilters[filtIdx].filt[0]; + v1 = &tcxLtpFilters[filtIdx].filt[pitch_res]; + + L = tcxLtpFilters[filtIdx].length; + + + for (j = 0; j < length; j++) + { + s = 0; + s2 = 0; + for (i = 0, k = 0; i < L; i++, k += pitch_res) + { + s += w0[k] * x0[i] + w1[k] * x1[-i]; + s2 += v0[k] * y0[i] + v1[k] * y1[-i]; + } + + s2 *= ALPHA; + synth_ltp[j] = synth[j] - gain * s2 + gain * s; + + x0++; + x1++; + y0++; + y1++; + } + } + else + { + mvr2r( synth, synth_ltp, length ); + } + + return; +} + + +/*------------------------------------------------------------------- + * tcx_ltp_synth_filter_zir() + * + * + *-------------------------------------------------------------------*/ + +static void tcx_ltp_synth_filter_zir( + float *synth_ltp, + float *synth, + int length, + int pitch_int, + int pitch_fr, + float gain, + int pitch_res, + float *zir, + short filtIdx +) +{ + float *x0, *x1, s; + float *y0, *y1, s2; + const float *v0, *v1; + const float *w0, *w1; + int 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[pitch_res - pitch_fr]; + v0 = &tcxLtpFilters[filtIdx].filt[0]; + v1 = &tcxLtpFilters[filtIdx].filt[pitch_res]; + L = tcxLtpFilters[filtIdx].length; + + for (j = 0; j < length; j++) + { + s = 0; + s2 = 0; + + for (i = 0, k = 0; i < L; i++, k += pitch_res) + { + s += w0[k] * x0[i] + w1[k] * x1[-i]; + s2 += v0[k] * y0[i] + v1[k] * y1[-i]; + } + + s2 *= ALPHA; + + synth_ltp[j] = ( synth[j] - gain * s2 + gain * s ) -zir[j]; + + x0++; + x1++; + y0++; + y1++; + } + + return; +} + + +/*------------------------------------------------------------------- + * tcx_ltp_synth_filter_fadein() + * + * + *-------------------------------------------------------------------*/ + +static void tcx_ltp_synth_filter_fadein( + float *synth_ltp, + float *synth, + int length, + int pitch_int, + int pitch_fr, + float gain, + int pitch_res, + short filtIdx +) +{ + float *x0, *x1, s; + float *y0, *y1, s2; + const float *v0, *v1; + const float *w0, *w1; + int i, j, k, L; + float alpha, step; + + if ( gain > 0.f ) + { + 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[pitch_res - pitch_fr]; + v0 = &tcxLtpFilters[filtIdx].filt[0]; + v1 = &tcxLtpFilters[filtIdx].filt[pitch_res]; + L = tcxLtpFilters[filtIdx].length; + + alpha = 0.f; + step = 1.f/(float)(length); + + + for (j = 0; j < length; j++) + { + s = 0; + s2 = 0; + + for (i = 0, k = 0; i < L; i++, k += pitch_res) + { + s += w0[k] * x0[i] + w1[k] * x1[-i]; + s2 += v0[k] * y0[i] + v1[k] * y1[-i]; + } + + s2 *= ALPHA; + + synth_ltp[j] = synth[j] - alpha * gain * s2 + alpha * gain * s; + + alpha += step; + + x0++; + x1++; + y0++; + y1++; + } + } + else + { + mvr2r( synth, synth_ltp, length ); + } + + return; +} + + +/*------------------------------------------------------------------- + * tcx_ltp_synth_filter_fadeout() + * + * + *-------------------------------------------------------------------*/ + +static void tcx_ltp_synth_filter_fadeout( + float *synth_ltp, + float *synth, + int length, + int pitch_int, + int pitch_fr, + float gain, + int pitch_res, + short filtIdx +) +{ + float *x0, *x1, s; + float *y0, *y1, s2; + const float *v0, *v1; + const float *w0, *w1; + int i, j, k, L; + float alpha, step; + + if ( gain > 0.f ) + { + 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[pitch_res - pitch_fr]; + v0 = &tcxLtpFilters[filtIdx].filt[0]; + v1 = &tcxLtpFilters[filtIdx].filt[pitch_res]; + L = tcxLtpFilters[filtIdx].length; + + alpha = 1.f; + step = 1.f/(float)(length); + + for (j = 0; j < length; j++) + { + s = 0; + s2 = 0; + + for (i = 0, k = 0; i < L; i++, k += pitch_res) + { + s += w0[k] * x0[i] + w1[k] * x1[-i]; + s2 += v0[k] * y0[i] + v1[k] * y1[-i]; + } + + s2 *= ALPHA; + synth_ltp[j] = synth[j] - alpha * gain * s2 + alpha * gain * s; + alpha -= step; + + x0++; + x1++; + y0++; + y1++; + } + } + else + { + mvr2r( synth, synth_ltp, length ); + } + + return; +} + + +/*------------------------------------------------------------------- + * tcx_ltp_decode_params() + * + * + *-------------------------------------------------------------------*/ +int tcx_ltp_decode_params( + int *ltp_param, + int *pitch_int, + int *pitch_fr, + float *gain, + int pitmin, + int pitfr1, + int pitfr2, + int pitmax, + int pitres +) +{ + int gainbits = 2; + + /* Decode Pitch and Gain */ + if ((ltp_param) && (ltp_param[0])) + { + if ( ltp_param[1] < ((pitfr2-pitmin)*pitres) ) + { + *pitch_int = pitmin + (ltp_param[1]/pitres); + *pitch_fr = ltp_param[1] - (*pitch_int - pitmin)*pitres; + } + else if (ltp_param[1] < ( (pitfr2-pitmin)*pitres + (pitfr1-pitfr2)*(pitres>>1)) ) + { + *pitch_int = pitfr2 + ((ltp_param[1]-(pitfr2-pitmin)*pitres)/(pitres>>1)); + *pitch_fr = (ltp_param[1]-(pitfr2-pitmin)*pitres) - (*pitch_int - pitfr2)*(pitres>>1); + *pitch_fr = *pitch_fr << 1; /* was *= (pitres>>1); */ + } + else + { + *pitch_int = ltp_param[1] + pitfr1 - ((pitfr2-pitmin)*pitres) - ((pitfr1-pitfr2)*(pitres>>1)); + *pitch_fr = 0; + } + *gain = (float)(ltp_param[2] + 1) * 0.625f/(float)(1<PIT_MAX_MAX) + { + /*pitch out of range due to bit error */ + *pitch_int = PIT_MAX_MAX; + return 1; + } + } + else + { + *pitch_int = pitmax; + *pitch_fr = 0; + *gain = 0.0f; + } + return 0; +} + + +/*------------------------------------------------------------------- + * tcx_ltp_post() + * + * + *-------------------------------------------------------------------*/ + +void tcx_ltp_post( + int tcxltp_on, + short core, + int L_frame, + int L_frame_core, + int delay, + float *sig, + float *tcx_buf, + short tcx_buf_len, + int bfi, + int pitch_int, + int pitch_fr, + float gain, + int *pitch_int_past, + int *pitch_fr_past, + float *gain_past, + int *filtIdx_past, + int pitres, + int *pitres_past, + float damping, + int SideInfoOnly, + float *mem_in, + float *mem_out, + int bitrate +) +{ + int tmp, L_transition, lpcorder, filtIdx; + float gain2; + float zir[L_FRAME_PLUS/4], A[TCXLTP_LTP_ORDER+1]; + float buf_in[TCXLTP_MAX_DELAY+L_FRAME48k+TCXLTP_MAX_DELAY], buf_out[2*L_FRAME48k]; + float *sig_in, *sig_out; + + + filtIdx = 0; /* just to avoid compilation warnings */ + + /******** Init ********/ + + /* Parameters */ + L_transition = L_frame/4; + lpcorder = TCXLTP_LTP_ORDER; + + /* Input buffer */ + sig_in = buf_in + tcx_buf_len; + mvr2r( mem_in, buf_in, tcx_buf_len ); + mvr2r( sig, buf_in+tcx_buf_len, L_frame ); + if ( core > ACELP_CORE ) + { + mvr2r( tcx_buf, sig_in+L_frame, tcx_buf_len ); + } + mvr2r( sig+L_frame-tcx_buf_len, mem_in, tcx_buf_len ); + + /* Output buffer */ + sig_out = buf_out + L_frame; + mvr2r( mem_out, buf_out, L_frame ); + + /* TCX-LTP parameters: integer pitch, fractional pitch, gain */ + + if ( !(SideInfoOnly || tcxltp_on) || core==ACELP_CORE ) + { + /* No LTP */ + pitch_int = 0; + pitch_fr = 0; + gain = 0.f; + } + else if ( !bfi ) + { + /* LTP and good frame */ + if (L_frame != L_frame_core) + { + tmp = pitch_int * pitres + pitch_fr; + tmp = (tmp * L_frame + L_frame_core/2) / L_frame_core; + pitch_int = tmp / pitres; + pitch_fr = tmp % pitres; + } + + if ( bitrate == HQ_48k && L_frame_core == L_FRAME16k ) + { + gain *= 0.32f; + } + else if ( bitrate == HQ_48k && L_frame_core == 512 ) + { + gain *= 0.40f; + } + else + { + gain *= 0.64f; + } + + } + 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; + pitch_fr = *pitch_fr_past; + gain = *gain_past * damping; + } + else + { + gain = 0.f; + } + } + + if ( SideInfoOnly ) + { + gain = 0.f; + if ( bfi ) + { + *gain_past = 0.f; + } + } + gain2 = gain; + + if (L_frame_core == L_FRAME) + { + switch ( L_frame ) + { + case L_FRAME8k: + filtIdx = 0; + break; + case L_FRAME16k: + filtIdx = 1; + break; + case L_FRAME32k: + filtIdx = 2; + break; + case L_FRAME48k: + filtIdx = 3; + break; + default: + assert(0); + break; + } + } + else if (L_frame_core == L_FRAME16k) + { + switch ( L_frame ) + { + case L_FRAME8k: + filtIdx = 4; + break; + case L_FRAME16k: + filtIdx = 5; + break; + case L_FRAME32k: + filtIdx = 6; + break; + case L_FRAME48k: + filtIdx = 7; + break; + default: + assert(0); + break; + } + } + else if (L_frame_core == 512) + { + switch ( L_frame ) + { + case L_FRAME8k: + filtIdx = 8; + break; + case L_FRAME16k: + filtIdx = 9; + break; + case L_FRAME32k: + filtIdx = 10; + break; + case L_FRAME48k: + filtIdx = 11; + break; + default: + assert(0); + break; + } + } + else + { + filtIdx = -1; + } + + + /******** Previous-frame part ********/ + tcx_ltp_synth_filter( sig_out, sig_in, delay, *pitch_int_past, *pitch_fr_past, *gain_past, *pitres_past, *filtIdx_past ); + + /******** Transition part ********/ + if ( gain==0.f && *gain_past==0.f ) + { + mvr2r( sig_in+delay, sig_out+delay, L_transition ); + } + else if ( *gain_past==0.f ) + { + tcx_ltp_synth_filter_fadein( sig_out+delay, sig_in+delay, L_transition, pitch_int, pitch_fr, gain, pitres, filtIdx ); + } + else if ( gain==0.f ) + { + tcx_ltp_synth_filter_fadeout( sig_out+delay, sig_in+delay, L_transition, *pitch_int_past, *pitch_fr_past, *gain_past, *pitres_past, *filtIdx_past ); + } + else if ( gain==*gain_past && pitch_int==*pitch_int_past && pitch_fr==*pitch_fr_past ) + { + tcx_ltp_synth_filter( sig_out+delay, sig_in+delay, L_transition, pitch_int, pitch_fr, gain, pitres, 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_zir( sig_out+delay, sig_in+delay, L_transition, pitch_int, pitch_fr, gain, pitres, zir, 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, filtIdx ); + + /******** Output ********/ + + /* copy to output */ + mvr2r( sig_out, sig, L_frame ); + + /* Update */ + *pitch_int_past = pitch_int; + *pitch_fr_past = pitch_fr; + *gain_past = gain2; + *filtIdx_past = filtIdx; + *pitres_past = pitres; + mvr2r( sig_out, mem_out, L_frame ); + + return; +} diff --git a/lib_com/tcx_mdct.c b/lib_com/tcx_mdct.c new file mode 100644 index 000000000..5e8ac204f --- /dev/null +++ b/lib_com/tcx_mdct.c @@ -0,0 +1,137 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include "cnst.h" +#include "prot.h" + + +/*-------------------------------------------------------------------* + * TCX_MDCT() + * + * + *-------------------------------------------------------------------*/ + +void TCX_MDCT( + float const *x, + float *y, + int l, + int m, + int r +) +{ + short i; + float dctInBuffer[N_MAX]; + + /* Init */ + for(i=0; i> 1, R2 = r >> 1; + float f; + + edct( x, y + L2, L2 + m + R2 ); + + for (i = 0; i < R2; i++) + { + y[l + m + R2 + i] = -1.0f * y[L2 + i]; /* fold out right end of DCT */ + } + + mvr2r(y + L2 + m + R2, y, L2); /* negate, fold out left end of DCT */ + + for (i = 0; i < ((L2 + m + R2) >> 1); i++) + { + f = y[L2 + i]; + y[L2 + i] = -1.0f * y[l + m + R2 - 1 - i]; /* time-reverse mid of DCT */ + y[l + m + R2 - 1 - i] = -1.0f * f; + } + + v_multc( y, (float)sqrt((float)(l/2 + m + r/2) / NORM_MDCT_FACTOR), y, l + m + r ); + + return; +} diff --git a/lib_com/tcx_mdct_window.c b/lib_com/tcx_mdct_window.c new file mode 100644 index 000000000..77c875539 --- /dev/null +++ b/lib_com/tcx_mdct_window.c @@ -0,0 +1,189 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + + +/*------------------------------------------------------------------- + * mdct_window_sine() + * + * + *-------------------------------------------------------------------*/ + +void mdct_window_sine( + float *window, + int n +) +{ + int i; + float c; + + c = EVS_PI / ( 2.0f * (float)n ); + + for ( i = 0 ; i < n ; i++ ) + { + window[i] = (float)sin( c * ( 0.5f + (float)i ) ); + } + + return; + +} + +/*------------------------------------------------------------------- + * mdct_window_aldo() + * + * + *-------------------------------------------------------------------*/ + +void mdct_window_aldo( + float *window1, + float *window2, + int n +) +{ + int i, n1, n2, d; + const float *p1, *p2; + + /* set table pointers and decimation factor */ + switch (n) + { + case 320/2: + p1 = window_48kHz + 2; + p2 = window_48kHz + 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 + 1; + p2 = window_48kHz + 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 + 1; + p2 = window_48kHz + 1110 - 2; + d = 3; + break; + case 1920/2: + p1 = window_48kHz; + p2 = window_48kHz + 1110 - 1; + d = 1; + break; + default: + assert(0); + return; + } + + /* set lengths */ + n1 = n * 23 / 32; /* left slope length */ + n2 = n * 14 / 32; /* right slope length */ + + /* first part (long slope) */ + if (n != 1280/2) + { + for (i = 0; i < n/2; i++) + { + *window1 = *p1; + window1++; + p1 += d; + } + + if ((n == 512/2) || (n == 320 / 2)) p1++; + + for ( ; i < n1; i++) + { + *window1 = *p1; + window1++; + p1 += d; + } + } + else + { + const float *pi = window_8_16_32kHz; + + for (i = 0; i < n/2; i+=2) + { + *window1 = *p1; + window1++; + p1 += d; + + *window1 = *pi; + window1++; + pi++; + } + for ( ; i < n1; i+=2) + { + *window1 = *pi; + window1++; + pi++; + + *window1 = *p1; + window1++; + p1 += d; + } + } + + /* second part (short slope) */ + + if (n != 1280/2) + { + for (i = 0; i < n2/2; i++) + { + *window2 = *p2; + window2++; + p2 -= d; + } + + if ((n == 512/2) || (n == 320 / 2)) p2--; + + for ( ; i < n2; i++) + { + *window2 = *p2; + window2++; + p2 -= d; + } + } + else + { + const float *pi = window_8_16_32kHz + 370 - 1; + + for (i = 0; i < n2/2; i+=2) + { + *window2 = *p2; + window2++; + p2 -= d; + + *window2 = *pi; + window2++; + pi--; + } + + for ( ; i < n2; i+=2) + { + *window2 = *pi; + window2++; + pi--; + + *window2 = *p2; + window2++; + p2 -= d; + } + } + + return; +} diff --git a/lib_com/tcx_utils.c b/lib_com/tcx_utils.c new file mode 100644 index 000000000..acc36ec97 --- /dev/null +++ b/lib_com/tcx_utils.c @@ -0,0 +1,941 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" + +/*-------------------------------------------------------------------* +* tcx_get_windows() +* +* +*-------------------------------------------------------------------*/ + +static void tcx_get_windows( + TCX_config const * tcx_cfg, /* i: TCX configuration */ + const short left_mode, /* i: overlap mode of left window half */ + const short right_mode, /* i: overlap mode of right window half */ + int *left_overlap, /* o: left overlap length */ + float const **left_win, /* o: left overlap window */ + int *right_overlap, /* o: right overlap length */ + float const **right_win, /* o: right overlap window */ + int fullband /* i: fullband flag */ +) +{ + if (!fullband) + { + /* Left part */ + + if (left_mode == TRANSITION_OVERLAP) + { + /* ACELP->TCX transition */ + *left_overlap = tcx_cfg->tcx_mdct_window_trans_length; + *left_win = tcx_cfg->tcx_mdct_window_trans; + } + else if (left_mode == MIN_OVERLAP) + { + *left_overlap = tcx_cfg->tcx_mdct_window_min_length; + *left_win = tcx_cfg->tcx_mdct_window_minimum; + } + else if (left_mode == HALF_OVERLAP) + { + *left_overlap = tcx_cfg->tcx_mdct_window_half_length; + *left_win = tcx_cfg->tcx_mdct_window_half; + } + else if (left_mode == FULL_OVERLAP) + { + *left_overlap = tcx_cfg->tcx_mdct_window_length; + *left_win = tcx_cfg->tcx_aldo_window_1_trunc; + } + else + { + assert(!"Not supported overlap"); + } + + /* Right part */ + + if (right_mode == MIN_OVERLAP) + { + *right_overlap = tcx_cfg->tcx_mdct_window_min_length; + *right_win = tcx_cfg->tcx_mdct_window_minimum; + } + else if (right_mode == HALF_OVERLAP) + { + *right_overlap = tcx_cfg->tcx_mdct_window_half_length; + *right_win = tcx_cfg->tcx_mdct_window_half; + } + else if (right_mode == FULL_OVERLAP) + { + *right_overlap = tcx_cfg->tcx_mdct_window_delay; + *right_win = tcx_cfg->tcx_aldo_window_2; + } + else + { + assert(!"Not supported overlap"); + } + } + else + { + /* Left part */ + + if (left_mode == TRANSITION_OVERLAP) + { + /* ACELP->TCX transition */ + *left_overlap = tcx_cfg->tcx_mdct_window_trans_lengthFB; + *left_win = tcx_cfg->tcx_mdct_window_transFB; + } + else if (left_mode == MIN_OVERLAP) + { + *left_overlap = tcx_cfg->tcx_mdct_window_min_lengthFB; + *left_win = tcx_cfg->tcx_mdct_window_minimumFB; + } + else if (left_mode == HALF_OVERLAP) + { + *left_overlap = tcx_cfg->tcx_mdct_window_half_lengthFB; + *left_win = tcx_cfg->tcx_mdct_window_halfFB; + } + else if (left_mode == RECTANGULAR_OVERLAP) + { + *left_overlap = 0; + *left_win = NULL; + } + else if (left_mode == FULL_OVERLAP) + { + *left_overlap = tcx_cfg->tcx_mdct_window_lengthFB; + *left_win = tcx_cfg->tcx_aldo_window_1_FB_trunc; + } + else + { + assert(!"Not supported overlap"); + } + + /* Right part */ + + if (right_mode == MIN_OVERLAP) + { + *right_overlap = tcx_cfg->tcx_mdct_window_min_lengthFB; + *right_win = tcx_cfg->tcx_mdct_window_minimumFB; + } + else if (right_mode == HALF_OVERLAP) + { + *right_overlap = tcx_cfg->tcx_mdct_window_half_lengthFB; + *right_win = tcx_cfg->tcx_mdct_window_halfFB; + } + else if (right_mode == RECTANGULAR_OVERLAP) + { + *right_overlap = 0; + *right_win = NULL; + } + else if (right_mode == FULL_OVERLAP) + { + *right_overlap = tcx_cfg->tcx_mdct_window_delayFB; + *right_win = tcx_cfg->tcx_aldo_window_2_FB; + } + else + { + assert(!"Not supported overlap"); + } + } + + return; +} + +/*-------------------------------------------------------------------* +* tcx_windowing_analysis() +* +* +*-------------------------------------------------------------------*/ + +void tcx_windowing_analysis( + float const *signal, /* i: signal vector */ + int L_frame, /* i: frame length */ + int left_overlap, /* i: left overlap length */ + float const *left_win, /* i: left overlap window */ + int right_overlap, /* i: right overlap length */ + float const *right_win, /* i: right overlap window */ + float *output /* o: windowed signal vector */ +) +{ + int w; + + /* Left overlap */ + for (w = 0; w < left_overlap; w++) + { + *output++ = *signal++ * left_win[w]; + } + + /* Non overlapping region */ + for (w = 0; w < L_frame-(left_overlap+right_overlap)/2; w++) + { + *output++ = *signal++; + } + + /* Right overlap */ + for (w = 0; w < right_overlap; w++) + { + *output++ = *signal++ * right_win[right_overlap-1-w]; + } + + return; +} + + +/*-------------------------------------------------------------------* +* WindowSignal() +* +* +*-------------------------------------------------------------------*/ + +void WindowSignal( + TCX_config const *tcx_cfg, /* input: configuration of TCX */ + int offset, /* input: left folding point offset relative to the input signal pointer */ + const short left_overlap_mode, /* input: overlap mode of left window half */ + const short right_overlap_mode, /* input: overlap mode of right window half */ + int * left_overlap_length, /* output: TCX window left overlap length */ + int * right_overlap_length, /* output: TCX window right overlap length */ + float const in[], /* input: input signal */ + int * L_frame, /* input/output: frame length */ + float out[], /* output: output windowed signal */ + int fullband /* input: fullband flag */ +) +{ + int l, r; + float const * left_win; + float 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 (left_overlap_mode == TRANSITION_OVERLAP) + { + /* Increase frame size for 5ms */ + if (!fullband) + { + *L_frame += tcx_cfg->tcx5Size; + offset = -tcx_cfg->tcx_mdct_window_trans_length/2; + } + else + { + *L_frame += tcx_cfg->tcx5SizeFB; + offset = -tcx_cfg->tcx_mdct_window_trans_lengthFB/2; + } + } + + /*-----------------------------------------------------------* + * Windowing * + *-----------------------------------------------------------*/ + + tcx_windowing_analysis(in-l/2+offset, *L_frame, l, left_win, r, right_win, out); + + if (left_overlap_mode == FULL_OVERLAP) + { + /* fade truncated ALDO window to avoid discontinuities */ + if (!fullband) + { + v_mult(out, tcx_cfg->tcx_mdct_window_minimum, out, tcx_cfg->tcx_mdct_window_min_length); + } + else + { + v_mult(out, tcx_cfg->tcx_mdct_window_minimumFB, out, tcx_cfg->tcx_mdct_window_min_lengthFB); + } + } + + *left_overlap_length = l; + *right_overlap_length = r; + + return; +} + + +/*-------------------------------------------------------------------* +* tcx_windowing_synthesis_current_frame() +* +* +*-------------------------------------------------------------------*/ + +void tcx_windowing_synthesis_current_frame( + float *signal, /* i/o: signal vector */ + float *window, /* i: TCX window vector */ + float *window_half, /* i: TCX window vector for half-overlap window */ + float *window_min, /* i: TCX minimum overlap window */ + int window_length, /* i: TCX window length */ + int window_half_length, /* i: TCX half window length */ + int window_min_length, /* i: TCX minimum overlap length */ + int left_rect, /* i: left part is rectangular */ + int left_mode, /* i: overlap mode of left window half */ + float *acelp_zir, /* i: acelp ZIR */ + float *old_syn, /* i: old synthesis */ + float *syn_overl, /* i: overlap synthesis */ + float *A_zir, + float *window_trans, + int acelp_zir_len, + int acelp_mem_len, + int last_core_bfi, /* i: last mode */ + int last_is_cng, + int fullbandScale +) +{ + int i, overlap; + float tmp[L_FRAME_MAX/2]; + + /* Init */ + overlap = window_length>>1; + + /* Past-frame is TCX concealed as CNG and current-frame is TCX */ + if ( last_is_cng==1 && left_rect==0 ) + { + if (!fullbandScale) + { + set_zero(acelp_zir, acelp_zir_len); + syn_filt(A_zir, M,acelp_zir, acelp_zir, acelp_zir_len, signal+overlap+acelp_mem_len-M, 0); + } + else + { + lerp(acelp_zir, tmp, acelp_zir_len, acelp_zir_len*FSCALE_DENOM/fullbandScale); + acelp_zir = tmp; + } + + 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); + } + } + else if ( left_rect==1 && last_core_bfi==ACELP_CORE ) /* Rectangular window (past-frame is ACELP) */ + { + for (i=0; i= 2.0f * 64) + { + /* apply a simple low-pass to the ZIR, to avoid potentially unmasked HF content */ + for(i=2; i=0; i--) + { + acelp_zir[i] = 0.40f * acelp_zir[i] + 0.35f * acelp_zir[i+1] + 0.25f * acelp_zir[i+2]; + } + } + } + + for (i = 0; i < acelp_zir_len; i++) + { + /*remove reconstructed ZIR and add ACELP ZIR*/ + signal[i+overlap+acelp_mem_len] -= acelp_zir[i]*(float)(acelp_zir_len-i)/(float)acelp_zir_len; + } + } + else if ( left_rect==1 && last_core_bfi!=0 ) /* Rectangular window (past-frame is TCX) */ + { + for (i=0; i lpcGains[i]) + { + tmp = lpcGains[i]; + } + if (max < lpcGains[i]) + { + max = lpcGains[i]; + } + } + + tmp *= 32.0f; + + if ((max < tmp) && (tmp > FLT_MIN)) + { + fac = tmp = (float)pow(max / tmp, 0.0078125f); + + if (lf_deemph_factors) + { + /* gradual lowering of lowest 32 bins; DC is lowered by (max/tmp)^1/4 */ + for (i = 31; i >= 0; i--) + { + x[i] *= fac; + lf_deemph_factors[i] *= fac; + fac *= tmp; + } + } + else + { + /* gradual lowering of lowest 32 bins; DC is lowered by (max/tmp)^1/4 */ + for (i = 31; i >= 0; i--) + { + x[i] *= fac; + fac *= tmp; + } + } + } + + return; +} + + +/*-------------------------------------------------------------------* +* AdaptLowFreqDeemph() +* +* +*-------------------------------------------------------------------*/ + +void AdaptLowFreqDeemph( + float x[], + short tcx_lpc_shaped_ari, + const float lpcGains[], + const int lg, + float lf_deemph_factors[] +) +{ + + int i, i_max_old,i_max; + + if(!tcx_lpc_shaped_ari) + { + /* 1. find first magnitude maximum in lower quarter of spectrum */ + i_max = -1; + + for (i = 0; i < lg/4; i++) + { + if ((x[i] <= -4.0f) || (x[i] >= 4.0f)) + { + x[i] += (x[i] < 0.0f) ? 2.0f : -2.0f; + i_max = i; + break; + } + } + /* 2. expand value range of all xi up to i_max: two extra steps */ + + for (i = 0; i < i_max; i++) + { + x[i] *= 0.5f; + lf_deemph_factors[i] *= 0.5f; + } + /* 3. find first magnitude maximum in lower quarter of spectrum */ + i_max_old = i_max; + + if (i_max_old > -1) + { + i_max = -1; + + for (i = 0; i < lg/4; i++) + { + if ((x[i] <= -4.0f) || (x[i] >= 4.0f)) + { + x[i] += (x[i] < 0.0f) ? 2.0f : -2.0f; + i_max = i; + break; + } + } + } + /* 4. expand value range of all xi up to i_max: two extra steps */ + for (i = 0; i < i_max; i++) + { + x[i] *= 0.5f; + lf_deemph_factors[i] *= 0.5f; + } + /* 5. always expand two lines; lines could be at index 0 and 1! */ + if (i_max < i_max_old) + { + i_max = i_max_old; + } + i = i_max + 1; + if (x[i] < 0.0f) + { + if (x[i] > -4.0f) + { + lf_deemph_factors[i] *= 0.5f; + } + x[i] = (x[i] <= -4.0f) ? x[i] + 2.0f : x[i] * 0.5f; + } + else + { + if (x[i] < 4.0f) + { + lf_deemph_factors[i] *= 0.5f; + } + x[i] = (x[i] >= 4.0f) ? x[i] - 2.0f : x[i] * 0.5f; + } + i++; + if (x[i] < 0.0f) + { + if (x[i] > -4.0f) + { + lf_deemph_factors[i] *= 0.5f; + } + x[i] = (x[i] <= -4.0f) ? x[i] + 2.0f : x[i] * 0.5f; + } + else + { + if (x[i] < 4.0f) + { + lf_deemph_factors[i] *= 0.5f; + } + x[i] = (x[i] >= 4.0f) ? x[i] - 2.0f : x[i] * 0.5f; + } + } + else + { + /*if(!tcx_lpc_shaped_ari)*/ + PsychAdaptLowFreqDeemph(x, lpcGains, lf_deemph_factors); + }/*if(!tcx_lpc_shaped_ari)*/ + + return; +} + + +/*-------------------------------------------------------------------* +* tcx_noise_filling() +* +* +*-------------------------------------------------------------------*/ + +void tcx_noise_filling( + float *Q, + const int noiseFillSeed, + const int iFirstLine, + const int lowpassLine, + const int nTransWidth, + const int L_frame, + float tiltCompFactor, + float fac_ns, + unsigned char *infoTCXNoise +) +{ + int i, m, segmentOffset; + int win; /* window coefficient */ + Word16 seed; + float tilt_factor, nrg, tmp1, tmp2; + + /* 16-bit random number generator seed for generating filled lines */ + seed = (Word16)noiseFillSeed; + + tilt_factor = (float)pow(max(0.375f, tiltCompFactor), 1.0f/(float)L_frame); + fac_ns /= (float)(nTransWidth * nTransWidth); + + /* find last nonzero line below iFirstLine, use it as start offset */ + for (i = iFirstLine; i > (iFirstLine >> 1); i--) + { + if (Q[i] != 0.0f) + { + break; + } + } + fac_ns *= (float)pow(tilt_factor, (float)i); + + nrg = 1e-9f; + win = 0; + segmentOffset = ++i; + + for (; i < lowpassLine; i++) + { + fac_ns *= tilt_factor; + + if (Q[i] != 0.0f) + { + if (win > 0) + { + /* RMS-normalize current noise-filled segment */ + tmp1 = (float)sqrt((i - segmentOffset) / nrg); + tmp2 = tmp1 * (float)nTransWidth; + + for (m = segmentOffset; m < i-win; m++) + { + Q[m] *= tmp2; + } + + for (; win > 0; win--) + { + Q[m++] *= tmp1 * (float)win; + } + nrg = 1e-9f; /* start new segment: reset noise segment energy */ + } + segmentOffset = i + 1; + } + else + { + /* line is zero, so fill line and update window and energy */ + if (win < nTransWidth) + { + win++; + } + tmp1 = (float)own_random(&seed); + nrg += tmp1 * tmp1; /* sum up energy of current noise segment */ + Q[i] = tmp1 * (float)win * fac_ns; + + if(infoTCXNoise) + { + /* set noiseflags for IGF */ + infoTCXNoise[i] = 1; + } + } + } + + if (win > 0) + { + /* RMS-normalize uppermost noise-filled segment */ + tmp1 = (float)sqrt((lowpassLine - segmentOffset) / nrg); + tmp2 = tmp1 * (float)nTransWidth; + + for (m = segmentOffset; m < lowpassLine; m++) + { + Q[m] *= tmp2; + } + } + + return; +} + + +/*-------------------------------------------------------------------* +* InitTnsConfigs() +* +* +*-------------------------------------------------------------------*/ + +void InitTnsConfigs( + int nSampleRate, + int L_frame, + STnsConfig tnsConfig[2][2], + int igfStopFreq, + int bitrate +) +{ + if (bitrate > ACELP_32k) + { + InitTnsConfiguration(nSampleRate, L_frame/2, &tnsConfig[0][0], igfStopFreq, bitrate); + } + InitTnsConfiguration(nSampleRate, L_frame, &tnsConfig[1][0], igfStopFreq, bitrate); + InitTnsConfiguration(nSampleRate, L_frame +L_frame/4, &tnsConfig[1][1], igfStopFreq, bitrate); + + return; +} + + + +/*-------------------------------------------------------------------* +* SetTnsConfig() +* +* +*-------------------------------------------------------------------*/ + +void SetTnsConfig( + TCX_config * tcx_cfg, + int isTCX20, + int isAfterACELP +) +{ + tcx_cfg->pCurrentTnsConfig = &tcx_cfg->tnsConfig[isTCX20][isAfterACELP]; + assert(tcx_cfg->pCurrentTnsConfig != NULL); + + return; +} diff --git a/lib_com/tec_com.c b/lib_com/tec_com.c new file mode 100644 index 000000000..763df1625 --- /dev/null +++ b/lib_com/tec_com.c @@ -0,0 +1,930 @@ + /*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + + #include + #include "wmc_auto.h" + #include + #include + #include + #include "rom_com.h" + #include "prot.h" + #include "stat_dec.h" + + /*------------------------------------------------------------------- + * Local constants + *-------------------------------------------------------------------*/ + + #define LOBUF_NO_SMOOTHING_MODE 1 + + #define EPS (1e-12f) + #define ENV_SCALE_OFFSET_1 90.309f /* 10*log10(2^30) */ + #define MAX_TEC_BW_LO (12) + #define MAX_NB_TEC_LOW_BAND (3) + + const float TecSC[] = {0.3662f, 0.1078f, 0.1194f, 0.1289f, 0.1365f, 0.1412f}; +const int TecLowBandTable[] = {0, 2, 4, 6}; + + #define TecSmoothingDeg 5 + #define NbTecLowBand 3 + + #define ratioHiLoFac 1.5894f + #define thRatio 0.3649f + #define thRatio2 2.0288f + #define thCorrCoef 0.8795f + #define ratioHiLoFacDec (1.5894f * 0.75f) + + /*------------------------------------------------------------------- + * calcLoBufferDec() + * + * + *-------------------------------------------------------------------*/ + + static void calcLoBufferDec( + float **pCldfbReal, + float **pCldfbImag, + float* loBuffer, + int startPos, + int stopPos, + int bandOffsetBottom, + float scaleOffset + ) + { + int slot, k, lb, li, ui; + float nrg, tmp; + + /* calc loTempEnv */ + for (slot = startPos; slot < stopPos; slot++) + { + tmp = 0; + + for (lb = 0; lb < NbTecLowBand; lb++) + { + li = TecLowBandTable[lb]; + ui = TecLowBandTable[lb+1]; + + nrg = 0; + for (k = li; k < ui; k++) + { + nrg += pCldfbReal[slot][k + bandOffsetBottom] * pCldfbReal[slot][k + bandOffsetBottom] + + pCldfbImag[slot][k + bandOffsetBottom] * pCldfbImag[slot][k + bandOffsetBottom]; + } + tmp += (float) log10(nrg * normReciprocal[ui - li] + EPS); + } + + loBuffer[slot] = 10.0f * tmp / NbTecLowBand + scaleOffset; + } + + return; + } + + + /*------------------------------------------------------------------- + * calcLoBufferEnc() + * + * + *-------------------------------------------------------------------*/ + + static void calcLoBufferEnc( + float** pCldfbPow, + int startPos, + int stopPos, + int bandOffsetBottom, + float scaleOffset, + float* loBuffer + ) + { + int slot, k, lb, li, ui; + float nrg, tmp; + + /* calc loTempEnv */ + for (slot = startPos; slot < stopPos; slot++) + { + tmp = 0; + + for (lb = 0; lb < NbTecLowBand; lb++) + { + li = TecLowBandTable[lb]; + ui = TecLowBandTable[lb+1]; + + nrg = 0; + for (k = li; k < ui; k++) + { + nrg += pCldfbPow[slot][k + bandOffsetBottom]; + } + tmp += (float) log10(nrg * normReciprocal[ui - li] + EPS); + } + + loBuffer[slot] = 10.0f * tmp / NbTecLowBand + scaleOffset; + } + + return; + } + + + /*------------------------------------------------------------------- + * calcLoTempEnv() + * + * + *-------------------------------------------------------------------*/ + + static void calcLoTempEnv( + float* loBuffer, + int noCols, + float* loTempEnv, + float adjFac + ) + { + int slot, i; + + for (slot = 0; slot < noCols; slot++) + { + loTempEnv[slot] = TecSC[0] * loBuffer[slot]; + for (i = 1; i < TecSmoothingDeg + 1; i++) + { + loTempEnv[slot] += TecSC[i] * loBuffer[slot - i]; + } + + loTempEnv[slot] *= adjFac; + } + + return; + } + + /*------------------------------------------------------------------- + * calcHiTempEnv() + * + * + *-------------------------------------------------------------------*/ + + static void calcHiTempEnv( + float** pCldfbPow, + int startPos, + int stopPos, + int lowSubband, + int highSubband, + float scaleOffset, + float* hiTempEnv + ) + { + int timeIndex, k; + int bwHigh = highSubband - lowSubband; + + /* set hiTempEnv */ + for (timeIndex = startPos; timeIndex < stopPos; timeIndex++) + { + hiTempEnv[timeIndex] = 0; + for (k = lowSubband; k < highSubband; k++) + { + hiTempEnv[timeIndex] += pCldfbPow[timeIndex][k]; + } + hiTempEnv[timeIndex] = (float)(10 * log10(hiTempEnv[timeIndex] / bwHigh + EPS) + scaleOffset); + } + + return; + } + + + /*------------------------------------------------------------------- + * calcVar() + * + * + *-------------------------------------------------------------------*/ + + static float calcVar( + const float in[], + int len, + float* x + ) + { + float xx; + int i; + + xx = 0; + *x = 0; + + for(i=0; ipGainTemp, 0, CLDFB_NO_COL_MAX); + + set_f(hTecDec->loBuffer, 0.f, CLDFB_NO_COL_MAX + MAX_TEC_SMOOTHING_DEG); + + return; + } + + + /*------------------------------------------------------------------- + * calcLoTempEnv_TBE() + * + * + *-------------------------------------------------------------------*/ + + static void calcLoTempEnv_TBE( + float* loBuffer, + int noCols, + float* loTempEnv, + float adjFac + ) + { + int slot, i; + int delay = 1; + + for (slot = 0; slot < noCols; slot++) + { + loTempEnv[slot] = TecSC[0] * loBuffer[slot - delay]; + + for (i = 1; i < TecSmoothingDeg + 1; i++) + { + loTempEnv[slot] += TecSC[i] * loBuffer[slot - delay - i]; + } + + loTempEnv[slot] *= adjFac; + } + + return; + } + + + /*------------------------------------------------------------------- + * set_TEC_TFA_code() + * + * + *-------------------------------------------------------------------*/ + + void set_TEC_TFA_code( + const short corrFlag, + short* tec_flag, + short* tfa_flag + ) + { + *tec_flag = 0; + if (*tfa_flag == 0) + { + if (corrFlag == 1) + { + *tec_flag = 1; + } + else if (corrFlag == 2) + { + *tec_flag = 1; + *tfa_flag = 1; + } + } + + return; + } + + + /*------------------------------------------------------------------- + * calcLoTempEnv_ns_TBE() + * + * + *-------------------------------------------------------------------*/ + + static void calcLoTempEnv_ns_TBE( + float* loBuffer, + int noCols, + float* loTempEnv + ) + { + int slot; + int delay = 1; + float fac = 1.4f; + + for (slot = 0; slot < noCols; slot++) + { + loTempEnv[slot] = fac * loBuffer[slot - delay]; + } + + return; + } + + + /*------------------------------------------------------------------- + * calcLoTempEnv_ns() + * + * + *-------------------------------------------------------------------*/ + + static void calcLoTempEnv_ns( + float* loBuffer, + int noCols, + float* loTempEnv + ) + { + int slot; + + for (slot = 0; slot < noCols; slot++) + { + loTempEnv[slot] = loBuffer[slot]; + } + + return; + } + + /*------------------------------------------------------------------- + * calcGainLinear_TBE() + * + * + *-------------------------------------------------------------------*/ + + static void calcGainLinear_TBE( + const float* loTempEnv, + const int startPos, + const int stopPos, + float* pGainTemp + ) + { + int timeIndex; + float ftmp; + + for (timeIndex = startPos; timeIndex < stopPos; timeIndex++) + { + ftmp = loTempEnv[timeIndex]; + pGainTemp[timeIndex] = (float) pow(10.0, 0.1 * ftmp); + } + + return; + } + + + /*------------------------------------------------------------------- + * calcGainTemp_TBE() + * + * + *-------------------------------------------------------------------*/ + + void calcGainTemp_TBE( + float** pCldfbRealSrc, + float** pCldfbImagSrc, + float* loBuffer, + int startPos, /*!< Start position of the current envelope. */ + int stopPos, /*!< Stop position of the current envelope. */ + int lowSubband, /* lowSubband */ + float* pGainTemp, + short code + ) + { + float loTempEnv[16]; + const int BW_LO = TecLowBandTable[NbTecLowBand]; + int slot; + /*int lowSubband = pFreqBandTable[0];*/ + int noCols = stopPos - startPos; + int bandOffset = 0; + float scaleOffset = 0; + + assert(lowSubband >= BW_LO); + + + bandOffset = lowSubband - BW_LO; + + calcLoBufferDec( pCldfbRealSrc, pCldfbImagSrc, loBuffer + MAX_TEC_SMOOTHING_DEG, startPos, stopPos, bandOffset, scaleOffset ); + + if (code > 0) + { + if (code != 2) + { + calcLoTempEnv_TBE(loBuffer + MAX_TEC_SMOOTHING_DEG, noCols, loTempEnv, ratioHiLoFacDec); + } + else + { + calcLoTempEnv_ns_TBE(loBuffer + MAX_TEC_SMOOTHING_DEG, noCols, loTempEnv); + } + + calcGainLinear_TBE(loTempEnv, startPos, stopPos, pGainTemp); + } + + + for (slot = 0; slot < MAX_TEC_SMOOTHING_DEG; slot++) + { + loBuffer[slot] = loBuffer[slot + stopPos]; + } + + return; + } + + + /*------------------------------------------------------------------- + * setSubfrConfig() + * + * + *-------------------------------------------------------------------*/ + + static void setSubfrConfig( + int i_offset, + int* k_offset, + int* n_subfr, + int l_subfr + ) + { + *n_subfr = N_TEC_TFA_SUBFR - i_offset; + *k_offset = i_offset * l_subfr; + + return; + } + + + /*------------------------------------------------------------------- + * calcSubfrNrg() + * + * + *-------------------------------------------------------------------*/ + + static float calcSubfrNrg( + const float* hb_synth, + const int i_offset, + float* enr, + int k_offset, + int l_subfr + ) + { + int i, j, k; + float enr_all = 1e-12f; + + for (i=i_offset, k = k_offset; i (tmp = 1.0 / max_inv_curr_enr)) + { + lower_limit_gain = tmp * 0.5; + } + + upper_limit_gain = 1.2f; + if (code == LOBUF_NO_SMOOTHING_MODE) + { + upper_limit_gain = 3.0; + } + + for (i=i_offset, k=k_offset; i gain[i]) + { + gain[i] = lower_limit_gain; + } + gain[i] *= inv_curr_enr[i]; + + if (gain[i] > upper_limit_gain) + { + gain[i] = upper_limit_gain; + } + + gain[i] = sqrt(gain[i]); + for(j=0; jloBuffer, 0.f, CLDFB_NO_COL_MAX + MAX_TEC_SMOOTHING_DEG + DELAY_TEMP_ENV_BUFF_TEC); + set_f(hTecEnc->hiTempEnv, 0.f, CLDFB_NO_COL_MAX + DELAY_TEMP_ENV_BUFF_TEC + EXT_DELAY_HI_TEMP_ENV); + set_f(hTecEnc->loTempEnv, 0.f, CLDFB_NO_COL_MAX); + set_f(hTecEnc->loTempEnv_ns, 0.f, CLDFB_NO_COL_MAX); + } + else + { + set_f(hTecEnc->loBuffer, 0.f, MAX_TEC_SMOOTHING_DEG); + } + + return; + } + + + /*------------------------------------------------------------------- + * calcHiEnvLoBuff() + * + * + *-------------------------------------------------------------------*/ + + void calcHiEnvLoBuff( + int noCols, + const int* pFreqBandTable, /*!< freqbandTable. */ + int nSfb, /*!< Number of scalefactors. */ + float** pCldfbPow, + float* loBuffer, + float* hiTempEnvOrig + ) + { + const int BW_LO = TecLowBandTable[NbTecLowBand]; + const int lowSubband = pFreqBandTable[0]; + const int highSubband = pFreqBandTable[nSfb]; + + int bandOffsetBottom = lowSubband - BW_LO; + + float scaleOffset = 0; + float* hiTempEnv = hiTempEnvOrig + EXT_DELAY_HI_TEMP_ENV; + + assert(bandOffsetBottom > 0); + + /* calc hiTempEnv*/ + calcHiTempEnv( pCldfbPow, 0, noCols, lowSubband, highSubband, scaleOffset, hiTempEnv + DELAY_TEMP_ENV_BUFF_TEC ); + + /* calc loBuffer */ + calcLoBufferEnc( pCldfbPow, 0, noCols, bandOffsetBottom, scaleOffset, loBuffer + MAX_TEC_SMOOTHING_DEG + DELAY_TEMP_ENV_BUFF_TEC ); + + return; + } + + + /*------------------------------------------------------------------- + * calcLoEnvCheckCorrHiLo() + * + * + *-------------------------------------------------------------------*/ + + void calcLoEnvCheckCorrHiLo( + int noCols, + const int* pFreqBandTable, /*!< freqbandTable. */ + float* loBuffer, + float* loTempEnv, + float* loTempEnv_ns, + float* hiTempEnvOrig, + int* corrFlag + ) + { + const int BW_LO = TecLowBandTable[NbTecLowBand]; + const int lowSubband = pFreqBandTable[0]; + int i; + float corrCoef; + int bandOffsetBottom = lowSubband - BW_LO; + float ratio; + float hiVar, loVar; + float hiSum, loSum; + short code = 0; /* SET TENTATIVELY */ + float loVar_ns; + float loSum_ns; + float diff_hi_lo_sum; + + float* hiTempEnv = hiTempEnvOrig + EXT_DELAY_HI_TEMP_ENV; + + assert(bandOffsetBottom > 0); + + hiVar = calcVar(hiTempEnv, noCols, &hiSum); + + /* calc loTempEnv */ + calcLoTempEnv( loBuffer + MAX_TEC_SMOOTHING_DEG, noCols, loTempEnv, ratioHiLoFac ); + + calcLoTempEnv_ns( loBuffer + MAX_TEC_SMOOTHING_DEG, noCols, loTempEnv_ns ); + + loVar_ns = calcVar(loTempEnv_ns, noCols, &loSum_ns); + diff_hi_lo_sum = loSum_ns - hiSum; + + if (hiVar > 800 && loVar_ns > 720 && diff_hi_lo_sum < 100) + { + code = 1; + } + + *corrFlag = 0; + + assert(code == 0 || code == 1); + + if (code) + { + /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + /* ++++ code == 1 +++++*/ + /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + int maxPosHi, maxPosLo; + float maxHi, maxLo; + + maxHi = hiTempEnv[0]; + maxLo = loTempEnv_ns[0]; + maxPosHi = maxPosLo = 0; + + for (i = 1; i < noCols; i++) + { + if (maxHi < hiTempEnv[i]) + { + maxHi = hiTempEnv[i]; + maxPosHi = i; + } + + if (maxLo < loTempEnv_ns[i]) + { + maxLo = loTempEnv_ns[i]; + maxPosLo = i; + } + } + + if (abs(maxPosHi - maxPosLo) < 2) + { + *corrFlag = 2; + } + + { + float feature_max = 0; + int pos_feature_max = 0; + float feature[16]; + + float min_local, max_local; + int j; + int len_window = EXT_DELAY_HI_TEMP_ENV + 1; + float* curr_pos = hiTempEnv; + + feature_max = 0; + pos_feature_max = 0; + + for (i = 0; i < 16; i++, curr_pos++) + { + max_local = min_local = curr_pos[0]; + + for (j = 1; j < len_window; j++) + { + if (max_local < curr_pos[-j]) + { + max_local = curr_pos[-j]; + } + + if (min_local > curr_pos[-j]) + { + min_local = curr_pos[-j]; + } + } + + feature[i] = max_local - min_local; + + if (feature_max < feature[i]) + { + feature_max = feature[i]; + pos_feature_max = i; + } + } + + if (*corrFlag > 0) + { + if (!(feature_max > 20 && abs(pos_feature_max - maxPosHi) < 3 )) + { + *corrFlag = 0; + } + } + } + } + else + { + /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + /* ++++ code == 0 ++++*/ + /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + + /* calc the variance of loTempEnv */ + loVar = calcVar(loTempEnv, noCols, &loSum); + + /* calc correlation coefficient between loTempEnv and hiTempEnv */ + corrCoef = calcCorrelationCoefficient2( hiTempEnv, loTempEnv, noCols, hiVar, loVar, hiSum, loSum ); + + ratio = hiVar / (loVar + EPS); + + if (corrCoef >= thCorrCoef && ratio > thRatio && ratio < thRatio2) + { + *corrFlag = 1; + } + + } + + for (i = 0; i < MAX_TEC_SMOOTHING_DEG + DELAY_TEMP_ENV_BUFF_TEC; i++) + { + loBuffer[i] = loBuffer[noCols + i]; + } + + for (i = 0; i < DELAY_TEMP_ENV_BUFF_TEC + EXT_DELAY_HI_TEMP_ENV; i++) + { + hiTempEnvOrig[i] = hiTempEnvOrig[noCols + i]; + } + + return; + } + + + /*------------------------------------------------------------------- + * tecEnc_TBE() + * + * + *-------------------------------------------------------------------*/ + + void tecEnc_TBE( + int* corrFlag, + const float *voicing, + short coder_type + ) + { + float voice_sum; + float voice_diff; + + /*-----------------------------------------------------------------* + * TEC updates + *-----------------------------------------------------------------*/ + + voice_sum = voicing[0] + voicing[1]; + voice_diff = voicing[0] - voicing[1]; + + if( voice_diff < 0 ) + { + voice_diff *= -1.0f; + } + + if( *corrFlag == 1 ) + { + if( coder_type == INACTIVE || (((voice_sum > 0.35 * 2 && voice_sum < 0.55 * 2) && (voice_diff < 0.2))) ) + { + *corrFlag = 0; + } + } + if( voice_sum > 0.6 * 2 ) + { + *corrFlag = 0; + } + + return; + } diff --git a/lib_com/tns_base.c b/lib_com/tns_base.c new file mode 100644 index 000000000..fc7f33545 --- /dev/null +++ b/lib_com/tns_base.c @@ -0,0 +1,735 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +#define WMC_TOOL_SKIP + + +/** Inverse quantization for reflection coefficients. + * + * @param index input quantized values. + * @param parCoeff output reflection coefficients. + * @param order number of coefficients/values. + */ +static void Index2Parcor(int const index[], float parCoeff[], int 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 float (* TLinearPredictionFilter)(int order, float const parCoeff[], float * state, float x); + +/** Linear prediction analysis filter. + * See TLinearPredictionFilter for details. + */ +static float FIRLattice(int order, const float *parCoeff, float *state, float x); + +/** Linear prediction synthesis filter. + * See TLinearPredictionFilter for details. + */ +static float IIRLattice(int order, const float *parCoeff, float *state, float 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(float const spectrum[], int numOfLines, + float const parCoeff[], int order, + TLinearPredictionFilter filter, float * state, + float output[]); + + +/********************************/ +/* Interface functions */ +/********************************/ + +TNS_ERROR InitTnsConfiguration( + int nSampleRate, + int frameLength, + STnsConfig * pTnsConfig, + int igfStopFreq, + int bitrate +) +{ + int iFilter = 0; + short int * startLineFilter = &pTnsConfig->iFilterBorders[1]; + + /* Sanity checks */ + assert((nSampleRate > 0) && (frameLength > 0) && (pTnsConfig != NULL)); + if ((nSampleRate <= 0) || (frameLength <= 0) || (pTnsConfig == NULL)) + return TNS_FATAL_ERROR; + /* WMOPS: All initializations are either for safety or static (tables) and thus not to be counted */ + /* Initialize TNS filter flag and maximum order */ + pTnsConfig->maxOrder = TNS_MAX_FILTER_ORDER; + if (bitrate <= ACELP_32k) + { + pTnsConfig->nMaxFilters = sizeof(tnsParametersIGF32kHz_LowBR)/sizeof(tnsParametersIGF32kHz_LowBR[0]); + + pTnsConfig->pTnsParameters = tnsParametersIGF32kHz_LowBR; + } + else + { + if (nSampleRate > 32000 && nSampleRate == 100 * frameLength) + { + pTnsConfig->nMaxFilters = sizeof(tnsParameters48kHz_grouped)/sizeof(tnsParameters48kHz_grouped[0]); + pTnsConfig->pTnsParameters = tnsParameters48kHz_grouped; + } + else if (nSampleRate > 16000) + { + pTnsConfig->nMaxFilters = sizeof(tnsParameters32kHz)/sizeof(tnsParameters32kHz[0]); + if (nSampleRate == 100 * frameLength) /* sub-frame length is <= 10 ms */ + { + pTnsConfig->pTnsParameters = tnsParameters32kHz_grouped; + } + else + { + pTnsConfig->pTnsParameters = tnsParameters32kHz; + } + } + else + { + if (nSampleRate == 100 * frameLength) /* sub-frame length is <= 10 ms */ + { + pTnsConfig->nMaxFilters = sizeof(tnsParameters16kHz_grouped)/sizeof(tnsParameters16kHz_grouped[0]); + pTnsConfig->pTnsParameters = tnsParameters16kHz_grouped; + } + else + { + 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); + startLineFilter[iFilter] = (frameLength * 2 * pTnsConfig->pTnsParameters[iFilter].startLineFrequency) / nSampleRate; + } + if (igfStopFreq > 0) + { + pTnsConfig->iFilterBorders[0] = (frameLength * 2 * igfStopFreq) / nSampleRate; + } + else + { + pTnsConfig->iFilterBorders[0] = frameLength; + } + + return TNS_NO_ERROR; +} + +TNS_ERROR ApplyTnsFilter( + STnsConfig const * pTnsConfig, + STnsData const * pTnsData, + float spectrum[], + int fIsAnalysis) +{ + TLinearPredictionFilter filter; + float state[TNS_MAX_FILTER_ORDER]; + int iFilter; + int stopLine, startLine; + short int const * pBorders; + filter = fIsAnalysis ? FIRLattice : IIRLattice; + set_f(state, 0, TNS_MAX_FILTER_ORDER); + pBorders = pTnsConfig->iFilterBorders; + for (iFilter = pTnsConfig->nMaxFilters-1; iFilter >= 0; iFilter--) + { + float parCoeff[TNS_MAX_FILTER_ORDER]; + STnsFilter const * const pFilter = &pTnsData->filter[iFilter]; + + set_f( parCoeff, 0, TNS_MAX_FILTER_ORDER ); /* WMOPS: Initialization for safety and thus not to be counted */ + 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]); + + } + return (pTnsData->nFilters < 0) ? TNS_FATAL_ERROR : TNS_NO_ERROR; +} + +/*********************************************************************************************/ +/* Definitions of functions used in the mapping between TNS parameters and a bitstream. */ +/*********************************************************************************************/ + +/* Helper functions for hufmann table coding */ + +/** Get number of bits from a Huffman table. + * The table must be sorted by values. + */ +static int GetBitsFromTable(int value, const Coding codes[], int nSize) +{ + (void)nSize; + assert((value >= 0) && (value < nSize) && (nSize >= 0) && (nSize <= 256)); + return codes[value].nBits; +} + +/** Get the code for a value from a Huffman table. + * The table must be sorted by values. + */ +static int EncodeUsingTable(int value, const Coding codes[], int nSize) +{ + (void)nSize; + assert((value >= 0) && (value < nSize) && (nSize >= 0) && (nSize <= 256)); + return codes[value].code; +} + +/** Decode a value from a bitstream using a Huffman table. */ +static int DecodeUsingTable(Decoder_State *st, int * pValue, const Coding codes[], int nSize) +{ + unsigned short int code = 0; + unsigned char nBits = 0; + unsigned char valueIndex = nSize; + + assert((nSize >= 0) && (nSize <= 256)); + /* Variable initialization. All are required! */ + while (valueIndex == nSize) + { + code = (code << 1) + (unsigned short int)get_next_indice(st, 1); + ++nBits; + if (nBits > nSize || nBits > 16) + { + st->BER_detect = 1; + *pValue = 0; + return -1; + } + for (valueIndex = 0; valueIndex < nSize; valueIndex++) + { + if (codes[valueIndex].nBits == nBits) + { + if (codes[valueIndex].code == code) + break; + } + } + /* Loop condition */ + } + + if (valueIndex < nSize) + { + *pValue = codes[valueIndex].value; + } + else + { + st->BER_detect = 1; + *pValue = 0; + return -1; + } + + return nBits; +} + +/* TNS filter coefficients */ + +void const * GetTnsFilterCoeff(void const * p, int index, int * pValue) +{ + *pValue = ((int const *)p)[index] + INDEX_SHIFT; + return NULL; +} + +void * SetTnsFilterCoeff(void * p, int index, int value) +{ + ((int *)p)[index] = value - INDEX_SHIFT; + return NULL; +} + +int GetSWBTCX20TnsFilterCoeffBits(int value, int index) +{ + assert((index >= 0) && (index < nTnsCoeffTables)); + return GetBitsFromTable(value, codesTnsCoeffSWBTCX20[index], nTnsCoeffCodes); +} + +int EncodeSWBTCX20TnsFilterCoeff(int value, int index) +{ + assert((index >= 0) && (index < nTnsCoeffTables)); + return EncodeUsingTable(value, codesTnsCoeffSWBTCX20[index], nTnsCoeffCodes); +} + +int DecodeSWBTCX20TnsFilterCoeff(Decoder_State *st, int index, int * pValue) +{ + assert((index >= 0) && (index < nTnsCoeffTables)); + return DecodeUsingTable(st, pValue, codesTnsCoeffSWBTCX20[index], nTnsCoeffCodes); +} + +int GetSWBTCX10TnsFilterCoeffBits(int value, int index) +{ + assert((index >= 0) && (index < nTnsCoeffTables)); + return GetBitsFromTable(value, codesTnsCoeffSWBTCX10[index], nTnsCoeffCodes); +} + +int EncodeSWBTCX10TnsFilterCoeff(int value, int index) +{ + assert((index >= 0) && (index < nTnsCoeffTables)); + return EncodeUsingTable(value, codesTnsCoeffSWBTCX10[index], nTnsCoeffCodes); +} + +int DecodeSWBTCX10TnsFilterCoeff(Decoder_State *st, int index, int * pValue) +{ + assert((index >= 0) && (index < nTnsCoeffTables)); + return DecodeUsingTable(st, pValue, codesTnsCoeffSWBTCX10[index], nTnsCoeffCodes); +} + +int GetWBTCX20TnsFilterCoeffBits(int value, int index) +{ + assert((index >= 0) && (index < nTnsCoeffTables)); + return GetBitsFromTable(value, codesTnsCoeffWBTCX20[index], nTnsCoeffCodes); +} + +int EncodeWBTCX20TnsFilterCoeff(int value, int index) +{ + assert((index >= 0) && (index < nTnsCoeffTables)); + return EncodeUsingTable(value, codesTnsCoeffWBTCX20[index], nTnsCoeffCodes); +} + +int DecodeWBTCX20TnsFilterCoeff(Decoder_State *st, int index, int * pValue) +{ + assert((index >= 0) && (index < nTnsCoeffTables)); + return DecodeUsingTable(st, pValue, codesTnsCoeffWBTCX20[index], nTnsCoeffCodes); +} + + +/* TNS filter order */ + +void const * GetTnsFilterOrder(void const * p, int index, int * pValue) +{ + *pValue = ((STnsFilter const *)p)[index].order; + return ((STnsFilter const *)p)[index].coefIndex; +} + +void * SetTnsFilterOrder(void * p, int index, int value) +{ + ((STnsFilter *)p)[index].order = value; + return ((STnsFilter *)p)[index].coefIndex; +} + +int GetTnsFilterOrderBitsSWBTCX20(int value, int index) +{ + (void)index; + return GetBitsFromTable(value-1, codesTnsOrderTCX20, nTnsOrderCodes); +} + +int EncodeTnsFilterOrderSWBTCX20(int value, int index) +{ + (void)index; + return EncodeUsingTable(value-1, codesTnsOrderTCX20, nTnsOrderCodes); +} + +int DecodeTnsFilterOrderSWBTCX20(Decoder_State *st, int index, int * pValue) +{ + (void)index; + return DecodeUsingTable(st, pValue, codesTnsOrderTCX20, nTnsOrderCodes); +} + +int GetTnsFilterOrderBitsSWBTCX10(int value, int index) +{ + (void)index; + return GetBitsFromTable(value-1, codesTnsOrderTCX10, nTnsOrderCodes); +} + +int EncodeTnsFilterOrderSWBTCX10(int value, int index) +{ + (void)index; + return EncodeUsingTable(value-1, codesTnsOrderTCX10, nTnsOrderCodes); +} + +int DecodeTnsFilterOrderSWBTCX10(Decoder_State *st, int index, int * pValue) +{ + (void)index; + return DecodeUsingTable(st, pValue, codesTnsOrderTCX10, nTnsOrderCodes); +} + +int GetTnsFilterOrderBits(int value, int index) +{ + (void)index; + return GetBitsFromTable(value-1, codesTnsOrder, nTnsOrderCodes); +} + +int EncodeTnsFilterOrder(int value, int index) +{ + (void)index; + return EncodeUsingTable(value-1, codesTnsOrder, nTnsOrderCodes); +} + +int DecodeTnsFilterOrder(Decoder_State *st, int index, int * pValue) +{ + (void)index; + return DecodeUsingTable(st, pValue, codesTnsOrder, nTnsOrderCodes); +} + +/* Number of TNS filters */ + +void const * GetNumOfTnsFilters(void const * p, int index, int * pValue) +{ + *pValue = ((STnsData const *)p)[index].nFilters; + return ((STnsData const *)p)[index].filter; +} + +void * SetNumOfTnsFilters(void * p, int index, int value) +{ + ((STnsData *)p)[index].nFilters = value; + return ((STnsData *)p)[index].filter; +} + +/* TNS enabled/disabled flag */ + +void const * GetTnsEnabled(void const * p, int index, int * pValue) +{ + *pValue = ((STnsData const *)p)[index].nFilters > 0 ? 1 : 0; + return NULL; +} + +void * SetTnsEnabled(void * p, int index, int value) +{ + (void)p,(void)index,(void)value; + return NULL; +} + +void const * GetTnsEnabledSingleFilter(void const * p, int index, int * pValue) +{ + *pValue = ((STnsData const *)p)[index].nFilters > 0 ? 1 : 0; + return ((STnsData const *)p)[index].filter; +} + +void * SetTnsEnabledSingleFilter(void * p, int index, int value) +{ + ((STnsData *)p)[index].nFilters = value; + return ((STnsData *)p)[index].filter; +} + +/********************************/ +/* Private functions */ +/********************************/ + +void ResetTnsData(STnsData * pTnsData) +{ + unsigned int iFilter; + + pTnsData->nFilters = 0; + for (iFilter = 0; iFilter < sizeof(pTnsData->filter)/sizeof(pTnsData->filter[0]); iFilter++) + { + STnsFilter * const pTnsFilter = &pTnsData->filter[iFilter]; + pTnsFilter->spectrumLength = 0; + pTnsFilter->predictionGain = 1.0f; + pTnsFilter->avgSqrCoef = 0; + ClearTnsFilterCoefficients(pTnsFilter); + } + +} + +void ClearTnsFilterCoefficients(STnsFilter * pTnsFilter) +{ + pTnsFilter->order = 0; + set_i(pTnsFilter->coefIndex, 0, (int)sizeof(pTnsFilter->coefIndex)/(int)sizeof(pTnsFilter->coefIndex[0])); +} + +static void Index2Parcor(const int index[], float parCoeff[], int order) +{ + float const * values = tnsCoeff4; + int i; + for (i = 0; i < order; i++) + { + parCoeff[i] = values[index[i] + INDEX_SHIFT]; + } + +} + +static float FIRLattice(int order, const float *parCoeff, float *state, float x) +{ + int i; + float tmpSave; + tmpSave = x; + for (i = 0; i < order-1; i++) + { + float const tmp = parCoeff[i] * x + state[i]; + /* Variable initialization */ + x += parCoeff[i] * state[i]; + state[i] = tmpSave; + tmpSave = tmp; + } + + /* last stage: only need half operations */ + x += parCoeff[order-1] * state[order-1]; + state[order-1] = tmpSave; + return x; +} + +static float IIRLattice(int order, const float *parCoeff, float *state, float x) +{ + int i; + /* first stage: no need to calculate state[order-1] */ + x -= parCoeff[order-1] * state[order-1]; + for (i = order-2; i >= 0; i--) + { + x -= parCoeff[i] * state[i]; + state[i+1] = parCoeff[i] * x + state[i]; + } + + state[0] = x; + return x; +} + +static void TnsFilter(float const spectrum[], int numOfLines, + float const parCoeff[], int order, + TLinearPredictionFilter filter, float * state, + float output[]) +{ + int j; + + assert((order >= 0) && (order <= TNS_MAX_FILTER_ORDER)); + assert((numOfLines > 0) || ((numOfLines == 0) && (order == 0))); + if (order == 0) + { + if ((spectrum != output) && (numOfLines > 0)) + { + mvr2r(spectrum, output, numOfLines); + } + } + else + { + { + for (j = 0; j < numOfLines; j++) + { + output[j] = filter(order, parCoeff, state, spectrum[j]); + } + } + } +} + + +static void ITF_TnsFilter(float const spectrum[], int numOfLines, + const float A[], int order, + float output[]) +{ + int j; + assert((order >= 0) && (order <= ITF_MAX_FILTER_ORDER)); + assert((numOfLines > 0) || ((numOfLines == 0) && (order == 0))); + if (order == 0) + { + if ((spectrum != output) && (numOfLines > 0)) + { + mvr2r(spectrum, output, numOfLines); + } + } + else + { + int i; + float buf[ITF_MAX_FILTER_ORDER + N_MAX]; + float* p = buf + ITF_MAX_FILTER_ORDER; + set_f(buf, 0, ITF_MAX_FILTER_ORDER); + mvr2r(spectrum, p, numOfLines); + for (j = 0; j < numOfLines; j++, p++) + { + output[j] = p[0]; + for (i = 1; i < order; i++) + { + output[j] += A[i] * p[-i]; + } + } + } +} + + + +/*********************************************************************************************/ +/* Definitions of functions used in the mapping between TNS parameters and a bitstream. */ +/*********************************************************************************************/ + +/* Helper functions for hufmann table coding */ + +/********************************/ +/* Private functions */ +/********************************/ + +/** Autocorrelation to parcor coefficients. + * Conversion of autocorrelation to parcor/reflection coefficients. + * @param input Autocorrelation function/coefficients. + * @param parCoeff output filter (PARCOR) coefficients. + * @param order filter order. + * @return prediction gain. + */ +static float ITF_AutoToLPcoef(const float input[], float a[], int order) +{ + int i, j; + float tmp, tmp2; + float workBuffer[2*ITF_MAX_FILTER_ORDER]; + float parCoeff[ITF_MAX_FILTER_ORDER]; + float * const pWorkBuffer = &workBuffer[order]; /* temp pointer */ /* WMOPS: No need for counting as it can be realized as a separate buffer */ + + for(i=0; i HLM_MIN_NRG); iSubdivisions++) + { + float const fac = 1.0f/norms[iSubdivisions]; + int const iStartLine = idx0 + spectrumLength*iSubdivisions/nSubdivisions; + int const iEndLine = idx0 + spectrumLength*(iSubdivisions+1)/nSubdivisions; + float const * pWindow = tnsAcfWindow; + float const * pEndWindowCoeff = &tnsAcfWindow[sizeof(tnsAcfWindow)/sizeof(tnsAcfWindow[0])]; /* WMOPS: Not counted as it is used only in the assertion */ + int lag; + (void)pEndWindowCoeff; + /* For additional loop condition */ + /* Variable initialization */ + for (lag = 1; lag <= maxOrder; lag++) + { + rxx[lag] += fac * (*pWindow) * Autocorrelation(pSpectrum+iStartLine-IGF_START_MN, iEndLine-iStartLine, lag); + pWindow++; + } + } + *predictionGain = 0; + if (iSubdivisions == nSubdivisions) /* meaning there is no subdivision with low energy */ + { + rxx[0] = (float)nSubdivisions; + + /* Limit the maximum order to spectrum length/4 */ + *predictionGain = ITF_AutoToLPcoef(rxx, A, min(maxOrder, spectrumLength/4) ); + + *curr_order = maxOrder; + } + } + + return 1; +} diff --git a/lib_com/tools.c b/lib_com/tools.c new file mode 100644 index 000000000..88f6742de --- /dev/null +++ b/lib_com/tools.c @@ -0,0 +1,1479 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include +#include +#include "options.h" +#include "prot.h" + + +/*------------------------------------------------------------------* + * own_random() + * + * Random generator + *------------------------------------------------------------------*/ + +short own_random( /* o : output random value */ + short *seed /* i/o: random seed */ +) +{ + *seed = (short) (*seed * 31821L + 13849L); + + return(*seed); +} + +/*--------------------------------------------------------------------- + * sign() + * + *---------------------------------------------------------------------*/ + +float sign( /* o : sign of x (+1/-1) */ + const float x /* i : input value of x */ +) +{ + if (x < 0.0f) + { + return -1.0f; + } + else + { + return 1.0f; + } +} + +/*--------------------------------------------------------------------- + * log2_f() + * + *---------------------------------------------------------------------*/ + +float log2_f( /* o : logarithm2 of x */ + const float x /* i : input value of x */ +) +{ + return (float)(log(x)/log(2.0f)); +} + +short norm_ul( unsigned int UL_var1) +{ + short var_out; + + if (UL_var1 == 0) + { + var_out = 0; + } + else + { + for (var_out = 0; UL_var1 < (unsigned int) 0x80000000U; var_out++) + { + UL_var1 <<= 1; + } + } + BASOP_CHECK(); + return (var_out); +} + + + + + +/*--------------------------------------------------------------------- + * sum_s() + * sum_f() + * + *---------------------------------------------------------------------*/ + +short sum_s( /* o : sum of all vector elements */ + const short *vec, /* i : input vector */ + const short lvec /* i : length of input vector */ +) +{ + short i; + short tmp; + + tmp = 0; + for( i=0; i= 0; i--) + { + y[i] = x[i]; + } + } + + return; +} + +void mvs2s( + const short x[], /* i : input vector */ + short y[], /* o : output vector */ + const short n /* i : vector size */ +) +{ + short i; + + if ( n <= 0 ) + { + /* cannot transfer vectors with size 0 */ + return; + } + + if (y < x) + { + for (i = 0; i < n; i++) + { + y[i] = x[i]; + } + } + else + { + for (i = n-1; i >= 0; i--) + { + y[i] = x[i]; + } + } + + return; +} + +unsigned int mvr2s( + const float x[], /* i : input vector */ + short y[], /* o : output vector */ + const short n /* i : vector size */ +) +{ + short i; + float temp; + unsigned int noClipping = 0; + + if ( n <= 0 ) + { + /* cannot transfer vectors with size 0 */ + return 0; + } + + if ((void*)y < (const void*)x) + { + for (i = 0; i < n; i++) + { + temp = x[i]; + temp = (float)floor(temp + 0.5f); + + if (temp > 32767.0f ) + { + temp = 32767.0f; + noClipping++; + } + else if (temp < -32768.0f ) + { + temp = -32768.0f; + noClipping++; + } + + y[i] = (short)temp; + } + } + else + { + for (i = n-1; i >= 0; i--) + { + temp = x[i]; + temp = (float)floor(temp + 0.5f); + + if (temp > 32767.0f ) + { + temp = 32767.0f; + noClipping++; + } + else if (temp < -32768.0f ) + { + temp = -32768.0f; + noClipping++; + } + + y[i] = (short)temp; + } + } + + return noClipping; +} + +void mvs2r( + const short x[], /* i : input vector */ + float y[], /* o : output vector */ + const short n /* i : vector size */ +) +{ + short i; + + if ( n <= 0 ) + { + /* cannot transfer vectors with size 0 */ + return; + } + + if ((void*)y < (const void*)x) + { + for (i = 0; i < n; i++) + { + y[i] = (float)x[i]; + } + } + else + { + for (i = n-1; i >= 0; i--) + { + y[i] = (float)x[i]; + } + } + + return; +} + + +void mvi2i( + const int x[], /* i : input vector */ + int y[], /* o : output vector */ + const int n /* i : vector size */ +) +{ + int i; + + if ( n <= 0 ) + { + /* no need to transfer vectors with size 0 */ + return; + } + + if (y < x) + { + for (i = 0; i < n; i++) + { + y[i] = x[i]; + } + } + else + { + for (i = n-1; i >= 0; i--) + { + y[i] = x[i]; + } + } + + return; +} + +/*---------------------------------------------------------------------* + * maximum() + * + * Find index and value of the maximum in a vector + *---------------------------------------------------------------------*/ + +short maximum( /* o : index of the maximum value in the input vector */ + const float *vec, /* i : input vector */ + const short lvec, /* i : length of input vector */ + float *max /* o : maximum value in the input vector */ +) +{ + short j, ind; + float tmp; + + ind = 0; + tmp = vec[0]; + + for ( j=1; j tmp ) + { + ind = j; + tmp = vec[j]; + } + } + + if ( max != 0 ) + { + *max = tmp; + } + + return ind; +} + +/*---------------------------------------------------------------------* + * minimum() + * + * Find index of a minimum in a vector + *---------------------------------------------------------------------*/ + +short minimum( /* o : index of the minimum value in the input vector */ + const float *vec, /* i : input vector */ + const short lvec, /* i : length of input vector */ + float *min /* o : minimum value in the input vector */ +) +{ + short j, ind; + float tmp; + + ind = 0; + tmp = vec[0]; + + for ( j=1 ; j *ener_max ) + { + ind = j; + *ener_max = temp; + } + } + + return ind; +} + + +/*---------------------------------------------------------------------* + * mean() + * + * Find the mean of the vector + *---------------------------------------------------------------------*/ + +float mean( /* o : mean of vector */ + const float *vec, /* i : input vector */ + const short lvec /* i : length of input vector */ +) +{ + float tmp; + + tmp = sum_f( vec, lvec ) / (float)lvec; + + return tmp; +} + +/*---------------------------------------------------------------------* + * dotp() + * + * Dot product of vector x[] and vector y[] + *---------------------------------------------------------------------*/ + +float dotp( /* o : dot product of x[] and y[] */ + const float x[], /* i : vector x[] */ + const float y[], /* i : vector y[] */ + const short n /* i : vector length */ +) +{ + short i; + float suma; + + suma = x[0] * y[0]; + + for(i=1; i= 0; d--) + { + tmp = x[d] - cb[j++]; + dist += weights[d]*(tmp*tmp); + } + + if (dist < mindist) + { + mindist = dist; + idx = c; + } + } + + if (xq == 0) + { + return idx; + } + + j = idx*dim; + for ( d = k; d >= 0; d--) + { + xq[d] = cb[j++]; + } + } + else + { + for ( c = 0; c < cbsize; c++) + { + dist = 0.0f; + + for( d = 0; d < dim; d++) + { + tmp = x[d] - cb[j++]; + dist += weights[d]*(tmp*tmp); + } + + if (dist < mindist) + { + mindist = dist; + idx = c; + } + } + + if (xq == 0) + { + return idx; + } + + j = idx*dim; + for ( d = 0; d < dim; d++) + { + xq[d] = cb[j++]; + } + } + + if (x_mean != 0) + { + for( d = 0; d < dim; d++) + { + xq[d] += x_mean[d]; + } + } + + return idx; +} + + +/*----------------------------------------------------------------------------------* + * v_sort() + * + * Sorting of vectors. This is very fast with almost ordered vectors. + *----------------------------------------------------------------------------------*/ + +void v_sort( + float *r, /* i/o: Vector to be sorted in place */ + const short lo, /* i : Low limit of sorting range */ + const short up /* I : High limit of sorting range */ +) +{ + short i, j; + float tempr; + + for ( i=up-1; i>=lo; i-- ) + { + tempr = r[i]; + for ( j=i+1; j<=up && (tempr>r[j]); j++ ) + { + r[j-1] = r[j]; + } + + r[j-1] = tempr; + } + + return; +} + +/*---------------------------------------------------------------------* + * var() + * + * Calculate the variance of a vector + *---------------------------------------------------------------------*/ + +float var( /* o: variance of vector */ + const float *x, /* i: input vector */ + const int len /* i: length of inputvector */ +) +{ + float m; + float v; + short i; + + m = mean(x, (const short)len); + + v = 0.0f; + for (i = 0; i < len; i++) + { + v += (x[i] - m)*(x[i] - m); + } + v /= len; + + return v; +} + + +/*---------------------------------------------------------------------* + * std_dev() + * + * Calculate the standard deviation of a vector + *---------------------------------------------------------------------*/ + +float std_dev( /* o: standard deviation */ + const float *x, /* i: input vector */ + const int len /* i: length of the input vector */ +) +{ + short i; + float std; + + std = 1e-16f; + for( i = 0; i < len; i++) + { + std += x[i] * x[i]; + } + + std = (float)sqrt( std / len ); + + return std; +} + + + +/*---------------------------------------------------------------------* + * dot_product_mat() + * + * Calculates dot product of type x'*A*x, where x is column vector of size m, + * and A is square matrix of size m*m + *---------------------------------------------------------------------*/ + +float dot_product_mat( /* o : the dot product x'*A*x */ + const float *x, /* i : vector x */ + const float *A, /* i : matrix A */ + const short m /* i : vector & matrix size */ +) +{ + short i,j; + float suma, tmp_sum; + const float *pt_x, *pt_A; + + pt_A = A; + suma = 0; + + for(i=0; i 1.0) + { + mod_a /= 2.0; + shift_a--; + } + + while (mod_a < 0.5) + { + mod_a *= 2.0; + shift_a++; + } + +#undef WMC_TOOL_SKIP + + shift_a &= 0xfffe; + mod_a = fleft_shift(a, (int) shift_a); + + approx = 0.27f + 1.0127f * mod_a - 0.2864f * mod_a * mod_a; + + approx = fright_shift(approx, (int) (shift_a >> 1)); + + return (approx); +} + +/*--------------------------------------------------------------------------------* + * root_a_over_b() + * + * Implements an approximation to sqrt(a/b) + * Firstly a & b are normalized to lie between 0.25 & 1.0 + * by shifting the inputs left or right by an even number + * of shifts. + * Even shifts represent powers of 4 which, after the sqrt, + * become powers of 2 and are easily dealt with. + * At the heart of the algorithm is an approximation of the + * curve sqrt(a/b) for 0.25 <= a <= 1.0 & 0.25 <= b <= 1.0. + * Given the value of b, the 2nd order coefficients p0, p1 + * & p2 can be determined so that... + * Sqrt(a/b) approx = p0 + p1 * a + p2 * a^2 + * where p0 approx = 0.7176 - 0.8815 * b + 0.4429 * b^2 + * p1 approx = 2.6908 - 3.3056 * b + 1.6608 * b^2 + * p2 approx = -0.7609 + 0.9346 * b - 0.4695 * b^2 + * + *---------------------------------------------------------------------------------*/ + +float root_a_over_b(float a, float b) +{ + short int shift_a, shift_b, shift; + float mod_a, mod_b; + float p2 = -0.7609f; + float p1 = 2.6908f; + float p0 = 0.7176f; + float b_sqr; + float approx; + +#define WMC_TOOL_SKIP + if ((a <= 0.0f) || (b <= 0.0f)) +#undef WMC_TOOL_SKIP + { + return 0.0; + } +#define WMC_TOOL_SKIP + if ( isinf(a) ) +#undef WMC_TOOL_SKIP + { + return FLT_MAX; + } +#define WMC_TOOL_SKIP + if ( isinf(b) ) +#undef WMC_TOOL_SKIP + { + return 0.f; + } + + a += 0x00000001; + b += 0x00000001; + +#define WMC_TOOL_SKIP + /* This next piece of code implements a "norm" function */ + /* and returns the shift needed to scale "a" to have a */ + /* 1 in the (MSB-1) position. This is equivalent to */ + /* giving a value between 0.5 & 1.0. */ + mod_a = a; + + shift_a = 0; + while (mod_a > 1.0) + { + mod_a /= 2.0; + shift_a--; + } + + while (mod_a < 0.5) + { + mod_a *= 2.0; + shift_a++; + } +#undef WMC_TOOL_SKIP + + shift_a &= 0xfffe; + mod_a = fleft_shift(a, (int) shift_a); + +#define WMC_TOOL_SKIP + /* This next piece of code implements a "norm" function */ + /* and returns the shift needed to scale "b" to have a */ + /* 1 in the (MSB-1) position. This is equivalent to */ + /* giving a value between 0.5 & 1.0. */ + mod_b = b; + + shift_b = 0; + while (mod_b > 1.0) + { + mod_b /= 2.0; + shift_b--; + } + + while (mod_b < 0.5) + { + mod_b *= 2.0; + shift_b++; + } +#undef WMC_TOOL_SKIP + + shift_b &= 0xfffe; + mod_b = fleft_shift(b, (int) shift_b); + + shift = (shift_b - shift_a) >> 1; + + b_sqr = mod_b * mod_b; + + p2 += 0.9346f * mod_b + -0.4695f * b_sqr; + p1 += -3.3056f * mod_b + 1.6608f * b_sqr; + p0 += -0.8815f * mod_b + 0.4429f * b_sqr; + + approx = p0 + p1 * mod_a + p2 * mod_a * mod_a; + + approx = fleft_shift(approx, (int) shift); + + return (approx); +} + +/*--------------------------------------------------------------------------------* + * rint_new() + * + * Round to the nearest integer with mid-point exception + *---------------------------------------------------------------------------------*/ + +double rint_new( + double x +) +{ + int a; + + /* middle value point test */ + if (ceil (x + 0.5) == floor (x + 0.5)) + { + a = (int) ceil (x); + + if (a % 2 == 0) + { + return ceil (x); + } + else + { + return floor (x); + } + } + else + { + return floor (x + 0.5); + } +} + + +/*-------------------------------------------------------------------* + * anint() + * + * Round to the nearest integer. + *-------------------------------------------------------------------*/ + +double anint( + double x +) +{ + return (x)>=0?(int)((x)+0.5):(int)((x)-0.5); +} + +/*-------------------------------------------------------------------* + * is_numeric_float() + * + * Returns 0 for all NaN and Inf values defined according to IEEE 754 + * floating point number's definition. Returns 1 for numeric values. + *-------------------------------------------------------------------*/ +short is_numeric_float( + float x +) +{ + union float_int + { + float float_val; + int int_val; + } float_int; + float_int.float_val=x; + return ((float_int.int_val & 0x7f800000) != 0x7f800000); +} diff --git a/lib_com/trans_direct.c b/lib_com/trans_direct.c new file mode 100644 index 000000000..4a3a84bf7 --- /dev/null +++ b/lib_com/trans_direct.c @@ -0,0 +1,142 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + + +/*------------------------------------------------------------------- + * direct_transform() + * + * Transformation of the signal to DCT domain + *-------------------------------------------------------------------*/ + +void direct_transform( + const float *in32, /* i : input signal */ + float *out32, /* o : transformation */ + const short is_transient, /* i : is transient */ + const short L /* i : length */ +) +{ + short i; + short seg; + short segment_length; + + const float *wh; + const float *wl; + float *sh; + float *sl; + float *iseg; + float *oseg; + float dctin32[L_FRAME48k]; + float in32_r16[L_FRAME48k]; + + const float *win; + + + segment_length = L/2; + + if (is_transient) + { + if (L == L_FRAME48k) + { + win = wscw16q15; + } + else if (L == L_FRAME32k) + { + win = wscw16q15_32; + } + else if (L == L_FRAME8k) + { + win = wscw16q15_8; + } + else + { + win = wscw16q15_16; + } + + for (i = 0; i < L/2; i++) + { + in32_r16[i] = in32[L-1-i]; + in32_r16[L-1-i] = in32[i]; + } + iseg = in32_r16 - segment_length/4; + oseg = out32; + + wh = win + segment_length/4; + wl = win + segment_length/4 - 1; + sh = iseg + 3*segment_length/4; + sl = iseg + 3*segment_length/4 - 1; + for (i = 0; i < segment_length/4; i++) + { + dctin32[i] = ((*wl-- **sl--) - (*wh++ **sh++)); + } + + sl = iseg + segment_length/2 - 1; + + for (i = 0; i < segment_length/4; i++) + { + dctin32[segment_length/4 + i] = -(*sl--); + } + + edct(dctin32, oseg, segment_length/2); + + iseg = iseg + segment_length/2; + oseg = oseg + segment_length/2; + + for (seg = 1 ; seg < NUM_TIME_SWITCHING_BLOCKS-1; seg++) + { + wh = win + segment_length/4; + wl = win + segment_length/4 - 1; + sh = iseg + 3*segment_length/4; + sl = iseg + 3*segment_length/4 - 1; + for (i = 0; i < segment_length/4; i++) + { + dctin32[i] = ((*wl-- **sl--) - (*wh++ **sh++)); + } + + sh = iseg; + sl = iseg + segment_length/2 - 1; + wh = win + segment_length/2 - 1; + wl = win + 0; + + for (i = 0; i < segment_length/4; i++) + { + dctin32[segment_length/4 + i] = ((*wl++ **sl--) + (*wh-- **sh++)); + } + + edct(dctin32, oseg, segment_length/2); + + iseg = iseg + segment_length/2; + oseg = oseg + segment_length/2; + } + + sh = iseg + 3*segment_length/4 - 1; + for (i = 0; i < segment_length /4; i++) + { + dctin32[i] = -(*sh--); + } + + sh = iseg; + sl = iseg + segment_length/2 - 1; + wh = win + segment_length/2 - 1; + wl = win + 0; + + for (i = 0; i < segment_length/4; i++) + { + dctin32[segment_length/4 + i] = ((*wh-- **sh++) + (*wl++ **sl--)); + } + + edct(dctin32, oseg, segment_length/2); + } + else + { + edct(in32, out32, L); + } + + return; +} diff --git a/lib_com/trans_inv.c b/lib_com/trans_inv.c new file mode 100644 index 000000000..5cf3ebd8a --- /dev/null +++ b/lib_com/trans_inv.c @@ -0,0 +1,862 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*--------------------------------------------------------------------------* + * Local constants + *--------------------------------------------------------------------------*/ + +#define NUMSF 8 +#define LOG2_NUMSF 3 +#define INV_NUMSF (float)0.125 + +/*--------------------------------------------------------------------------* + * preecho_sb() + * + * Time-domain sub-band based pre-echo reduction + *--------------------------------------------------------------------------*/ + +void preecho_sb( + const long brate, /* i : core bit-rate */ + const float wtda_audio[], /* i : imdct signal */ + float *rec_sig, /* i : reconstructed signal, output of the imdct transform */ + const short framelength, /* i : frame length */ + float *memfilt_lb, /* i/o: memory */ + float *mean_prev_hb, /* i/o: memory */ + float *smoothmem, /* i/o: memory */ + float *mean_prev, /* i/o: memory */ + float *mean_prev_nc, /* i/o: memory */ + float *wmold_hb, /* i/o: memory */ + short *prevflag, /* i/o: flag */ + short *pastpre, /* i/o: flag */ + const short bwidth +) +{ + short i, j, len3xLp20; + float es_mdct[9]; /* 0..3 (0..7): energy of the 4 (8) subframes, 4..5: (8..10) energy of the future subframes */ + float es_mdct_hb[9]; /* 0..3 (0..7): energy of the 4 (8) subframes, 4..5: (8..10) energy of the future subframes */ + short zcr[9]; /* 0..3 (0..7): zero crossing of the 4 (8) subframes, 4..5: (8..10) zero crossing of the future subframes */ + short maxnzcr[8], cntnzcr; /* max number of samples without zero crossing */ + float plus_es_mdct[64]; /* 8*8 subsubframes */ + float imdct_mem[L_FRAME48k]; /* memory of the imdct transform, used in the next frame */ + + short maxind, stind, stind_hb, cnt2, cnt5, adv, advmem; + short ind2, ind3, pluslim; + float max_es; + float *ptr; + float min_g[13], g, gt[13]; + float min_g_hb[13], gt_hb[13]; + float preechogain[960+PREECHO_SMOOTH_LEN]; + float preechogain_hb[960]; + short subframelength, subsubframelength; + float maxcrit, savehalfe, savehalfe_hb; + float rec_sig_lb[960], rec_sig_hb[960]; /* 960 max frame length at 48 kHz */ + float eshbmean2, eshbmean3, sxyhb2, sxylb3, sxyhb3; + float *fptr1, *fptr2, *fptr3, *fptr4, *fptr5, *fptr6; + short *sptr1, *sptr2; + float wmold; + float lim16, lim32; + short limzcr, limmaxnzcr; + float max_es_hb; + short num_subsubframes, log2_num_subsubframes; + float ftmp, fattnext; + float sum_plus_es, mean_plus_es[65]; + float last2, last2_hb; + float max_plus_es_mdct; + short nb_flag, smooth_len; + short firstnzcr; + float es_mdct_half[9]; + float es_mdct_quart[9]; + double invsmoothlenp1; /*double just to have bit-exactness with the previous version, otherwise rounding difference of +-1*/ + short subframelength_s2, subframelength_s34; + float oldgain, oldgain_hb; + + if( brate <= HQ_32k ) + { + nb_flag = 0; + if( bwidth == NB ) + { + nb_flag = 1; + } + + limzcr = 16; + smooth_len = 4; + invsmoothlenp1 = 0.2; + + if( nb_flag == 1 ) + { + limzcr = 10; + smooth_len = PREECHO_SMOOTH_LEN; + invsmoothlenp1 = INV_PREECHO_SMOOTH_LENP1; + } + + limmaxnzcr = framelength/24; + num_subsubframes = 8; + log2_num_subsubframes = 3; + + if( framelength == L_FRAME8k ) + { + num_subsubframes = 4; + log2_num_subsubframes = 2; + } + len3xLp20 = framelength/2-(short)((float)framelength*N_ZERO_MDCT_NS/FRAME_SIZE_NS); + for( i = 0; i < len3xLp20; i++ ) + { + imdct_mem[i] = -wtda_audio[len3xLp20 - 1 - i]; + } + + for( i = 0; i < framelength/2; i++ ) + { + imdct_mem[len3xLp20 + i] = -wtda_audio[i]; + } + + + subframelength = framelength >> LOG2_NUMSF; + subsubframelength = subframelength >> log2_num_subsubframes; + wmold = *smoothmem; + subframelength_s2 = subframelength/2; + subframelength_s34 = subframelength*3/4; + + cntnzcr = -1; + + lim16 = 0.1f; + lim32 = 0.01f; + savehalfe = 0.0f; + savehalfe_hb = 0.0f; + + if( *pastpre == 0 ) + { + /* if past frame mean energies are not known (no preecho_sb in the past frame), limit max attenuation to 1*/ + lim16 = (float)1; + lim32 = (float)1; + } + + *pastpre = 2; + fptr1 = rec_sig_lb; + fptr2 = rec_sig; + fptr3 = rec_sig + 1; + fptr4 = rec_sig + 2; + *fptr1 = (float)(0.25*(*memfilt_lb + *fptr3) + 0.5 * *fptr2); + fptr1++; + + for(j = 1; j < framelength - 1; j++) + { + *fptr1 = (float)(0.25*(*fptr2+*fptr4)+0.5* *fptr3); + fptr1++; + fptr2++; + fptr3++; + fptr4++; + } + + *fptr1 = (float)(0.25*(*fptr2)+0.5* *fptr3); + fptr1 = rec_sig_lb; + fptr2 = rec_sig; + fptr3 = rec_sig_hb; + + for(j = 0; j < framelength; j++) + { + *fptr3 = *fptr2 - *fptr1; + fptr1++; + fptr2++; + fptr3++; + } + + fptr2--; + *memfilt_lb = *fptr2; + + /* energy of low bands 8 present and 1 future sub-frames */ + fptr1 = es_mdct; + fptr5 = es_mdct_half; + fptr6 = es_mdct_quart; + fptr4 = es_mdct_hb; + fptr2 = rec_sig; + fptr3 = rec_sig_hb; + sptr1 = zcr; + *sptr1 = 0; + sptr2 = maxnzcr; + for (j = 0; j < NUMSF; j++) /* 8 present subframes */ + { + *fptr1 = 100 + *fptr2 **fptr2; + *fptr4 = 100 + *fptr3 **fptr3; + + *sptr2 = 0; + firstnzcr = 1; + if( j == 0 ) + { + firstnzcr = 0; + } + + fptr2++; + fptr3++; + + for (i = 1; i < subframelength; i++) + { + if( i == subframelength_s2 ) + { + *fptr5 = *fptr1; + } + + if( i == subframelength_s34 ) + { + *fptr6 = *fptr1; + } + *fptr1 += *fptr2 **fptr2; + *fptr4 += *fptr3 **fptr3; + cntnzcr++; + if( *fptr2 **(fptr2-1) < 0 ) + { + (*sptr1)++; + if(cntnzcr > *sptr2) + { + *sptr2 = cntnzcr; + } + + if( (firstnzcr > 0) && (cntnzcr > maxnzcr[j-1]) ) + { + maxnzcr[j-1] = cntnzcr; + } + + firstnzcr = 0; + cntnzcr = -1; + } + fptr2++; + fptr3++; + } + + if(cntnzcr > *sptr2) + { + *sptr2 = cntnzcr; + } + fptr4++; + sptr1++; + sptr2++; + + if( (firstnzcr > 0) && (cntnzcr > maxnzcr[j-1]) ) + { + maxnzcr[j-1] = cntnzcr; + } + + *sptr1 = 0; + if((j < NUMSF-1) && ((*fptr2 **(fptr2-1) < 0))) /* zcr between 2 subframes */ + { + (*sptr1)++; /* counts for the nexte subframe */ + cntnzcr = -1; + } + + if( *fptr5 < (*fptr1)/2 ) + { + *fptr5 = 2*(*fptr1 - *fptr5); + } + else + { + *fptr5 = *fptr1; + } + fptr1++; + fptr5++; + fptr6++; + } + + fptr2 = imdct_mem; + j = NUMSF; + *fptr1 = 100 + *fptr2 **fptr2; + *sptr1 = 0; + fptr2++; + for (i = 1; i < len3xLp20; i++) /* one future subframe but 140 samples (not 80) (enough with ALDO window) */ + { + *fptr1 += *fptr2 **fptr2; + + if(*fptr2 **(fptr2-1) < 0) + { + (*sptr1)++; + } + + fptr2++; + } + + fptr2 = imdct_mem; + fptr3 = imdct_mem + 1; + fptr4 = imdct_mem + 2; + ftmp = (float)(-0.25*(rec_sig[framelength-1] + *fptr3) + 0.5 * *fptr2); + es_mdct_hb[NUMSF] = 100 + ftmp * ftmp; + + for(j = 1; j < len3xLp20 - 1; j++) + { + ftmp = (float)(-0.25*(*fptr2+*fptr4)+0.5* *fptr3); + es_mdct_hb[NUMSF] += ftmp * ftmp; + fptr2++; + fptr3++; + fptr4++; + } + + ftmp = (float)(-0.25*(*fptr2)+0.5* *fptr3); + es_mdct_hb[NUMSF] += ftmp * ftmp; + max_es_hb = es_mdct_hb[0]; /* for memorising the max energy */ + + max_es = es_mdct[0]; /* for memorising the max energy */ + maxind = 0; + for (i = 1; i <= NUMSF; i++) + { + if (es_mdct_hb[i] >= max_es_hb) /* '=' to handle the first window*/ + { + max_es_hb = es_mdct_hb[i]; /* max energy low band, 8 present and 1 future subframes */ + } + + if (es_mdct[i] >= max_es) /* '=' to handle the first window*/ + { + max_es = es_mdct[i]; /* max energy low band, 8 present and 1 future subframes */ + maxind = i; + } + } + + cnt2 = cnt5 = 0; + if( *prevflag != 0 || max_es < subframelength * 10000 ) + { + maxind = 0; + } + + if( max_es < 4 * *mean_prev ) + { + maxind = 0; + } + *prevflag = 0; + + for (i = 0; i < maxind; i++) /* only subbands before max energy subband are handled */ + { + g = 1; /* default gain */ + min_g[i] = 1; + min_g_hb[i] = 1; + if( (es_mdct_half[i] > 100*(*mean_prev_nc+500000)) || /* less then 20% energy in 3/4 of the subframe -> starting onset in the last quarter */ + ((es_mdct_half[i] > 10*(*mean_prev_nc+500000)) && + ((zcr[i] < limzcr) || (es_mdct_quart[i] < es_mdct[i]/6)) )) /* already an offset, plosif, do not touch */ + { + maxind = i; /* no preecho reduction after the first subframe with gain 1 */ + *prevflag = 1; + for(j = i-1; j >= 0; j--) + { + if (es_mdct[j] > es_mdct[i] / 2) + { + maxind = j; + } + } + } + else + { + if (es_mdct[i] < max_es / 16) + { + g = lim16; + cnt5++; + + if (es_mdct[i] < max_es / 32) + { + g = lim32; + cnt2++; + } + + min_g[i] = (float)sqrt((double)(*mean_prev / es_mdct[i])); /*limitation of attenuation gain */ + min_g_hb[i] = (float)sqrt((double)(*mean_prev_hb / es_mdct_hb[i])); /*limitation of attenuation gain */ + if( (zcr[i] < limzcr/2) || (maxnzcr[i] > limmaxnzcr) ) + { + if(min_g[i] < 1) /* *mean_prev < es_mdct[i]) */ + { + *mean_prev = es_mdct[i]; + } + min_g[i] = 1; /* not noise-like, do not touch the amplitude, but may do in HB*/ + } + + if(min_g[i] > 1) /* in fix point will be min_g = min(min_g, 1), weight 1 */ + { + min_g[i] = (float)1; + } + + if(min_g_hb[i] > 1) /* in fix point will be min_g = min(min_g, 1), weight 1 */ + { + min_g_hb[i] = (float)1; + } + } + else + { + if( i > 0 && maxind < NUMSF ) + { + *prevflag = 1; + } + maxind = i; /* no preecho reduction after the first subframe with gain 1*/ + } + } + gt[i] = g; + gt_hb[i] = g; + } + + for ( i = maxind; i <= NUMSF; i++ ) /* also for the first memory subframe */ + { + gt[i] = 1; + min_g[i] = 1; + gt_hb[i] = 1; + min_g_hb[i] = 1; + + } + + ind2 = 0; + for( i = 0; i < NUMSF; i++ ) + { + if( gt[i] < 1 ) /*gt not yet limited by min_g*/ + { + ind2 = i+1; /* first subframe with gain = 1 after last gain < 1 --> frame with the attack*/ + } + } + + if( (wmold > 0.5) && ((cnt2+cnt5) < 2) ) /* mini either 1 cnt2 (and so also cnt5) or 2 cnt5 */ + { + /* maxind = 0; false alarm, no echo reduction */ + ind2 = 0; + } + + fptr3 = gt; + fptr4 = gt_hb; + fptr5 = min_g; + fptr6 = min_g_hb; + + for (i = 0; i < ind2; i++) /* only subbands before max energy subband are handled*/ + { + if(*fptr3 < *fptr5) /* in fix point will be g = max(g, min_g), weight 1 */ + { + *fptr3 = *fptr5; + } + + if(*fptr4 < *fptr6) /* in fix point will be g = max(g, min_g), weight 1 */ + { + *fptr4 = *fptr6; + } + + fptr1 = preechogain + i*subframelength+smooth_len; + fptr2 = preechogain_hb + i*subframelength; + for(j = 0; j < subframelength; j++) + { + *fptr1 = *fptr3; + *fptr2 = *fptr4; + fptr1++; + fptr2++; + } + + fptr3++; + fptr4++; + fptr5++; + fptr6++; + } + + max_plus_es_mdct = 0; + adv = smooth_len; /* samples needed to have near 1 gain after smoothing at the beggining of the attack subframe*/ + advmem = adv; + + if( ind2 > 0 || wmold < 1 || *wmold_hb < 1 ) + { + ptr = imdct_mem; + pluslim = num_subsubframes; /* if ind2 == NUMSF */ + + if( ind2 < NUMSF ) + { + ptr = rec_sig + subframelength*ind2; + pluslim = (NUMSF-ind2)*num_subsubframes; + } + + maxcrit = *mean_prev_nc; + if( ind2 == 0 ) + { + sum_plus_es = *mean_prev_nc; /* 8 times mean sususb enenrgy (=maxcrit)*/ + pluslim = num_subsubframes; + oldgain = wmold; + oldgain_hb = *wmold_hb; + } + else /* ind2 > 0*/ + { + sum_plus_es = es_mdct[ind2-1]; /* 8 times mean sususb enenrgy (=maxcrit)*/ + oldgain = gt[ind2-1]; + oldgain_hb = gt_hb[ind2-1]; + maxcrit = es_mdct[ind2-1]*gt[ind2-1]*gt[ind2-1]; /* /1 (iso /8) : 8 times of the pevious subframe mean*/ + + if( (max_es/80 > maxcrit) && (zcr[ind2] > limzcr) ) + { + maxcrit = max_es/80; /* still 10 times smaller then mean max_es*/ + } + } + + for (j = 0; j < pluslim; j++) /* 8 sub-subframes */ + { + plus_es_mdct[j] = 100; + for (i = 0; i < subsubframelength; i++) + { + + ftmp = *ptr **ptr; + plus_es_mdct[j] += ftmp; + if( plus_es_mdct[j] > max_plus_es_mdct ) + { + max_plus_es_mdct = plus_es_mdct[j]; + } + ptr++; + } + + sum_plus_es += 4 * plus_es_mdct[j]; + mean_plus_es[j+1] = sum_plus_es / (j+2); /* 4/j could be tabulated in fixed point */ + if( mean_plus_es[j+1] < maxcrit) + { + mean_plus_es[j+1] = maxcrit; + } + } + mean_plus_es[0] = plus_es_mdct[0]; + if( mean_plus_es[0] < maxcrit) + { + mean_plus_es[0] = maxcrit; + } + mean_plus_es[pluslim] = -1; + + j = 0; + while((plus_es_mdct[j] < mean_plus_es[j]) && (plus_es_mdct[j] < max_plus_es_mdct/8 )) + { + j++; + } + + adv -= j*subsubframelength; + + if( ind2 < NUMSF ) /* onset not in future frame */ + { + fptr1 = preechogain + ind2*subframelength+smooth_len; + fptr2 = preechogain_hb + ind2*subframelength; + + for (i = 0; i < j*subsubframelength; i++) + { + *fptr1 = oldgain; /*keep the gain of the previous subframe*/ + *fptr2 = oldgain_hb; /*keep the gain of the previous subframe*/ + fptr1++; + fptr2++; + } + } + } + + if( ind2 > 0 ) + { + /* check increasing energy of preecho by regression last 3 subframes (if possible) */ + ind3 = ind2 + (j >> log2_num_subsubframes); /* return (with rounding) to subframe basis */ + if( ind3 > 1 ) + { + /* case of 3 points is simply */ + eshbmean2 = es_mdct_hb[ind3-1] + es_mdct_hb[ind3-2]; + sxyhb2 = (es_mdct_hb[ind3 - 1] - es_mdct_hb[ind3 - 2]); /* / eshbmean2 * 2; 04042013: division not needed, only sign of sxyhb2 is used*/ + + if( ind3 > 2 ) + { + eshbmean3 = (eshbmean2 + es_mdct_hb[ind3-3]) / 3; + sxylb3 = (es_mdct[ind3 - 1] - es_mdct[ind3 - 3]); /* /eslbmean3 / 2; /2 for 3 points regression calc; 04042013: division not needed, only sign of sxylb3 is used*/ + sxyhb3 = (es_mdct_hb[ind3 - 1] - es_mdct_hb[ind3 - 3])/eshbmean3 / 2; + if ((sxyhb3 < (float)0.2) || (sxylb3 < 0)) + { + ind2 = 0; + adv = advmem; + } + } + else + { + if (sxyhb2 < (float)0.0) + { + ind2 = 0; + adv = advmem; /* 04042013: small bug corection*/ + } + } + + eshbmean3 = (eshbmean2 + es_mdct_hb[ind3]) / 3; /*verif toward future subsubframe*/ + sxyhb3 = (es_mdct_hb[ind3] - es_mdct_hb[ind3 - 2])/eshbmean3 / 2; + if (sxyhb3 < (float)0.2) + { + ind2 = 0; + adv = advmem; + } + } + } + + stind = ind2*subframelength-adv; + stind_hb = stind + advmem; + if( stind < 0 ) + { + stind = 0; + } + + if( stind_hb < 0 ) + { + stind_hb = 0; + } + + fptr1 = preechogain + stind + smooth_len; + fptr2 = preechogain_hb + stind_hb; + + for (i = stind + smooth_len; i < framelength; i++) /* rest of the gains, without 4 (PREECHO_SMOOTH_LEN) 1 for fadeout */ + { + *(fptr1++) = 1; + } + + for (i = stind_hb; i < framelength; i++) /* rest of the gains*/ + { + *(fptr2++) = 1; + } + + for (i = 0; i < smooth_len; i++) + { + preechogain[i] = *smoothmem; + } + + fattnext = 1; + if( stind > framelength ) + { + fattnext = gt[ind2-1]; + } + + for (i = 0; i < smooth_len; i++) + { + preechogain[framelength + i] = fattnext; + } + + fptr1 = preechogain; + for (i = 0; i < framelength; i++) + { + fptr2 = fptr1; + for(j = 1; j <= smooth_len; j++) + { + *fptr1 += *(++fptr2); + } + + *fptr1 *= (float)invsmoothlenp1; + fptr1++; + } + + *smoothmem = fattnext; + *wmold_hb = preechogain_hb[framelength-1]; + + /* apply gain */ + fptr1 = preechogain; + fptr2 = preechogain_hb; + fptr3 = rec_sig; + fptr4 = rec_sig_lb; + fptr5 = rec_sig_hb; + + for (i = 0; i < framelength; i++) + { + *fptr3 = *fptr4 **fptr1 + *fptr5 **fptr2; + fptr1++; + fptr2++; + fptr3++; + fptr4++; + fptr5++; + } + + *mean_prev_nc = es_mdct[0]; /* compute mean not corrected by the actual gains*/ + + for (i = 1; i < NUMSF; i++) /* all present subbands */ + { + if( i == NUMSF/2 ) + { + savehalfe = *mean_prev_nc; + } + *mean_prev_nc += es_mdct[i]; + } + + if( savehalfe < *mean_prev_nc/2 ) + { + *mean_prev_nc = 2*(*mean_prev_nc - savehalfe); + } + *mean_prev_nc = *mean_prev_nc * INV_NUMSF; /* >> LOG2_NUMSF in fixpoint */ + + for( i = 0; i < ind2; i++ ) /* only subbands before max energy subband are handled*/ + { + es_mdct[i] = es_mdct[i]*gt[i]*gt[i]; + es_mdct_hb[i] = es_mdct_hb[i]*gt_hb[i]*gt_hb[i]; + } + + *mean_prev = es_mdct[0]; /* compute mean used in next frame to limit gain*/ + *mean_prev_hb = es_mdct_hb[0]; /* compute mean used in next frame to limit gain*/ + + for (i = 1; i < NUMSF; i++) /* all present subbands */ + { + if(i == NUMSF/2) + { + savehalfe = *mean_prev; + savehalfe_hb = *mean_prev_hb; + } + + *mean_prev += es_mdct[i]; + *mean_prev_hb += es_mdct_hb[i]; + } + + if( savehalfe < *mean_prev/2 ) + { + *mean_prev = 2*(*mean_prev - savehalfe); + } + + if( savehalfe_hb < *mean_prev_hb/2 ) + { + *mean_prev_hb = 2*(*mean_prev_hb - savehalfe_hb); + } + + *mean_prev = *mean_prev * INV_NUMSF; /* >> LOG2_NUMSF in fixpoint */ + *mean_prev_hb = *mean_prev_hb * INV_NUMSF; /* >> LOG2_NUMSF in fixpoint */ + last2 = (es_mdct[NUMSF-1] + es_mdct[NUMSF-2])/2; + last2_hb = (es_mdct_hb[NUMSF-1] + es_mdct_hb[NUMSF-2])/2; + + if( last2 > *mean_prev ) + { + *mean_prev = last2; + } + + if( last2_hb > *mean_prev_hb ) + { + *mean_prev_hb = last2_hb; + } + } + + return; +} + + +/*--------------------------------------------------------------------------* + * inverse_transform() + * + * Inverse transform from the DCT domain to time domain + *--------------------------------------------------------------------------*/ + +void inverse_transform( + const float *in_mdct, /* i : input MDCT vector */ + float *out, /* o : output vector */ + const short is_transient, /* i : transient flag */ + const short L, /* i : output frame length */ + const short L_inner /* i : length of the transform */ +) +{ + float out_alias[L_FRAME48k]; + float alias[MAX_SEGMENT_LENGTH]; + const float *in_segment; + float *out_segment; + float tmp; + short ta, seg; + short segment_length; + float in_mdct_modif[L_FRAME48k]; + float *in_segment_modif; + const float *win; + + segment_length = L/2; + + if (is_transient) + { + if (L == L_FRAME48k) + { + win = short_window_48kHz; + } + else if (L == L_FRAME32k) + { + win = short_window_32kHz; + } + else if( L == L_FRAME16k ) + { + win = short_window_16kHz; + } + else /* L == L_FRAME8k */ + { + win = short_window_8kHz; + } + + set_f( out_alias, 0.0f, L ); + + in_segment = in_mdct; + in_segment_modif = in_mdct_modif; + + if( L == L_inner ) + { + mvr2r( in_mdct, in_mdct_modif, L ); + } + else if( L > L_inner ) + { + for( seg = 0; seg < NUM_TIME_SWITCHING_BLOCKS; seg++ ) + { + for( ta = 0; ta < L_inner/NUM_TIME_SWITCHING_BLOCKS; ta++ ) + { + *in_segment_modif++ = *in_segment++; + } + + for( ta = 0; ta < (L-L_inner)/NUM_TIME_SWITCHING_BLOCKS; ta++ ) + { + *in_segment_modif++ = 0; + } + } + } + else /* L < L_inner */ + { + for( seg = 0; seg < NUM_TIME_SWITCHING_BLOCKS; seg++ ) + { + for( ta = 0; ta < segment_length/2; ta++ ) + { + *in_segment_modif++ = *in_segment++; + } + in_segment += (L_inner-L)/NUM_TIME_SWITCHING_BLOCKS; + } + } + + out_segment = out_alias - segment_length/4; + in_segment = in_mdct_modif; + + iedct_short( in_segment, alias, segment_length ); + + for( ta = segment_length/4; ta < segment_length/2; ta++ ) + { + out_segment[ta] = alias[ta]; + } + + for( ta = segment_length/2; ta < segment_length; ta++ ) + { + out_segment[ta] = alias[ta] * win[ta]; + } + + out_segment = out_segment + segment_length/2; + in_segment = in_segment + segment_length/2; + + for( seg = 1; seg < NUM_TIME_SWITCHING_BLOCKS-1; seg++ ) + { + iedct_short( in_segment, alias, segment_length ); + + for( ta = 0; ta < segment_length; ta++ ) + { + out_segment[ta] = out_segment[ta] + alias[ta] * win[ta]; + } + + in_segment = in_segment + segment_length/2; + out_segment = out_segment + segment_length/2; + } + + iedct_short( in_segment, alias, segment_length ); + + for (ta = 0; ta < segment_length/2; ta++) + { + out_segment[ta] = out_segment[ta] + alias[ta] * win[ta]; + } + + for (ta = segment_length/2; ta < 3*segment_length/4; ta++) + { + out_segment[ta] = alias[ta]; + } + + for (ta = 0; ta < L/2; ta++) + { + tmp = out_alias[ta]; + out[ta] = out_alias[L-1-ta]; + out[L-1-ta] = tmp; + } + } + else + { + edct( in_mdct, out, L ); + } + + return; +} diff --git a/lib_com/typedef.h b/lib_com/typedef.h new file mode 100644 index 000000000..aa8d9193c --- /dev/null +++ b/lib_com/typedef.h @@ -0,0 +1,94 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +/* + =========================================================================== + 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. | + |_____________________| +*/ + +#include "options.h" + +#ifndef TYPEDEF_H +#define 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 unsigned char UWord8; +typedef short Word16; +typedef int Word32; +typedef unsigned short UWord16; +typedef unsigned int UWord32; +typedef __int64 Word40; +typedef int Flag; + +#elif defined(__CYGWIN__) +typedef signed char Word8; +typedef unsigned char UWord8; +typedef short Word16; +typedef int Word32; +typedef unsigned short UWord16; +typedef unsigned int UWord32; +typedef long long Word40; +typedef int Flag; + +#elif defined(__sun) +typedef signed char Word8; +typedef unsigned char UWord8; +typedef short Word16; +typedef long Word32; +/*#error "The 40-bit operations have not been tested on __sun : need to define Word40"*/ +typedef unsigned short UWord16; +typedef unsigned long UWord32; +typedef long long Word40; +typedef int Flag; + +#elif defined(__unix__) || defined(__unix) || defined(__APPLE__) +typedef signed char Word8; +typedef unsigned char UWord8; +typedef short Word16; +typedef int Word32; +typedef unsigned short UWord16; +typedef unsigned int UWord32; +/*#error "The 40-bit operations have not been tested on unix : need to define Word40"*/ +typedef long long Word40; +typedef int Flag; +#endif + +typedef float Float32; + +#endif /* ifndef _TYPEDEF_H */ + + +/* end of file */ + + + + diff --git a/lib_com/vlpc_2st_com.c b/lib_com/vlpc_2st_com.c new file mode 100644 index 000000000..97c81ae1f --- /dev/null +++ b/lib_com/vlpc_2st_com.c @@ -0,0 +1,58 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "cnst.h" +#include "prot.h" + + +/*------------------------------------------------------------------* +* lsf_weight_2st() +* +* +*------------------------------------------------------------------*/ + +void lsf_weight_2st( + const float *lsfq, + float *w, + int mode, + float sr_core +) +{ + int i; + float d[M+1]; + float freq_max = sr_core / 2.f; + float freq_div = freq_max / (float)M; + + /* compute lsf distance */ + d[0] = lsfq[0]; + for (i=1; i0); + + if (mode == 0) + { + w[i] = (float) (60.0f / (freq_div/sqrt(d[i]*d[i+1]))); /* abs */ + } + else if (mode == 1) + { + w[i] = (float) (65.0f / (freq_div/sqrt(d[i]*d[i+1]))); /* mid */ + } + else + { + w[i] = (float) (63.0f / (freq_div/sqrt(d[i]*d[i+1]))); /* rel2 */ + } + } + + return; +} diff --git a/lib_com/weight.c b/lib_com/weight.c new file mode 100644 index 000000000..41e59b4e0 --- /dev/null +++ b/lib_com/weight.c @@ -0,0 +1,335 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*--------------------------------------------------------------------------* + * sfm2mqb() + * + * Map sub-vectors to pbands + *--------------------------------------------------------------------------*/ + +static void sfm2mqb( + short spe[], /* i : sub-vectors */ + short spe2q[], /* o : pbands */ + const short nb_sfm /* i : number of norms */ +) +{ + short tmp, i; + + /* short groups */ + spe2q[0] = spe[0] + 3; + spe2q[1] = spe[1] + 3; + spe2q[2] = spe[2] + 3; + spe2q[3] = spe[3] + 3; + spe2q[4] = spe[4] + 3; + spe2q[5] = spe[5] + 3; + spe2q[6] = spe[6] + 3; + spe2q[7] = spe[7] + 3; + spe2q[8] = spe[8] + 3; + spe2q[9] = spe[9] + 3; + + spe2q[10] = ((spe[10] + spe[11]) >> 1) + 4; + spe2q[11] = ((spe[12] + spe[13]) >> 1) + 4; + spe2q[12] = ((spe[14] + spe[15]) >> 1) + 4; + + spe2q[13] = ((spe[16] + spe[17]) >> 1) + 5; + spe2q[14] = ((spe[18] + spe[19]) >> 1) + 5; + + tmp = 0; + for (i=20; i < 24; i++) + { + tmp += spe[i]; + } + spe2q[15] = (short)(((int)tmp * 8192L) >> 15) + 6; + + tmp = 0; + for (i=24; i < 27; i++) + { + tmp += spe[i]; + } + spe2q[16] = (short)(((int)tmp * 10923L) >> 15) + 6; + + if (nb_sfm > 27) + { + tmp = 0; + for (i=27; i < 30; i++) + { + tmp += spe[i]; + } + spe2q[17] = (short)(((int)tmp * 10923L) >> 15) + 6; + + if (nb_sfm > 30) + { + tmp = 0; + for (i=30; i < 35; i++) + { + tmp += spe[i]; + } + spe2q[18] = (short)(((int)tmp * 6553L) >> 15) + 7; + + tmp = 0; + for (i=35; i < 44; i++) + { + tmp += spe[i]; + } + spe2q[19] = (short)(((int)tmp * 3641L) >> 15) + 8; + } + } + + return; +} + +/*--------------------------------------------------------------------------* + * mqb2sfm() + * + * Map pbands to sub-vectors + *--------------------------------------------------------------------------*/ + +static void mqb2sfm( + short spe2q[], /* i : pbands */ + short spe[], /* o : sub-vectors */ + const short lnb_sfm /* i : number of norms */ +) +{ + short i; + + spe[0] = spe2q[0]; + spe[1] = spe2q[1]; + spe[2] = spe2q[2]; + spe[3] = spe2q[3]; + spe[4] = spe2q[4]; + spe[5] = spe2q[5]; + spe[6] = spe2q[6]; + spe[7] = spe2q[7]; + spe[8] = spe2q[8]; + spe[9] = spe2q[9]; + + spe[10] = spe2q[10]; + spe[11] = spe2q[10]; + + spe[12] = spe2q[11]; + spe[13] = spe2q[11]; + + spe[14] = spe2q[12]; + spe[15] = spe2q[12]; + + spe[16] = spe2q[13]; + spe[17] = spe2q[13]; + + spe[18] = spe2q[14]; + spe[19] = spe2q[14]; + for (i=20; i < 24; i++) + { + spe[i] = spe2q[15]; + } + + for (i=24; i < 27; i++) + { + spe[i] = spe2q[16]; + } + + if (lnb_sfm>SFM_N_STA_8k) + { + for (i=27; i < 30; i++) + { + spe[i] = spe2q[17]; + } + + if (lnb_sfm>SFM_N_STA_10k) + { + for (i=30; i < 35; i++) + { + spe[i] = spe2q[18]; + } + + for (i=35; i < 44; i++) + { + spe[i] = spe2q[19]; + } + } + } + + return; +} + +/*--------------------------------------------------------------------------* + * map_quant_weight() + * + * Calculate the quantization weights + *--------------------------------------------------------------------------*/ + +void map_quant_weight( + const short normqlg2[], /* i : quantized norms */ + short wnorm[], /* o : weighted norm */ + const short is_transient /* i : transient flag */ +) +{ + short sfm; + short tmp16; + short spe2q[NUM_MAP_BANDS]; + short spe[NB_SFM]; + + short spe2q_max; + short spe2q_min; + short norm_max; + short shift; + short sum; + short k; + short lnb_sfm,num_map_bands; + + if (is_transient) + { + lnb_sfm = NB_SFM; + num_map_bands = NUM_MAP_BANDS; + + for (sfm = 0; sfm < lnb_sfm; sfm+=4) + { + sum = 0; + for (k=0; k < 4; k++) + { + sum = sum + normqlg2[sfm+k]; + } + sum = sum >> 2; + for (k=0; k < 4; k++) + { + spe[sfm +k] = sum; + } + } + } + else + { + lnb_sfm = NB_SFM; + num_map_bands = NUM_MAP_BANDS; + + + for (sfm = 0; sfm < lnb_sfm; sfm++) + { + spe[sfm] = normqlg2[sfm]; + } + } + + sfm2mqb(spe, spe2q, lnb_sfm); + + for (sfm = 0; sfm < num_map_bands; sfm++) + { + spe2q[sfm] = spe2q[sfm] - 10; + } + + /* spectral smoothing */ + for (sfm = 1; sfm < num_map_bands; sfm++) + { + tmp16 = spe2q[sfm-1] - 4; + if (spe2q[sfm]= 0 ; sfm--) + { + tmp16 = spe2q[sfm+1] - 8; + if (spe2q[sfm]spe2q[sfm]) + { + spe2q_min = spe2q[sfm]; + } + } + + for (sfm = 0; sfm < num_map_bands; sfm++) + { + spe2q[sfm] = spe2q[sfm] - spe2q_min; + } + + spe2q_max = spe2q_max - spe2q_min; + + if (spe2q_max == 0) + { + norm_max = 0; + } + else + { + if (spe2q_max < 0) + { + spe2q_max = ~spe2q_max; + } + for (norm_max=0; spe2q_max<0x4000; norm_max++) + { + spe2q_max <<= 1; + } + } + + shift = norm_max - 13; + for (sfm = 0; sfm < num_map_bands ; sfm++) + { + if (shift<0) + { + spe2q[sfm] = spe2q[sfm] >> (-shift); + } + else + { + spe2q[sfm] = spe2q[sfm] << shift; + } + } + + mqb2sfm(spe2q,spe,lnb_sfm); + + if (is_transient) + { + for (sfm = 0; sfm < lnb_sfm; sfm+=4) + { + sum = 0; + for (k=0; k < 4; k++) + { + sum = sum + spe[sfm+k]; + } + + sum = sum >> 2; + + for (k=0; k < 4; k++) + { + spe[sfm +k] = sum; + } + } + } + + /* modify the norms for bit-allocation */ + for (sfm = 0; sfm < lnb_sfm ; sfm++) + { + wnorm[sfm] = spe[sfm] + normqlg2[sfm]; + } + + return; +} diff --git a/lib_com/weight_a.c b/lib_com/weight_a.c new file mode 100644 index 000000000..a867a76fd --- /dev/null +++ b/lib_com/weight_a.c @@ -0,0 +1,74 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "prot.h" + +/*------------------------------------------------------------------ + * weight_a() + * + * Weighting of LP filter coefficients, ap[i] = a[i] * (gamma^i) + *------------------------------------------------------------------*/ + +void weight_a( + const float *a, /* i : LP filter coefficients */ + float *ap, /* o : weighted LP filter coefficients */ + const float gamma, /* i : weighting factor */ + const short m /* i : order of LP filter */ +) +{ + float f; + short i; + + ap[0] = a[0]; + f = gamma; + + for (i = 1; i <= m; i++) + { + ap[i] = f*a[i]; + f *= gamma; + } + + return; +} + + + +/*------------------------------------------------------------------ + * weight_a_subfr() + * + * Weighting of LP filter coefficients for multiple subframes, + * ap[i] = a[i] * (gamma^i) + *------------------------------------------------------------------*/ + +void weight_a_subfr( + const short nb_subfr, /* i : number of subframes */ + const float *A, /* i : LP filter coefficients */ + float *Aw, /* o : weighted LP filter coefficients */ + const float gamma, /* i : weighting factor */ + const short m /* i : order of LP filter */ +) +{ + short i, j; + float tmp; + + for( j=0; j +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include "wmc_auto.h" + + + /*-------------------------------------------------------------------* + * Local constants + * + * + *-------------------------------------------------------------------*/ + + #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 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() + * + * DTFS structure initialization. + *-------------------------------------------------------------------*/ + + DTFS_STRUCTURE* DTFS_new( + void + ) + { + short i ; + DTFS_STRUCTURE* dtfs = NULL; + +MOVE(1); + dtfs = (DTFS_STRUCTURE *) calloc(1,sizeof(DTFS_STRUCTURE)); +#define WMC_TOOL_SKIP +MOVE(1); dtfs->lag = 0; + dtfs->nH=0; + dtfs->nH_4kHz=0; + dtfs->upper_cut_off_freq_of_interest=3300.0; + dtfs->upper_cut_off_freq=4000.0; +LOOP(1); for(i=0;ia[i]=dtfs->b[i]=0.0 ; + } +#undef WMC_TOOL_SKIP + + return dtfs; /* o: DTFS structure */ + } + + + /*-------------------------------------------------------------------* + * DTFS_copy() + * + * Copy from one DTFS STRUCTURE to another. + *-------------------------------------------------------------------*/ + + void DTFS_copy( + DTFS_STRUCTURE *Xout, /* o: DTFS structure */ + DTFS_STRUCTURE Xinp /* i: DTFS structure */ + ) + { + short k; +#define WMC_TOOL_SKIP +LOOP(1); for(k=0;ka[k]=Xinp.a[k]; + } +LOOP(1); for(k=0;kb[k]=Xinp.b[k]; + } +MOVE(1); Xout->lag=Xinp.lag; + Xout->nH=Xinp.nH; + Xout->nH_4kHz=Xinp.nH_4kHz; + Xout->upper_cut_off_freq_of_interest=Xinp.upper_cut_off_freq_of_interest; + Xout->upper_cut_off_freq=Xinp.upper_cut_off_freq; +#undef WMC_TOOL_SKIP + + return; + } + + + /*-------------------------------------------------------------------* + * DTFS_sub() + * + * Difference of A and B coefficients in cartesian domain. + * Equivalent to time domain subtraction. + *-------------------------------------------------------------------*/ + + DTFS_STRUCTURE DTFS_sub( + DTFS_STRUCTURE X1, /* i: DTFS input 1 */ + DTFS_STRUCTURE X2 /* i: DTFS input 2 */ + ) + { + DTFS_STRUCTURE tmp ; + short i ; +#define WMC_TOOL_SKIP +MULT(1); +LOOP(1); for(i=0; i<=X1.lag/2; i++) + { +MOVE(1); +MULT(1); tmp.a[i] = X1.a[i] ; +MOVE(1); tmp.b[i] = X1.b[i] ; + } +MULT(1); +LOOP(1); for(i=0; i<=X2.lag/2; i++) + { +MAC(1); tmp.a[i] -= X2.a[i] ; +ADD(1); tmp.b[i] -= X2.b[i] ; + } +MOVE(1); tmp.lag = max(X1.lag, X2.lag) ; + tmp.nH=max(X1.nH,X2.nH); + tmp.nH_4kHz=max(X1.nH_4kHz,X2.nH_4kHz); + tmp.upper_cut_off_freq_of_interest=X1.upper_cut_off_freq_of_interest; + tmp.upper_cut_off_freq=X1.upper_cut_off_freq; +#undef WMC_TOOL_SKIP + + return tmp ; + } + + /*-------------------------------------------------------------------* + * DTFS_fast_fs_inv() + * + * DTFS inverse. + *-------------------------------------------------------------------*/ + + void DTFS_fast_fs_inv( + DTFS_STRUCTURE *X1_DTFS, /* i : DTFS */ + float *out, /* o : time domain output */ + int N /* i : number of output samples */ + ) + { + unsigned short i, M_2 = (unsigned short) min(X1_DTFS->lag>>1,X1_DTFS->nH), N_2 = (unsigned short) N>>1 ; + float dbuf[256+1]; /* N can't be > 256 */ + +#define WMC_TOOL_SKIP + if (Nlag) + { + N=X1_DTFS->lag; + } + + /* Populate the dbuf array */ + dbuf[1] = X1_DTFS->a[0] ; + + if (N_2 == M_2) + { + dbuf[2] = X1_DTFS->a[M_2] * X1_DTFS->lag ; + } + else + { + dbuf[2] = 0.0 ; + } + for (i=1; ia[i] * N_2 ; +MAC(1); dbuf[2*i+2] =X1_DTFS->b[i] * N_2 ; + } + + if (N_2 != M_2) + { + dbuf[2*i+1] = X1_DTFS->a[i] * N_2 ; + dbuf[2*i+2] = X1_DTFS->b[i] * N_2 ; + i++; + } + + /* Zero-padding in the frequency domain */ + for ( ; i>1,X2_DTFS.nH_4kHz); k++, freq+=fdiff) + { +LOGIC(1); if(freq=lband) + { +MAC(1); +ADD(1); corr += (X1_DTFS.a[k]*X2_DTFS.a[k] + X1_DTFS.b[k]*X2_DTFS.b[k]); + } + } +MULT(1); +DIV(1); +FUNC(3); +SQRT(1); +#undef WMC_TOOL_SKIP + + return corr/sqrt(DTFS_getEngy_band (X1_DTFS,lband, hband)*DTFS_getEngy_band(X2_DTFS,lband, hband)) ; + } + + + /*-------------------------------------------------------------------* + * DTFS_alignment_weight() + * + * Estimate the shift to find the best match between the reference + * DTFS and the test DTFS. + *-------------------------------------------------------------------*/ + + float DTFS_alignment_weight( + DTFS_STRUCTURE refX1_DTFS, /* i : X1 the reference DTFS to keep fixed */ + DTFS_STRUCTURE X2_DTFS, /* i : X2 the test DTFS to shift to find best match */ + float Eshift, /* i : Expected shift - coarse value */ + const float *LPC1, /* i : LPC to filter to find correlation in spch */ + const float *LPC2 /* i : LPC to filter to find correlation in spch */ + ) + { + /* Eshift is w.r.t X2 */ + short k ; + float maxcorr, corr, Adiff, diff, tmp, tmp1, fshift, n, wcorr ; + float pwf = (float) 0.7, tmplpc[M+1] ; + DTFS_STRUCTURE X1_DTFS; + +#define WMC_TOOL_SKIP + +FUNC(2); DTFS_copy (&X1_DTFS,refX1_DTFS); +FUNC(2); DTFS_adjustLag (&X1_DTFS,X2_DTFS.lag) ; +FUNC(3); +ADD(1); DTFS_poleFilter (&X1_DTFS,LPC1,M+1) ; +MOVE(1); tmp=1.0; +LOOP(1); for(k=0,tmp=1.0;k>1,X2_DTFS.nH_4kHz); k++, tmp+=tmp1) + { + /* Not counting math function cos and sin since they will be implemented as look-up tables */ +MAC(1); +ADD(1); corr += (float) ((X1_DTFS.a[k]*X2_DTFS.a[k] + X1_DTFS.b[k]*X2_DTFS.b[k])* cos(tmp)); +MAC(1); +ADD(1); corr += (float) ((X1_DTFS.b[k]*X2_DTFS.a[k] - X1_DTFS.a[k]*X2_DTFS.b[k])* sin(tmp)); + } +MOVE(1); +MAC(2); +ABS(1); wcorr=(float) (corr*(1.0f-0.01f* fabs(n-Eshift))) ; +LOGIC(1); if( wcorr > maxcorr ) + { +MOVE(1); fshift = n ; +MOVE(1); maxcorr = wcorr ; + } + } +#undef WMC_TOOL_SKIP + + return fshift ; /* o : shift value to shift X2_DTFS by */ + } + + + /*-------------------------------------------------------------------* + * DTFS_alignment_extract() + * + * Alignment for the best match between the reference DTFS and the test DTFS. + *-------------------------------------------------------------------*/ + + float DTFS_alignment_extract( + DTFS_STRUCTURE refX1_DTFS, /* i : X1 the reference DTFS to keep fixed */ + DTFS_STRUCTURE X2_DTFS, /* i : X2 the test DTFS to shift to find best match */ + float Eshift, /* i : Expected shift - coarse value */ + const float *LPC2 /* i : LPC to filter to find correlation in spch */ + ) + { + /* Eshift is w.r.t X2 */ + short k ; + float maxcorr, corr, Adiff, diff, tmp, tmp1, fshift, n ; + float pwf = 0.7f, tmplpc[M+1] ; + DTFS_STRUCTURE X1_DTFS; + +#define WMC_TOOL_SKIP + +MOVE(1); X1_DTFS = refX1_DTFS; /* copy into local copy */ + +FUNC(2); DTFS_adjustLag (&X1_DTFS,X2_DTFS.lag) ; + +FUNC(3); +ADD(1); DTFS_poleFilter (&X1_DTFS,LPC2,M+1) ; +FUNC(3); DTFS_poleFilter (&X2_DTFS,LPC2,M+1) ; + +MOVE(1); +LOOP(1); for(k=0,tmp=1.0;k>1,X2_DTFS.nH_4kHz); k++, tmp+=tmp1) + + { +MAC(1); +ADD(1); corr += (float) ((X1_DTFS.a[k]*X2_DTFS.a[k] + X1_DTFS.b[k]*X2_DTFS.b[k])* cos(tmp)); +MAC(1); +ADD(1); corr += (float) ((X1_DTFS.b[k]*X2_DTFS.a[k] - X1_DTFS.a[k]*X2_DTFS.b[k])* sin(tmp)); + } + +MAC(2); +LOGIC(1); if( corr*(1.0f-0.01f*fabs(n-Eshift) ) > maxcorr ) + { +MOVE(1); fshift = n ; +MOVE(1); maxcorr = corr ; + } + } + +#undef WMC_TOOL_SKIP + + return fshift ; /* o : shift value to shift X2 by */ + } + + + + /*-------------------------------------------------------------------* + * DTFS_alignment_fine_new() + * + * Shift value for DTFS finer alignment. + *-------------------------------------------------------------------*/ + + float DTFS_alignment_fine_new( + DTFS_STRUCTURE X1_DTFS, /* i : X1 the reference DTFS to keep fixed */ + DTFS_STRUCTURE X2_DTFS, /* i : X2 the test DTFS to shift to find best match */ + float Eshift /* i : Expected shift - coarse value */ + ) + { + short k ; + float maxcorr, corr, Adiff, diff, tmp, tmp1, fshift, n ; + +#define WMC_TOOL_SKIP + +LOGIC(1); if (X1_DTFS.lag < X2_DTFS.lag) + { +FUNC(2); DTFS_zeroPadd (X2_DTFS.lag,&X1_DTFS) ; + } +MOVE(1); +ADD(1); maxcorr = (float) -HUGE_VAL; +MOVE(1); fshift = Eshift ; +MOVE(1); Adiff = 20.0f ; +MOVE(1); diff = 1.0f; +ADD(1); +ADD(1); +LOOP(1); for(n=Eshift-Adiff+1; n<=Eshift+Adiff; n+=diff) + { +MOVE(2); corr = tmp = 0.0 ; + /* bit-exact optimization - PI2/X2_DTFS.lag should be counted as a single divide outside loops */ +MULT(1); tmp1 = (float) (PI2*n/X2_DTFS.lag) ; +ADD(1); + +LOOP(1); for(k=0; k<=min(X2_DTFS.lag>>1,X2_DTFS.nH); k++, tmp+=tmp1) + { +MAC(1); +ADD(2); corr += (float) ((X1_DTFS.a[k]*X2_DTFS.a[k] + X1_DTFS.b[k]*X2_DTFS.b[k])* cos(tmp)); +MAC(1); +ADD(1); corr += (float) ((X1_DTFS.b[k]*X2_DTFS.a[k] - X1_DTFS.a[k]*X2_DTFS.b[k])* sin(tmp)); + } +MAC(2); +LOGIC(1); +ABS(1); if( corr*(1.0f-0.01f*fabs(n-Eshift) ) > maxcorr ) + { +MOVE(1); fshift = n ; +MOVE(1); maxcorr = corr ; + } + } + +#undef WMC_TOOL_SKIP + + return fshift ; /* o : shift value to shift X2 by */ + } + + + /*-------------------------------------------------------------------* + * DTFS_alignment_full() + * + * Shift value for DTFS full alignment. + *-------------------------------------------------------------------*/ + + float DTFS_alignment_full( + DTFS_STRUCTURE X1_DTFS, /* i : reference DTFS */ + DTFS_STRUCTURE X2_DTFS, /* i : DTFS to shift */ + int num_steps /* i : resolution */ + ) + { + short k ; + float maxcorr, corr, tmp, tmp1, fshift, n, diff ; + +#define WMC_TOOL_SKIP + +LOGIC(1); if (X1_DTFS.lag < X2_DTFS.lag) + { +FUNC(2); DTFS_zeroPadd (X2_DTFS.lag,&X1_DTFS) ; + } + +MOVE(1); +ADD(1); maxcorr = (float) -HUGE_VAL; + /* bit-exact optimization - 1/num_steps can be constant => should be counted as a multiply */ +MOVE(1); +MULT(1); diff = (float) X2_DTFS.lag / num_steps ; + +LOOP(1); for(fshift=n=0.0; n<(float)X2_DTFS.lag; n+=diff) + { +MOVE(2); corr = tmp = 0.0f ; +MOVE(1); +MULT(2); tmp1 = (float) (PI2*n/X2_DTFS.lag) ; +ADD(1); + +LOOP(1); for(k=0; k<=min(X2_DTFS.lag>>1,X2_DTFS.nH_4kHz); k++, tmp+=tmp1) + + { +MAC(1); +ADD(2); corr += (float) ((X1_DTFS.a[k]*X2_DTFS.a[k] + X1_DTFS.b[k]*X2_DTFS.b[k])* cos(tmp)); +MAC(1); +ADD(1); corr += (float) ((X1_DTFS.b[k]*X2_DTFS.a[k] - X1_DTFS.a[k]*X2_DTFS.b[k])* sin(tmp)); + } +LOGIC(1); if(corr>maxcorr) + { +MOVE(1); fshift = n ; +MOVE(1); maxcorr = corr ; + } + } +#undef WMC_TOOL_SKIP + + return fshift ; + } + + + /*-------------------------------------------------------------------* + * DTFS_phaseShift() + * + * Phase shift the DTFS coefficients. + * ph is the amount of phase shift (between 0 and 2pi), where positive + * value indicates a shift to right, and a negative ph value indicates a + * left shift. + *-------------------------------------------------------------------*/ + + void DTFS_phaseShift( + DTFS_STRUCTURE *X, /* i/o: DTFS to shift */ + float ph /* i : phase to shift */ + ) + { + short k ; + float tmp, tmp2=0.0f ; +#define WMC_TOOL_SKIP + +ADD(1); +LOOP(1); for(k=0; k<=min(X->lag>>1,X->nH); k++, tmp2+=ph) + { +MOVE(1); +ADD(1); tmp = X->a[k] ; +MOVE(1); +MAC(1); X->a[k] = (float) (tmp*cos(tmp2) - X->b[k]*sin(tmp2)) ; +MOVE(1); +MAC(1); X->b[k] = (float) (tmp*sin(tmp2) + X->b[k]*cos(tmp2)) ; + } +#undef WMC_TOOL_SKIP + + return; + } + + + /*-------------------------------------------------------------------* + * DTFS_zeroPadd() + * + * Zero-pad the DTFS coefficients. + *-------------------------------------------------------------------*/ + + void DTFS_zeroPadd( + int N, /* i : Target lag */ + DTFS_STRUCTURE *X /* i/o: DTFS */ + ) + { + int i ; + float diff; + +LOGIC(1); if(N == X->lag) + { + return ; + } + +#define WMC_TOOL_SKIP +#ifdef DEBUGGING +LOGIC(1); if (N < X->lag) + { + fprintf(stderr,"\n ERROR IN ZEROPADD \n"); + exit(1) ; + } +#endif +ADD(1); +LOOP(1); for(i=(X->lag>>1)+1; i<=N>>1; i++) + { +MOVE(2); X->a[i]=X->b[i]=0.0 ; + } +MOVE(1); X->lag = N ; + /* recompute nH for new lag */ + X->nH=(int)floor(X->upper_cut_off_freq/(12800.0/X->lag)); +MOVE(1); +MULT(1); diff = 12800.0f / X->lag ; +MULT(1); +ADD(1); +LOGIC(1); if (X->upper_cut_off_freq-(diff*X->nH)>=diff) + { + X->nH++; + } +#undef WMC_TOOL_SKIP + + return; + } + + + /*-------------------------------------------------------------------* + * DTFS_to_fs() + * + * DTFS to fs conversion. + *-------------------------------------------------------------------*/ + + void DTFS_to_fs( + const float *x, /* i : time domain signal */ + int N, /* i : Length of input vector */ + DTFS_STRUCTURE *X, /* o : DTFS structure with a, b, lag */ + short Fs, /* i : sampling rate */ + short FR_flag /* i : FR flag */ + ) + { + short n; + int nH, k, nH_band, nH_4kHz; + float sum, tmp, diff; + +#define WMC_TOOL_SKIP + if (!FR_flag) + { + if (Fs==16000) + { + X->upper_cut_off_freq_of_interest=4000.0; + X->upper_cut_off_freq=6400.0; + X->Fs=INT_FS_12k8; + } + else if (Fs==8000) + { + X->upper_cut_off_freq_of_interest=3300.0; + X->upper_cut_off_freq=4000.0; + X->Fs=INT_FS_12k8; + } + } + else + { + X->upper_cut_off_freq_of_interest=8000.0; + X->upper_cut_off_freq=8000.0; + X->Fs=16000.0; + } + + X->lag = N ; +MOVE(1); +MULT(1); nH_band=(int)floor(X->upper_cut_off_freq/(12800.0/X->lag)); + + nH_4kHz=(int)floor(4000/(12800.0/X->lag)); +MOVE(1); +MULT(1); diff = 12800.0f / X->lag ; +MULT(1); +ADD(1); +LOGIC(1); if (X->upper_cut_off_freq-(diff*nH_band)>=diff) + { + nH_band++; + } + if (4000-(diff*nH_4kHz)>=diff) + { + nH_4kHz++; + } + /* Number of harmonics excluding the ones at 0 and at pi */ +MOVE(1); +MULT(1); +ADD(1); nH = (N-1) >> 1; + /* The DC component */ + X->a[0] = 0.0 ; + X->b[0] = 0.0 ; +LOOP(1); for( n=0; na[0] += x[n] ; + } +MULT(1); X->a[0] /= N ; + + /* Strictly set the DC componet to zero */ +MOVE(1); X->a[0] = 0.0 ; + + /* The harmonics excluding the one at pi */ +LOOP(1); for( k=1; k<=nH; k++ ) + { + X->a[k] = x[0] ; + X->b[k] = 0.0 ; +MOVE(2); +MULT(1); sum = tmp = (float) (PI2*k/N) ; +LOOP(1); for( n=1; na[k] += (float) (x[n] * cos(sum)) ; +ADD(1); X->b[k] += (float) (x[n] * sin(sum)) ; + } +MULT(2); X->a[k] *= (2.0f/N) ; +MULT(2); X->b[k] *= (2.0f/N) ; + } + + /* The harmonic at 'pi' */ +LOGIC(1); if( N%2 == 0 ) + { +MOVE(1); X->a[k] = 0.0 ; +MOVE(1); tmp = 1.0 ; +LOOP(1); for( n=0; na[k] += x[n] * tmp ; + } +MULT(1); X->a[k] /= N ; +MOVE(1); X->b[k] = 0.0 ; + } +ADD(1); +LOOP(1); for(k=nH_band+1;k<=min((X->lag>>1),(MAXLAG_WI-1));k++) + { +MOVE(1); X->a[k]=0.0; +MOVE(1); X->b[k]=0.0; + } + X->nH=nH_band; + X->nH_4kHz=nH_4kHz; +#undef WMC_TOOL_SKIP + + return; + } + + + /*-------------------------------------------------------------------* + * DTFS_fs_inv() + * + * DTFS Inverse + *-------------------------------------------------------------------*/ + + void DTFS_fs_inv( + DTFS_STRUCTURE *X, /* i : DTFS input */ + float *x, /* o : time domain sig */ + int N, /* i : Output length */ + float ph0 /* i : phase shift applied to the output */ + ) + { + float phase, tmp ; + short k, n ; + +#define WMC_TOOL_SKIP + +LOOP(1); for( n=0; na[0] ; +MOVE(2); +MAC(1); tmp = phase = (float) (PI2*n/X->lag + ph0) ; +ADD(1); +LOOP(1); for( k=1; k <=min(X->lag>>1,X->nH); k++, tmp+=phase ) + { +MAC(1); +ADD(1); x[n] += (float) (X->a[k]*cos(tmp) + X->b[k]*sin(tmp)) ; + } + } +#undef WMC_TOOL_SKIP + + return; + + } + + + /*-------------------------------------------------------------------* + * DTFS_transform() + * + * DTFS transform. + *-------------------------------------------------------------------*/ + + void DTFS_transform( + DTFS_STRUCTURE X, /* i : Starting DTFS to use in WI */ + DTFS_STRUCTURE X2, /* i : Ending DTFS to use in WI */ + const float *phase, /* i : Phase contour */ + float *out, /* o : Output time domain waveform */ + int N, /* i : Number of samples to generate */ + short FR_flag /* i : Flag to indicate called in FR context */ + ) + { + short i, j,j1; + float w, tmp ; + float x1_256[256], x2_256[256]; + float sum1, sum2; + short m, l1, k; + int N1; + float nrg_flag = 0; + float x_r_fx[L_FRAME]; + float temp_w; + +#define WMC_TOOL_SKIP + + DTFS_STRUCTURE *tmp1_dtfs=DTFS_new(); + DTFS_STRUCTURE *tmp2_dtfs=DTFS_new(); + DTFS_STRUCTURE *tmp3_dtfs=DTFS_new(); +FUNC(2); DTFS_copy (tmp1_dtfs,X); +FUNC(2); DTFS_copy (tmp2_dtfs,X2); +FUNC(3); DTFS_fast_fs_inv (tmp1_dtfs,x1_256,256); +FUNC(3); DTFS_fast_fs_inv (tmp2_dtfs,x2_256,256); +MOVE(1); +MAC(1); +ADD(1); +LOG(1); tmp = (float) (log(1.0 - WI_THRESHLD) / (X.lag - N)) ; +LOOP(1); for(i=0; i X.lag ) + { + /* pre-computed and stored in a table */ +MOVE(1); w = (float) (1.0 - exp (- (i+1) * tmp)) ; + } + else + { + /* can be a look-up table */ +MOVE(1); w = (float) (i+1) / N ; + } + } + else + { + if (nrg_flag) + { + w = (float) (i+1)/N; + } + else + { + if (N <= tmp2_dtfs->lag) + { + N=tmp2_dtfs->lag+1; + } + + N1 = N - tmp2_dtfs->lag; + if ( i < N1 ) + { + w = (float) (i+1)/N1; + } + else w = 1.0; + } + } + + /* add sinc interpolation of two time domain waveforms at + appropriate phase position */ +MULT(1); +DIV(1); +FUNC(1); +ADD(1); j = (LL_OS*10 + (int)rint_new (phase[i]*LL_OS/PI2)) % LL_OS; + + if (j<0) + { + j=0; + } + +MOVE(1); +DIV(1); k=j%WARP_OS_RATE; +MOVE(1); +MULT(1); l1=j/WARP_OS_RATE; +MOVE(2); + + set_f( x_r_fx, 0.0f, L_FRAME ); + + temp_w =( 1 - w ); + + for( j1=0; j1<12; j1++ ) + { + m=(1000*LL+l1-OSLENGTH/2+j1)%LL; + + if( m < 0 ) + { + m=0; + } + + x_r_fx[m] = x1_256[m]* temp_w + x2_256[m] * w; + } + +LOOP(1); for(j1=0,sum1=sum2=0.0;j1lag) ; +LOOP(1); for( k=0 ; k<=min(X->lag>>1,X->nH) ; k++ ) + { +MOVE(2); +MULT(1); tmp = tmp2 = k*tmp1 ; + /* Calculate sum1 and sum2 */ +MOVE(1); sum1 = 1.0; +MOVE(1); sum2 = 0.0; +ADD(1); +LOOP(1); for( n=0 ; na[k] ; +MOVE(1); +MAC(1); X->a[k] = tmp * sum1 - X->b[k] * sum2 ; +MOVE(1); +MAC(1); X->b[k] = X->b[k] * sum1 + tmp * sum2 ; + } +#undef WMC_TOOL_SKIP + + return; + + } + + /*-------------------------------------------------------------------* + * DTFS_poleFilter() + * + * DTFS pole filter response. + *-------------------------------------------------------------------*/ + + void DTFS_poleFilter( + DTFS_STRUCTURE *X, /* i/o : DTFS to poleFilter inplace */ + const float *LPC, /* i : LPCs */ + int N /* i : LPC order */ + ) + { + float tmp, tmp1, tmp2, sum1, sum2 ; + short k, n ; +#define WMC_TOOL_SKIP + +MOVE(1); +MULT(1); tmp1 = (float) (PI2/X->lag) ; +LOOP(1); for( k=0; k<=min(X->lag>>1,X->nH) ; k++ ) + { +MOVE(2); +MULT(1); tmp = tmp2 = k*tmp1 ; + /* Calculate sum1 and sum2 */ +MOVE(1); sum1 = 1.0; +MOVE(1); sum2 = 0.0; +ADD(1); +LOOP(1); for( n=0 ; na[k] ; +MAC(1); tmp2 = sum1 * sum1 + sum2 * sum2 ; +MAC(1); +DIV(1); X->a[k] = ( tmp * sum1 + X->b[k] * sum2 ) / tmp2 ; +MAC(1); +ADD(1); X->b[k] = ( -tmp * sum2 + X->b[k] * sum1 ) / tmp2 ; + } +#undef WMC_TOOL_SKIP + + return; + + } + + + /*-------------------------------------------------------------------* + * DTFS_adjustLag() + * + * Adjust DTFS lag based on a target lag. + *-------------------------------------------------------------------*/ + + void DTFS_adjustLag( + DTFS_STRUCTURE *X_DTFS, /* i/o : DTFS to adjust lag for */ + int N /* i : Target lag */ + ) + { + int k ; + float en,diff ; + +LOGIC(1); if (N==X_DTFS->lag) + { + return ; + } + +#define WMC_TOOL_SKIP + +LOGIC(1); if(N>X_DTFS->lag) + { + +FUNC(2); DTFS_zeroPadd (N, X_DTFS) ; + } + else + { +FUNC(1); +MOVE(1); en = DTFS_getEngy (*X_DTFS) ; +ADD(1); +LOOP(1); for(k=(N>>1)+1; k<=min(X_DTFS->lag>>1,X_DTFS->nH); k++) + { +MOVE(1); X_DTFS->a[k] = 0.0 ; +MOVE(1); X_DTFS->b[k] = 0.0 ; + } +FUNC(2); DTFS_setEngy (X_DTFS, en) ; +MOVE(1); X_DTFS->lag = N ; + /* recompute nH for new lag */ + X_DTFS->nH=(int)floor(X_DTFS->upper_cut_off_freq/(12800.0/X_DTFS->lag)); + + X_DTFS->nH_4kHz=(int)floor(4000.0/(12800.0/X_DTFS->lag)); +MOVE(1); +MULT(1); diff = 12800.0f / X_DTFS->lag ; +MULT(1); +ADD(1); +LOGIC(1); if (X_DTFS->upper_cut_off_freq-(diff*X_DTFS->nH)>=diff) + { + X_DTFS->nH++; + } + if (4000.0-(diff*X_DTFS->nH_4kHz)>=diff) + { + X_DTFS->nH_4kHz++; + } + } +#undef WMC_TOOL_SKIP + + return; + + } + + + /*-------------------------------------------------------------------* + * DTFS_getEngy() + * + * Get DTFS energy. + *-------------------------------------------------------------------*/ + + float DTFS_getEngy( + DTFS_STRUCTURE X /* i : DTFS to compute energy of */ + ) + { + short k; + float en=0.0 ; +#define WMC_TOOL_SKIP + +LOOP(1); for(k=1; k<=min((X.lag-1)>>1,X.nH); k++) + { +MAC(1); +ADD(1); en += X.a[k]*X.a[k] + X.b[k]*X.b[k] ; + } +MULT(1); en /= 2.0 ; +MULT(1); +ADD(1); en += X.a[0]*X.a[0] ; +LOGIC(1); if(X.lag%2 == 0) + { +MAC(1); +ADD(1); en += X.a[k]*X.a[k] + X.b[k]*X.b[k]; + } +#undef WMC_TOOL_SKIP + + return en ; + } + + + /*-------------------------------------------------------------------* + * DTFS_getEngy_band() + * + * Get DTFS energy in the specified range from lband to hband. + *-------------------------------------------------------------------*/ + + float DTFS_getEngy_band( + DTFS_STRUCTURE X, /* i : DTFS to compute energy of */ + float lband, /* i : low end of band of interest */ + float hband /* i : high end of band of interest */ + ) + { + short k; + float en=0.0f, freq, fdiff=12800.0f/X.lag ; +#define WMC_TOOL_SKIP + +MOVE(1); +ADD(1); +LOOP(1); for(freq=fdiff, k=1; k<=min((X.lag-1)>>1,X.nH_4kHz); k++, freq+=fdiff) + { +ADD(1); +LOGIC(1); if(freq=lband) + { +MAC(1); +ADD(1); en += X.a[k]*X.a[k] + X.b[k]*X.b[k] ; + } + } +MULT(1); en /= 2.0 ; +LOGIC(1); if(lband == 0.0) + { +MULT(1); +ADD(1); en += X.a[0]*X.a[0] ; + } +LOGIC(1); if((X.lag%2 == 0) && (hband == X.upper_cut_off_freq)) + { +MAC(1); +ADD(1); en += X.a[k]*X.a[k] + X.b[k]*X.b[k]; + } +#undef WMC_TOOL_SKIP + + return en ; + } + + /*-------------------------------------------------------------------* + * DTFS_getEngy_band_wb() + * + * Get DTFS energy in the specified range from lband to hband. + * This function is different to "DTFS_getEngy_band" as this can calculate + * lband, hband \in [1,6400] where "DTFS_getEngy_band" only upperlimited to + * 4Khz. Possibility: modify ""DTFS_getEngy_band"" and get rid of this + * function. + *-------------------------------------------------------------------*/ + + float DTFS_getEngy_band_wb( + DTFS_STRUCTURE X, /* i : DTFS to compute energy of */ + float lband, /* i : low end of band of interest */ + float hband /* i : high end of band of interest */ + ) + { + short k; + float en=0.0f, freq, fdiff=12800.0f/X.lag ; +#define WMC_TOOL_SKIP + +MOVE(1); +ADD(1); +LOOP(1); for(freq=fdiff, k=1; k<=((X.lag-1)>>1); k++, freq+=fdiff) + { +ADD(1); +LOGIC(1); if(freq=lband) + { +MAC(1); +ADD(1); en += X.a[k]*X.a[k] + X.b[k]*X.b[k] ; + } + } +MULT(1); en /= 2.0 ; +LOGIC(1); if(lband == 0.0) + { +MULT(1); +ADD(1); en += X.a[0]*X.a[0] ; + } +LOGIC(1); if((X.lag%2 == 0) && (hband == X.upper_cut_off_freq)) + { +MAC(1); +ADD(1); en += X.a[k]*X.a[k] + X.b[k]*X.b[k]; + } +#undef WMC_TOOL_SKIP + + return en ; + } + + + /*-------------------------------------------------------------------* + * DTFS_setEngy() + * + * Set DTFS energy. + *-------------------------------------------------------------------*/ + + float DTFS_setEngy( + DTFS_STRUCTURE *X_DTFS, /* i/o : DTFS structure to set engy */ + float en2 /* i : Energy to set to */ + ) + { + short k ; + float en1, tmp ; + + en1 = DTFS_getEngy (*X_DTFS); + if(en1 == 0.0) + { + return 0.0; + } + +#define WMC_TOOL_SKIP +MOVE(1); +DIV(1); +SQRT(1); tmp = (float) sqrt(en2/en1) ; +LOOP(1); for(k=0; k<=min(X_DTFS->lag>>1,X_DTFS->nH); k++) + { +MULT(1); X_DTFS->a[k] *= tmp ; +MULT(1); X_DTFS->b[k] *= tmp ; + } +#undef WMC_TOOL_SKIP + + return en1 ; + } + + + /*-------------------------------------------------------------------* + * DTFS_car2pol() + * + * DTFS cartesian to polar co-ordinates conversion. + *-------------------------------------------------------------------*/ + + void DTFS_car2pol( + DTFS_STRUCTURE *X /* i/o : DTFS structure a, b, lag */ + ) + { + short k ; + float tmp ; +#define WMC_TOOL_SKIP + +LOOP(1); for( k=1 ; k<=min((X->lag-1)>>1,X->nH) ; k++ ) + { +MOVE(1); tmp = X->a[k] ; +MOVE(1); +FUNC(2); +MULT(1); X->a[k] = (float) (0.5f * sqrt( tmp*tmp + X->b[k]*X->b[k] )) ; +MOVE(1); X->b[k] = (float) atan2(X->b[k], tmp) ; + } +LOGIC(1); if(X->lag%2==0) + { +MOVE(1); tmp = X->a[k] ; +FUNC(2); +MOVE(1); X->a[k] = (float) sqrt( tmp*tmp + X->b[k]*X->b[k] ) ; +MOVE(1); X->b[k] = (float) atan2 (X->b[k], tmp) ; + } +#undef WMC_TOOL_SKIP + + return; + + } + + + /*-------------------------------------------------------------------* + * DTFS_pol2car() + * + * DTFS polar to cartesian co-ordinates conversion. + *-------------------------------------------------------------------*/ + + void DTFS_pol2car( + DTFS_STRUCTURE *X /* i/o : DTFS structure a, b, lag */ + ) + { + short k ; + float tmp ; +#define WMC_TOOL_SKIP + +LOOP(1); for( k=1 ; k<=min((X->lag-1)>>1,X->nH) ; k++ ) + { +MOVE(1); tmp = X->b[k] ; +MOVE(1); +MULT(2); X->b[k] = (float) (2.0f * X->a[k] * sin(tmp)) ; +MOVE(1); +MULT(2); X->a[k] = (float) (2.0f * X->a[k] * cos(tmp)) ; + } +LOGIC(1); if(X->lag%2==0) + { +MOVE(1); tmp = X->b[k] ; +MOVE(1); +MULT(1); X->b[k] = (float) (X->a[k] * sin(tmp)) ; +MOVE(1); +MULT(1); X->a[k] = (float) (X->a[k] * cos(tmp)) ; + } +#undef WMC_TOOL_SKIP + return; + + } + + + /*-------------------------------------------------------------------* + * DTFS_setEngyHarm() + * + * Adjust DTFS energy based on the input target energy. + *-------------------------------------------------------------------*/ + + float DTFS_setEngyHarm( + float f1, /* i : lower band freq of input to control energy */ + float f2, /* i : upper band freq of input to control energy */ + float g1, /* i : lower band freq of output to control energy */ + float g2, /* i : upper band freq of output to control energy */ + float en2, /* i : Target Energy to set the DTFS to */ + DTFS_STRUCTURE *X /* i/o: DTFS to adjust the energy of */ + ) + { + short k, count=0; + float en1=0.0f, tmp, factor, diff=12800.0f/X->lag ; + +#define WMC_TOOL_SKIP + +LOGIC(1); if(f1==0.0) + { +MULT(1); +ADD(1); en1 += X->a[0]*X->a[0] ; + count ++; + } +MOVE(1); +ADD(1); +ADD(1); +LOOP(1); for(k=1, tmp=diff; k<=min((X->lag-1)>>1,X->nH); k++, tmp+=diff) + { + if( X->a[k] < EPSILON ) + { + X->a[k]=0; + } + +LOGIC(1); if(tmp>f1 && tmp<=f2) + { +MULT(1); +ADD(1); en1 += X->a[k]*X->a[k] ; + count ++; + } + } + + if (count <= 0.0) + { + count=1; + } + + +DIV(1); en1 /= count ; + + if (en2 < 0.0) + { + en2=0.0; + } + +LOGIC(1); if(en1>0.0) + { +MOVE(1); +DIV(1); +SQRT(1); factor = (float) sqrt(en2/en1) ; + } + else + { +MOVE(1); factor = 0.0f ; + } +LOGIC(1); if(g1==0.0) + { +MULT(1); X->a[k] *= factor ; + } +MOVE(1); +ADD(1); +ADD(1); +LOOP(1); for(k=1, tmp=diff; k<=min((X->lag-1)>>1,X->nH); k++, tmp+=diff) + { +ADD(1); +ADD(1); +LOGIC(1); if(tmp>g1 && tmp<=g2) + { +MULT(1); X->a[k]*=factor ; + } + } +ADD(1); +#undef WMC_TOOL_SKIP + + return (float)(en1+1e-20); /* o : Return Input RMS between f1 and f2 before scaling */ + } + + + /*-------------------------------------------------------------------* + * cubicPhase() + * + * Compute coefficients of cubic phase function + *-------------------------------------------------------------------*/ + static + void cubicPhase( + float ph1, /* i : phase offset */ + float ph2, /* i : phase 2 */ + float L1, /* i : previous lag */ + float L2, /* i : current lag */ + int N, /* i : input length */ + float *phOut /* o : cubic phase output */ + ) + { + float coef[4], f1, f2, c1, c2, factor ; + short n ; + double diff; + +#define WMC_TOOL_SKIP + +ADD(1); N -= (int) L2; + + if (N<=0) + { + N=1; + } + + /* Computation of the coefficients of the cubic phase function */ +MOVE(1); +DIV(1); f1 = (float) (PI2 / L1) ; +MOVE(1); +DIV(1); f2 = (float) (PI2 / L2) ; +MOVE(1); +DIV(1); ph1 = (float) fmod ((double)(ph1), PI2) ; +MOVE(1); +DIV(1); ph2 = (float) fmod ((double)(ph2), PI2) ; +MOVE(1); coef[3] = ph1 ; +MOVE(1); coef[2] = f1 ; +MOVE(1); +MAC(1); +ADD(1); +FUNC(1); +ADD(1); factor = (float) (anint (( ph1 - ph2 + 0.5*N*(f2+f1) ) / PI2 )) ; +MOVE(1); +ADD(1); c1 = f2-f1 ; +MOVE(1); +MAC(1); +ADD(2); c2 = (float) (ph2 - ph1 - N*f1 + PI2 * factor) ; +MOVE(1); +MAC(1); +DIV(1); coef[0] = (N*c1 - 2*c2 ) / (N*N*N) ; +MOVE(1); +MULT(4); +DIV(1); +ADD(1); coef[1] = (c1 - 3*N*N*coef[0]) / (2*N) ; + /* Computation of the phase value at each sample point */ +MOVE(1); phOut[0] = ph1 ; +LOOP(1); for(n=1; n>1,X.nH); i++, freq+=diff) + { + if (!(freq <= erb[num_erb])) + { + freq = erb[num_erb]; + } + +LOOP(1); for( ; j 1) + { +DIV(1); out[i] /= count[i] ; + } + } +#undef WMC_TOOL_SKIP + + return; + } + + /*-------------------------------------------------------------------* + * erb_slot() + * + * Estimation of ERB slots. + *-------------------------------------------------------------------*/ + static + void erb_slot( + int lag, /* i : input lag */ + int *out, /* o : ERB slots */ + float *mfreq, /* i : ERB frequencies */ + short num_erb /* i : number of ERBs */ + ) + { + unsigned short i, j ; + float freq, diff ; + short upper_cut_off_freq; + const float *erb=NULL; + int nH_band; + +#define WMC_TOOL_SKIP + upper_cut_off_freq=4000; + if (num_erb==NUM_ERB_NB) + { + upper_cut_off_freq=4000; + erb=&(erb_NB[0]); + } + else if (num_erb==NUM_ERB_WB) + { + upper_cut_off_freq=6400; + erb=&(erb_WB[0]); + } +MOVE(1); +MULT(1); nH_band=(int)floor(upper_cut_off_freq/(12800.0/lag)); + +LOOP(1); for(i=0; i=diff) + { + nH_band++; + } +MOVE(2); +ADD(1); +LOOP(1); for(i=j=0, freq=0.0; i<=min(lag>>1,nH_band); i++, freq+=diff) + { + + if (!(freq <= erb[num_erb])) + { + freq = erb[num_erb]; + } + +MOVE(1); freq = min(freq, upper_cut_off_freq) ; + +LOOP(1); for( ; j1) + { +DIV(1); mfreq[j]/=out[j] ; + } + } +#undef WMC_TOOL_SKIP + + return; + } + + /*-------------------------------------------------------------------* + * DTFS_erb_inv() + * + * .DTFS after ERB inverse + *-------------------------------------------------------------------*/ + + void DTFS_erb_inv( + float *in, /* i : ERB inpt */ + int *slot, /* i : ERB slots filled based on lag */ + float *mfreq, /* i : erb frequence edges */ + DTFS_STRUCTURE *X, /* o : DTFS after erb-inv */ + short num_erb /* i : Number of ERB bands */ + ) + { + short i, j, m=0 ; + float diff ; + float freq, f[NUM_ERB_WB+2], amp[NUM_ERB_WB+2] ; + short upper_cut_off_freq = 0; + const float *erb = NULL; + +#define WMC_TOOL_SKIP + + if (num_erb==NUM_ERB_NB) + { + upper_cut_off_freq=4000; + erb=&(erb_NB[0]); + } + else if (num_erb==NUM_ERB_WB) + { + upper_cut_off_freq=6400; + erb=&(erb_WB[0]); + } + +MOVE(1); f[m]=0.0; +MOVE(1); amp[m]=0.0; m++; +LOOP(1); for(i=0; ilag ; + +MOVE(2); +ADD(1); +LOOP(1); for(i=0, j=1, freq=0.0; i<=min(X->lag>>1,X->nH); i++, freq+=diff) + { + if (!(freq <= erb[num_erb])) + { + freq = erb[num_erb]; + } + + if (!(m<=num_erb+2)) + { + m = num_erb+2; + } + +LOGIC(1); if(freq>upper_cut_off_freq) + { +MOVE(1); freq=upper_cut_off_freq; + } +LOOP(1); for( ; ja[i] = amp[j]*(freq-f[j-1]) + amp[j-1]*(f[j]-freq) ; +LOGIC(1); if(f[j] != f[j-1]) + { +DIV(1); +ADD(1); X->a[i] /= (f[j] - f[j-1]) ; + } + break ; + } + } + + X->a[0] = 0.0f; + } +#undef WMC_TOOL_SKIP + + return; + + } + + + /*-------------------------------------------------------------------* + * LPCPowSpect() + * + * LPC power spectrum + *-------------------------------------------------------------------*/ + static + void LPCPowSpect( + const float *freq, /* i : ERB frequencies */ + int Nf, /* i : Number of ERBs */ + const float *LPC, /* i : LPC coefficients */ + int Np, /* i : Number of LPCs */ + float *out /* o : LPC power spectrum */ + ) + { + float w, tmp, Re, Im ; + short i, k ; + +#define WMC_TOOL_SKIP + +LOOP(1); for(k=0; k>1,X.nH_4kHz); k++, freq+=fdiff) + { + if (X.a[k]<0.0) + { + X.a[k]=0.0; + } + +LOGIC(1); if(freq=lband) + { +MOVE(1); Re = 1.0f ; +MOVE(1); Im = 0.0f ; +MOVE(1); +MULT(2); tmp = (float) (PI2*freq/12800.0f) ; +MOVE(1); +ADD(2); +LOOP(1); for(i=0, w=tmp; i>1)) + { +MAC(1); +DIV(1); +ADD(1); en += X.a[k]*X.a[k] / (Re*Re + Im*Im) ; + } + else + { +MAC(1); +DIV(1); +ADD(1); en += 2.0 * X.a[k]*X.a[k] / (Re*Re + Im*Im) ; + } + } + } +#undef WMC_TOOL_SKIP + + return ((float) en); + } + + + /*-------------------------------------------------------------------* + * erb_diff() + * + * ERB difference + *-------------------------------------------------------------------*/ + static + void erb_diff( + const float *prev_erb, /* i : previous ERB */ + int pl, /* i : previous lag */ + const float *curr_erb, /* i : current ERB */ + int l, /* i : current lag */ + const float *curr_lsp, /* i : current LSP coefficients */ + float *out, /* o : ERB difference */ + int *index, /* i : ERB index */ + short num_erb /* i : Number of ERBs */ + ) + { + short i, j; + int pslot[NUM_ERB_WB], cslot[NUM_ERB_WB], mmseindex ; + float tmp, tmp1, t_prev_erb[NUM_ERB_WB], LPC[M+1], mfreq[NUM_ERB_WB], PowSpect[NUM_ERB_WB], mmse ; + const float (*AmpCB1)[10] = 0; + +#define WMC_TOOL_SKIP + + if (num_erb==NUM_ERB_NB) + { + AmpCB1=AmpCB1_NB; + } + else if (num_erb==NUM_ERB_WB) + { + AmpCB1=AmpCB1_WB; + + } + +FUNC(3); erb_slot (l,cslot,mfreq,num_erb); +FUNC(3); erb_slot (pl,pslot,t_prev_erb,num_erb); +MOVE(1); +ADD(1); +LOOP(1); for(i=0,tmp=1.0f;il) + { +MOVE(1); tmp = t_prev_erb[0] ; +LOOP(1); for (i=0; ipl) + { +MOVE(1); tmp = t_prev_erb[num_erb-1] ; +ADD(1); +LOOP(1); for(i=num_erb-1; i>=0; i--) + { +LOGIC(1); if (pslot[i]!=0) + { +MOVE(1); tmp = t_prev_erb[i]; + } + else + { +MOVE(1); t_prev_erb[i] = tmp ; + } + } + } + +LOOP(1); for(i=0; i=0)) + { + mmseindex=0; + } + +MOVE(1); index[0] = mmseindex ; + + /* Second Band Amplitude Search */ +MOVE(1); mmse = (float) HUGE_VAL; +MOVE(1); mmseindex=-1 ; +LOOP(1); for(j=0; j=0)) + { + mmseindex=0; + } + +MOVE(1); index[1] = mmseindex; + +#undef WMC_TOOL_SKIP + + return; + } + + /*-------------------------------------------------------------------* + * erb_add() + * + * Add current and past ERB + *-------------------------------------------------------------------*/ + static + void erb_add( + float *curr_erb, /* i/o: current ERB */ + int l, /* i : current lag */ + const float *prev_erb, /* i : previous ERB */ + int pl, /* i : previous lag */ + const int *index, /* i : ERB index */ + short num_erb /* i : number of ERBs */ + ) + { + int i, pslot[NUM_ERB_WB], cslot[NUM_ERB_WB] ; + float tmp, t_prev_erb[NUM_ERB_WB] ; + const float (*AmpCB1)[10] = 0; + +#define WMC_TOOL_SKIP + + if (num_erb==NUM_ERB_NB) + { + AmpCB1=AmpCB1_NB; + } + else if (num_erb==NUM_ERB_WB) + { + AmpCB1=AmpCB1_WB; + } +FUNC(3); erb_slot (l, cslot, t_prev_erb, num_erb); +FUNC(3); erb_slot (pl, pslot, t_prev_erb, num_erb); + +LOOP(1); for(i=0; il) + { +MOVE(1); tmp = t_prev_erb[0] ; +LOOP(1); for(i=0; i=0)) + { + pslot[i] = 0; + } + +LOGIC(1); if(pslot[i]!=0) + { +MOVE(1); tmp = t_prev_erb[i] ; + } + else + { +MOVE(1); t_prev_erb[i] = tmp ; + } + } + } + else if (l>pl) + { +MOVE(1); tmp = t_prev_erb[num_erb-1] ; +ADD(1); +LOOP(1); for(i=num_erb-1; i>=0; i--) + { +LOGIC(1); if(pslot[i]!=0) + { +MOVE(1); tmp = t_prev_erb[i] ; + } + else + { +MOVE(1); t_prev_erb[i] = tmp ; + } + } + } + +LOOP(1); for(i=1; i<11; i++) + { +LOGIC(1); if(cslot[i]!=0) + { +MOVE(1); +ADD(1); curr_erb[i] = (float) (AmpCB1[index[0]][i-1] + t_prev_erb[i]) ; +MOVE(1); curr_erb[i] = max(0.0f, curr_erb[i]); + } + else + { +MOVE(1); curr_erb[i] = 0.0; + } + } +LOOP(1); for(i=11; i<(num_erb-2); i++) + { +LOGIC(1); if(cslot[i]!=0) + { +MOVE(1); if (num_erb==NUM_ERB_NB) + { +ADD(1); curr_erb[i] = (float)(AmpCB2_NB[index[1]][i-11] + t_prev_erb[i]) ; +MOVE(1); curr_erb[i] = max(0.0f, curr_erb[i]); + } + else if (num_erb==NUM_ERB_WB) + { +ADD(1); curr_erb[i] = (float)(AmpCB2_WB[index[1]][i-11] + t_prev_erb[i]) ; +MOVE(1); curr_erb[i] = max(0.0f, curr_erb[i]); + } + } + else + { +MOVE(1); curr_erb[i] = 0.0f; + } + } + +#undef WMC_TOOL_SKIP + + return; + + } + + /*-------------------------------------------------------------------* + * DTFS_quant_cw() + * + * DTFS quantization + *-------------------------------------------------------------------*/ + + short DTFS_quant_cw( + DTFS_STRUCTURE *X, /* i/o: DTFS unquant inp, quant out */ + int pl, /* i : Previous lag */ + const float *curr_lpc, /* i : LPC */ + int *POWER_IDX, /* o : Power index */ + int *AMP_IDX, /* o : Amplitude index */ + float *lastLgainE, /* i/o: last frame lowband gain */ + float *lastHgainE, /* i/o: last frame highband gain */ + float *lasterbE /* i/o: last frame ERB vector */ + ) + { + short num_erb = 0; + const float (*PowerCB)[2]=NULL; + float G_CURR_ERB[NUM_ERB_WB]; + float G_A_POWER[2]; + float tmp, w[2], target1, target2, error, minerror ; + float mfreq[NUM_ERB_WB], diff_erb[NUM_ERB_WB], curr_erb[NUM_ERB_WB] ; + int j, slot[NUM_ERB_WB],bincount; + short returnFlag = 1; + float amperror; + +#define WMC_TOOL_SKIP + + if (X->upper_cut_off_freq==4000.0) + { + num_erb=NUM_ERB_NB; + PowerCB=PowerCB_NB; + } + else if (X->upper_cut_off_freq==6400.0) + { + num_erb=NUM_ERB_WB; + PowerCB=PowerCB_WB; + } + + /* Getting the Speech Domain Energy LOG Ratio */ +FUNC(4); +MOVE(1); +LOG(1); w[0] = (float) max(1E-10, log10(DTFS_getSpEngyFromResAmp (*X,0.0,1104.5,curr_lpc))); +FUNC(4); +MOVE(1); + w[1] = (float) max(1E-10, log10(DTFS_getSpEngyFromResAmp (*X,1104.5,X->upper_cut_off_freq,curr_lpc))); +MOVE(1); +ADD(1); tmp = w[0]+w[1] ; +DIV(1); w[0] /= tmp; +DIV(1); w[1] /= tmp; + + /* Power Quantization */ +MOVE(1); +FUNC(6); +MULT(1); +LOG(1); G_A_POWER[0] = (float) log10(X->lag*DTFS_setEngyHarm (92.0,1104.5,0.0,1104.5,1.0,X)); +MOVE(1); +FUNC(6); +MULT(1); +LOG(1); G_A_POWER[1] = (float) log10(X->lag*DTFS_setEngyHarm (1104.5,X->upper_cut_off_freq_of_interest,1104.5,X->upper_cut_off_freq,1.0,X)); +MOVE(1); +ADD(1); target1 = G_A_POWER[0]-*lastLgainE ; +MOVE(1); +ADD(1); target2 = G_A_POWER[1]-*lastHgainE ; +MOVE(1); minerror=(float) HUGE_VAL ; +MOVE(1); *POWER_IDX=-1 ; +LOOP(1); for(j=0; j=PowerCB[j][0]) && (target2>=PowerCB[j][1])) + { +MULT(1); error*=0.8f ; + } +LOGIC(1); if(error < minerror) + { +MOVE(1); minerror = error ; +MOVE(1); *POWER_IDX = j ; + } + } +FUNC(2); DTFS_to_erb (*X,curr_erb) ; + +LOOP(1); for(j=0; jlag, slot, mfreq,num_erb) ; + /* Amplitude Quantization */ +FUNC(7); erb_diff (lasterbE, pl, curr_erb, X->lag, curr_lpc, diff_erb, AMP_IDX,num_erb) ; + + /* Amplitude Dequantization */ +FUNC(5); erb_add (curr_erb, X->lag, lasterbE, pl, AMP_IDX,num_erb) ; +MOVE(1); +MULT(1); curr_erb[0] = curr_erb[1] * 0.3f ; + curr_erb[num_erb-2] = curr_erb[num_erb-3] * 0.3f; + curr_erb[num_erb-1] = 0; + /* Determine if the amplitude quantization is good enough */ +MOVE(1); amperror=0.0; +MOVE(1); bincount=0; +LOOP(1); for(j=1;j<10;j++) + { +LOGIC(1); if(slot[j]!=0) + { +ADD(1); +ADD(1); +ABS(1); amperror += (float)(fabs(G_CURR_ERB[j]-curr_erb[j])); + bincount++; + } + } +DIV(1); amperror /= bincount ; + +LOGIC(1); if((amperror>0.47) && (target1>-0.4)) + { +MOVE(1); returnFlag = 0 ; /* Bumping up */ + } + +FUNC(4); DTFS_erb_inv (curr_erb, slot, mfreq, X,num_erb) ; + + /* Back up the lasterbE memory after power normalization */ +FUNC(6); DTFS_setEngyHarm (92.0,1104.5,0.0,1104.5,1.0,X) ; +FUNC(6); DTFS_setEngyHarm (1104.5,X->upper_cut_off_freq_of_interest,1104.5,X->upper_cut_off_freq,1.0,X) ; + + DTFS_to_erb(*X,lasterbE); + + /* Power Dequantization */ +ADD(1); *lastLgainE += (float) PowerCB[*POWER_IDX][0] ; +ADD(1); *lastHgainE += (float) PowerCB[*POWER_IDX][1] ; +MOVE(1); +MULT(1); +POWER(1); target1 = (float) pow(10.0, (double)(*lastLgainE))/X->lag ; + + if (!(target1 >= 0.0)) + { + target1 = 0; + } + +FUNC(6); DTFS_setEngyHarm (92.0f,1104.5f,0.0f,1104.5f,target1,X); +MOVE(1); +MULT(1); +POWER(1); target2 = (float) pow(10.0, (double)(*lastHgainE))/X->lag ; + + if (!(target2 >= 0.0)) + { + target2 = 0; + } + +FUNC(6); DTFS_setEngyHarm (1104.5,X->upper_cut_off_freq_of_interest,1104.5,X->upper_cut_off_freq,target2,X); +#undef WMC_TOOL_SKIP + + return returnFlag; /* amp quant performance pass/fail */ + } + + /*-------------------------------------------------------------------* + * DTFS_dequant_cw() + * + * DTFS dequantization + *-------------------------------------------------------------------*/ + + void DTFS_dequant_cw( + int pl, /* i : Previous lag */ + int POWER_IDX, /* i : POWER index */ + const int *AMP_IDX, /* i : Amp Shape index */ + float *lastLgainD, /* i/o: low band last gain */ + float *lastHgainD, /* i/o: high band last gain */ + float *lasterbD, /* i/o: last frame ERB vector */ + DTFS_STRUCTURE *X, /* o : DTFS structure dequantized */ + short num_erb /* i : Number of ERB bands */ + ) + { + float tmp, mfreq[NUM_ERB_WB], curr_erb[NUM_ERB_WB]; + int slot[NUM_ERB_WB] ; + const float (*PowerCB)[2]=NULL; + +#define WMC_TOOL_SKIP + + if (num_erb==NUM_ERB_NB) + { + PowerCB=PowerCB_NB; + } + else if (num_erb==NUM_ERB_WB) + { + PowerCB=PowerCB_WB; + } + + /* Amplitude Dequantization */ +FUNC(5); erb_add (curr_erb, X->lag, lasterbD, pl, AMP_IDX,num_erb) ; +MOVE(1); +MULT(1); curr_erb[0] = curr_erb[1] * 0.3f ; + curr_erb[num_erb-2] = curr_erb[num_erb-3] * 0.3f; + curr_erb[num_erb-1] = 0; +MOVE(1); +FUNC(3); erb_slot(X->lag, slot, mfreq,num_erb) ; +FUNC(4); DTFS_erb_inv(curr_erb, slot, mfreq, X,num_erb) ; + + /* Back up the lasterbD memory after power normalization */ +FUNC(6); DTFS_setEngyHarm(92.0,1104.5,0.0,1104.5,1.0,X) ; +FUNC(6); DTFS_setEngyHarm(1104.5,X->upper_cut_off_freq_of_interest,1104.5,X->upper_cut_off_freq,1.0,X) ; +FUNC(2); DTFS_to_erb(*X,lasterbD) ; + + /* Power Dequantization */ +ADD(1); *lastLgainD += (float) PowerCB[POWER_IDX][0] ; +ADD(1); *lastHgainD += (float) PowerCB[POWER_IDX][1] ; +MOVE(1); +MULT(1); +POWER(1); tmp = (float) pow(10.0, (double)(*lastLgainD))/X->lag ; + + if (!(tmp >= 0.0)) + { + tmp = 0.0; + } + +FUNC(6); DTFS_setEngyHarm (92.0,1104.5,0.0,1104.5,tmp,X) ; +MOVE(1); +MULT(1); +POWER(1); tmp = (float) pow(10.0, (double)(*lastHgainD))/X->lag ; + + if (!(tmp >= 0.0)) + { + tmp = 0.0; + } + +FUNC(6); DTFS_setEngyHarm (1104.5,X->upper_cut_off_freq_of_interest,1104.5,X->upper_cut_off_freq,tmp,X) ; + +#undef WMC_TOOL_SKIP + + return; + + } + + /*-------------------------------------------------------------------* + * WI_syn() + * + * Synthesis using waveform interpolation + *-------------------------------------------------------------------*/ + + void WIsyn( + DTFS_STRUCTURE PREVCW, /* i : Prev frame DTFS */ + DTFS_STRUCTURE *CURR_CW_DTFS, /* i/o: Curr frame DTFS */ + const float *curr_lpc, /* i : LPC */ + float *ph_offset, /* i/o: Phase offset to line up at end of frame */ + float *out, /* o : Waveform Interpolated time domain signal */ + int N, /* i : Number of output samples to generate */ + int FR_flag /* i : called for post-smoothing in FR */ + ) + { + DTFS_STRUCTURE *CURRCW_DTFS; + unsigned short I=1, flag=0; + float alignment, tmp, *phase; + +MOVE(1); + phase = (float *) calloc(N,sizeof(float)); +#define WMC_TOOL_SKIP + + CURRCW_DTFS = DTFS_new(); + +FUNC(2); DTFS_copy (CURRCW_DTFS,*CURR_CW_DTFS); + + /* Calculating the expected alignment shift */ +MOVE(1); +MULT(2); +INDIRECT(1); +INDIRECT(1); alignment = (float) (*ph_offset /PI2 * PREVCW.lag) ; +LOGIC(1); if(flag==1) + { +MULT(1); alignment *= I ; + } + /* Calculating the expected alignment shift */ +MOVE(1); +DIV(1); +ADD(2); +DIV(1); tmp = (float) fmod((N%((PREVCW.lag+CURRCW_DTFS->lag)>>1) + alignment), CURRCW_DTFS->lag) ; + + /* Compute the alignment shift */ + if (FR_flag==0) + { +FUNC(5); +MOVE(1); alignment = DTFS_alignment_weight (PREVCW, *CURRCW_DTFS, tmp, curr_lpc, curr_lpc) ; + } + else /* FR case */ + { +FUNC(5); +MOVE(1); alignment = DTFS_alignment_full(PREVCW, *CURRCW_DTFS, CURRCW_DTFS->lag*2); + } + +MOVE(1); +MULT(2); tmp = (float) (PI2*alignment/CURRCW_DTFS->lag) ; +FUNC(2); DTFS_phaseShift (CURRCW_DTFS,tmp) ; +FUNC(2); +MULT(2); DTFS_phaseShift (CURR_CW_DTFS,(float) (PI2*alignment/CURR_CW_DTFS->lag)) ; + + /* Compute the cubic phase track and transform to 1-D signal */ +FUNC(6); cubicPhase (*ph_offset, tmp, (float) PREVCW.lag , (float) CURRCW_DTFS->lag, N, phase) ; + + if (FR_flag==0) + { +FUNC(6); DTFS_transform (PREVCW, *CURRCW_DTFS, phase, out, N,0) ; + } + else + { +FUNC(6); DTFS_transform (PREVCW, *CURRCW_DTFS, phase, out, N,1) ; + } + + /* Adjust the phase offset and wrap it between 0 and 2pi */ +LOGIC(1); if( flag == 2 ) + { +MULT(1); tmp *= I ; + } +MOVE(1); +DIV(1); *ph_offset = (float) fmod ((double)(tmp), PI2) ; + +#undef WMC_TOOL_SKIP + free(phase) ; + free(CURRCW_DTFS); + return; + } + + + /*-------------------------------------------------------------------* + * ppp_extract_pitch_period() + * + * Pitch period extraction + *-------------------------------------------------------------------*/ + + short ppp_extract_pitch_period( + const float *in, /* i : input residual */ + float *out, /* o : output residual */ + int l, /* i : lag */ + short *out_of_bound /* o : out of bound flag */ + ) + { + int i,j,k; + int spike=0,range; + float max1=0.0; + const float *ptr=in+L_FRAME-l; + float en1=0.0, en2=0.0, tmp; + short spike_near_edge=0; + float pos_max,neg_max; + int spike_pos=0,spike_neg=0; + float x; +#define WMC_TOOL_SKIP + + pos_max = (float) -HUGE_VAL; + neg_max = 0.0; +MOVE(1); *out_of_bound = 0; + +LOOP(1); for(i=0;imax1) + { +MOVE(1); max1=x; +MOVE(1); spike=i; + } +MULT(1); +ADD(1); en1 += ptr[i]*ptr[i] ; + } + + if (ptr[spike]>0) + { + spike_pos=spike; + + /* search for neg spike around the pos spike */ + for(j=spike-10;jpos_max) + { + pos_max=ptr[k]; + spike_pos=k; + } + } + } + if (((l-1-max(spike_pos,spike_neg))<=2) ||(min(spike_pos,spike_neg)<=2)) + { + *out_of_bound=1; +#undef WMC_TOOL_SKIP + return spike_near_edge; +#define WMC_TOOL_SKIP + } +MOVE(1); +FUNC(1); +MULT(1); range=(int)anint (max(CUTFREE_REL_RANGE*l,CUTFREE_ABS_RANGE)); +ADD(1); +ADD(1); +LOGIC(1); if((spike-range<0) || (spike+range>=l)) + { + /* need to grab from one lag before + ensure that there is no array bound read */ +ADD(2); +LOGIC(1); if(L_FRAME -l -l < 0) + { +MOVE(1); *out_of_bound=1; +#undef WMC_TOOL_SKIP + return spike_near_edge; +#define WMC_TOOL_SKIP + } + spike_near_edge=1; + } +ADD(1); +LOGIC(1); if(spike-range<0) + { +ADD(1); +ADD(1); +LOOP(1); for(i=0;i=l) + { +ADD(1); +LOOP(1); for(i=0;i=in) + { +ADD(1); +LOOP(1); for(ptr-=l;i= 0) + { +LOGIC(1); if(tmp>maxPosEn) + { +MOVE(1); maxPosEn = tmp ; + } + } + else + { +LOGIC(1); if(tmp>maxNegEn) + { +MOVE(1); maxNegEn = tmp ; + } + } +ADD(1); sum += tmp ; + } + +LOGIC(1); if (sum==0.0) + { +MOVE(2); *pos = 0.0f; + *neg = 0.0f; + } + else + { +MOVE(1); +MULT(1); +DIV(1); +SQRT(1); *pos = (float) sqrt(maxPosEn*X.lag/sum); +MOVE(1); +MULT(1); +DIV(1); +SQRT(1); *neg = (float) sqrt(maxNegEn*X.lag/sum); + } +#undef WMC_TOOL_SKIP + + return; + } + diff --git a/lib_com/window.c b/lib_com/window.c new file mode 100644 index 000000000..fc11ff0c2 --- /dev/null +++ b/lib_com/window.c @@ -0,0 +1,40 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + + +#include "wmc_auto.h" +#include +#include "options.h" +#include "prot.h" + +/*------------------------------------------------------------------- + * ham_cos_window() + * + * + *-------------------------------------------------------------------*/ + +void ham_cos_window( + float *fh, + int n1, + int n2 +) +{ + float cc, cte; + int i; + cte = PI2/(float)(2*n1 - 1); + cc = 0.0f; + for (i = 0; i < n1; i++) + { + *fh++ = 0.54f - 0.46f * (float)cos(cc); + cc += cte; + } + cte = PI2/(float)(4*n2 - 1); + cc = 0.0f; + for (i = 0; i < n2; i++) + { + *fh++ = (float)cos(cc); + cc += cte; + } + return; +} diff --git a/lib_com/window_ola.c b/lib_com/window_ola.c new file mode 100644 index 000000000..32239b779 --- /dev/null +++ b/lib_com/window_ola.c @@ -0,0 +1,436 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------------- +* window_ola() +* +* Windowing, Overlap and Add +*--------------------------------------------------------------------------*/ + + +void window_ola( + const float *ImdctOut, /* i : input */ + float *auOut, /* o : output audio */ + float *OldauOut, /* i/o: audio from previous frame */ + const short L, /* i : length */ + const short right_mode, + const short left_mode, /* window overlap of current frame (0: full, 2: none, or 3: half) */ + const short use_bfi_win, /* i : use BFI windowing */ + const short oldHqVoicing, /* i : previous HqVoicing */ + float *oldgapsynth /* i : previous gapsynth */ +) +{ + short i, decimate, decay; + short n ,n16, windecay48, windecay16; + float win_right[R2_48]; + float win_int_left[R1_16]; + float win_left[R1_48]; + float win_int_right[R2_16]; + + + float SS2[L_FRAME48k-NS2SA(48000, N_ZERO_MDCT_NS)]; + float wret2[L_FRAME48k-NS2SA(48000, N_ZERO_MDCT_NS)]; + + float *paout; + + + n = (short)((float)L*N_ZERO_MDCT_NS/FRAME_SIZE_NS); + n16 = (short)((float)L_FRAME16k*N_ZERO_MDCT_NS/FRAME_SIZE_NS); + windecay48 = (short)(2*((float)L_FRAME48k*N_ZERO_MDCT_NS/FRAME_SIZE_NS))+R1_48; + windecay16 = (short)(2*((float)L_FRAME16k*N_ZERO_MDCT_NS/FRAME_SIZE_NS))+R1_16; + decimate = 1; + decay = 0; + + tcx_get_windows_mode1( left_mode, right_mode, win_left, win_right, win_int_left, win_int_right, L); + + if ( L == L_FRAME32k || L == L_FRAME16k ) + { + decimate = 3; + decay = 1; + } + else if ( L == L_FRAME8k ) + { + decimate = 6; + decay = 2; + } + + else if (L == 512) + { + windecay48 = (short)(2*((float)512*N_ZERO_MDCT_NS/FRAME_SIZE_NS))+R1_25; + decimate = 1; + decay = 0; + } + else if (L== 256) + { + windecay48 = (short)(2*((float)512*N_ZERO_MDCT_NS/FRAME_SIZE_NS))+R1_25; + decimate = 2; + decay = 0; + } + + paout=auOut-n; + + if( use_bfi_win ) + { + if ( L == L_FRAME32k ) + { + for (i = 0; i < L/2; i+=2) + { + wret2[L/2-n + i +1] = win_left[(L_FRAME16k/2-i/2-1)*decimate+decay]; + wret2[L/2-n + i] = win_int_left[(L_FRAME16k/2-i/2-1)]; + } + + for (i = n; i < L/2; i+=2) + { + wret2[ i -n] = win_left[(L_FRAME16k-i/2)*decimate-decay-1]; + wret2[ i +1-n] = win_int_left[L_FRAME16k-(i/2)-1]; + } + } + else + { + for (i = 0; i < L/2; i++) + { + wret2[i+L/2-n] = win_left[(L/2-i-1)*decimate+decay]; + } + + for (i =n; i < L/2; i++) + { + wret2[i-n] = win_left[(L-i)*decimate-decay-1]; + } + } + sinq(EVS_PI/(2*(L-n)), EVS_PI/(4*(L-n)), L-n, SS2); + + for (i = n; i < L/2; i++) + { + paout[i] = ImdctOut[L/2 + i]; + } + + for (i = 0; i < L/2; i++) + { + paout[L/2 + i] = -ImdctOut[L - 1 - i]; + } + + if( oldHqVoicing ) + { + for (i=0 ; i < L-n; i++) + { + auOut[i] = auOut[i]*SS2[i]+ oldgapsynth[i+n]*(SS2[L-n-i-1]); + } + } + else + { + for (i=0 ; i < L-n; i++) + { + auOut[i] =auOut[i]*SS2[i]+ OldauOut[i+n]*(SS2[L-n-i-1])/(wret2[i]+0.01f); + } + } + } + + if ( L == L_FRAME32k ) + { + if (use_bfi_win==0) + { + for (i = n; i < L/2; i+=2) + { + paout[i] = ImdctOut[L/2 + i] * win_right[(2*L_FRAME16k-(n16+(i-n)/2))*decimate-1-decay-windecay48]+OldauOut[i]; + paout[i+1] = ImdctOut[L/2 + i +1] * win_int_right[2*L_FRAME16k-(n16+(i-n)/2)-1-windecay16]+OldauOut[i+1]; + } + + for (i = 0; i < L/2-n; i+=2) + { + paout[L/2 + i +1] = -ImdctOut[L - 1 - (i+1)] * win_right[(3*L_FRAME16k/2-1-i/2)*decimate+decay-windecay48]+OldauOut[i+L/2+1]; + paout[L/2 + i ] = -ImdctOut[L - 1 - i] * win_int_right[(3*L_FRAME16k/2-1-i/2)-windecay16]+OldauOut[i+L/2]; + } + + for (i = L/2-n; i < L/2; i+=2) + { + paout[L/2 + i +1] = -ImdctOut[L - 1 - (i+1)]+OldauOut[i+L/2+1] ; + paout[L/2 + i ] = -ImdctOut[L - 1 - i]+OldauOut[i+L/2]; + } + } + + for (i = 0; i < L/2; i+=2) + { + OldauOut[L/2 + i +1] = -ImdctOut[i+1] * win_left[(L_FRAME16k/2-i/2-1)*decimate+decay]; + OldauOut[L/2 + i] = -ImdctOut[i] * win_int_left[(L_FRAME16k/2-i/2-1)]; + } + + + for (i = n; i < L/2; i+=2) + { + OldauOut[ i] = -ImdctOut[L/2 - 1 - i] *win_left[(L_FRAME16k-i/2)*decimate-decay-1]; + OldauOut[ i +1] = -ImdctOut[L/2 - 1 - (i +1)] * win_int_left[L_FRAME16k-(i/2)-1]; + } + } + else + { + if (use_bfi_win==0) + { + + for (i = n; i < L/2; i++) + { + paout[i] = ImdctOut[L/2 + i] * win_right[(2*L-i)*decimate-1-decay-windecay48]+OldauOut[i]; + } + + for (i = 0; i < L/2-n; i++) + { + paout[L/2 + i] = -ImdctOut[L - 1 - i] * win_right[(3*L/2-1-i)*decimate+decay-windecay48]+OldauOut[i+L/2]; + } + for (i = L/2-n; i < L/2; i++) + { + paout[L/2 + i] = -ImdctOut[L - 1 - i] + OldauOut[i+L/2]; + } + } + + for (i = 0; i < L/2; i++) + { + OldauOut[L/2 + i] = -ImdctOut[i] * win_left[(L/2-i-1)*decimate+decay]; + } + + + for (i = n; i < L/2; i++) + { + OldauOut[ i] = -ImdctOut[L/2 - 1 - i] * win_left[(L-i)*decimate-decay-1]; + } + + + } + + for (i = 0; i < n; i++) + { + OldauOut[i] = -ImdctOut[L/2 - 1 - i]; + } + for (i = 0; i < n; i++) + { + paout[L + i] = OldauOut[i]; + } + + return; +} + +/*---------------------------------------------------------------------* +* core_switching_OLA() +* +* modify window after HQ core decoding +* Overlap ACELP and HQ +*---------------------------------------------------------------------*/ + +void core_switching_OLA( + const float *mem_over_hp, /* i : upsampling filter memory */ + const short last_L_frame, /* i : last L_frame lengthture */ + const int output_Fs, /* i : output sampling rate */ + float *synth, /* i/o: synthesized signal from HQ core */ + const float *synth_subfr_out, /* i : synthesized signal from ACELP core */ + float *synth_subfr_bwe, /* i : synthesized BWE from ACELP core */ + const short output_frame, /* i : output frame length */ + const short bwidth /* i : output bandwidth */ +) +{ + short i, L, Loverlapp, out_filt_length, filt_delay, decimate, decay; + float tmp_buf_switch[SWITCH_MAX_GAP], tmp_buf_switch2[HQ_DELAY_COMP*HQ_DELTA_MAX+2]; + float delta; + const float *win, *win_int; + + win = window_48kHz; + win_int = window_8_16_32kHz; + decimate = 1; + decay = 0; + + if( output_frame == L_FRAME32k || output_frame == L_FRAME16k ) + { + decimate = 3; + decay = 1; + } + else if( output_frame == L_FRAME8k ) + { + decimate = 6; + decay = 2; + } + + /* set multiplication factor according to the sampling rate */ + delta = 1; + if( output_frame == L_FRAME16k ) + { + delta = 2; + } + else if( output_frame == L_FRAME32k ) + { + delta = 4; + } + else if( output_frame == L_FRAME48k ) + { + delta = 6; + } + + set_f( tmp_buf_switch, 0, SWITCH_MAX_GAP ); + set_f( tmp_buf_switch2, 0, HQ_DELAY_COMP*HQ_DELTA_MAX+2); + + Loverlapp = (short)(delta*SWITCH_OVERLAP_8k); + + mvr2r( synth_subfr_out,tmp_buf_switch, NS2SA(output_Fs, SWITCH_GAP_LENGTH_NS)); /* copy 6.25 ms subframe */ + + /* conversion from 12.8kHz to output_Fs */ + if( last_L_frame == L_FRAME) + { + /* resample filter memory */ + if( output_frame == L_FRAME8k ) + { + mvr2r( synth_subfr_out + NS2SA(output_Fs, SWITCH_GAP_LENGTH_NS), tmp_buf_switch+NS2SA(output_Fs,SWITCH_GAP_LENGTH_NS),NS2SA(output_Fs, DELAY_CLDFB_NS)); /* copy subframe to tmp buffer */ + } + else + { + out_filt_length = modify_Fs_intcub3m_sup( mem_over_hp+2, NS2SA(12800,DELAY_CLDFB_NS), 12800, tmp_buf_switch2, output_Fs , &filt_delay ); + + for( i=0; i=16000) || (bwidth > NB && output_Fs>16000) ) + { + /* mix cubic and CLDFB resampled buffers in case of resampling to higher frequency rates */ + for(i=0; i=16000) || (bwidth > NB && output_Fs>16000) ) + { + /* mix cubic and CLDFB resampled buffers in case of resampling to higher frequency rates */ + for(i=0; i 0.0001f) + { + A = (x[2]+x[0])/x[1]; + } + else + { + A = 0; + } + + for (i=3; i + + +/*--------------------------------------------------------------------------* +* mvr2r_inv() +* +* +*--------------------------------------------------------------------------*/ + +static void mvr2r_inv( + const float *in, + float *out, + short L, + short decimate +) +{ + short i; + + in=in+(short) ((decimate-1)/2); + out=out+L-1; + + for (i=0; i +#include +#include +#include +#include +#include + +#ifndef _MSC_VER +#include +#include +#else +#include +#endif + +#include "wmc_auto.h" + +#define WMC_TOOL_SKIP /* Skip the instrumentation of this file, if invoked by accident */ + +#ifdef WMOPS + +/*-------------------------------------------------------------------* + * Complexity counting tool + *--------------------------------------------------------------------*/ + +#define MAX_FUNCTION_NAME_LENGTH 200 /* Maximum length of the function name */ +#define MAX_PARAMS_LENGTH 200 /* Maximum length of the function parameter string */ +#define MAX_NUM_RECORDS 300 /* Initial maximum number of records -> might be increased during runtime, if needed */ +#define MAX_NUM_RECORDS_REALLOC_STEP 50 /* When re-allocating the list of records, increase the number of records by this number */ +#define MAX_CALL_TREE_DEPTH 100 /* maximum depth of the function call tree */ +#define DOUBLE_MAX 0x80000000 +#define FAC ( FRAMES_PER_SECOND / 1e6 ) + + +typedef struct +{ + char label[MAX_FUNCTION_NAME_LENGTH]; + long call_number; + long update_cnt; + int call_tree[MAX_CALL_TREE_DEPTH]; + long LastWOper; + double start_selfcnt; + double current_selfcnt; + double max_selfcnt; + double min_selfcnt; + double tot_selfcnt; + double start_cnt; + double current_cnt; + double max_cnt; + double min_cnt; + double tot_cnt; +#ifdef WMOPS_WC_FRAME_ANALYSIS + int32_t current_call_number; + double wc_cnt; + double wc_selfcnt; + int32_t wc_call_number; +#endif +} wmops_record; + +double ops_cnt; +double prom_cnt; +double inst_cnt[NUM_INST]; + +static wmops_record *wmops = NULL; +static int num_wmops_records, max_num_wmops_records; +static int current_record; +static long update_cnt; +static double start_cnt; +static double max_cnt; +static double min_cnt; +static double inst_cnt_wc[NUM_INST]; +static long fnum_cnt_wc; +static int *wmops_caller_stack = NULL, wmops_caller_stack_index, max_wmops_caller_stack_index = 0; +static int *heap_allocation_call_tree = NULL, heap_allocation_call_tree_size = 0, heap_allocation_call_tree_max_size = 0; + +void reset_wmops( void ) +{ + int i, j; + unsigned int *ptr; + + num_wmops_records = 0; + max_num_wmops_records = MAX_NUM_RECORDS; + current_record = -1; + update_cnt = 0; + + max_cnt = 0.0; + min_cnt = DOUBLE_MAX; + start_cnt = 0.0; + ops_cnt = 0.0; + + /* allocate the list of wmops records */ + if ( wmops == NULL ) + { + wmops = (wmops_record *)malloc( max_num_wmops_records * sizeof( wmops_record ) ); + } + + if ( wmops == NULL ) + { + fprintf( stderr, "Error: Unable to Allocate List of WMOPS Records!" ); + exit( -1 ); + } + + /* allocate the BASOP WMOPS counter */ + if ( multiCounter == NULL ) + { + multiCounter = (BASIC_OP *) malloc( max_num_wmops_records * sizeof( BASIC_OP ) ); + } + + if ( multiCounter == NULL ) + { + fprintf( stderr, "Error: Unable to Allocate the BASOP WMOPS counter!" ); + exit( -1 ); + } + + /* initilize the list of WMOPS records */ + /* initilize the BASOP WMOPS counters */ + for ( i = 0; i < max_num_wmops_records; i++ ) + { + strcpy( &wmops[i].label[0], "\0" ); + wmops[i].call_number = 0; + wmops[i].update_cnt = 0; + for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ ) + { + wmops[i].call_tree[j] = -1; + } + wmops[i].start_selfcnt = 0.0; + wmops[i].current_selfcnt = 0.0; + wmops[i].max_selfcnt = 0.0; + wmops[i].min_selfcnt = DOUBLE_MAX; + wmops[i].tot_selfcnt = 0.0; + wmops[i].start_cnt = 0.0; + wmops[i].current_cnt = 0.0; + wmops[i].max_cnt = 0.0; + wmops[i].min_cnt = DOUBLE_MAX; + wmops[i].tot_cnt = 0.0; +#ifdef WMOPS_WC_FRAME_ANALYSIS + wmops[i].wc_cnt = 0.0; + wmops[i].wc_selfcnt = 0.0; + wmops[i].current_call_number = 0; + wmops[i].wc_call_number = -1; +#endif + + /* clear all BASOP operation counters */ + ptr = (unsigned int*) &multiCounter[i]; + for ( j = 0; j < (int) ( sizeof(BASIC_OP ) / sizeof( unsigned int ) ); j++ ) + { + *ptr++ = 0; + } + wmops[i].LastWOper = 0; + } + + /* allocate the list of wmops callers to track the sequence of function calls */ + wmops_caller_stack_index = 0; + max_wmops_caller_stack_index = MAX_NUM_RECORDS; + if ( wmops_caller_stack == NULL ) + { + wmops_caller_stack = malloc( max_wmops_caller_stack_index * sizeof( int ) ); + } + + if ( wmops_caller_stack == NULL ) + { + fprintf( stderr, "Error: Unable to Allocate List of WMOPS Callers!" ); + exit( -1 ); + } + + for ( i = 0; i < max_wmops_caller_stack_index; i++ ) + { + wmops_caller_stack[i] = -1; + } + + /* initialize auxiliary BASOP WMOPS variables */ + call_occurred = 1; + funcId_where_last_call_to_else_occurred = INT_MAX; + + return; +} + +void push_wmops_fct( const char *label, ... ) +{ + int new_flag; + int i, j, index_record; + unsigned int *ptr; + va_list arg; + char func_name[MAX_FUNCTION_NAME_LENGTH] = ""; + + /* concatenate all function name labels into a single string */ + va_start( arg, label ); + while ( label ) + { + strcat( func_name, label ); + label = va_arg( arg, const char * ); + } + va_end( arg ); + + /* Check, if this is a new function label */ + new_flag = 1; + for ( i = 0; i < num_wmops_records; i++ ) + { + if ( strcmp( wmops[i].label, func_name ) == 0 ) + { + new_flag = 0; + break; + } + } + index_record = i; + + /* Create a new record in the list */ + if ( new_flag ) + { + if ( num_wmops_records >= max_num_wmops_records ) + { + /* There is no room for a new WMOPS record -> reallocate the list */ + max_num_wmops_records += MAX_NUM_RECORDS_REALLOC_STEP; + wmops = realloc( wmops, max_num_wmops_records * sizeof( wmops_record ) ); + multiCounter = realloc( multiCounter, max_num_wmops_records * sizeof( BASIC_OP ) ); + + /* initilize newly created WMOPS records */ + for ( i = num_wmops_records; i < max_num_wmops_records; i++ ) + { + strcpy( &wmops[i].label[0], "\0" ); + wmops[i].call_number = 0; + wmops[i].update_cnt = 0; + for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ ) + { + wmops[i].call_tree[j] = -1; + } + wmops[i].start_selfcnt = 0.0; + wmops[i].current_selfcnt = 0.0; + wmops[i].max_selfcnt = 0.0; + wmops[i].min_selfcnt = DOUBLE_MAX; + wmops[i].tot_selfcnt = 0.0; + wmops[i].start_cnt = 0.0; + wmops[i].current_cnt = 0.0; + wmops[i].max_cnt = 0.0; + wmops[i].min_cnt = DOUBLE_MAX; + wmops[i].tot_cnt = 0.0; +#ifdef WMOPS_WC_FRAME_ANALYSIS + wmops[i].wc_cnt = 0.0; + wmops[i].wc_selfcnt = 0.0; + wmops[i].current_call_number = 0; + wmops[i].wc_call_number = -1; +#endif + + /* initialize BASOP WMOPS counters */ + ptr = (unsigned int *) &multiCounter[i]; + for ( j = 0; j < (int) ( sizeof( BASIC_OP ) / sizeof( unsigned int ) ); j++ ) + { + *ptr++ = 0; + } + wmops[i].LastWOper = 0; + } + + } + + strcpy( wmops[index_record].label, func_name ); + + num_wmops_records++; + } + + /* Push the current context info to the new record */ + if ( current_record >= 0 ) + { + if ( wmops_caller_stack_index >= max_wmops_caller_stack_index ) + { + /* There is no room for a new record -> reallocate the list */ + max_wmops_caller_stack_index += MAX_NUM_RECORDS_REALLOC_STEP; + wmops_caller_stack = realloc( wmops_caller_stack, max_wmops_caller_stack_index * sizeof( int ) ); + } + wmops_caller_stack[wmops_caller_stack_index++] = current_record; + + /* accumulate op counts */ + wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt; + + /* update call tree */ + for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ ) + { + if ( wmops[index_record].call_tree[j] == current_record ) + { + break; + } + else if ( wmops[index_record].call_tree[j] == -1 ) + { + wmops[index_record].call_tree[j] = current_record; + break; + } + } + } + + /* update the current context info */ + current_record = index_record; + wmops[index_record].start_selfcnt = ops_cnt; + wmops[index_record].start_cnt = ops_cnt; + wmops[index_record].call_number++; +#ifdef WMOPS_WC_FRAME_ANALYSIS + wmops[index_record].current_call_number++; +#endif + + /* set the ID of BASOP functions counters */ + Set_BASOP_WMOPS_counter( index_record ); + + return; +} + + +void pop_wmops( void ) +{ + long tot; + + /* Check for underflow */ + if ( current_record < 0 ) + { + fprintf( stdout, "\r pop_wmops(): stack underflow, too many calls to pop_wmops()\n" ); + exit( -1 ); + } + + /* add the BASOP complexity to the counter */ + tot = DeltaWeightedOperation(); + ops_cnt += tot; + + /* update count of current record */ + wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt; + wmops[current_record].current_cnt += ops_cnt - wmops[current_record].start_cnt; + + /* Get back previous context from stack */ + if ( wmops_caller_stack_index > 0 ) + { + current_record = wmops_caller_stack[--wmops_caller_stack_index]; + wmops[current_record].start_selfcnt = ops_cnt; + + /* set the ID of the previous BASOP counter */ + Set_BASOP_WMOPS_counter( current_record ); + } + else + { + current_record = -1; + } + + + return; +} + + +void update_wmops( void ) +{ + int i; + double current_cnt; +#ifdef WMOPS_PER_FRAME + static FILE *fid = NULL; + const char filename[] = "wmops_analysis"; + float tmpF; +#endif + + if ( wmops_caller_stack_index != 0 ) + { + fprintf( stdout, "update_wmops(): WMOPS caller stack corrupted - check that all push_wmops() are matched with pop_wmops()!\n" ); + exit( -1 ); + } + +#ifdef WMOPS_PER_FRAME + /* Check, if the output file has already been opened */ + if ( fid == NULL ) + { + fid = fopen( filename, "wb" ); + + if ( fid == NULL ) + { + fprintf( stderr, "\nCannot open %s!\n\n", filename ); + exit( -1 ); + } + } + + /* Write current complexity to the external file */ + tmpF = (float) ( FAC * wmops[0].current_cnt ); + fwrite( &tmpF, sizeof( float ), 1, fid ); +#endif + +#ifdef WMOPS_WC_FRAME_ANALYSIS + if ( ops_cnt - start_cnt > max_cnt ) + { + for ( i = 0; i < num_wmops_records; i++ ) + { + wmops[i].wc_cnt = wmops[i].current_cnt; + wmops[i].wc_selfcnt = wmops[i].current_selfcnt; + wmops[i].wc_call_number = wmops[i].current_call_number; + } + } +#endif + + for ( i = 0; i < num_wmops_records; i++ ) + { + wmops[i].tot_selfcnt += wmops[i].current_selfcnt; + wmops[i].tot_cnt += wmops[i].current_cnt; + + if ( wmops[i].current_selfcnt > 0 ) + { + if ( wmops[i].current_selfcnt > wmops[i].max_selfcnt ) + { + wmops[i].max_selfcnt = wmops[i].current_selfcnt; + } + + if ( wmops[i].current_selfcnt < wmops[i].min_selfcnt ) + { + wmops[i].min_selfcnt = wmops[i].current_selfcnt; + } + } + + wmops[i].current_selfcnt = 0; + + if ( wmops[i].current_cnt > 0 ) + { + if ( wmops[i].current_cnt > wmops[i].max_cnt ) + { + wmops[i].max_cnt = wmops[i].current_cnt; + } + + + if ( wmops[i].current_cnt < wmops[i].min_cnt ) + { + wmops[i].min_cnt = wmops[i].current_cnt; + } + + wmops[i].update_cnt++; + } + + wmops[i].current_cnt = 0; +#ifdef WMOPS_WC_FRAME_ANALYSIS + wmops[i].current_call_number = 0; +#endif + + /* update the WC of all BASOP counters */ + Set_BASOP_WMOPS_counter( i ); + Reset_BASOP_WMOPS_counter(); + } + + current_cnt = ops_cnt - start_cnt; + if ( current_cnt > max_cnt ) + { + max_cnt = current_cnt; + + for ( i = 0; i < NUM_INST; i++ ) + { + inst_cnt_wc[i] = inst_cnt[i]; + } + + fnum_cnt_wc = update_cnt + 1; + } + + if ( current_cnt < min_cnt ) + { + min_cnt = current_cnt; + } + + for ( i = 0; i < NUM_INST; i++ ) + { + inst_cnt[i] = 0.0; + } + + start_cnt = ops_cnt; + + /* increment frame counter */ + update_cnt++; + + return; +} + + +void print_wmops( void ) +{ + int i, label_len, max_label_len; + + char *sfmts = "%*s %8s %8s %7s %7s\n"; + char *dfmts = "%*s %8.2f %8.3f %7.3f %7.3f\n"; + char *sfmt = "%*s %8s %8s %7s %7s %7s %7s %7s\n"; + char *dfmt = "%*s %8.2f %8.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n"; + +#ifdef WMOPS_WC_FRAME_ANALYSIS + int j; + char *sfmtt = "%20s %4s %15s\n"; + char *dfmtt = "%20s %4d "; +#endif + + /* calculate maximum label length for compact prinout */ + max_label_len = 0; + for ( i = 0; i < num_wmops_records; i++ ) + { + label_len = strlen( wmops[i].label ); + if ( label_len > max_label_len ) + { + max_label_len = label_len; + } + } + max_label_len += 4; + + fprintf( stdout, "\n\n --- Complexity analysis [WMOPS] --- \n\n" ); + + fprintf( stdout, "%*s %33s %23s\n", max_label_len, "", "|------ SELF ------|", "|--- CUMULATIVE ---|" ); + fprintf( stdout, sfmt, max_label_len, " routine", " calls", " min ", " max ", " avg ", " min ", " max ", " avg " ); + fprintf( stdout, sfmt, max_label_len, "---------------", "------", "------", "------", "------", "------", "------", "------" ); + + for ( i = 0; i < num_wmops_records; i++ ) + { + fprintf( stdout, dfmt, max_label_len, wmops[i].label, update_cnt == 0 ? 0 : (float) wmops[i].call_number / update_cnt, + wmops[i].min_selfcnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_selfcnt, + FAC * wmops[i].max_selfcnt, + wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_selfcnt / wmops[i].update_cnt, + wmops[i].min_cnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_cnt, + FAC * wmops[i].max_cnt, + wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_cnt / wmops[i].update_cnt ); + } + + fprintf( stdout, sfmts, max_label_len, "---------------", "------", "------", "------", "------" ); + fprintf( stdout, dfmts, max_label_len, "total", (float) update_cnt, update_cnt == 0 ? 0 : FAC * min_cnt, FAC * max_cnt, update_cnt == 0 ? 0 : FAC * ops_cnt / update_cnt ); + fprintf( stdout, "\n" ); + +#ifdef WMOPS_WC_FRAME_ANALYSIS + fprintf( stdout, "\nComplexity analysis for the worst-case frame %ld:\n\n", fnum_cnt_wc ); + fprintf( stdout, "%*s %8s %10s %12s\n", max_label_len, " routine", " calls", " SELF", " CUMULATIVE" ); + fprintf( stdout, "%*s %8s %10s %10s\n", max_label_len, "---------------", "------", "------", "----------" ); + + for ( i = 0; i < num_wmops_records; i++ ) + { + if ( wmops[i].wc_call_number > 0 ) + { + fprintf( stdout, "%*s %8d %10.3f %12.3f\n", max_label_len, wmops[i].label, wmops[i].wc_call_number, FAC * wmops[i].wc_selfcnt, FAC * wmops[i].wc_cnt ); + } + } + + fprintf( stdout, "\nCall tree for the worst-case frame %ld:\n\n", fnum_cnt_wc ); + fprintf( stdout, sfmtt, " function", "num", "called by " ); + fprintf( stdout, sfmtt, "---------------", "---", "--------------" ); + + for ( i = 0; i < num_wmops_records; i++ ) + { + if ( wmops[i].wc_call_number > 0 ) + { + fprintf( stdout, dfmtt, wmops[i].label, i ); + for ( j = 0; wmops[i].call_tree[j] != -1 && j < MAX_CALL_TREE_DEPTH; j++ ) + { + if ( j != 0 ) + { + fprintf( stdout, ", " ); + } + fprintf( stdout, "%d", wmops[i].call_tree[j] ); + } + fprintf( stdout, "\n" ); + } + } + + fprintf( stdout, "\n\n" ); + + fprintf( stdout, "\nInstruction type analysis for the worst-case frame %ld:\n\n", fnum_cnt_wc ); + for ( i = 0; i < NUM_INST; i++ ) + { + switch ( (enum instructions) i ) + { + case _ADD: + fprintf( stdout, "\tAdds: %12.1f\n", inst_cnt_wc[i] ); + break; + case _ABS: + fprintf( stdout, "\tAbsolutes: %12.1f\n", inst_cnt_wc[i] ); + break; + case _MULT: + fprintf( stdout, "\tMultiplies: %12.1f\n", inst_cnt_wc[i] ); + break; + case _MAC: + fprintf( stdout, "\tMACs: %12.1f\n", inst_cnt_wc[i] ); + break; + case _MOVE: + fprintf( stdout, "\tMoves: %12.1f\n", inst_cnt_wc[i] ); + break; + case _STORE: + fprintf( stdout, "\tStores: %12.1f\n", inst_cnt_wc[i] ); + break; + case _LOGIC: + fprintf( stdout, "\tLogicals: %12.1f\n", inst_cnt_wc[i] ); + break; + case _SHIFT: + fprintf( stdout, "\tShifts: %12.1f\n", inst_cnt_wc[i] ); + break; + case _BRANCH: + fprintf( stdout, "\tBranches: %12.1f\n", inst_cnt_wc[i] ); + break; + case _DIV: + fprintf( stdout, "\tDivisions: %12.1f\n", inst_cnt_wc[i] ); + break; + case _SQRT: + fprintf( stdout, "\tSquare Root: %12.1f\n", inst_cnt_wc[i] ); + break; + case _TRANS: + fprintf( stdout, "\tTrans: %12.1f\n", inst_cnt_wc[i] ); + break; + case _FUNC: + fprintf( stdout, "\tFunc Call: %12.1f\n", inst_cnt_wc[i] ); + break; + case _LOOP: + fprintf( stdout, "\tLoop Init: %12.1f\n", inst_cnt_wc[i] ); + break; + case _INDIRECT: + fprintf( stdout, "\tIndirect Addr: %12.1f\n", inst_cnt_wc[i] ); + break; + case _PTR_INIT: + fprintf( stdout, "\tPointer Init: %12.1f\n", inst_cnt_wc[i] ); + break; + case _TEST: + fprintf( stdout, "\tExtra condit.: %12.1f\n", inst_cnt_wc[i] ); + break; + case _POWER: + fprintf( stdout, "\tExponential: %12.1f\n", inst_cnt_wc[i] ); + break; + case _LOG: + fprintf( stdout, "\tLogarithm: %12.1f\n", inst_cnt_wc[i] ); + break; + case _MISC: + fprintf( stdout, "\tAll other op.: %12.1f\n", inst_cnt_wc[i] ); + break; + default: + fprintf( stdout, "\tERROR: Invalid instruction type: %d\n\n", i ); + } + } +#endif + + /* De-allocate the list of wmops record */ + if ( wmops != NULL ) + { + free( wmops ); + } + + /* De-allocate the list of wmops caller functions */ + if ( wmops_caller_stack != NULL ) + { + free( wmops_caller_stack ); + } + + /* De-allocate the BASOP WMOPS counter */ + if ( multiCounter != NULL ) + { + free( multiCounter ); + } + + return; +} + + +/*-------------------------------------------------------------------* + * Memory counting tool measuring RAM usage (stack and heap) + * + * Maximum RAM is measured by monitoring the total allocated memory (stack and heap) in each frame. + * + * Maximum stack is measured by monitoring the difference between the 'top' and 'bottom' of the stack. The 'bottom' of the stack is updated in each function + * with a macro 'func_start_' which is inserted automatically to all functions during the instrumentation process. + * + * Maximum heap is measured by summing the sizes of all memory blocks allocated by malloc() or calloc() and deallocated by free(). The maximum heap size is + * updated each time when the macros malloc_() or calloc_() is invoked. The macros 'malloc_ and calloc_' are inserted automatically during the instrumentation process. + * As part of heap measurements, intra-frame heap and inter-frame heap are measured separately. Intra-frame heap refers to heap memory which is allocated and deallocated + * within a single frame. Inter-frame heap, on the contrary, refers to heap memory which is reserved for more than one frame. + * + * In order to run the memory counting tool the function reset_mem(cnt_size) must be called at the beginning of the encoding/decoding process. + * The unit in which memory consumption is reported is set via the parameter 'cnt_size'. It can be set to 0 (bytes), 1 (32b words) or 2 (64b words). + * At the end of the encoding/decoding process, 'print_mem()' function may be called to print basic information about memory consumption. If the macro 'MEM_COUNT_DETAILS' + * is activated, detailed information is printed + * + * The macro 'WMOPS' needs to be activated to enable memory counting. To avoid the instrumentation of malloc()/calloc()/free() calls, use + * #define WMC_TOOL_SKIP ... #undef WMC_TOOL_SKIP macro pair around the malloc(), calloc() and free(). + *--------------------------------------------------------------------*/ + +/* This is the value (in bytes) towards which the block size is rounded. For example, a block of 123 bytes, when using + a 32 bits system, will end up taking 124 bytes since the last unused byte cannot be used for another block. */ +#ifdef MEM_ALIGN_64BITS +#define BLOCK_ROUNDING 8 /* Align on 64 Bits */ +#else +#define BLOCK_ROUNDING 4 /* Align on 32 Bits */ +#endif + +#define N_32BITS_BLOCKS ( BLOCK_ROUNDING / sizeof( int32_t ) ) +#define ROUND_BLOCK_SIZE( n ) ( ( ( n ) + BLOCK_ROUNDING - 1 ) & ~( BLOCK_ROUNDING - 1 ) ) + +#define MAGIC_VALUE_OOB 0x12A534F0 /* Signature value which is inserted before and after each allocated memory block, used to detect out-of-bound access */ +#define MAGIC_VALUE_USED ( ~MAGIC_VALUE_OOB ) /* Value used to pre-fill allocated memory blocks, used to calculate actual memory usage */ +#define OOB_START 0x1 /* Flag indicating out-of-bounds access before memory block */ +#define OOB_END 0x2 /* Flag indicating out-of-bounds access after memory block */ + +#ifdef MEM_COUNT_DETAILS +const char *csv_filename = "mem_analysis.csv"; +static FILE *fid_csv_filename = NULL; +#endif + +typedef struct +{ + char function_name[MAX_FUNCTION_NAME_LENGTH + 1]; + int16_t *stack_ptr; +} caller_info; + +static caller_info *stack_callers[2] = {NULL, NULL}; + +static int16_t *ptr_base_stack = 0; /* Pointer to the bottom of stack (base pointer). Stack grows up. */ +static int16_t *ptr_current_stack = 0; /* Pointer to the current stack pointer */ +static int16_t *ptr_max_stack = 0; /* Pointer to the maximum stack pointer (the farest point from the bottom of stack) */ +static int32_t wc_stack_frame = 0; /* Frame corresponding to the worst-case stack usage */ +static int current_calls = 0, max_num_calls = MAX_NUM_RECORDS; +static char location_max_stack[256] = "undefined"; + +/* Heap-related variables */ +typedef struct +{ + char name[MAX_FUNCTION_NAME_LENGTH + 1]; /* +1 for NUL */ + char params[1 + MAX_PARAMS_LENGTH + 1]; /* +1 for 'm'/'c' alloc & +1 for NUL */ + unsigned long hash; + int lineno; + void *block_ptr; + int block_size; + unsigned long total_block_size; /* Cumulative sum of the allocated size in the session */ + unsigned long total_used_size; /* Cumulative sum of the used size in the session */ + int wc_heap_size_intra_frame; /* Worst-Case Intra-Frame Heap Size */ + int wc_heap_size_inter_frame; /* Worst-Case Inter-Frame Heap Size */ + int frame_allocated; /* Frame number in which the Memory Block has been allocated (-1 if not allocated at the moment) */ + int OOB_Flag; + int noccurances; /* Number of times that the memory block has been allocated in a frame */ +} allocator_record; + +allocator_record *allocation_list = NULL; + +static int Num_Records, Max_Num_Records; +static size_t Stat_Cnt_Size = USE_BYTES; +static const char *Count_Unit[] = { "bytes", "words", "words", "words" }; + +static int32_t wc_ram_size, wc_ram_frame; +static int32_t current_heap_size; +static int *list_wc_intra_frame_heap, n_items_wc_intra_frame_heap, max_items_wc_intra_frame_heap, size_wc_intra_frame_heap, location_wc_intra_frame_heap; +static int *list_current_inter_frame_heap, n_items_current_inter_frame_heap, max_items_current_inter_frame_heap, size_current_inter_frame_heap; +static int *list_wc_inter_frame_heap, n_items_wc_inter_frame_heap, max_items_wc_inter_frame_heap, size_wc_inter_frame_heap, location_wc_inter_frame_heap; + +/* Local Functions */ +static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str ); +allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record ); +static void *mem_alloc_block( size_t size, const char *size_str ); + +/*-------------------------------------------------------------------* + * reset_mem() + * + * Initialize/reset memory counting tool (stack and heap) + *--------------------------------------------------------------------*/ + +void reset_mem( Counting_Size cnt_size ) +{ + int16_t something; + size_t tmp_size; + + /* initialize list of stack records */ + if ( stack_callers[0] == NULL ) + { + stack_callers[0] = malloc( MAX_NUM_RECORDS * sizeof( caller_info ) ); + stack_callers[1] = malloc( MAX_NUM_RECORDS * sizeof( caller_info ) ); + } + + if ( stack_callers[0] == NULL || stack_callers[1] == NULL ) + { + fprintf( stderr, "Error: Unable to Allocate List of Stack Records!" ); + exit( -1 ); + } + + current_calls = 0; + max_num_calls = MAX_NUM_RECORDS; + + /* initialize stack pointers */ + ptr_base_stack = &something; + ptr_max_stack = ptr_base_stack; + ptr_current_stack = ptr_base_stack; + + /* initialize the unit of memory block size */ + Stat_Cnt_Size = cnt_size; + + /* Check, if sizeof(int32_t) is 4 bytes */ + tmp_size = sizeof( int32_t ); + if ( tmp_size != 4 ) + { + fprintf( stderr, "Error: Expecting 'int32_t' to be a 32 Bits Integer!" ); + exit( -1 ); + } + + /* create allocation list for malloc() memory blocks */ + if ( allocation_list == NULL ) + { + allocation_list = malloc( MAX_NUM_RECORDS * sizeof( allocator_record ) ); + } + + if ( allocation_list == NULL ) + { + fprintf( stderr, "Error: Unable to Create List of Memory Blocks!" ); + exit( -1 ); + } + + Num_Records = 0; + Max_Num_Records = MAX_NUM_RECORDS; + + wc_ram_size = 0; + wc_ram_frame = -1; + current_heap_size = 0; + + /* heap allocation tree */ + heap_allocation_call_tree_max_size = MAX_NUM_RECORDS; + if ( heap_allocation_call_tree == NULL ) + { + heap_allocation_call_tree = (int *) malloc( heap_allocation_call_tree_max_size * sizeof( int ) ); + memset( heap_allocation_call_tree, -1, heap_allocation_call_tree_max_size * sizeof( int ) ); + } + heap_allocation_call_tree_size = 0; + + /* wc intra-frame heap */ + max_items_wc_intra_frame_heap = MAX_NUM_RECORDS; + if ( list_wc_intra_frame_heap == NULL ) + { + list_wc_intra_frame_heap = (int *) malloc( max_items_wc_intra_frame_heap * sizeof( int ) ); + memset( list_wc_intra_frame_heap, -1, max_items_wc_intra_frame_heap * sizeof( int ) ); + } + n_items_wc_intra_frame_heap = 0; + size_wc_intra_frame_heap = 0; + location_wc_intra_frame_heap = -1; + + /* current inter-frame heap */ + max_items_current_inter_frame_heap = MAX_NUM_RECORDS; + if ( list_current_inter_frame_heap == NULL ) + { + list_current_inter_frame_heap = (int *) malloc( max_items_current_inter_frame_heap * sizeof( int ) ); + memset( list_current_inter_frame_heap, -1, max_items_current_inter_frame_heap * sizeof( int ) ); + } + n_items_current_inter_frame_heap = 0; + size_current_inter_frame_heap = 0; + + /* wc inter-frame heap */ + max_items_wc_inter_frame_heap = MAX_NUM_RECORDS; + if ( list_wc_inter_frame_heap == NULL ) + { + list_wc_inter_frame_heap = (int *) malloc( max_items_wc_inter_frame_heap * sizeof( int ) ); + memset( list_wc_inter_frame_heap, -1, max_items_wc_inter_frame_heap * sizeof( int ) ); + } + n_items_wc_inter_frame_heap = 0; + size_wc_inter_frame_heap = 0; + location_wc_inter_frame_heap = -1; + +#ifdef MEM_COUNT_DETAILS + /* Check, if the .csv file has already been opened */ + if ( fid_csv_filename == NULL ) + { + fid_csv_filename = fopen( csv_filename, "wb" ); + + if ( fid_csv_filename == NULL ) + { + fprintf( stderr, "\nCannot open %s!\n\n", csv_filename ); + exit( -1 ); + } + } + else + { + /* reset file */ + rewind( fid_csv_filename ); + } +#endif + + return; +} + +/*-------------------------------------------------------------------* + * reset_stack() + * + * Reset stack pointer + *--------------------------------------------------------------------*/ + +void reset_stack( void ) +{ + int16_t something; + + /* initialize/reset stack pointers */ + ptr_base_stack = &something; + ptr_max_stack = ptr_base_stack; + ptr_current_stack = ptr_base_stack; + + return; +} + +/*-------------------------------------------------------------------* + * push_stack() + * + * Check the current stack pointer and update the maximum stack pointer, if new maximum found. + *--------------------------------------------------------------------*/ + +int push_stack( const char *filename, const char *fctname ) +{ + int16_t something; + int32_t current_stack_size; + + ptr_current_stack = &something; + + (void) *filename; /* to avoid compilation warning */ + + if ( current_calls >= max_num_calls ) + { + /* There is no room for a new record -> reallocate the list */ + max_num_calls += MAX_NUM_RECORDS_REALLOC_STEP; + stack_callers[0] = realloc( stack_callers[0], max_num_calls * sizeof( caller_info ) ); + stack_callers[1] = realloc( stack_callers[1], max_num_calls * sizeof( caller_info ) ); + } + + /* Valid Function Name? */ + if ( fctname[0] == 0 ) + { /* No */ + fprintf( stderr, "Invalid function name for call stack info." ); + exit( -1 ); + } + + /* Save the Name of the Calling Function in the Table */ + strncpy( stack_callers[0][current_calls].function_name, fctname, MAX_FUNCTION_NAME_LENGTH ); + stack_callers[0][current_calls].function_name[MAX_FUNCTION_NAME_LENGTH] = 0; /* Nul Terminate */ + + /* Save the Stack Pointer */ + stack_callers[0][current_calls].stack_ptr = ptr_current_stack; + + /* Increase the Number of Calls in the List */ + current_calls++; + + /* Is this the First Time or the Worst Case? */ + if ( ptr_current_stack < ptr_max_stack || ptr_max_stack == NULL ) + { /* Yes */ + /* Save Info about it */ + ptr_max_stack = ptr_current_stack; + + /* save the worst-case frame number */ + /* current frame number is stored in the variable update_cnt and updated in the function update_wmops() */ + wc_stack_frame = update_cnt; + strncpy( location_max_stack, fctname, sizeof( location_max_stack ) - 1 ); + location_max_stack[sizeof( location_max_stack ) - 1] = '\0'; + + /* Save Call Tree */ + memmove( stack_callers[1], stack_callers[0], sizeof( caller_info ) * current_calls ); + + /* Terminate the List with 0 (for printing purposes) */ + if ( current_calls < max_num_calls ) + { + stack_callers[1][current_calls].function_name[0] = 0; + } + } + + /* Check, if This is the New Worst-Case RAM (stack + heap) */ + current_stack_size = (int32_t) ( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) ); + + if ( current_stack_size < 0 ) + { + /* prevent negative stack size */ + current_stack_size = 0; + } + + if ( current_stack_size + current_heap_size > wc_ram_size ) + { + wc_ram_size = current_stack_size + current_heap_size; + wc_ram_frame = update_cnt; + } + + return 0 /* for Now */; +} + +/*-------------------------------------------------------------------* + * pop_stack() + * + * Remove stack caller entry from the list + *--------------------------------------------------------------------*/ + +int pop_stack( const char *filename, const char *fctname ) +{ + caller_info *caller_info_ptr; + + (void) *filename; /* to avoid compilation warning */ + + /* Decrease the Number of Records */ + current_calls--; + + /* Get Pointer to Caller Information */ + caller_info_ptr = &stack_callers[0][current_calls]; + + /* Check, if the Function Names Match */ + if ( strncmp( caller_info_ptr->function_name, fctname, MAX_FUNCTION_NAME_LENGTH ) != 0 ) + { + fprintf( stderr, "Invalid usage of pop_stack()" ); + exit( -1 ); + } + + /* Erase Entry */ + caller_info_ptr->function_name[0] = 0; + + /* Retrieve previous stack pointer */ + if ( current_calls == 0 ) + { + ptr_current_stack = ptr_base_stack; + } + else + { + ptr_current_stack = stack_callers[0][current_calls - 1].stack_ptr; + } + + return 0 /* for Now */; +} + +#ifdef MEM_COUNT_DETAILS +/*-------------------------------------------------------------------* + * print_stack_call_tree() + * + * Print detailed information about worst-case stack usage + *--------------------------------------------------------------------*/ + +static void print_stack_call_tree( void ) +{ + caller_info *caller_info_ptr; + int call_level; + char fctname[MAX_FUNCTION_NAME_LENGTH + 1]; + + fprintf( stdout, "\nList of functions when maximum stack size is reached:\n\n" ); + + caller_info_ptr = &stack_callers[1][0]; + for ( call_level = 0; call_level < max_num_calls; call_level++ ) + { + /* Done? */ + if ( caller_info_ptr->function_name[0] == 0 ) + { + break; + } + + /* Print Name */ + strncpy( fctname, caller_info_ptr->function_name, MAX_FUNCTION_NAME_LENGTH ); + strcat( fctname, "()" ); + fprintf( stdout, "%-42s", fctname ); + + /* Print Stack Usage (Based on Difference) */ + if ( call_level != 0 ) + { + fprintf( stdout, "%lu %s\n", ( ( ( caller_info_ptr - 1 )->stack_ptr - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] ); + } + else + { + fprintf( stdout, "%lu %s\n", ( ( ptr_base_stack - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] ); + } + + /* Advance */ + caller_info_ptr++; + } + + fprintf( stdout, "\n" ); + + return; +} +#endif + + +/*-------------------------------------------------------------------* + * mem_alloc() + * + * Creates new record, stores auxiliary information about which function allocated the memory, line number, parameters, etc. + * Finally, it allocates physical memory using malloc() + * The function also updates worst-case heap size and worst-case RAM size + *--------------------------------------------------------------------*/ + +void *mem_alloc( + const char *func_name, + int func_lineno, + size_t size, + char *size_str /* the first char indicates m-alloc or c-alloc */ ) +{ + int index_record; + int32_t current_stack_size; + unsigned long hash; + allocator_record *ptr_record; + + if ( size == 0 ) + { + fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Size of Zero not Supported" ); + exit( -1 ); + } + + /* Search for an existing record (that has been de-allocated before) */ + index_record = 0; + while ( ( ptr_record = get_mem_record( &hash, func_name, func_lineno, size_str, &index_record ) ) != NULL ) + { + if ( ptr_record->frame_allocated == -1 ) + { + break; + } + else + { + index_record++; + } + } + + /* Create new record */ + if ( ptr_record == NULL ) + { + if ( Num_Records >= Max_Num_Records ) + { + /* There is no room for a new record -> reallocate memory */ + Max_Num_Records += MAX_NUM_RECORDS_REALLOC_STEP; + allocation_list = realloc( allocation_list, Max_Num_Records * sizeof( allocator_record ) ); + } + + ptr_record = &( allocation_list[Num_Records] ); + + /* Initialize new record */ + ptr_record->hash = hash; + ptr_record->noccurances = 0; + ptr_record->total_block_size = 0; + ptr_record->total_used_size = 0; + ptr_record->frame_allocated = -1; + ptr_record->OOB_Flag = 0; + ptr_record->wc_heap_size_intra_frame = -1; + ptr_record->wc_heap_size_inter_frame = -1; + + index_record = Num_Records; + Num_Records++; + } + + /* Allocate memory block for the new record, add signature before the beginning and after the memory block and fill it with magic value */ + ptr_record->block_ptr = mem_alloc_block( size, size_str ); + + if ( ptr_record->block_ptr == NULL ) + { + fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Error: Cannot Allocate Memory!" ); + exit( -1 ); + } + + /* Save all auxiliary information about the memory block */ + strncpy( ptr_record->name, func_name, MAX_FUNCTION_NAME_LENGTH ); + ptr_record->name[MAX_FUNCTION_NAME_LENGTH] = '\0'; + strncpy( ptr_record->params, size_str, MAX_PARAMS_LENGTH ); /* Note: The size string starts with either 'm' or 'c' to indicate 'm'alloc or 'c'alloc */ + ptr_record->params[MAX_PARAMS_LENGTH] = '\0'; + ptr_record->lineno = func_lineno; + ptr_record->block_size = size; + ptr_record->total_block_size += size; + +#ifdef MEM_COUNT_DETAILS + /* Export heap memory allocation record to the .csv file */ + fprintf( fid_csv_filename, "A,%ld,%s,%d,%d\n", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size ); +#endif + + if ( ptr_record->frame_allocated != -1 ) + { + fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Error: Attempt to Allocate the Same Memory Block with Freeing it First!" ); + exit( -1 ); + } + + ptr_record->frame_allocated = update_cnt; /* Store the current frame number -> later it will be used to determine the total duration */ + + /* Update Heap Size in the current frame */ + current_heap_size += ptr_record->block_size; + + /* Check, if this is the new Worst-Case RAM (stack + heap) */ + current_stack_size = (int32_t) ( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) ); + if ( current_stack_size + current_heap_size > wc_ram_size ) + { + wc_ram_size = current_stack_size + current_heap_size; + wc_ram_frame = update_cnt; + } + + /* Add new entry to the heap allocation call tree */ + if ( heap_allocation_call_tree == NULL ) + { + fprintf( stderr, "Error: Heap allocation call tree not created!" ); + exit( -1 ); + } + + /* check, if the maximum size of the call tree has been reached -> resize if so */ + if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size ) + { + heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP; + heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) ); + } + + /* push new entry (positive number means push op, neagtive number means pop op; zero index must be converted to 0.01 :-) */ + heap_allocation_call_tree[heap_allocation_call_tree_size++] = index_record; + + return ptr_record->block_ptr; +} + +/*-------------------------------------------------------------------* + * mem_alloc_block() + * + * Physical allocation of memory using malloc(). Appends 'signature' before and after the block, + * pre-fills memory block with magic value + *--------------------------------------------------------------------*/ + +static void *mem_alloc_block( size_t size, const char *size_str ) +{ + size_t rounded_size; + void *block_ptr; + char *tmp_ptr; + size_t n, f; + int32_t fill_value; + int32_t *ptr32; + int32_t mask, temp; + + /* Round Up Block Size */ + rounded_size = ROUND_BLOCK_SIZE( size ); + + /* Allocate memory using the standard malloc() by adding room for Signature Values */ + block_ptr = malloc( rounded_size + BLOCK_ROUNDING * 2 ); + + if ( block_ptr == NULL ) + { + return NULL; + } + + /* Add Signature Before the Start of the Block */ + ptr32 = (int32_t *) block_ptr; + n = N_32BITS_BLOCKS; + do + { + *ptr32++ = MAGIC_VALUE_OOB; + } while ( --n ); + + /* Fill Memory Block with Magic Value or 0 */ + fill_value = MAGIC_VALUE_USED; + if ( size_str[0] == 'c' ) + { + fill_value = 0x00000000; + } + n = size / sizeof( int32_t ); + while ( n-- ) + { + *ptr32++ = fill_value; + } + + /* Fill the Reminder of the Memory Block - After Rounding */ + n = rounded_size - size; + f = n % sizeof( int32_t ); + if ( f != 0 ) + { + /* when filling with '0' need to adapt the magic value */ + /* shift by [1->24, 2->16, 3->8] */ + mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 ); /* (1) */ + temp = MAGIC_VALUE_OOB & mask; + if ( fill_value != 0x0 ) + { /* for malloc merge fill value */ + temp += ( ~mask ) & MAGIC_VALUE_USED; + } /* for calloc the code in (1) above already introduces zeros */ + *ptr32++ = temp; + } + n /= sizeof( int32_t ); + n += N_32BITS_BLOCKS; + + /* Add Signature After the End of Block */ + do + { + *ptr32++ = MAGIC_VALUE_OOB; + } while ( --n ); + + /* Adjust the Memory Block Pointer (Magic Value Before and After the Memory Block Requested) */ + tmp_ptr = (char *) block_ptr; + tmp_ptr += BLOCK_ROUNDING; + block_ptr = (void *) tmp_ptr; + + return block_ptr; +} + +/*-------------------------------------------------------------------* + * mem_set_usage() + * + * Calculates actual usage of memory block by checking the magic value that was used to pre-fill + * each memory block during its allocation + *--------------------------------------------------------------------*/ + +static int mem_set_usage( allocator_record *record_ptr ) +{ + int total_bytes_used; + + size_t n; + int32_t *ptr32; + char *ptr8; + size_t total_bytes; + int32_t fill_value; + + fill_value = MAGIC_VALUE_USED; + if ( ( record_ptr->params[0] ) == 'c' ) + { + fill_value = 0x00000000; + } + + total_bytes = record_ptr->block_size; + + /* Check 4 bytes at a time */ + ptr32 = (int32_t *) record_ptr->block_ptr; + total_bytes_used = 0; + for ( n = total_bytes / sizeof( int32_t ); n > 0; n-- ) + { + if ( *ptr32++ != fill_value ) + { + total_bytes_used += sizeof( int32_t ); + } + } + + /* Check remaining bytes (If Applicable) 1 byte at a time */ + ptr8 = (char *) ptr32; + for ( n = total_bytes % sizeof( int32_t ); n > 0; n-- ) + { + if ( *ptr8++ != (char) fill_value ) + { + total_bytes_used++; + } + + /* Update Value */ + fill_value >>= 8; + } + + return total_bytes_used; +} + +/*-------------------------------------------------------------------* + * mem_check_OOB() + * + * Checks, if out-of-bounds access has occured. This is done by inspecting the 'signature' value + * taht has been added before and after the memory block during its allocation + *--------------------------------------------------------------------*/ + +static unsigned int mem_check_OOB( allocator_record *record_ptr ) +{ + int32_t *ptr32; + unsigned int OOB_Flag = 0x0; + int32_t mask; + size_t i; + int f; + + ptr32 = (int32_t *) record_ptr->block_ptr - N_32BITS_BLOCKS; + + /* Check the Signature at the Beginning of Memory Block */ + i = N_32BITS_BLOCKS; + do + { + if ( *ptr32++ ^ MAGIC_VALUE_OOB ) + { + OOB_Flag |= OOB_START; + } + } while ( --i ); + + /* Advance to End (Snap to lowest 32 Bits) */ + ptr32 += record_ptr->block_size / sizeof( int32_t ); + + /* Calculate Unused Space That has been added to get to the rounded Block Size */ + i = ROUND_BLOCK_SIZE( record_ptr->block_size ) - record_ptr->block_size; + + /* Partial Check of Signature at the End of Memory Block (for block size that has been rounded) */ + f = i % sizeof( int32_t ); + if ( f != 0 ) + { + mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 ); + if ( ( *ptr32++ ^ MAGIC_VALUE_OOB ) & mask ) + { + OOB_Flag |= OOB_END; + } + } + + /* Full Check of Signature at the End of Memory Block, i.e. all 32 Bits (for the remainder after rounding) */ + i /= sizeof( int32_t ); + i += N_32BITS_BLOCKS; + do + { + if ( *ptr32++ ^ MAGIC_VALUE_OOB ) + { + OOB_Flag |= OOB_END; + } + } while ( --i ); + + return OOB_Flag; +} + +/*-------------------------------------------------------------------* + * malloc_hash() + * + * Calculate hash from function name, line number and malloc size + *--------------------------------------------------------------------*/ + +static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str ) +{ + unsigned long hash = 5381; + const char *ptr_str; + + ptr_str = func_name; + while ( ptr_str != NULL && *ptr_str != '\0' ) + { + hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */ + } + + hash = ( ( hash << 5 ) + hash ) + func_lineno; /* hash * 33 + func_lineno */ + + ptr_str = size_str; + while ( ptr_str != NULL && *ptr_str != '\0' ) + { + hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */ + } + + return hash; +} + +/*-------------------------------------------------------------------* + * get_mem_record() + * + * Search for memory record in the internal list, return NULL if not found + * Start from index_record + *--------------------------------------------------------------------*/ + +allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record ) +{ + int i; + + if ( *index_record < 0 || *index_record > Num_Records ) + { + return NULL; + } + + /* calculate hash */ + *hash = malloc_hash( func_name, func_lineno, size_str ); + + for ( i = *index_record; i < Num_Records; i++ ) + { + /* check, if memory block is not allocated at the moment and the hash matches */ + if ( allocation_list[i].block_ptr == NULL && *hash == allocation_list[i].hash ) + { + *index_record = i; + return &( allocation_list[i] ); + } + } + + /* not found */ + *index_record = -1; + return NULL; +} + + +/*-------------------------------------------------------------------* + * mem_free() + * + * This function de-allocates memory blocks and frees physical memory with free(). + * It also updates the actual and average usage of memory blocks. + * + * Note: The record is not removed from the list and may be reused later on in mem_alloc()! + *--------------------------------------------------------------------*/ + +void mem_free( const char *func_name, int func_lineno, void *ptr ) +{ + int i, index_record; + char *tmp_ptr; + allocator_record *ptr_record; + + /* Search for the Block Pointer in the List */ + ptr_record = NULL; + index_record = -1; + for ( i = 0; i < Num_Records; i++ ) + { + if ( ptr == allocation_list[i].block_ptr ) + { /* Yes, Found it */ + ptr_record = &( allocation_list[i] ); + index_record = i; + break; + } + } + + if ( ptr_record == NULL ) + { + fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Error: Unable to Find Record Corresponding to the Allocated Memory Block!" ); + exit( -1 ); + } + + /* Update the Heap Size */ + current_heap_size -= ptr_record->block_size; + + /* Calculate the Actual Usage of the Memory Block (Look for Signature) */ + ptr_record->total_used_size += mem_set_usage( ptr_record ); + + /* Check, if Out-Of-Bounds Access has been Detected */ + ptr_record->OOB_Flag = mem_check_OOB( ptr_record ); + +#ifdef MEM_COUNT_DETAILS + /* Export heap memory de-allocation record to the .csv file */ + fprintf( fid_csv_filename, "D,%ld,%s,%d,%d\n", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size ); +#endif + + /* De-Allocate Memory Block */ + tmp_ptr = (char *) ptr; + tmp_ptr -= BLOCK_ROUNDING; + ptr = (void *) tmp_ptr; + free( ptr ); + + /* Add new entry to the heap allocation call tree */ + if ( heap_allocation_call_tree == NULL ) + { + fprintf( stderr, "Error: Heap allocation call tree not created!" ); + exit( -1 ); + } + + /* check, if the maximum size of the call tree has been reached -> resize if so */ + if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size ) + { + heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP; + heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) ); + } + + heap_allocation_call_tree[heap_allocation_call_tree_size++] = -index_record; + + /* Reset memory block pointer (this is checked when updating wc intra-frame and inter-frame memory) */ + ptr_record->block_ptr = NULL; + + return; +} + + +/*-------------------------------------------------------------------* + * update_mem() + * + * This function updates the worst-case intra-frame memory and the worst-case inter-frame memory. + *--------------------------------------------------------------------*/ + +void update_mem( void ) +{ + int i, j, flag_alloc = -1, i_record; + int size_current_intra_frame_heap; + int *list_current_intra_frame_heap = NULL, n_items_current_intra_frame_heap; + allocator_record *ptr_record; + + /* process the heap allocation call tree and prepare lists of intra-frame and inter-frame heap memory blocks for this frame */ + n_items_current_intra_frame_heap = 0; + size_current_intra_frame_heap = 0; + for ( i = 0; i < heap_allocation_call_tree_size; i++ ) + { + /* get the record */ + i_record = heap_allocation_call_tree[i]; + + if ( i_record > 0 ) + { + flag_alloc = 1; + } + else if ( i_record < 0 ) + { + flag_alloc = 0; + i_record = -i_record; + } + ptr_record = &( allocation_list[i_record] ); + + if ( ptr_record->frame_allocated == update_cnt && ptr_record->block_ptr == NULL ) + { + /* intra-frame heap memory */ + if ( list_current_intra_frame_heap == NULL ) + { + list_current_intra_frame_heap = (int *) malloc( heap_allocation_call_tree_size * sizeof( int ) ); + memset( list_current_intra_frame_heap, -1, heap_allocation_call_tree_size * sizeof( int ) ); + } + + /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */ + if ( i_record == 0 ) + { + flag_alloc = 1; + for ( j = 0; j < n_items_current_intra_frame_heap; j++ ) + { + if ( list_current_intra_frame_heap[j] == i_record ) + { + flag_alloc = 0; + break; + } + } + } + + if ( flag_alloc ) + { + /* add to list */ + list_current_intra_frame_heap[n_items_current_intra_frame_heap++] = i_record; + size_current_intra_frame_heap += ptr_record->block_size; + + /* no need to re-size the list -> the initially allocated size should be large enough */ + } + else + { + /* remove from list */ + for ( j = 0; j < n_items_current_intra_frame_heap; j++ ) + { + if ( list_current_intra_frame_heap[j] == i_record ) + { + break; + } + } + memmove( &list_current_intra_frame_heap[j], &list_current_intra_frame_heap[j + 1], ( n_items_current_intra_frame_heap - j ) * sizeof( int ) ); + n_items_current_intra_frame_heap--; + size_current_intra_frame_heap -= ptr_record->block_size; + + /* reset block size */ + ptr_record->frame_allocated = -1; + ptr_record->block_size = 0; + } + } + else + { + /* inter-frame heap memory */ + + /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */ + if ( i_record == 0 ) + { + flag_alloc = 1; + for ( j = 0; j < n_items_current_inter_frame_heap; j++ ) + { + if ( list_current_inter_frame_heap[j] == i_record ) + { + flag_alloc = 0; + break; + } + } + } + + if ( flag_alloc ) + { + /* add to list */ + if ( n_items_current_inter_frame_heap >= max_items_current_inter_frame_heap ) + { + /* resize list, if needed */ + max_items_current_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; + list_current_inter_frame_heap = realloc( list_current_inter_frame_heap, max_items_current_inter_frame_heap * sizeof( int ) ); + } + + list_current_inter_frame_heap[n_items_current_inter_frame_heap++] = i_record; + size_current_inter_frame_heap += ptr_record->block_size; + } + else + { + /* remove from list */ + for ( j = 0; j < n_items_current_inter_frame_heap; j++ ) + { + if ( list_current_inter_frame_heap[j] == i_record ) + { + break; + } + } + memmove( &list_current_inter_frame_heap[j], &list_current_inter_frame_heap[j + 1], ( n_items_current_inter_frame_heap - j ) * sizeof( int ) ); + n_items_current_inter_frame_heap--; + size_current_inter_frame_heap -= ptr_record->block_size; + + /* reset block size */ + ptr_record->frame_allocated = -1; + ptr_record->block_size = 0; + } + } + } + + /* check, if this is the new worst-case for intra-frame heap memory */ + if ( size_current_intra_frame_heap > size_wc_intra_frame_heap ) + { + if ( n_items_current_intra_frame_heap >= max_items_wc_intra_frame_heap ) + { + /* resize the list, if needed */ + max_items_wc_intra_frame_heap = n_items_current_intra_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; + list_wc_intra_frame_heap = realloc( list_wc_intra_frame_heap, max_items_wc_intra_frame_heap * sizeof( int ) ); + } + + /* copy current-frame list to worst-case list */ + memmove( list_wc_intra_frame_heap, list_current_intra_frame_heap, n_items_current_intra_frame_heap * sizeof( int ) ); + n_items_wc_intra_frame_heap = n_items_current_intra_frame_heap; + size_wc_intra_frame_heap = size_current_intra_frame_heap; + location_wc_intra_frame_heap = update_cnt; + + /* update the wc numbers in all individual records */ + for ( i = 0; i < n_items_wc_intra_frame_heap; i++ ) + { + i_record = list_wc_intra_frame_heap[i]; + ptr_record = &( allocation_list[i_record] ); + ptr_record->wc_heap_size_intra_frame = ptr_record->block_size; + } + } + + /* check, if this is the new worst-case for inter-frame heap memory */ + if ( size_current_inter_frame_heap > size_wc_inter_frame_heap ) + { + if ( n_items_current_inter_frame_heap >= max_items_wc_inter_frame_heap ) + { + /* resize list, if needed */ + max_items_wc_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; + list_wc_inter_frame_heap = realloc( list_wc_inter_frame_heap, max_items_wc_inter_frame_heap * sizeof( int ) ); + } + + /* copy current-frame list to worst-case list */ + memmove( list_wc_inter_frame_heap, list_current_inter_frame_heap, n_items_current_inter_frame_heap * sizeof( int ) ); + n_items_wc_inter_frame_heap = n_items_current_inter_frame_heap; + size_wc_inter_frame_heap = size_current_inter_frame_heap; + location_wc_inter_frame_heap = update_cnt; + + /* update the wc numbers in all individual records */ + for ( i = 0; i < n_items_wc_inter_frame_heap; i++ ) + { + i_record = list_wc_inter_frame_heap[i]; + ptr_record = &( allocation_list[i_record] ); + ptr_record->wc_heap_size_inter_frame = ptr_record->block_size; + } + } + + /* reset heap allocation call tree */ + heap_allocation_call_tree_size = 0; + + /* de-allocate list of intra-frame heap memory blocks in the current fraeme - it's needed only inside this function */ + if ( list_current_intra_frame_heap ) + { + free( list_current_intra_frame_heap ); + } + + return; +} + +#ifdef MEM_COUNT_DETAILS +/*-------------------------------------------------------------------* + * subst() + * + * Substitute character in string + *--------------------------------------------------------------------*/ + +static void subst( char *s, char from, char to ) +{ + while ( *s == from ) + { + *s++ = to; + } + + return; +} + + +/*-------------------------------------------------------------------* + * mem_count_summary() + * + * Print detailed (per-item) information about heap memory usage + *--------------------------------------------------------------------*/ + +static void mem_count_summary( void ) +{ + int i, j, index, index_record; + size_t length; + char buf[300], format_str[50], name_str[MAX_FUNCTION_NAME_LENGTH + 3], parms_str[MAX_PARAMS_LENGTH + 1], type_str[10], usage_str[20], size_str[20], line_str[10]; + allocator_record *ptr_record, *ptr; + + /* Prepare format string */ + sprintf( format_str, "%%-%d.%ds %%5.5s %%6.6s %%-%d.%ds %%20.20s %%6.6s ", 50, 50, 50, 50 ); + + if ( n_items_wc_intra_frame_heap > 0 ) + { + /* Intra-Frame Heap Size */ + fprintf( stdout, "\nList of memory blocks when maximum intra-frame heap size is reached:\n\n" ); + + /* Find duplicate records (same hash and worst-case heap size) */ + for ( i = 0; i < n_items_wc_intra_frame_heap; i++ ) + { + index_record = list_wc_intra_frame_heap[i]; + if ( index_record == -1 ) + { + continue; + } + + ptr_record = &( allocation_list[index_record] ); + for ( j = i + 1; j < n_items_wc_intra_frame_heap; j++ ) + { + index = list_wc_intra_frame_heap[j]; + if ( index == -1 ) + { + continue; + } + ptr = &( allocation_list[index] ); + + if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_intra_frame == ptr_record->wc_heap_size_intra_frame ) + { + ptr_record->noccurances++; + list_wc_intra_frame_heap[j] = -1; + } + } + } + + /* Print Header */ + sprintf( buf, format_str, "Function Name", "Line", "Type", "Function Parameters", "Maximum Size", "Usage" ); + puts( buf ); + length = strlen( buf ); + sprintf( buf, "%0*d\n", (int) length - 1, 0 ); + subst( buf, '0', '-' ); + puts( buf ); + + for ( i = 0; i < n_items_wc_intra_frame_heap; i++ ) + { + index_record = list_wc_intra_frame_heap[i]; + + if ( index_record != -1 ) + { + /* get the record */ + ptr_record = &( allocation_list[index_record] ); + + /* prepare information strings */ + strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH ); + strcat( name_str, "()" ); + name_str[MAX_FUNCTION_NAME_LENGTH] = '\0'; + strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH ); + parms_str[MAX_PARAMS_LENGTH] = '\0'; + + if ( ptr_record->params[0] == 'm' ) + { + strcpy( type_str, "malloc" ); + } + else + { + strcpy( type_str, "calloc" ); + } + + sprintf( line_str, "%d", ptr_record->lineno ); + + /* prepare average usage & memory size strings */ + sprintf( usage_str, "%d%%", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 1 ) ) * 100.0f ) ); + + if ( ptr_record->noccurances > 1 ) + { + sprintf( size_str, "%dx%d %s", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); + } + else + { + sprintf( size_str, "%d %s", (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); + } + + sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str ); + puts( buf ); + } + } + + fprintf( stdout, "\n" ); + } + + if ( n_items_wc_inter_frame_heap > 0 ) + { + /* Inter-Frame Heap Size */ + fprintf( stdout, "\nList of memory blocks when maximum inter-frame heap size is reached:\n\n" ); + + /* Find duplicate records (same hash and worst-case heap size) */ + for ( i = 0; i < n_items_wc_inter_frame_heap; i++ ) + { + index_record = list_wc_inter_frame_heap[i]; + if ( index_record == -1 ) + { + continue; + } + ptr_record = &( allocation_list[index_record] ); + ptr_record->noccurances = 1; /* reset the counter as some blocks may have been both, intra-frame and inter-frame */ + for ( j = i + 1; j < n_items_wc_inter_frame_heap; j++ ) + { + index = list_wc_inter_frame_heap[j]; + if ( index == -1 ) + { + continue; + } + ptr = &( allocation_list[index] ); + + if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_inter_frame == ptr_record->wc_heap_size_inter_frame ) + { + ptr_record->noccurances++; + list_wc_inter_frame_heap[j] = -1; + } + } + } + + /* Print Header */ + sprintf( buf, format_str, "Function Name", "Line", "Type", "Function Parameters", "Memory Size", "Usage" ); + puts( buf ); + length = strlen( buf ); + sprintf( buf, "%0*d\n", (int) length - 1, 0 ); + subst( buf, '0', '-' ); + puts( buf ); + + for ( i = 0; i < n_items_wc_inter_frame_heap; i++ ) + { + index_record = list_wc_inter_frame_heap[i]; + + if ( index_record != -1 ) + { + /* get the record */ + ptr_record = &( allocation_list[index_record] ); + + /* prepare information strings */ + strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH ); + strcat( name_str, "()" ); + name_str[MAX_FUNCTION_NAME_LENGTH] = '\0'; + strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH ); + parms_str[MAX_PARAMS_LENGTH] = '\0'; + + if ( ptr_record->params[0] == 'm' ) + { + strcpy( type_str, "malloc" ); + } + else + { + strcpy( type_str, "calloc" ); + } + + sprintf( line_str, "%d", ptr_record->lineno ); + + /* prepare average usage & memory size strings */ + sprintf( usage_str, "%d%%", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 0.1f ) ) * 100.0f + 0.5f ) ); + + if ( ptr_record->noccurances > 1 ) + { + sprintf( size_str, "%dx%d %s", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); + } + else + { + sprintf( size_str, "%d %s", (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); + } + + sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str ); + puts( buf ); + } + } + + fprintf( stdout, "\n" ); + } + + return; +} + +#endif + +/*-------------------------------------------------------------------* + * print_mem() + * + * Print information about ROM and RAM memory usage + *--------------------------------------------------------------------*/ + +void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] ) +{ + int i, nElem; + + fprintf( stdout, "\n\n --- Memory usage --- \n\n" ); + + if ( Const_Data_PROM_Table != NULL ) + { + nElem = 0; + while ( strcmp( Const_Data_PROM_Table[nElem].file_spec, "" ) != 0 ) + nElem++; + + for ( i = 0; i < nElem; i++ ) + { + if ( Stat_Cnt_Size > 0 ) + { + /* words */ + fprintf( stdout, "Program ROM size (%s): %d words\n", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size ); + } + else + { + /* bytes (here, we assume that each instruction takes PROM_INST_SIZE bits of the PROM memory) */ + fprintf( stdout, "Program ROM size (%s): %d bytes\n", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size * ( PROM_INST_SIZE / 8 ) ); + } + } + + for ( i = 0; i < nElem; i++ ) + { + if ( Const_Data_PROM_Table[i].Get_Const_Data_Size_Func == NULL ) + { + fprintf( stdout, "Error: Cannot retrieve or calculate Table ROM size of (%s)!\n", Const_Data_PROM_Table[i].file_spec ); + } + + fprintf( stdout, "Table ROM (const data) size (%s): %d %s\n", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].Get_Const_Data_Size_Func() >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] ); + } + } + else + { + fprintf( stdout, "Program ROM size: not available\n" ); + fprintf( stdout, "Table ROM (const data) size: not available\n" ); + } + + if ( wc_ram_size > 0 ) + { + fprintf( stdout, "Maximum RAM (stack + heap) size: %d %s in frame %d\n", wc_ram_size >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], wc_ram_frame ); + } + else + { + fprintf( stdout, "Maximum RAM (stack + heap) size: not available\n" ); + } + + /* check, if the stack is empty */ + if ( ptr_current_stack != ptr_base_stack ) + { + fprintf( stderr, "Warning: Stack is not empty.\n" ); + } + + if ( ptr_base_stack - ptr_max_stack > 0 ) + { + fprintf( stdout, "Maximum stack size: %lu %s in frame %d\n", ( ( ptr_base_stack - ptr_max_stack ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], + wc_stack_frame ); + } + else + { + fprintf( stdout, "Maximum stack size: not available\n" ); + } + + /* last update of intra-frame memory and inter-frame memory, if needed */ + if ( heap_allocation_call_tree_size > 0 ) + { + update_mem(); + } + + /* check, if all memory blocks have been deallocated (freed) */ + for ( i = 0; i < Num_Records; i++ ) + { + if ( allocation_list[i].block_ptr != NULL ) + { + fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", allocation_list[i].name, allocation_list[i].lineno, "Error: Memory Block has not been De-Allocated with free()!" ); + exit( -1 ); + } + } + + if ( n_items_wc_intra_frame_heap > 0 ) + { + fprintf( stdout, "Maximum intra-frame heap size: %d %s in frame %d\n", size_wc_intra_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_intra_frame_heap ); + } + else + { + fprintf( stdout, "Maximum intra-frame heap size: 0\n" ); + } + + if ( n_items_wc_inter_frame_heap > 0 ) + { + fprintf( stdout, "Maximum inter-frame heap size: %d %s in frame %d\n", size_wc_inter_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_inter_frame_heap ); + } + else + { + fprintf( stdout, "Maximum inter-frame heap size: 0\n" ); + } + +#ifdef MEM_COUNT_DETAILS + /* Print detailed information about worst-case stack usage */ + if ( ptr_base_stack - ptr_max_stack > 0 ) + { + print_stack_call_tree(); + } + + /* Print detailed information about worst-case heap usage */ + mem_count_summary(); +#endif + + if ( Stat_Cnt_Size > 0 ) + { + /* words */ + fprintf( stdout, "\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bits\n", 8 << Stat_Cnt_Size ); + } + else + { + /* bytes */ + fprintf( stdout, "\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bits\n", PROM_INST_SIZE ); + } + fprintf( stdout, "Note: The Data ROM size is calculated using the sizeof(type) built-in function\n" ); + + if ( n_items_wc_intra_frame_heap > 0 ) + { + fprintf( stdout, "Intra-frame heap memory is allocated and de-allocated in the same frame\n" ); + } + + /* De-allocate list of heap memory blocks */ + if ( allocation_list != NULL ) + { + free( allocation_list ); + } + + /* De-allocate list of stack records */ + if ( stack_callers[0] != NULL ) + { + free( stack_callers[0] ); + } + + if ( stack_callers[1] != NULL ) + { + free( stack_callers[1] ); + } + + /* De-allocate heap allocation call tree */ + if ( heap_allocation_call_tree != NULL ) + { + free( heap_allocation_call_tree ); + } + + /* De-allocate intra-frame and inter-frame heap lists */ + if ( list_wc_intra_frame_heap != NULL ) + { + free( list_wc_intra_frame_heap ); + } + + if ( list_current_inter_frame_heap != NULL ) + { + free( list_current_inter_frame_heap ); + } + + if ( list_wc_inter_frame_heap != NULL ) + { + free( list_wc_inter_frame_heap ); + } + +#ifdef MEM_COUNT_DETAILS + if ( fid_csv_filename != NULL ) + { + fclose( fid_csv_filename ); + } +#endif + + return; +} + +#endif /* WMOPS */ + +#ifndef WMOPS +int cntr_push_pop = 0; /* global counter for checking balanced push_wmops()/pop_wmops() pairs when WMOPS is not activated */ +#endif + +#ifdef WMOPS +/* Global counter for the calculation of BASOP complexity */ +BASIC_OP *multiCounter = NULL; +int currCounter = 0; +int funcId_where_last_call_to_else_occurred; +long funcid_total_wmops_at_last_call_to_else; +int call_occurred = 1; + +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, 3, 1, + + 1, 1, 1, 3, 1, + 4, 1, 18, 1, 1, + 2, 1, 2, 2, 1, + 1, 1, 1, 1, 1, + 3, 3, 3, 3, 1, + + 1, 1, 1, 1, 1, + 1, 1, 1, 2, + 1, 2, 2, 4, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 3, + 3, 3, 3, 3, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 4, 4, + 4, 8, 3, 4, 4, + + 5, 32, 3 +}; + +/* Set the counter group to use, default is zero */ +void Set_BASOP_WMOPS_counter( int counterId ) +{ + if ( ( counterId > num_wmops_records ) || ( counterId < 0 ) ) + { + currCounter = 0; + return; + } + currCounter = counterId; + call_occurred = 1; +} + +extern int32_t frame; + +long TotalWeightedOperation() +{ + int i; + unsigned int *ptr, *ptr2; + long tot; + + tot = 0; + ptr = (unsigned int *) &multiCounter[currCounter]; + ptr2 = (unsigned int *) &op_weight; + + for ( i = 0; i < ( int )( sizeof( multiCounter[currCounter] ) / sizeof( unsigned int ) ); i++ ) + { + tot += ( ( *ptr++ ) * ( *ptr2++ ) ); + } + + return ( tot ); +} + +long DeltaWeightedOperation( void ) +{ + long NewWOper, delta; + + NewWOper = TotalWeightedOperation(); + + delta = NewWOper - wmops[currCounter].LastWOper; + wmops[currCounter].LastWOper = NewWOper; + + return ( delta ); +} + +/* Resets the current BASOP WMOPS counter */ +void Reset_BASOP_WMOPS_counter( void ) +{ + int i; + long *ptr; + + /* clear the current BASOP operation counter before new frame begins */ + ptr = (long *) &multiCounter[currCounter]; + for ( i = 0; i < (int) ( sizeof( multiCounter[currCounter] ) / sizeof( long ) ); i++ ) + { + *ptr++ = 0; + } + + wmops[currCounter].LastWOper = 0; + + return; +} + +#endif + + diff --git a/lib_debug/wmc_auto.h b/lib_debug/wmc_auto.h new file mode 100644 index 000000000..0cfc2a535 --- /dev/null +++ b/lib_debug/wmc_auto.h @@ -0,0 +1,1449 @@ +/* + * (C) 2023 copyright VoiceAge Corporation. All Rights Reserved. + * + * This software is protected by copyright law and by international treaties. The source code, and all of its derivations, + * is provided by VoiceAge Corporation under the "ITU-T Software Tools' General Public License". Please, read the license file + * or refer to ITU-T Recommendation G.191 on "SOFTWARE TOOLS FOR SPEECH AND AUDIO CODING STANDARDS". + * + * Any use of this software is permitted provided that this notice is not removed and that neither the authors nor + * VoiceAge Corporation are deemed to have made any representations as to the suitability of this software + * for any purpose nor are held responsible for any defects of this software. THERE IS NO WARRANTY FOR THIS SOFTWARE. + * + * Authors: Guy Richard, Vladimir Malenovsky (Vladimir.Malenovsky@USherbrooke.ca) + */ + +#ifndef WMOPS_H +#define WMOPS_H + +#ifndef EXIT_FAILURE +#include /* stdlib is needed for exit() */ +#endif + +#ifndef EOF +#include /* stdio is needed for fprintf() */ +#endif + +#include "options.h" + +/* To Prevent "warning: '$' in identifier or number" message under GCC */ +#ifdef __GNUC__ +#pragma GCC system_header +#endif + +#ifndef INT_MAX +#define INT_MAX 32767 +#endif + +#define FRAMES_PER_SECOND 50.0 +#define PROM_INST_SIZE 32 /* number of bits of each program instruction when stored in the PROM memory (applied only when the user selects reporting in bytes) */ + +#ifdef WMOPS +enum instructions +{ + _ADD, + _ABS, + _MULT, + _MAC, + _MOVE, + _STORE, + _LOGIC, + _SHIFT, + _BRANCH, + _DIV, + _SQRT, + _TRANS, + _FUNC, + _LOOP, + _INDIRECT, + _PTR_INIT, + _TEST, + _POWER, + _LOG, + _MISC, + NUM_INST +}; + +#define _ADD_C 1 +#define _ABS_C 1 +#define _MULT_C 1 +#define _MAC_C 1 +#define _MOVE_C 1 +#define _STORE_C 1 +#define _LOGIC_C 1 +#define _SHIFT_C 1 +#define _BRANCH_C 4 +#define _DIV_C 18 +#define _SQRT_C 10 +#define _TRANS_C 25 +#define _FUNC_C 2 /* need to add number of arguments */ +#define _LOOP_C 3 +#define _INDIRECT_C 2 +#define _PTR_INIT_C 1 +#define _TEST_C 2 +#define _POWER_C 25 +#define _LOG_C 25 +#define _MISC_C 1 + +#define _ADD_P 1 +#define _ABS_P 1 +#define _MULT_P 1 +#define _MAC_P 1 +#define _MOVE_P 1 +#define _STORE_P 0 +#define _LOGIC_P 1 +#define _SHIFT_P 1 +#define _BRANCH_P 2 +#define _DIV_P 2 +#define _SQRT_P 2 +#define _TRANS_P 2 +#define _FUNC_P 2 /* need to add number of arguments */ +#define _LOOP_P 1 +#define _INDIRECT_P 2 +#define _PTR_INIT_P 1 +#define _TEST_P 1 +#define _POWER_P 2 +#define _LOG_P 2 +#define _MISC_P 1 + +#define ADD( x ) \ + { \ + { \ + ops_cnt += ( _ADD_C * ( x ) ); \ + inst_cnt[_ADD] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _ADD_P * ( x ) ); \ + } \ + } \ + } \ + } +#define ABS( x ) \ + { \ + { \ + ops_cnt += ( _ABS_C * ( x ) ); \ + inst_cnt[_ABS] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _ABS_P * ( x ) ); \ + } \ + } \ + } \ + } +#define MULT( x ) \ + { \ + { \ + ops_cnt += ( _MULT_C * ( x ) ); \ + inst_cnt[_MULT] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _MULT_P * ( x ) ); \ + } \ + } \ + } \ + } +#define MAC( x ) \ + { \ + { \ + ops_cnt += ( _MAC_C * ( x ) ); \ + inst_cnt[_MAC] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _MAC_P * ( x ) ); \ + } \ + } \ + } \ + } +#define MOVE( x ) \ + { \ + { \ + ops_cnt += ( _MOVE_C * ( x ) ); \ + inst_cnt[_MOVE] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _MOVE_P * ( x ) ); \ + } \ + } \ + } \ + } +#define STORE( x ) \ + { \ + { \ + ops_cnt += ( _STORE_C * ( x ) ); \ + inst_cnt[_STORE] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _STORE_P * ( x ) ); \ + } \ + } \ + } \ + } +#define LOGIC( x ) \ + { \ + { \ + ops_cnt += ( _LOGIC_C * ( x ) ); \ + inst_cnt[_LOGIC] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _LOGIC_P * ( x ) ); \ + } \ + } \ + } \ + } +#define SHIFT( x ) \ + { \ + { \ + ops_cnt += ( _SHIFT_C * ( x ) ); \ + inst_cnt[_SHIFT] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _SHIFT_P * ( x ) ); \ + } \ + } \ + } \ + } +#define BRANCH( x ) \ + { \ + { \ + ops_cnt += ( _BRANCH_C * ( x ) ); \ + inst_cnt[_BRANCH] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _BRANCH_P * ( x ) ); \ + } \ + } \ + } \ + } +#define DIV( x ) \ + { \ + { \ + ops_cnt += ( _DIV_C * ( x ) ); \ + inst_cnt[_DIV] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _DIV_P * ( x ) ); \ + } \ + } \ + } \ + } +#define SQRT( x ) \ + { \ + { \ + ops_cnt += ( _SQRT_C * ( x ) ); \ + inst_cnt[_SQRT] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _SQRT_P * ( x ) ); \ + } \ + } \ + } \ + } +#define TRANS( x ) \ + { \ + { \ + ops_cnt += ( _TRANS_C * ( x ) ); \ + inst_cnt[_TRANS] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _TRANS_P * ( x ) ); \ + } \ + } \ + } \ + } +#define LOOP( x ) \ + { \ + { \ + ops_cnt += ( _LOOP_C * ( x ) ); \ + inst_cnt[_LOOP] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _LOOP_P * ( x ) ); \ + } \ + } \ + } \ + } +#define INDIRECT( x ) \ + { \ + { \ + ops_cnt += ( _INDIRECT_C * ( x ) ); \ + inst_cnt[_INDIRECT] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _INDIRECT_P * ( x ) ); \ + } \ + } \ + } \ + } +#define PTR_INIT( x ) \ + { \ + { \ + ops_cnt += ( _PTR_INIT_C * ( x ) ); \ + inst_cnt[_PTR_INIT] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _PTR_INIT_P * ( x ) ); \ + } \ + } \ + } \ + } +#define TEST( x ) \ + { \ + { \ + ops_cnt += ( _TEST_C * ( x ) ); \ + inst_cnt[_TEST] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _TEST_P * ( x ) ); \ + } \ + } \ + } \ + } +#define POWER( x ) \ + { \ + { \ + ops_cnt += ( _POWER_C * ( x ) ); \ + inst_cnt[_POWER] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _POWER_P * ( x ) ); \ + } \ + } \ + } \ + } +#define LOG( x ) \ + { \ + { \ + ops_cnt += ( _LOG_C * ( x ) ); \ + inst_cnt[_LOG] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _LOG_P * ( x ) ); \ + } \ + } \ + } \ + } +#define MISC( x ) \ + { \ + { \ + ops_cnt += ( _MISC_C * ( x ) ); \ + inst_cnt[_MISC] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _MISC_P * ( x ) ); \ + } \ + } \ + } \ + } + +#define FUNC( x ) \ + { \ + { \ + ops_cnt += ( _FUNC_C + _MOVE_C * ( x ) ); \ + inst_cnt[_FUNC]++; \ + inst_cnt[_MOVE] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _FUNC_P + _MOVE_P * ( x ) ); \ + } \ + } \ + } \ + } + +#define DADD( x ) \ + { \ + { \ + ops_cnt += ( 2 * _ADD_C * ( x ) ); \ + inst_cnt[_ADD] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _ADD_P * ( x ) ); \ + } \ + } \ + } \ + } +#define DMULT( x ) \ + { \ + { \ + ops_cnt += ( 2 * _MULT_C * ( x ) ); \ + inst_cnt[_MULT] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _MULT_P * ( x ) ); \ + } \ + } \ + } \ + } +#define DMAC( x ) \ + { \ + { \ + ops_cnt += ( 2 * _MAC_C * ( x ) ); \ + inst_cnt[_MAC] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _MAC_P * ( x ) ); \ + } \ + } \ + } \ + } +#define DMOVE( x ) \ + { \ + { \ + ops_cnt += ( 2 * _MOVE_C * ( x ) ); \ + inst_cnt[_MOVE] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _MOVE_P * ( x ) ); \ + } \ + } \ + } \ + } +#define DSTORE( x ) \ + { \ + { \ + ops_cnt += ( 2 * _STORE_C * ( x ) ); \ + inst_cnt[_STORE] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _STORE_P * ( x ) ); \ + } \ + } \ + } \ + } +#define DLOGIC( x ) \ + { \ + { \ + ops_cnt += ( 2 * _LOGIC_C * ( x ) ); \ + inst_cnt[_LOGIC] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _LOGIC_P * ( x ) ); \ + } \ + } \ + } \ + } +#define DSHIFT( x ) \ + { \ + { \ + ops_cnt += ( 2 * _SHIFT_C * ( x ) ); \ + inst_cnt[_SHIFT] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _SHIFT_P * ( x ) ); \ + } \ + } \ + } \ + } +#define DDIV( x ) \ + { \ + { \ + ops_cnt += ( 2 * _DIV_C * ( x ) ); \ + inst_cnt[_DIV] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _DIV_P * ( x ) ); \ + } \ + } \ + } \ + } +#define DSQRT( x ) \ + { \ + { \ + ops_cnt += ( 2 * _SQRT_C * ( x ) ); \ + inst_cnt[_SQRT] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _SQRT_P * ( x ) ); \ + } \ + } \ + } \ + } +#define DTRANS( x ) \ + { \ + { \ + ops_cnt += ( 2 * _TRANS_C * ( x ) ); \ + inst_cnt[_TRANS] += ( x ); \ + { \ + static int pcnt; \ + if ( !pcnt ) \ + { \ + pcnt = 1; \ + prom_cnt += ( _TRANS_P * ( x ) ); \ + } \ + } \ + } \ + } + +extern double ops_cnt; +extern double prom_cnt; +extern double inst_cnt[NUM_INST]; + +void reset_wmops( void ); +#define push_wmops( ... ) push_wmops_fct( __VA_ARGS__, NULL ) +void push_wmops_fct( const char *label, ... ); +void pop_wmops( void ); +void update_wmops( void ); +void update_mem( void ); +void print_wmops( void ); + +#else /* WMOPS counting disabled */ + +#define reset_wmops() +extern int cntr_push_pop; +#define push_wmops( x ) ( cntr_push_pop++ ) +#define pop_wmops() ( cntr_push_pop-- ) +#define update_wmops() ( assert( cntr_push_pop == 0 ) ) +#define update_mem() +#define print_wmops() + +#define ADD( x ) +#define ABS( x ) +#define MULT( x ) +#define MAC( x ) +#define MOVE( x ) +#define STORE( x ) +#define LOGIC( x ) +#define SHIFT( x ) +#define BRANCH( x ) +#define DIV( x ) +#define SQRT( x ) +#define TRANS( x ) +#define FUNC( x ) +#define LOOP( x ) +#define INDIRECT( x ) +#define PTR_INIT( x ) +#define TEST( x ) +#define POWER( x ) +#define LOG( x ) +#define MISC( x ) + +#define DADD( x ) +#define DMULT( x ) +#define DMAC( x ) +#define DMOVE( x ) +#define DSTORE( x ) +#define DLOGIC( x ) +#define DSHIFT( x ) +#define DDIV( x ) +#define DSQRT( x ) +#define DTRANS( x ) + +#endif + +#ifndef WMOPS +/* DESACTIVATE the Counting Mechanism */ +#define OP_COUNT_( op, n ) + +/* DESACTIVATE Operation Counter Wrappers */ +#define OP_COUNT_WRAPPER1_( op, val ) ( val ) +#define OP_COUNT_WRAPPER2_( expr ) +#define OP_COUNT_WRAPPER3_( op, expr ) expr + +/* DESACTIVATE Logical & Ternary Operators */ +#define __ +#define _ + +#else + +/* '*ops_cnt_ptr' is Used to Avoid: "warning: operation on 'ops_cnt' may be undefined" with Cygwin gcc Compiler */ +static double *ops_cnt_ptr = &ops_cnt; +#define OP_COUNT_( op, x ) ( *ops_cnt_ptr += ( op##_C * ( x ) ), inst_cnt[op] += ( x ) ) + +/******************************************************************/ +/* NOTES: */ +/* The 'wmc_flag_' flag is global to avoid declaration in every */ +/* function and 'static' to avoid clashing with other modules */ +/* that include this header file. */ +/* */ +/* The declarations of 'wmc_flag_' and 'wops_' in this header */ +/* file prevent the addition of a 'C' file to the Project. */ +/******************************************************************/ + +/* General Purpose Global Flag */ +static int wmc_flag_ = 0; + +/* Operation Counter Wrappers */ +#define OP_COUNT_WRAPPER1_( op, val ) ( op, val ) +#define OP_COUNT_WRAPPER2_( expr ) \ + if ( expr, 0 ) \ + ; \ + else +#define OP_COUNT_WRAPPER3_( op, expr ) \ + if ( op, 0 ) \ + ; \ + else \ + expr + +#endif + +/* Define all Macros without '{' & '}' (None of these should be called externally!) */ +#define ABS_( x ) OP_COUNT_( _ABS, ( x ) ) +#define ADD_( x ) OP_COUNT_( _ADD, ( x ) ) +#define MULT_( x ) OP_COUNT_( _MULT, ( x ) ) +#define MAC_( x ) OP_COUNT_( _MAC, ( x ) ) +#define MOVE_( x ) OP_COUNT_( _MOVE, ( x ) ) +#define STORE_( x ) OP_COUNT_( _STORE, ( x ) ) +#define LOGIC_( x ) OP_COUNT_( _LOGIC, ( x ) ) +#define SHIFT_( x ) OP_COUNT_( _SHIFT, ( x ) ) +#define BRANCH_( x ) OP_COUNT_( _BRANCH, ( x ) ) +#define DIV_( x ) OP_COUNT_( _DIV, ( x ) ) +#define SQRT_( x ) OP_COUNT_( _SQRT, ( x ) ) +#define TRANS_( x ) OP_COUNT_( _TRANS, ( x ) ) +#define POWER_( x ) TRANS_( x ) +#define LOG_( x ) TRANS_( x ) +#define LOOP_( x ) OP_COUNT_( _LOOP, ( x ) ) +#define INDIRECT_( x ) OP_COUNT_( _INDIRECT, ( x ) ) +#define PTR_INIT_( x ) OP_COUNT_( _PTR_INIT, ( x ) ) +#define FUNC_( x ) ( OP_COUNT_( _MOVE, ( x ) ), OP_COUNT_( _FUNC, 1 ) ) +#define MISC_( x ) ABS_( x ) + +/* Math Operations */ +#define abs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), abs ) +#define fabs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabs ) +#define fabsf_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabsf ) +#define labs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), labs ) +#define floor_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floor ) +#define floorf_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floorf ) +#define sqrt_ OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrt ) +#define sqrtf_ OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrtf ) +#define pow_ OP_COUNT_WRAPPER1_( POWER_( 1 ), pow ) +#define powf_ OP_COUNT_WRAPPER1_( POWER_( 1 ), powf ) +#define exp_ OP_COUNT_WRAPPER1_( POWER_( 1 ), exp ) +#define expf_ OP_COUNT_WRAPPER1_( POWER_( 1 ), expf ) +#define log_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log ) +#define logf_ OP_COUNT_WRAPPER1_( LOG_( 1 ), logf ) +#define log10_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log10 ) +#define log10f_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log10f ) +#define cos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cos ) +#define cosf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cosf ) +#define sin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sin ) +#define sinf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinf ) +#define tan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tan ) +#define tanf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanf ) +#define acos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), acos ) +#define acosf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), acosf ) +#define asin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), asin ) +#define asinf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), asinf ) +#define atan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan ) +#define atanf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atanf ) +#define atan2_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan2 ) +#define atan2f_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan2f ) +#define cosh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cosh ) +#define coshf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), coshf ) +#define sinh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinh ) +#define sinhf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinhf ) +#define tanh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanh ) +#define tanhf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanhf ) +#define fmod_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmod ) +#define fmodf_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmodf ) +#define frexp_ OP_COUNT_WRAPPER1_( MISC_( 2 ), frexp ) +#define frexpf_ OP_COUNT_WRAPPER1_( MISC_( 2 ), frexpf ) + +/* the macros below are instrumented versions of user-defined macros that might be used in the source code +/* representing some well-known and recognized mathematical operations (that are not defined in math.h) */ +/* Note: the 'wmc_flag_=wmc_flag_' is used to avoid warning: left-hand operand of comma expression has no effect with gcc */ + +#define min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), min( ( a ), ( b ) ) ) +#define max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), max( ( a ), ( b ) ) ) +#define MIN_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MIN( ( a ), ( b ) ) ) +#define MAX_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MAX( ( a ), ( b ) ) ) +#define Min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Min( ( a ), ( b ) ) ) +#define Max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Max( ( a ), ( b ) ) ) +#define sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), sqr( ( x ) ) ) +#define Sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Sqr( ( x ) ) ) +#define SQR_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQR( ( x ) ) ) +#define square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), square( ( x ) ) ) +#define Square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Square( ( x ) ) ) +#define SQUARE_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQUARE( ( x ) ) ) +#define sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), sign( ( x ) ) ) +#define Sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), Sign( ( x ) ) ) +#define SIGN_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), SIGN( ( x ) ) ) +#define inv_sqrt_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrt( ( x ) ) ) +#define inv_sqrtf_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrtf( ( x ) ) ) +#define log_base_2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log_base_2( ( x ) ) ) +#define log2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2( ( x ) ) ) +#define log2f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2f( ( x ) ) ) +#define log2_f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2_f( ( x ) ) ) +#define _round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, _round( ( x ) ) ) +#define round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round( ( x ) ) ) +#define round_f_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round_f( ( x ) ) ) +#define roundf_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, roundf( ( x ) ) ) +#define set_min_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_min( ( a ), ( b ) ) ) +#define set_max_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_max( ( a ), ( b ) ) ) + +/* Functions */ +#define func_( name, x ) OP_COUNT_WRAPPER1_( FUNC_( x ), name ) + +/* Logical Operators */ +#ifndef __ +#define __ ( BRANCH_( 1 ), 1 ) && +#endif + +/* Ternary Operators (? and :) */ +#ifndef _ +#define _ ( BRANCH_( 1 ), 0 ) ? 0: +#endif + +/* Flow Control keywords */ +#define if_ \ + OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \ + if +#define for_ OP_COUNT_WRAPPER2_( LOOP_(1)) for +#define while_( c ) \ + while \ + OP_COUNT_WRAPPER1_( BRANCH_( 1 ), ( c ) ) /* needs extra "()" if ',' encountered */ +#define do_ \ + do \ + { +#define _while \ + BRANCH_( 1 ); \ + } \ + while + +#define goto_ \ + OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \ + goto +#define break_ \ + OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \ + break +#define continue_ \ + OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \ + continue +#define return_ \ + OP_COUNT_WRAPPER2_( ( wmc_flag_ = stack_tree_level_, STACK_DEPTH_FCT_RETURN ) ) \ + return + +#define switch_ \ + OP_COUNT_WRAPPER2_( ( BRANCH_( 1 ), wmc_flag_ = 1 ) ) \ + switch +#define cost_( n ) OP_COUNT_WRAPPER2_( wmc_flag_ ? ( ADD_( n ), BRANCH_( n ), wmc_flag_ = 0 ) : 0 ); + +#ifdef WMOPS + +#define ACC 2 +#define MUL 1 + +/* Counting Function (should not be called externally!) */ +static void wops_( const char *ops ) +{ + char lm = 0; /* lm: Last Operation is Math */ + static char lo = 0; /* Last Operation */ + + void ( *fct )( const char *ops ) = wops_; + +st: + while ( *ops != '\0' ) + { + switch ( *ops++ ) + { + int cnt; + case '-': + for ( cnt = 0; ops[cnt] == '>'; cnt++ ) + ; + if ( cnt & 1 ) + goto ind; + case '+': + lm = 2; + if ( lo & MUL ) + { + MULT_( -1 ); + MAC_( 1 ); + break; + } + lo = ACC << 2; + case 'U': + case 'D': + ADD_( 1 ); + break; + case '*': + lm = 2; + if ( lo & ACC ) + { + ADD_( -1 ); + MAC_( 1 ); + break; + } + lo = MUL << 2; + MULT_( 1 ); + break; + case '/': + case '%': + lm = 2; + DIV_( 1 ); + break; + case '&': + case '|': + case '^': + lm = 2; + case '~': + LOGIC_( 1 ); + break; + case '<': + case '>': + if ( *ops != ops[-1] ) + goto error; + ops++; + case -85: + case -69: + lm = 2; + SHIFT_( 1 ); + break; + case 'L': + case 'G': + if ( *ops == 't' ) + goto comp; + case 'E': + case 'N': + if ( *ops != 'e' ) + goto error; + comp: + ops++; + ADD_( 1 ); + break; + case '!': + MISC_( 2 ); + break; + case 'M': + MOVE_( 1 ); + break; + case 'S': + STORE_( 1 ); + break; + case 'P': + PTR_INIT_( 1 ); + break; + case '[': + case ']': + goto st; + ind: + ops++; + case 'I': + case '.': + INDIRECT_( 1 ); + break; + case '=': + if ( lm ) + goto st; + case '\0': + /* This Shouldn't Happen */ + /* These are Used to Avoid: "warning: 'name' defined but not used" with Cygwin gcc Compiler */ + wmc_flag_ = wmc_flag_; + ops_cnt_ptr = ops_cnt_ptr; + fct( "" ); + error: + default: + fprintf( stderr, "\r wops: Invalid Counting Operation '%s'\n", ops - 1 ); + exit( -1 ); + } + lm >>= 1; + lo >>= 2; + } + + return; +} + +#endif + +/* All Other Operations */ +#define $( str ) OP_COUNT_WRAPPER2_( wops_( str ) ) + + +/*-------------------------------------------------------------------* + * Memory counting tool + *-------------------------------------------------------------------*/ + +/* Enhanced Const Data Size Counting (Rounding Up to the Nearest 'Integer' Size) */ +#define rsize( item ) ( ( sizeof( item ) + sizeof( int ) - 1 ) / sizeof( int ) * sizeof( int ) ) + +#ifdef _MSC_VER +/* Disable "warning C4210: nonstandard extension used : function given file scope" with Visual Studio Compiler */ +#pragma warning( disable : 4210 ) +#endif + +/* Const Data Size and PROM Size Wrapper Functions */ +#define Const_Data_Size_Func( file ) Const_Data_Size_##file( void ) +#define Get_Const_Data_Size( file, val_ptr ) \ + { \ + extern int Const_Data_Size_##file( void ); \ + *( val_ptr ) = Const_Data_Size_##file(); \ + } +#define PROM_Size_Func( file ) PROM_Size_##file( void ) +#define Get_PROM_Size( file, val_ptr ) \ + { \ + int PROM_Size_##file( void ); \ + *( val_ptr ) = PROM_Size_##file(); \ + } + +/* ROM Size Lookup Table - contains information about PROM size and Const Data Size in all source files */ +/* The print_mem() function looks for this table to print the results of Const Data usage and PROM usage */ +typedef struct ROM_Size_Lookup_Table +{ + const char file_spec[255]; + int PROM_size; + int ( *Get_Const_Data_Size_Func )( void ); +} ROM_Size_Lookup_Table; + +/* The WMC tool inserts the following declaration during the innstrumentation process in the .c file where the function print_mem() is located */ +/* and modifies it to print_mem(Const_Data_PROM_Table) */ + +/* #ifdef WMOPS + * ROM_Size_Lookup_Table Const_Data_PROM_Table[] = + * { + * {"../lib_enc/rom_enc.c", 0, NULL}, + * {"../lib_com/*.c", 0, NULL}, + * {"", -1, NULL} + * }; + * #endif + */ + +/*#define MEM_ALIGN_64BITS */ /* Define this when using 64 Bits values in the code (ex: double), otherwise it will align on 32 Bits */ +/*#define MEM_COUNT_DETAILS*/ + +typedef enum +{ + USE_BYTES = 0, + USE_16BITS = 1, + USE_32BITS = 2, + USE_64BITS = 3 +} Counting_Size; + +#if ( defined( _WIN32 ) && ( _MSC_VER <= 1800 ) && ( _MSC_VER >= 1300 ) ) +#define __func__ __FUNCTION__ +#elif defined( __STDC_VERSION__ ) && __STDC_VERSION__ < 199901L +#if ( __GNUC__ >= 2 ) +#define __func__ __FUNCTION__ +#else +#define __func__ "" +#endif +#elif defined( __GNUC__ ) +#define __func__ __extension__ __FUNCTION__ +#endif + + +#ifdef WMOPS + +void *mem_alloc( const char *func_name, int func_lineno, size_t size, char *alloc_str ); +void mem_free( const char *func_name, int func_lineno, void *ptr ); + +#define malloc_( size ) mem_alloc( __func__, __LINE__, size, "m:" #size ) +#define calloc_( n, size ) mem_alloc( __func__, __LINE__, ( n ) * ( size ), "c:" #n ", " #size ) +#define free_( ptr ) mem_free( __func__, __LINE__, ptr ) + +void reset_mem( Counting_Size cnt_size ); +void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] ); + +int push_stack( const char *filename, const char *fctname ); +int pop_stack( const char *filename, const char *fctname ); + +#ifdef WMOPS_DETAIL +#define STACK_DEPTH_FCT_CALL ( push_wmops( __func__, "[WMC_AUTO]" ), push_stack( __FILE__, __func__ ) ) /* add push_wmops() in all function calls */ +#define STACK_DEPTH_FCT_RETURN ( pop_wmops(), pop_stack( __FILE__, __func__ ) ) /* add pop_wmops() in all function returns */ +#else +#define STACK_DEPTH_FCT_CALL push_stack( __FILE__, __FUNCTION__ ) +#define STACK_DEPTH_FCT_RETURN pop_stack( __FILE__, __func__ ) +#endif + +void reset_stack( void ); +#define func_start_ int stack_tree_level_ = STACK_DEPTH_FCT_CALL; + +#else +#define malloc_( n1 ) malloc( n1 ) +#define calloc_( n1, n2 ) calloc( n1, n2 ) +#define free_( ptr ) free( ptr ) +#define reset_mem( cnt_size ) +#define print_mem( Const_Data_PROM_Table ) + +#define push_stack( file, fct ) +#define pop_stack( file, fct ) +#define reset_stack() +#define func_start_ + +#endif + + +/* Global counter variable for calculation of complexity weight */ +typedef struct +{ + unsigned int add; /* Complexity Weight of 1 */ + unsigned int sub; /* Complexity Weight of 1 */ + unsigned int abs_s; /* Complexity Weight of 1 */ + unsigned int shl; /* Complexity Weight of 1 */ + unsigned int shr; /* Complexity Weight of 1 */ + + unsigned int extract_h; /* Complexity Weight of 1 */ + unsigned int extract_l; /* Complexity Weight of 1 */ + unsigned int mult; /* Complexity Weight of 1 */ + unsigned int L_mult; /* Complexity Weight of 1 */ + unsigned int negate; /* Complexity Weight of 1 */ + + unsigned int round; /* Complexity Weight of 1 */ + unsigned int L_mac; /* Complexity Weight of 1 */ + unsigned int L_msu; /* Complexity Weight of 1 */ + unsigned int L_macNs; /* Complexity Weight of 1 */ + unsigned int L_msuNs; /* Complexity Weight of 1 */ + + unsigned int L_add; /* Complexity Weight of 1 */ + unsigned int L_sub; /* Complexity Weight of 1 */ + unsigned int L_add_c; /* Complexity Weight of 2 */ + unsigned int L_sub_c; /* Complexity Weight of 2 */ + unsigned int L_negate; /* Complexity Weight of 1 */ + + unsigned int L_shl; /* Complexity Weight of 1 */ + unsigned int L_shr; /* Complexity Weight of 1 */ + unsigned int mult_r; /* Complexity Weight of 1 */ + unsigned int shr_r; /* Complexity Weight of 3 */ + unsigned int mac_r; /* Complexity Weight of 1 */ + + unsigned int msu_r; /* Complexity Weight of 1 */ + unsigned int L_deposit_h; /* Complexity Weight of 1 */ + unsigned int L_deposit_l; /* Complexity Weight of 1 */ + unsigned int L_shr_r; /* Complexity Weight of 3 */ + unsigned int L_abs; /* Complexity Weight of 1 */ + + unsigned int L_sat; /* Complexity Weight of 4 */ + unsigned int norm_s; /* Complexity Weight of 1 */ + unsigned int div_s; /* Complexity Weight of 18 */ + unsigned int norm_l; /* Complexity Weight of 1 */ + unsigned int move16; /* Complexity Weight of 1 */ + + unsigned int move32; /* Complexity Weight of 2 */ + unsigned int Logic16; /* Complexity Weight of 1 */ + unsigned int Logic32; /* Complexity Weight of 2 */ + unsigned int Test; /* Complexity Weight of 2 */ + unsigned int s_max; /* Complexity Weight of 1 */ + + unsigned int s_min; /* Complexity Weight of 1 */ + unsigned int L_max; /* Complexity Weight of 1 */ + unsigned int L_min; /* Complexity Weight of 1 */ + unsigned int L40_max; /* Complexity Weight of 1 */ + unsigned int L40_min; /* Complexity Weight of 1 */ + + unsigned int shl_r; /* Complexity Weight of 3 */ + unsigned int L_shl_r; /* Complexity Weight of 3 */ + unsigned int L40_shr_r; /* Complexity Weight of 3 */ + unsigned int L40_shl_r; /* Complexity Weight of 3 */ + unsigned int norm_L40; /* Complexity Weight of 1 */ + + unsigned int L40_shl; /* Complexity Weight of 1 */ + unsigned int L40_shr; /* Complexity Weight of 1 */ + unsigned int L40_negate; /* Complexity Weight of 1 */ + unsigned int L40_add; /* Complexity Weight of 1 */ + unsigned int L40_sub; /* Complexity Weight of 1 */ + + unsigned int L40_abs; /* Complexity Weight of 1 */ + unsigned int L40_mult; /* Complexity Weight of 1 */ + unsigned int L40_mac; /* Complexity Weight of 1 */ + unsigned int mac_r40; /* Complexity Weight of 2 */ + + unsigned int L40_msu; /* Complexity Weight of 1 */ + unsigned int msu_r40; /* Complexity Weight of 2 */ + unsigned int Mpy_32_16_ss; /* Complexity Weight of 2 */ + unsigned int Mpy_32_32_ss; /* Complexity Weight of 4 */ + unsigned int L_mult0; /* Complexity Weight of 1 */ + + unsigned int L_mac0; /* Complexity Weight of 1 */ + unsigned int L_msu0; /* Complexity Weight of 1 */ + unsigned int lshl; /* Complexity Weight of 1 */ + unsigned int lshr; /* Complexity Weight of 1 */ + unsigned int L_lshl; /* Complexity Weight of 1 */ + + unsigned int L_lshr; /* Complexity Weight of 1 */ + unsigned int L40_lshl; /* Complexity Weight of 1 */ + unsigned int L40_lshr; /* Complexity Weight of 1 */ + unsigned int s_and; /* Complexity Weight of 1 */ + unsigned int s_or; /* Complexity Weight of 1 */ + + unsigned int s_xor; /* Complexity Weight of 1 */ + unsigned int L_and; /* Complexity Weight of 1 */ + unsigned int L_or; /* Complexity Weight of 1 */ + unsigned int L_xor; /* Complexity Weight of 1 */ + unsigned int rotl; /* Complexity Weight of 3 */ + + unsigned int rotr; /* Complexity Weight of 3 */ + unsigned int L_rotl; /* Complexity Weight of 3 */ + unsigned int L_rotr; /* Complexity Weight of 3 */ + unsigned int L40_set; /* Complexity Weight of 3 */ + unsigned int L40_deposit_h; /* Complexity Weight of 1 */ + + unsigned int L40_deposit_l; /* Complexity Weight of 1 */ + unsigned int L40_deposit32; /* Complexity Weight of 1 */ + unsigned int Extract40_H; /* Complexity Weight of 1 */ + unsigned int Extract40_L; /* Complexity Weight of 1 */ + unsigned int L_Extract40; /* Complexity Weight of 1 */ + + unsigned int L40_round; /* Complexity Weight of 1 */ + unsigned int L_saturate40; /* Complexity Weight of 1 */ + unsigned int round40; /* Complexity Weight of 1 */ + unsigned int If; /* Complexity Weight of 4 */ + unsigned int Goto; /* Complexity Weight of 4 */ + + unsigned int Break; /* Complexity Weight of 4 */ + unsigned int Switch; /* Complexity Weight of 8 */ + unsigned int For; /* Complexity Weight of 3 */ + unsigned int While; /* Complexity Weight of 4 */ + unsigned int Continue; /* Complexity Weight of 4 */ + + unsigned int L_mls; /* Complexity Weight of 6 */ + unsigned int div_l; /* Complexity Weight of 32 */ + unsigned int i_mult; /* Complexity Weight of 3 */ +} BASIC_OP; + +#ifdef WMOPS +extern BASIC_OP *multiCounter; +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; + +extern long TotalWeightedOperation( void ); +long DeltaWeightedOperation( void ); + +void Set_BASOP_WMOPS_counter( int counterId ); +void Reset_BASOP_WMOPS_counter( void ); + +#endif + +/***************************************************************************** + * + * 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 +#define FOR( a) if( incrFor(), 0); else for( a) + +static __inline void incrFor( void) { + multiCounter[currCounter].For++; +} +#endif + + +/***************************************************************************** + * + * 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 +#define WHILE( a) while( incrWhile(), a) + +static __inline void incrWhile( void) { + multiCounter[currCounter].While++; +} +#endif + + +/***************************************************************************** + * + * 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 +#define DO do + +#endif + + +/***************************************************************************** + * + * 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 +#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 = INT_MAX; +} +#endif + + +/***************************************************************************** + * + * 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 +#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 + + +/***************************************************************************** + * + * 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 +#define SWITCH( a) switch( incrSwitch(), a) + +static __inline void incrSwitch( void) { + multiCounter[currCounter].Switch++; +} +#endif + + +/***************************************************************************** + * + * 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 +#define CONTINUE if( incrContinue(), 0); else continue + +static __inline void incrContinue( void) { + multiCounter[currCounter].Continue++; +} +#endif + + +/***************************************************************************** + * + * 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 +#define BREAK if( incrBreak(), 0) break; else break + +static __inline void incrBreak( void) { + multiCounter[currCounter].Break++; +} +#endif + + +/***************************************************************************** + * + * 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 +#define GOTO if( incrGoto(), 0); else goto + +static __inline void incrGoto( void) { + multiCounter[currCounter].Goto++; +} +#endif + +#endif /* WMOPS_H */ + + diff --git a/lib_dec/ACcontextMapping_dec.c b/lib_dec/ACcontextMapping_dec.c new file mode 100644 index 000000000..34a6b4b7a --- /dev/null +++ b/lib_dec/ACcontextMapping_dec.c @@ -0,0 +1,279 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* +* ACcontextMapping_decode2_no_mem_s17_LC() +* +* Arithmetic decoder +*-------------------------------------------------------------------*/ + +long ACcontextMapping_decode2_no_mem_s17_LC( /* o: resQBits */ + Decoder_State *st, /* i/o: decoder state */ + int *x, /* o: decoded spectrum */ + long nt, /* i: size of spectrum */ + int nbbits, /* i: bit budget */ + int resQMaxBits, /* i: residual coding maximum bits */ + CONTEXT_HM_CONFIG *hm_cfg /* i: context-based harmonic model configuration*/ +) +{ + Tastat as; + int start_bit_pos, lsbs_bit_pos, overflow_bit_pos; + int a, b, t, a1, b1, a1_i, b1_i, k; + int lev, pki, esc_nb; + int rateFlag; + int r, lastnz, n; + int resQBits; + int rest_bits, rest_bits_overflow; + int nt_half; + int c[2], *ctx; + int p1, p2; + int ii[2], idx1, idx2, idx; + int numPeakIndicesOrig, numHoleIndices; + int nbbits_m2; + + + set_i(x, 0, nt); + + /* Rate flag */ + if (nbbits>400) + { + rateFlag = 2 << NBITS_CONTEXT; + } + else + { + rateFlag = 0; + } + + /*Decode number of ntuples*/ + start_bit_pos = st->next_bit_pos; + lsbs_bit_pos = start_bit_pos + nbbits - 1; + + n = 0; + k = 1; + nt_half = nt>>1; + + while (k nt || st->BER_detect) + { + st->BER_detect = 1; + return 0; + } + + if (hm_cfg) + { + /* mapped domain */ + numPeakIndicesOrig = hm_cfg->numPeakIndices; + hm_cfg->numPeakIndices = min(hm_cfg->numPeakIndices, lastnz ); + numHoleIndices = lastnz - hm_cfg->numPeakIndices; + + /* Mark hole indices beyond lastnz as pruned */ + for (k=numHoleIndices; knumHoleIndices; ++k) + { + hm_cfg->holeIndices[k] = hm_cfg->holeIndices[k] + nt; + } + + ii[0] = numPeakIndicesOrig; + ii[1] = 0; + + p1 = p2 = 0; /* to avoid compilation warnings */ + } + else + { + /* unmapped domain */ + ii[0] = 0; + p1 = p2 = 0; + } + + /* Start Decoding */ + + ari_start_decoding_14bits(st, &as); + overflow_bit_pos = st->next_bit_pos; + + nbbits_m2 = nbbits + cbitsnew - 2; + rest_bits_overflow = rest_bits = -nbbits_m2; + + /* Main Loop through the 2-tuples */ + for (k=0; k> (sizeof(int)*8-1)) << NBITS_CONTEXT; + + esc_nb = 0; + r = 0; + if (t < 0 || lsbs_bit_pos <= 0) + { + st->BER_detect = 1; + return 0; + } + + a = b = 0; + /* MSBs decoding */ + for (lev = 0; lev < 15 && lsbs_bit_pos > 0; ++lev) + { + esc_nb = min(lev, 3); + pki = ari_lookup_s17_LC[t + (esc_nb << (NBITS_CONTEXT + NBITS_RATEQ))]; + ari_decode_14bits_s17_ext(st,&r,&as,ari_pk_s17_LC_ext[pki]); + + if (r= VAL_ESC) || (lev > 14) ) + { + x[a1_i] = 0; + x[b1_i] = 0; + st->BER_detect = 1; + return 0; + } + + /* MSBs contributions */ + b1 = r>>2; + a1 = r&0x3; + a += a1 << lev; + b += b1 << lev; + + /* lsbs bits sign bits */ + rest_bits += 2*lev; + + rest_bits += min(a, 1); + rest_bits += min(b, 1); + + /* Dectect overflow */ + + if (st->next_bit_pos-start_bit_pos+rest_bits>0) + { + /* Roll back bit-stream position to overflow_bit_pos */ + get_next_indice_tmp(st, overflow_bit_pos - st->next_bit_pos); + rest_bits = rest_bits_overflow; + x[a1_i] = 0; + x[b1_i] = 0; + break; + } + + overflow_bit_pos = st->next_bit_pos; + rest_bits_overflow = rest_bits; + + /* Store decoded data */ + x[a1_i] = a; + x[b1_i] = b; + + /* Update context for next 2-tuple */ + if (p1 == p2) + { + /* peak-peak or hole-hole context */ + lev = esc_nb - 1; + + if (lev <= 0) + { + t = 1 + (a1 + b1)*(lev+2); + } + else + { + t = 13 + lev; + } + + *ctx = (*ctx & 0xf) * 16 + t; + } + else + { + /* mixed context */ + + if (idx1 & 1) + { + /* update first context */ + c[p1] = update_mixed_context(c[p1], a); + } + + if (idx2 & 1) + { + /* update second context */ + c[p2] = update_mixed_context(c[p2], b); + } + } + } + + /* Total number of decoded AC bits */ + get_next_indice_tmp(st, -(cbitsnew - 2)); + + /* detect overflow */ + + if(k!=lastnz) + { + rest_bits += nbbits_m2; + /* Set bit-stream position to (start_bit_pos+nbbits-rest_bits) */ + get_next_indice_tmp(st, (start_bit_pos+nbbits-rest_bits)-st->next_bit_pos); + } + + /* Decode signs */ + if (hm_cfg) + { + n = nt; + } + else + { + n = lastnz; + } + + for (k = 0; k < n; k++) + { + if (x[k] > 0) + { + x[k] *= 1-2*get_next_indice_1(st); + } + } + + /*Decode Residual Q*/ + resQBits = min(resQMaxBits, lsbs_bit_pos+1 - st->next_bit_pos); + + for (k=0; knext_bit_pos); + + + return resQBits; +} diff --git a/lib_dec/EvsRXlib.c b/lib_dec/EvsRXlib.c new file mode 100644 index 000000000..b08d5d5cb --- /dev/null +++ b/lib_dec/EvsRXlib.c @@ -0,0 +1,510 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include +#include "options.h" +#include "prot.h" +#include "EvsRXlib.h" +#include "jbm_jb4sb.h" +#include "jbm_pcmdsp_apa.h" +#include "jbm_pcmdsp_fifo.h" +#include "cnst.h" + + +struct EVS_RX +{ + unsigned int nSamplesFrame; + Decoder_State *st; + JB4_HANDLE hJBM; + unsigned int lastDecodedWasActive; + 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 int isSidFrame( unsigned int size ); + + +/* Opens the EVS Receiver instance. */ +EVS_RX_ERROR EVS_RX_Open(EVS_RX_HANDLE* phEvsRX, + Decoder_State *st, + Word16 jbmSafetyMargin) +{ + EVS_RX_HANDLE hEvsRX; + uint16_t wss, css; + + *phEvsRX = NULL; + + /* Create EVS Receiver handle */ + *phEvsRX = (EVS_RX_HANDLE) calloc(1, sizeof(struct EVS_RX) ); + if ( *phEvsRX == NULL ) + { + return EVS_RX_MEMORY_ERROR; + } + hEvsRX = *phEvsRX; + + hEvsRX->st = st; + /* do not use codec for time stretching (PLC) before initialization with first received frame */ + st->codec_mode = 0; + + /* open JBM */ + hEvsRX->hJBM = 0; + 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; + hEvsRX->nSamplesFrame = st->output_Fs / 50; + + if(st->output_Fs == 8000) + { + wss = 1; + css = 1; + } + else if(st->output_Fs == 16000) + { + wss = 2; + css = 1; + } + else if(st->output_Fs == 32000) + { + wss = 4; + css = 2; + } + else if(st->output_Fs == 48000) + { + wss = 6; + css = 3; + } + else + { + assert(0 || "unknown sample rate!"); + wss = css = 1; /* just to avoid compiler warning */ + } + + /* initialize time scaler and FIFO after time scaler */ + if( apa_init( &hEvsRX->hTimeScaler ) != 0 || + apa_set_rate( hEvsRX->hTimeScaler, st->output_Fs, 1 ) != 0 || + apa_set_complexity_options( hEvsRX->hTimeScaler, wss, css) != 0 || + apa_set_quality( hEvsRX->hTimeScaler, 1, 4, 4 ) != 0 || + pcmdsp_fifo_create( &hEvsRX->hFifoAfterTimeScaler ) != 0 || + pcmdsp_fifo_init( hEvsRX->hFifoAfterTimeScaler, st->output_Fs * 4 / 50 /* 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, + unsigned char *au, + unsigned int auSize, + unsigned short rtpSequenceNumber, + unsigned long rtpTimeStamp, + unsigned int rcvTime_ms + , Word16 isAMRWB_IOmode, + Word16 frameTypeIndex, + Word16 qBit + ) +{ + JB4_DATAUNIT_HANDLE dataUnit; + int16_t partialCopyFrameType, partialCopyOffset; + int 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); + memcpy(dataUnit->data, au, (auSize + 7) / 8); + dataUnit->dataSize = auSize; + dataUnit->duration = 20; + dataUnit->sequenceNumber = rtpSequenceNumber; + dataUnit->silenceIndicator = isSidFrame( dataUnit->dataSize ); + dataUnit->timeScale = 1000; + dataUnit->rcvTime = rcvTime_ms; + dataUnit->timeStamp = rtpTimeStamp; + dataUnit->partial_frame = 0; + dataUnit->partialCopyOffset = partialCopyOffset; + 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; + } + + if(partialCopyFrameType != RF_NO_DATA && partialCopyOffset != 0) + { + /* create data unit for partial copy in the frame */ + dataUnit = JB4_AllocDataUnit(hEvsRX->hJBM); + memcpy(dataUnit->data, au, (auSize + 7) / 8); + dataUnit->dataSize = auSize; + dataUnit->duration = 20; + dataUnit->sequenceNumber = rtpSequenceNumber; + dataUnit->silenceIndicator = 0; /* there are no partial copies for SID frames */ + dataUnit->timeScale = 1000; + dataUnit->rcvTime = rcvTime_ms; + dataUnit->timeStamp = rtpTimeStamp - partialCopyOffset * dataUnit->duration; + dataUnit->partial_frame = 1; + dataUnit->partialCopyOffset = partialCopyOffset; + 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, + unsigned int* nOutSamples, + Word16 *pcmBuf, + unsigned int pcmBufSize, + unsigned int systemTimestamp_ms + ) +{ + Decoder_State *st; + unsigned int soundCardFrameSize, extBufferedSamples; + uint32_t extBufferedTime_ms, scale, maxScaling; + uint16_t nTimeScalerOutSamples; + int timeScalingDone, result; + JB4_DATAUNIT_HANDLE dataUnit; + float output[3 * L_FRAME48k]; /* 'float' buffer for output synthesis */ + + assert(hEvsRX->nSamplesFrame <= pcmBufSize); + assert(hEvsRX->nSamplesFrame <= APA_BUF); + + st = hEvsRX->st; + soundCardFrameSize = hEvsRX->nSamplesFrame; + timeScalingDone = 0; + + + /* make sure that the FIFO after decoder/scaler contains at least one sound card frame (i.e. 20ms) */ + while( pcmdsp_fifo_nReadableSamples( hEvsRX->hFifoAfterTimeScaler ) < soundCardFrameSize ) + { + extBufferedSamples = pcmdsp_fifo_nReadableSamples( hEvsRX->hFifoAfterTimeScaler ); + extBufferedTime_ms = extBufferedSamples * 1000 / st->output_Fs; + dataUnit = NULL; + /* 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; + } + maxScaling = maxScaling * st->output_Fs / 1000; + /* avoid time scaling multiple times in one sound card slot */ + if( scale != 100U ) + { + if( timeScalingDone ) + { + scale = 100; + } + else + { + timeScalingDone = 1; + } + } + + /* copy bitstream into decoder state */ + if(dataUnit) + { + if( st->codec_mode != 0 ) + { + read_indices_from_djb( st, dataUnit->data, dataUnit->dataSize, + dataUnit->isAMRWB_IOmode, dataUnit->frameTypeIndex, dataUnit->qBit, + (dataUnit->partial_frame==TRUE)? 1: 0, 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, to correctly set st->last_codec_mode */ + st->ini_frame = 0; + st->prev_use_partial_copy = 0; + init_decoder( st ); + /* parse frame again because init_decoder() overwrites st->total_brate */ + read_indices_from_djb( st, dataUnit->data, dataUnit->dataSize, + dataUnit->isAMRWB_IOmode, dataUnit->frameTypeIndex, dataUnit->qBit, + 0, 0 ); + + } + } + else if( st->codec_mode != 0 ) + { + read_indices_from_djb( st, NULL, 0, + 0, 0, 0, + 0, 0 ); + } + + /* run the main decoding routine */ + if( st->codec_mode == MODE1 ) + { + if( st->Opt_AMR_WB ) + { + amr_wb_dec( st, output ); + } + else + { + evs_dec( st, output, FRAMEMODE_NORMAL ); + } + } + else if( st->codec_mode == MODE2 ) + { + if(st->bfi == 0) + { + evs_dec(st, output, FRAMEMODE_NORMAL); /* FRAMEMODE_NORMAL */ + } + else if ( st->bfi == 2 ) + { + evs_dec(st, output, FRAMEMODE_FUTURE); /* FRAMEMODE_FUTURE */ + } + else /* conceal */ + { + evs_dec(st, output, FRAMEMODE_MISSING); + } + } + /* convert 'float' output data to 'short' */ + if( st->codec_mode == MODE1 || st->codec_mode == MODE2 ) + { + syn_output( output, hEvsRX->nSamplesFrame, pcmBuf ); + + /* increase the counter of initialization frames */ + if( st->ini_frame < MAX_FRAME_COUNTER ) + { + st->ini_frame++; + } + } + else /* codec mode to use not known yet */ + { + set_s( pcmBuf, 0, hEvsRX->nSamplesFrame ); + } + + if(dataUnit) + { + if(dataUnit->partial_frame != 0) + { + hEvsRX->lastDecodedWasActive = 1; + } + else + { + hEvsRX->lastDecodedWasActive = !dataUnit->silenceIndicator; + } + /* data unit memory is no longer used */ + JB4_FreeDataUnit(hEvsRX->hJBM, dataUnit); + } + + /* limit scale to range supported by time scaler */ + if (scale < APA_MIN_SCALE) + { + scale = APA_MIN_SCALE; + } + else if (scale > APA_MAX_SCALE) + { + scale = APA_MAX_SCALE; + } + /* 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, hEvsRX->nSamplesFrame, + 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, + (uint8_t*)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; + /* 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, hEvsRX->lastDecodedWasActive, dataUnit->partialCopyOffset ); + } + else + { + fprintf( hEvsRX->jbmTraceFile, "%u;%u;%u;%f;%d\n", + dataUnit->sequenceNumber, dataUnit->timeStamp, dataUnit->rcvTime, + playTime, hEvsRX->lastDecodedWasActive ); + } + + } + else + { + fprintf( hEvsRX->jbmTraceFile, "%d;%d;%d;%f;%d\n", + -1, -1, -1, + playTime, hEvsRX->lastDecodedWasActive ); + } + } +#endif + } + + /* fetch one frame for the sound card from FIFO */ + *nOutSamples = soundCardFrameSize; + if( pcmdsp_fifo_read( hEvsRX->hFifoAfterTimeScaler, *nOutSamples, (uint8_t*)pcmBuf ) != 0 ) + { + return EVS_RX_TIMESCALER_ERROR; + } + return EVS_RX_NO_ERROR; +} + +EVS_RX_ERROR +EVS_RX_Get_FEC_offset( EVS_RX_HANDLE hEvsRX, short *offset + , short *FEC_hi + ) +{ + + *offset = JB4_getFECoffset(hEvsRX->hJBM); + *FEC_hi = JB4_FECoffset(hEvsRX->hJBM); + return EVS_RX_NO_ERROR; + +} + + + + +/* Returns 1 if the jitter buffer is empty, otherwise 0. */ +unsigned int +EVS_RX_IsEmpty(EVS_RX_HANDLE hEvsRX ) +{ + unsigned int isEmpty; + + isEmpty = 0; + if (JB4_bufferedDataUnits(hEvsRX->hJBM) == 0U) + { + isEmpty = 1; + } + + return isEmpty; +} + +/* Closes the receiver instance. */ +EVS_RX_ERROR +EVS_RX_Close(EVS_RX_HANDLE* phRX ) +{ + /* Free all memory */ + 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; + phRX = NULL; + + return EVS_RX_NO_ERROR; +} + +/* function to check if a frame contains a SID */ +static int isSidFrame( unsigned int size ) +{ + int ret = 0; + if(size == SID_1k75 / 50) + { + ret = 1; /* AMR-WB SID */ + } + else if(size == SID_2k40 / 50) + { + ret = 1; /* EVS SID */ + } + return ret; +} diff --git a/lib_dec/EvsRXlib.h b/lib_dec/EvsRXlib.h new file mode 100644 index 000000000..cfcc6f39f --- /dev/null +++ b/lib_dec/EvsRXlib.h @@ -0,0 +1,90 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#ifndef EvsRXLIB_H +#include "wmc_auto.h" +#define EvsRXLIB_H + +/* local headers */ +#include "stat_dec.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 *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, + unsigned char *au, + unsigned int auSize, + unsigned short rtpSequenceNumber, + unsigned long rtpTimeStamp, + unsigned int 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, + unsigned int* nOutSamples, + Word16 *pcmBuf, + unsigned int pcmBufSize, + unsigned int systemTimestamp_ms + ); + +EVS_RX_ERROR +EVS_RX_Get_FEC_offset( EVS_RX_HANDLE hEvsRX, short* offset + , short *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! */ +unsigned int +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.c b/lib_dec/FEC.c new file mode 100644 index 000000000..300cf92bb --- /dev/null +++ b/lib_dec/FEC.c @@ -0,0 +1,536 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "rom_dec.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static void gain_dec_bfi( float *past_qua_en ); +static void pulseRes_preCalc( Word16* cond1, Word16* cond2, Word32* cond3 ,Word16 new_pit, Word16 Tc, Word16 L_frame ); + + +/*-------------------------------------------------------------------* + * FEC_exc_estim() + * + * Calculation of excitation signal + *-------------------------------------------------------------------*/ + +void FEC_exc_estim( + Decoder_State *st, /* i/o: Decoder static memory */ + const short L_frame, /* i : length of the frame */ + float *exc, /* o : pointer to excitation buffer (with past) */ + float *exc2, /* o : total excitation (for synthesis) */ + float *exc_dct_in, /* o : GSC excitation in DCT domain */ + float *pitch_buf, /* o : pitch buffer for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *tmp_tc, /* o : FEC pitch */ + float *bwe_exc, /* o : excitation for SWB TBE */ + float *lsf_new, /* i : ISFs at the end of the frame */ + float *tmp_noise /* o : long-term noise energy */ +) +{ + short i, Tc, new_pit; + float exc2_buf[L_FRAME16k + MODE1_L_FIR_FER-1]; + float *pt_exc, *pt1_exc, alpha, step, gain_inov, gain, gainCNG, hp_filt[5]; + float fT0, delta, ftmp; + short Diff_len; + short Len, max_len; + short last_bin; + short extrapolationFailed = 1; + float predPitchLag; + Word16 cond1, cond2; + Word32 cond3; + + /*-----------------------------------------------------------------* + * Initializations + *-----------------------------------------------------------------*/ + + gainCNG = (float)sqrt( st->lp_ener ); + + ftmp = 2.0f * st->lp_gainc; + if ( gainCNG > ftmp ) + { + gainCNG = ftmp; + } + + Diff_len = 0; + set_f( exc_dct_in, 0.0f, L_FRAME16k ); + + /*-----------------------------------------------------------------* + * Pitch extrapolation + *-----------------------------------------------------------------*/ + + /* pitch extrapolation */ + pitch_pred_linear_fit( st->nbLostCmpt, st->last_good, st->old_pitch_buf, + L_frame == L_FRAME ? &st->old_pitch_buf[2*NB_SUBFR-1] : &st->old_pitch_buf[2*NB_SUBFR16k-1], + &predPitchLag, L_frame == L_FRAME? PIT_MIN_DOUBLEEXTEND: PIT16k_MIN_EXTEND, + L_frame == L_FRAME? PIT_MAX: PIT16k_MAX, st->mem_pitch_gain, 0, 0, &extrapolationFailed, L_frame/L_SUBFR ); + + new_pit = (int)(predPitchLag+0.5f); + + /* initialize FEC pitch to the long-term pitch */ + *tmp_tc = st->bfi_pitch; + if( L_frame == L_FRAME ) + { + if( ( ( st->old_pitch_buf[2*NB_SUBFR-1] < 1.8f * st->bfi_pitch ) && + ( st->old_pitch_buf[2*NB_SUBFR-1] > 0.6f * st->bfi_pitch ) ) || /* last pitch coherent with the past */ + ( st->upd_cnt >= MAX_UPD_CNT ) ) /* or last update too far in the past */ + { + /* take the pitch value of last subframe of the previous frame */ + *tmp_tc = st->old_pitch_buf[2*NB_SUBFR-1]; + } + } + else /* L_frame == L_FRAME16k */ + { + if( ( ( st->old_pitch_buf[2*NB_SUBFR16k-1] < 1.8f * st->bfi_pitch ) && + ( st->old_pitch_buf[2*NB_SUBFR16k-1] > 0.6f * st->bfi_pitch ) ) || /* last pitch coherent with the past */ + ( st->upd_cnt >= MAX_UPD_CNT ) ) /* or last update too far in the past */ + { + /* take the pitch value of last subframe of the previous frame */ + *tmp_tc = st->old_pitch_buf[2*NB_SUBFR16k-1]; + } + } + /* convert pitch period */ + Tc = (short)(*tmp_tc + 0.5f); + + pulseRes_preCalc( &cond1, &cond2, &cond3 , (Word16)new_pit, (Word16)Tc, (Word16)L_frame ); + + if( (cond1 < 0 ) && (new_pit > 0) && (cond2 != 0) && (cond3 > 0) && extrapolationFailed == 0 ) + { + fT0 = *tmp_tc; + delta = (float)(new_pit - fT0)/(L_frame/L_SUBFR); /* # of subframes */ + for ( i=0; ilast_coder_type == UNVOICED && st->nbLostCmpt <= 3 ) + { + /* last good frame was clearly unvoiced */ + alpha = ALPHA_UU; + } + else if( st->last_coder_type == AUDIO || st->last_good == INACTIVE_CLAS ) + { + if( st->Last_GSC_pit_band_idx > 0 && st->nbLostCmpt > 1 ) + { + alpha = 0.8f; + } + else if( st->nbLostCmpt <= 5 ) + { + alpha = 0.995f; + } + else + { + alpha = 0.95f; + } + } + else if(st->last_good == UNVOICED_CLAS ) + { + if( st->nbLostCmpt <= 1 ) + { + /* If stable, do not decrease the energy, pitch gain = 0 */ + alpha = st->stab_fac * (1.0f - 2.0f*ALPHA_U) + 2.0f*ALPHA_U; /* [0.8, 1.0] */ + } + else if ( st->nbLostCmpt == 2 ) + { + alpha = ALPHA_U * 1.5f; /* 0.6 */ + } + else + { + alpha = ALPHA_U; /* 0.4 go rapidly to CNG gain, pitch gain = 0 */ + } + } + else if(st->last_good == UNVOICED_TRANSITION ) + { + alpha = ALPHA_UT; + } + else if(st->last_good == ONSET && st->nbLostCmpt <= 3 && (st->last_coder_type == GENERIC || st->last_coder_type == TRANSITION) ) + { + alpha = 0.8f; /* mild convergence to 0 for the first 3 erased frames */ + } + else if( (st->last_good == VOICED_CLAS || st->last_good == ONSET ) && st->nbLostCmpt <= 3 ) + { + alpha = ALPHA_V; /* constant for the first 3 erased frames */ + } + else if(st->last_good == SIN_ONSET ) + { + alpha = ALPHA_S; + } + + if(st->last_good >= VOICED_CLAS && st->last_good < INACTIVE_CLAS && st->last_coder_type != AUDIO ) + { + if( st->nbLostCmpt == 1 ) + { + /* if this is the first erased frame, move pitch gain towards 1 for voiced to remove energy fluctuations */ + gain = (float)sqrt(st->lp_gainp); + if( gain > 0.98f ) + { + gain = 0.98f; + } + else if( gain < 0.85f ) + { + gain = 0.85f; + } + + alpha *= gain; + } + else + { + alpha = st->lp_gainp; + } + } + + /*-----------------------------------------------------------------* + * Extrapolate past excitation signal using estimated pitch period + *-----------------------------------------------------------------*/ + + if( (st->last_good >= UNVOICED_TRANSITION && st->last_good < INACTIVE_CLAS) || + ( (st->last_coder_type == AUDIO || st->last_good == INACTIVE_CLAS) && st->Last_GSC_pit_band_idx > 0) ) + { + /* Do pitch-based extrapolation only for stable voiced and audio signals */ + + pt_exc = exc; + pt1_exc = pt_exc - Tc; + + if ( st->nbLostCmpt == 1 ) + { + /* first pitch cycle is low-pass filtered */ + for( i=0 ; i< Tc; i++ ) + { + *pt_exc++ = ( 0.18f * pt1_exc[-1] + 0.64f * pt1_exc[0] + 0.18f * pt1_exc[1] ); + pt1_exc++; + } + } + + /* last pitch cycle of the previous frame is repeatedly copied up to an extra subframe */ + while( pt_exc < exc + L_frame + L_SUBFR ) + { + *pt_exc++ = *pt1_exc++; + } + + /* resynchronization of excitation based on glottal pulse locations in the last good frame */ + if ( new_pit > 0 ) + { + if ((cond1 < 0 ) && (new_pit > 0) && (cond2 != 0) && (cond3 > 0) && extrapolationFailed == 0 ) + { + mvr2r( exc, exc-L_frame-L_SUBFR, L_frame+L_SUBFR ); + PulseResynchronization( exc-L_frame-L_SUBFR, exc, L_frame, L_frame/L_SUBFR, Tc, new_pit ); + } + } + + if(st->last_good == UNVOICED_TRANSITION && ( st->last_coder_type == GENERIC || st->last_coder_type == TRANSITION ) ) + { + /* start of the frame gain */ + gain = 0.0f; + + /* end of the frame gain */ + st->lp_gainp = 0.0f; + + step = 0.0f; + } + else + { + /* start of the frame gain */ + gain = 1.0f; + + /* end of the frame gain */ + st->lp_gainp = alpha; + + /* linearly attenuate the gain throughout the frame */ + step = (1.0f/L_frame) * (gain - st->lp_gainp); + } + + /* scaling of the harmonic part of excitation */ + for( i=0 ; i< L_frame; i++ ) + { + exc[i] *= gain; + gain -= step; + } + + if( (st->last_coder_type == AUDIO || st->last_good == INACTIVE_CLAS) && st->Last_GSC_pit_band_idx > 0 ) + { + /* in case the last frame was coded by GSC, convert the excitation signal to frequency domain */ + edct( exc, exc_dct_in, st->L_frame); + + /* Reset unvaluable part of the adaptive (pitch) excitation contribution */ + Diff_len = (short)(mfreq_loc[st->Last_GSC_pit_band_idx]/BIN_SIZE); + max_len = st->L_frame - Diff_len; + Len = min( max_len, 80 ); + + for( i=0; ilast_coder_type == AUDIO || st->last_good == INACTIVE_CLAS) && st->total_brate <= ACELP_24k40 && !st->Opt_AMR_WB ) + { + /* Replication of the last spectrum, with a slight downscaling of its dynamic */ + st->GSC_noisy_speech = st->Last_GSC_noisy_speech_flag; + gsc_dec( st, exc_dct_in, st->Last_GSC_pit_band_idx, Diff_len, 0, st->L_frame/L_SUBFR, st->last_coder_type, &last_bin, lsf_new, NULL, tmp_noise ); + + /* Transform back to time domain */ + edct( exc_dct_in, exc, st->L_frame); + } + + /*-----------------------------------------------------------------* + * Construct the random part of excitation + *-----------------------------------------------------------------*/ + + else + { + /* generate the random part of the excitation */ + for (i=0; iseed ); + } + + /* start of the frame gain */ + gain = st->lp_gainc; + + /* end of the frame gain */ + st->lp_gainc = alpha * st->lp_gainc + (1.0f - alpha) * gainCNG; + + if( st->last_good == UNVOICED_TRANSITION && ( st->last_coder_type == GENERIC || st->last_coder_type == TRANSITION ) && gainCNG > 0 ) + { + st->lp_gainc = gainCNG; + } + + /* linearly attenuate the gain throughout the frame */ + step = (1.0f/L_frame) * (gain - st->lp_gainc); + + /* calculate gain to normalize energy */ + pt_exc = exc2_buf + MODE1_L_FIR_FER/2; + + gain_inov = 1.0f / (float)sqrt( dotp( pt_exc, pt_exc, L_frame ) / L_frame + 0.01f ); + + /* attenuate somewhat on unstable unvoiced */ + if( (st->last_good == UNVOICED_CLAS || st->last_good == INACTIVE_CLAS) && st->last_coder_type != UNVOICED ) + { + gain_inov *= 0.8f; + } + + /* scaling of the random part of excitation */ + pt_exc = exc2_buf; + for( i=0; i< MODE1_L_FIR_FER/2; i++ ) + { + /* non-causal ringing of the FIR filter */ + *pt_exc++ *= (gain_inov * gain); + } + + for( i=0; i< L_frame; i++ ) + { + /* the inner part of the FIR filter */ + *pt_exc++ *= (gain_inov * gain); + gain -= step; + } + + for( i=0; i< MODE1_L_FIR_FER/2; i++ ) + { + /* causal ringing of the FIR filter */ + *pt_exc++ *= (gain_inov * gain); + } + } + + /*-----------------------------------------------------------------* + * Total excitation + *-----------------------------------------------------------------*/ + + if( (st->last_coder_type == AUDIO || st->last_good == INACTIVE_CLAS) && st->total_brate <= ACELP_24k40 && !st->Opt_AMR_WB ) + { + /* For GSC - the excitation is already computed */ + mvr2r( exc, exc2, st->L_frame); + } + else if(st->last_good >= UNVOICED_TRANSITION && st->last_good < INACTIVE_CLAS ) + { + /* For voiced and generic signals - prepare a HP filter for the random part of excitation */ + for( i=0; itilt_code) * h_high[i]; + } + + /* HP filter the random part of the excitation and add the adaptive part */ + for( i=0; i< L_frame; i++ ) + { + exc2[i] = exc[i] + dotp( &exc2_buf[i], hp_filt, MODE1_L_FIR_FER ); + } + } + else + { + /* For purely unvoiced signals - just copy the unfiltered random part of the excitation */ + mvr2r( exc2_buf + MODE1_L_FIR_FER/2, exc, L_frame ); + mvr2r( exc2_buf + MODE1_L_FIR_FER/2, exc2, L_frame ); + } + + if( L_frame == L_FRAME ) + { + interp_code_5over2( exc, bwe_exc, L_frame ); + } + else + { + interp_code_4over2( exc, bwe_exc, L_frame ); + } + + /*-----------------------------------------------------------------* + * Updates + *-----------------------------------------------------------------*/ + + /* Update voicing factors of TBE */ + if( st->last_coder_type == AUDIO || st->last_good == INACTIVE_CLAS ) + { + if(st->L_frame == L_FRAME ) + { + set_f( voice_factors, 1.0f, NB_SUBFR ); + } + else + { + set_f( voice_factors, 1.0f, NB_SUBFR16k ); + } + } + else + { + if(st->L_frame == L_FRAME ) + { + set_f( voice_factors, st->last_voice_factor, NB_SUBFR); + } + else + { + set_f( voice_factors, st->last_voice_factor, NB_SUBFR16k ); + } + } + + if( st->Opt_AMR_WB ) + { + /* update buffer of gains for the next frame */ + gain_dec_bfi(st->past_qua_en); + } + + st->bfi_pitch = pitch_buf[L_frame/L_SUBFR - 1]; + st->bfi_pitch_frame = st->L_frame; + + return; +} + + +/*-------------------------------------------------------------------* + * gain_dec_bfi() + * + * Estimate past quantized gain prediction residual to be used in + * next frame + *-------------------------------------------------------------------*/ + +static void gain_dec_bfi( + float *past_qua_en /* i/o: gain quantization memory (4 words) */ +) +{ + short i; + float av_pred_en; + + av_pred_en = 0.0f; + for (i = 0; i < GAIN_PRED_ORDER; i++) + { + av_pred_en += past_qua_en[i]; + } + + av_pred_en = (float)(av_pred_en*(1.0f/(float)GAIN_PRED_ORDER)-3.0f); + + if (av_pred_en < -14.0f) + { + av_pred_en = -14.0f; + } + + for (i=GAIN_PRED_ORDER-1; i>0; i--) + { + past_qua_en[i] = past_qua_en[i-1]; + } + + past_qua_en[0] = av_pred_en; + + return; +} + + +#define WMC_TOOL_SKIP + /*-------------------------------------------------------------------* + * pulseRes_preCalc() + * + * 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); + + return; +} +#undef WMC_TOOL_SKIP diff --git a/lib_dec/FEC_HQ_core.c b/lib_dec/FEC_HQ_core.c new file mode 100644 index 000000000..540a1f738 --- /dev/null +++ b/lib_dec/FEC_HQ_core.c @@ -0,0 +1,1452 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_dec.h" +#include "rom_com.h" +#include "prot.h" + +/*---------------------------------------------------------------------* + * Local prototypes + *---------------------------------------------------------------------*/ + +static short FEC_phase_matching( Decoder_State *st, float *ImdctOut, float *auOut, float *OldauOut, float OldauOut_pha[2][N_LEAD_NB] ); + +static void FEC_phase_matching_nextgood( const float *ImdctOut, float *auOut, float *OldauOut, + float OldauOut_pha[2][N_LEAD_NB], float mean_en_high ); + +static void FEC_phase_matching_burst( const float *ImdctOut, float *auOut, float *OldauOut, + float OldauOut_pha[2][N_LEAD_NB], float *prev_oldauOut ); + +static void Repetition_smoothing_nextgood( const float *ImdctOut, float *auOut, float *OldImdctOut, float *OldauOut, + short cur_data_use_flag, short overlap_time ); + +static int Repetition_smoothing( const float *ImdctOut, float *auOut, float *OldImdctOut, float *OldauOut, + const short L, float *prev_oldauOut, short overlap_time ); + +static void Windowing_1st_NB( float *ImdctOutWin, const float *ImdctOut, const float *win, const float *smoothingWin, short smoothing_flag ); + +static void Windowing_2nd_NB( float *ImdctOutWin, const float *ImdctOut, const float *win ); + +static void common_overlapping( float *auOut, float *ImdctOutWin, float *OldauOut, short end1, short offset1, + short start2, short end2, short offset_i2, short offset2 ); + +static void Smoothing_vector_NB( const float OldauOutnoWin[], const float ImdctOutWin[], const float SmoothingWin[], + float auOut[], const short ol_size ); + +static void Smoothing_vector_scaledown_NB( const float OldauOutnoWin[], const float ImdctOutWin[], const float SmoothingWin[], + float auOut[], const short ol_size ); + +static void Scaledown( float x[], float y[], float scale_v, const short N ); + + +/*--------------------------------------------------------------------------* + * Regression_Anal() + * + * + *--------------------------------------------------------------------------*/ + +static void Regression_Anal( + const float *values, /* i : Previous values */ + float *r_p, /* o : Output r[a b] array : y=ax+b */ + const short num_pgf /* i : Number of previous good frame */ +) +{ + short i; + float aindex[MAX_PGF+1], b_p[MAX_PGF+1]; + + /* Initialize */ + for(i=0; ienergy_MA_Curr[0] < 1.0f) + { + st->energy_MA_Curr[0] = 1.0f; /*It seems to be in Q0 the FxP*/ + } + /* Decide the start frame number for adaptive muting */ + /* Normalized energy difference between the current frame and the moving average */ + energy_diff = (float)fabs((st->energy_MA_Curr[1] - st->energy_MA_Curr[0])/st->energy_MA_Curr[0]); + + if((energy_diffprev_old_bfi == 1 && st->nbLostCmpt == 1 && output_frame == L_FRAME8k ) + { + st->nbLostCmpt++; + } + + /* Frequency-domain FEC */ + if( st->nbLostCmpt == 1 ) /* First erasure frame */ + { + if ( is_transient == 0 ) + { + if(energy_diff < ED_THRES) + { + for (i=0; i < output_frame; i++) + { + t_audio_q[i] = st->old_coeffs[i]; + } + } + else + { + for (i=0; i < output_frame; i++) + { + st->old_coeffs[i] *= SCALE_DOWN_3dB; + t_audio_q[i] = st->old_coeffs[i]; + } + } + + /* Sign prediction in 4-dim bands up to 1.6 kHz*/ + if (st->old_is_transient[1] == 0) + { + if (st->old_is_transient[2] == 0) + { + for (sfm = 0; sfm < HQ_FEC_SIGN_SFM; sfm++) + { + if (st->prev_sign_switch[sfm] >= HQ_FEC_SIGN_THRES) + { + for(i = 0; i < HQ_FEC_BAND_SIZE; i++) + { + t_audio_q[i+sfm*HQ_FEC_BAND_SIZE]*= -1.0f; + } + } + } + } + else + { + for (sfm = 0; sfm < HQ_FEC_SIGN_SFM; sfm++) + { + if (st->prev_sign_switch[sfm] >= HQ_FEC_SIGN_THRES_TRANS) + { + for(i = 0; i < HQ_FEC_BAND_SIZE; i++) + { + t_audio_q[i+sfm*HQ_FEC_BAND_SIZE]*= -1.0f; + } + } + } + } + } + else + { + for (i = RANDOM_START*8; i < output_frame; i++) + { + if( (float)own_random( &st->HQ_FEC_seed ) < 0.0f ) + { + t_audio_q[i] *= -1.0f; + } + } + } + } + else + { + if( st->old_is_transient[1] ) /* hangover */ + { + for (i=0; i < output_frame; i++) + { + st->old_coeffs[i] *= SCALE_DOWN_3dB; + t_audio_q[i] = st->old_coeffs[i]; + } + } + else + { + for (i = 0; i < RANDOM_START*8; i++) + { + st->old_coeffs[i] *= SCALE_DOWN_3dB; + t_audio_q[i] = st->old_coeffs[i]; + } + + for (i = RANDOM_START*8; i < output_frame; i++) + { + st->old_coeffs[i] *= SCALE_DOWN_3dB; + if( (float)own_random( &st->HQ_FEC_seed ) < 0.0f ) + { + t_audio_q[i] = (-st->old_coeffs[i]); + } + else + { + t_audio_q[i] = st->old_coeffs[i]; + } + } + } + } + } + else /* st->nbLostCmpt > 1 */ + { + if( energy_diff < ED_THRES && is_transient == 0 ) + { + num_pgf = 4; + } + else + { + num_pgf = 2; + } + + Num_sb_bwe = num_Sb; + if( st->nbLostCmpt == 2 ) + { + for( i=0; inbLostCmpt >= mute_start ) + { + /* Scaling */ + for ( i=0; i < output_frame; i++ ) + { + st->old_coeffs[i] *= SCALE_DOWN_3dB; + } + } + + k=0; + for( i=0; i MAX_TILT ) + { + r_p[1] = MAX_TILT; + norm_p[i] = (float)(norm_values[0]+r_p[1]*(float)(st->nbLostCmpt-1)); + } + else + { + norm_p[i] = (float)(r_p[0]+r_p[1]*(float)(st->nbLostCmpt-1+num_pgf)); + } + + if( norm_values[0] != 0.0f && norm_p[i] > 0.0f ) /* Avoid negative value of the predicted energy */ + { + tmp = norm_p[i]/norm_values[0]; /* Pred_new / Old */ + + if( tmp > 1.0f ) + { + tmp = 1.f; + } + + for( j=0; jNorm_gain[k++] = tmp; + } + } + else + { + /* Scale down the last gain with the fixed gain(-3dB) */ + for(j=0; jNorm_gain[k++] *= SCALE_DOWN_3dB; + } + } + } + + /* Scaling for core band */ + FEC_scaling( st->old_coeffs, t_audio_q, st->Norm_gain, &st->HQ_FEC_seed, nb_sfm, sfm_start, sfm_end ); + } + + return; +} + + +/*--------------------------------------------------------------------------* + * HQ_FEC_Mem_update() + * + * + *--------------------------------------------------------------------------*/ + +void HQ_FEC_Mem_update( + Decoder_State *st, /* i/o: decoder state structure */ + float *t_audio_q, + float *normq, + short *ynrm, + short *Num_bands_p, + short is_transient, + short hqswb_clas, + short c_switching_flag, + short nb_sfm, + short num_Sb, + float *mean_en_high, + short hq_core_type, /* i : normal or low-rate MDCT(HQ) core */ + short output_frame +) +{ + short i, j, k; + float tmp; + float tmp_energy = 0; + float *norm_values; + short offset; + short Min_ind; + int Min_value; + float Max_coeff; + short Max_ind; + short stat_mode_curr; + float en_high[MAX_SB_NB]; + + if (is_transient) + { + set_s(st->prev_sign_switch_2, 0, HQ_FEC_SIGN_SFM); + set_s(st->prev_sign_switch, 0, HQ_FEC_SIGN_SFM); + } + else + { + for (j = 0; j < HQ_FEC_SIGN_SFM; j++) + { + st->prev_sign_switch[j] = st->prev_sign_switch_2[j]; + st->prev_sign_switch_2[j] = 0; + + for(i = 0; i < HQ_FEC_BAND_SIZE; i++) + { + tmp = st->old_coeffs[i+j*HQ_FEC_BAND_SIZE]*t_audio_q[i+j*HQ_FEC_BAND_SIZE]; + if (tmp < 0) + { + st->prev_sign_switch[j]++; + st->prev_sign_switch_2[j]++; + } + } + } + } + + if( output_frame == L_FRAME8k ) + { + /* if LR MDCT core is used, recalculate norms from decoded MDCT spectrum (using code from hq_hr_enc()) */ + if( ( hqswb_clas == HQ_HVQ ) || ( hq_core_type == LOW_RATE_HQ_CORE ) ) + { + /* First group */ + logqnorm( t_audio_q, ynrm, 32, WID_G1, thren_HQ ); + j = ynrm[0]; + offset = WID_G1; + + for( i=1; iynrm_values[i][0]; + mvr2r( norm_values, &norm_values[1], MAX_PGF-1 ); + + tmp = 0.f; + for(j=0; jlast_core == ACELP_CORE)&&(st->core == HQ_CORE))) + { + for(i=0; iynrm_values[i][j]=st->ynrm_values[i][0]; + } + } + } + set_f(st->Norm_gain, 1.f, SFM_N_NB); + + /* st->energy_MA_Curr[1]=Energy of the current frame */ + st->energy_MA_Curr[1] = tmp_energy/(float)nb_sfm; + + /* Moving Average */ + st->energy_MA_Curr[0] = 0.8f*st->energy_MA_Curr[0]+0.2f*st->energy_MA_Curr[1]; + + st->diff_energy = (float)fabs((st->energy_MA_Curr[1] - st->energy_MA_Curr[0])/st->energy_MA_Curr[0]); + /* Classify the stationary mode : 12% */ + if((st->diff_energystat_mode_old == stat_mode_curr) + { + st->stat_mode_out = stat_mode_curr; + } + + st->stat_mode_old = stat_mode_curr; + + + /* Find max. band index (Minimum value means maximum energy) */ + Min_ind=0; + Min_value = 100; + for( i=0; iynrm[i] ) + { + Min_value = ynrm[i]; + Min_ind = i; + } + } + + /* Find max. coeff in band 0 */ + Max_ind = 0; + if(Min_ind==0) + { + Max_coeff = 0.f; + for(i=0; i<8; i++) + { + tmp = (float)fabs(t_audio_q[i]); + if(Max_coeffynrm_values[i][j+1]; + } + } + + *mean_en_high = 0.f; + for(i=k; iynrm_values[i][0]); + } + *mean_en_high /= (float)(num_Sb-k); + + if ((Min_ind<5) && ( abs(Min_ind - st->old_Min_ind)< 2) &&(st->diff_energybfi) && (!st->prev_bfi)&&(!st->prev_old_bfi) + &&(!is_transient)&&(!st->old_is_transient[1]) && (st->prev_last_core==HQ_CORE) && (st->last_core==HQ_CORE)) + { + if((Min_ind==0)&&(Max_ind<3)) + { + st->phase_mat_flag = 0; + } + else + { + st->phase_mat_flag = 1; + } + } + else + { + st->phase_mat_flag = 0; + } + + st->old_Min_ind = Min_ind; + } + + for (i=0; i < L_FRAME8k; i++) + { + st->old_coeffs[i] = t_audio_q[i]; + } + + st->old_is_transient[2] = st->old_is_transient[1]; + st->old_is_transient[1] = st->old_is_transient[0]; + st->old_is_transient[0] = is_transient; + + return; +} + +/*--------------------------------------------------------------------------* + * find_best_delay() + * + * + *--------------------------------------------------------------------------*/ + +static short find_best_delay( + float *mu_o, + float *in, + short mind1, + short maxd1, + short lin, + short delta, + short *false_flag + +) +{ + short i, d1, k; + short d1m = 0; + float min_sq_cross, min_corr; + float accA, accB; + float Rxy[MAXDELAY_FEC], Ryy[MAXDELAY_FEC]; + + for( k = 0, d1 = mind1; k < (maxd1-mind1)/delta; d1 += delta, k++ ) + { + accA = accB = 0; + for( i = 0; i < lin; i += delta ) + { + accA += mu_o[d1+i] * mu_o[d1+i]; + accB += mu_o[d1+i] * in[i]; + } + + Rxy[k] = accB; + Ryy[k] = accA; + } + + /* Obtain the best delay values */ + min_sq_cross = -FLT_MAX; + min_corr = 0; + + for( d1 = 0; d1 < (maxd1-mind1)/delta; d1++ ) + { + if( Rxy[d1] * min_corr >= min_sq_cross * Ryy[d1] ) + { + d1m = d1; + min_corr = Ryy[d1]; + min_sq_cross = Rxy[d1]; + } + } + d1m *= delta; + + + if( min_sq_cross <= 0.f || min_corr <= 0.f ) + { + accA = 0.f; + } + else + { + accA = min_sq_cross/min_corr; + } + if(accA < 0.5 || accA > 1.5) + { + *false_flag = 1; + } + else + { + *false_flag = 0; + } + + return d1m; +} + +/*--------------------------------------------------------------------------* + * Search_Max_Corr() + * + * + *--------------------------------------------------------------------------*/ + +static short Search_Max_Corr( + float *mu_o, /* i : *old_auOut_2fr */ + short old_Min_ind, /* i : * Old Minimum index */ + const short L /* i : L/2 */ +) +{ + short pos; + short pos2,delta2; + short lin, delta; + short mind1,maxd1; + float *in; + short false_flag; + + short min_d1, max_d1; + + if(old_Min_ind == 0) + { + lin = 8*L/20; /* Basic size of the block for phase matching */ + + mind1 = 0; /* min value of delay d1 to search for */ + maxd1 = 12*L/20; /* max value of delay d1 to search for */ + + in = mu_o + 2*L - lin; + + /* generate correlation */ + delta = 2; + delta2 = 1; + + pos = find_best_delay(mu_o, in, mind1, maxd1, lin, delta, &false_flag); + + if(false_flag) + { + return 0; + } + min_d1 = max(mind1,mind1+pos-delta+1); + max_d1 = min(maxd1,mind1+pos+delta); + pos2 = find_best_delay(mu_o, in, min_d1, max_d1, lin, delta2, &false_flag); + + if(mind1 > (mind1+pos-delta+1)) + { + pos = pos2; + } + else + { + pos = pos + pos2 - delta + 1 ; + } + pos = pos+lin+mind1; + } + else + { + lin = 6*L/20; + + mind1 = 9*L/20; /* min value of delay d1 to search for */ + maxd1 = 14*L/20; /* max value of delay d1 to search for */ + + in = mu_o + 2*L - lin; + + /* generate correlation */ + delta = 2; + delta2 = 1; + + pos = find_best_delay(mu_o, in, mind1, maxd1, lin, delta, &false_flag); + + if(false_flag) + { + return 0; + } + + min_d1 = max(mind1, mind1+pos-delta+1); + max_d1 = min(maxd1, mind1+pos+delta); + pos2 = find_best_delay(mu_o, in, min_d1, max_d1, lin, delta2, &false_flag); + + if(mind1 > (mind1+pos-delta+1) ) + { + pos = pos2; + } + else + { + pos = pos + pos2 - delta + 1 ; + } + + pos = pos+lin+mind1; + } + + return pos; +} + +/*--------------------------------------------------------------------------* + * FEC_phase_matching() + * + * + *--------------------------------------------------------------------------*/ + +static short FEC_phase_matching( + Decoder_State *st, /* i : Decoder State */ + float *ImdctOut, /* i : input */ + float *auOut, /* o : output audio */ + float *OldauOut, + float OldauOut_pha[2][N_LEAD_NB] +) +{ + short i; + float ImdctOutWin[2*L_FRAME8k]; + short pos, remain; + short ol_size; + float OldauOutnoWin[L_FRAME8k]; + short L_overlap, L; + float OldauOut2[L_FRAME8k]; + float pow1=0, pow22=0; + float win_NB[L_FRAME8k + 25]; + float SmoothingWin_NB3[24]; + + L = L_FRAME8k; + + for(i=0; i<3*L/20; i++) + { + SmoothingWin_NB3[i] = SmoothingWin_NB875[i*3]; + } + + for(i=0; iold_auOut_2fr, st->old_Min_ind, L); + + if(pos == 0) + { + return 1; + } + + /* Repetition */ + remain = L+N_Z_L_NB - ((2*L)-pos); + mvr2r(&st->old_auOut_2fr[pos], &ImdctOutWin[N_ZERO_NB], (2*L)-pos); + + /* OldauOut without windowing */ + for(i = N_ZERO_NB; i < L/2; i++) + { + OldauOutnoWin[i-N_ZERO_NB] = -st->oldIMDCTout[L/2 - 1 - i]; + } + for(i = 0; i < L/2; i++) + { + OldauOutnoWin[i+N_ZERO_O_NB] = -st->oldIMDCTout[i]; + } + + mvr2r(OldauOutnoWin, &ImdctOutWin[N_ZERO_NB+(2*L)-pos], remain); + + for(i = 0; i < L; i++) + { + pow1 += (float)fabs(st->old_auOut_2fr[L+i]); + pow22 += (float)fabs(ImdctOutWin[N_ZERO_NB+i]); + } + + if(pow22!=0) + { + pow1 /= pow22; + for(i = N_ZERO_NB; i < 2*L; i++) + { + ImdctOutWin[i] *= pow1; + } + } + Smoothing_vector_NB(OldauOutnoWin, &ImdctOutWin[N_ZERO_NB], SmoothingWin_NB2, auOut, ol_size); + + for (i = 0; i < L/2; i++) + { + ImdctOutWin[3*L/2 + i] *= win_NB[L/2-i-1]; + } + + for (i = N_ZERO_NB; i < L/2; i++) + { + ImdctOutWin[L + i] *= win_NB[(L-1-i)]; + } + mvr2r(&ImdctOutWin[N_Z_L_O_NB], &OldauOut_pha[0][0], N_LEAD_NB); + mvr2r(&ImdctOutWin[ol_size+N_ZERO_NB], &auOut[ol_size], N_Z_L_NB-ol_size); + mvr2r(&ImdctOutWin[L], &auOut[N_Z_L_NB], N_ZERO_NB); + mvr2r(&ImdctOutWin[L], OldauOut, L); + + for(i = 0; i < L/2; i++) + { + OldauOut2[i] = -ImdctOut[L/2 - 1 - i]; + OldauOut2[L/2+i] = -ImdctOut[i]; + } + + L_overlap = 3*L/20; + Smoothing_vector_NB(&ImdctOutWin[N_Z_L_O_NB], &OldauOut2[N_ZERO_NB], SmoothingWin_NB3, &OldauOut_pha[1][0], L_overlap); + + for(i=L_overlap; i2.f)||(mean_en_high<0.5f)) + { + oldout_pha_idx = 1; + } + else + { + oldout_pha_idx = 0; + } + + /* Overlapping with next good frame : Overlapping to remove the discontinuity */ + L_overlap = N_LEAD_NB; + OldOut_pha = OldauOut_pha[oldout_pha_idx]; + for (i = 0; i < N_LEAD_NB; i++) + { + OldOut_pha[i] *= SmoothingWin_NB875[L_overlap-i-1]; + } + + if(oldout_pha_idx == 1) + { + /* Use phase matching and overlapping with the Oldauout*/ + /* Windowing */ + Windowing_1st_NB(ImdctOutWin, ImdctOut, win_NB, NULL, 0); + Windowing_2nd_NB(ImdctOutWin, ImdctOut, win_NB); + } + else + { + /* Only use phase matching */ + /* Windowing */ + Windowing_1st_NB(ImdctOutWin, ImdctOut, win_NB, SmoothingWin_NB875, 1); + Windowing_2nd_NB(ImdctOutWin, ImdctOut, win_NB); + } + + common_overlapping(auOut, ImdctOutWin, OldOut_pha, N_LEAD_NB, 0, N_LEAD_NB, L, N_ZERO_NB, 0); + mvr2r(&ImdctOutWin[L], OldauOut, L); + + return; +} + +/*--------------------------------------------------------------------------* + * FEC_phase_matching_burst() + * + * + *--------------------------------------------------------------------------*/ + +static void FEC_phase_matching_burst( + const float *ImdctOut, /* i : input */ + float *auOut, /* o : output audio */ + float *OldauOut, /* i/o: audio from previous frame */ + float OldauOut_pha[2][N_LEAD_NB], + float *prev_oldauOut /* i : OldauOut from previous frame */ +) +{ + short i; + short L_overlap; + float OldauOut2[L_FRAME8k]; + float ImdctOutWin[2*L_FRAME8k]; + short L; + float win_NB[L_FRAME8k + 25]; + float SmoothingWin_NB3[24]; + + L = L_FRAME8k; + + for(i=0; i<3*L/20; i++) + { + SmoothingWin_NB3[i] = SmoothingWin_NB875[i*3]; + } + + for(i=0; i pow1*3) + { + return 1; + } + + /* Update the OldauOut array for next overlapping */ + mvr2r(&ImdctOutWin[L], OldauOut, L); + Scaledown(prev_oldauOut, prev_oldauOut, SCALE_DOWN_3dB, L); + + return 0; +} + + +/*--------------------------------------------------------------------------* + * Windowing_1st() + * + * + *--------------------------------------------------------------------------*/ + +static void Windowing_1st_NB( + float *ImdctOutWin, /* o : Output */ + const float *ImdctOut, /* i : Input */ + const float *win, /* i : Window */ + const float *smoothingWin, /* i : Smoothing Window */ + short smoothing_flag /* i : 1=Smoothing window, 0=Original window */ +) +{ + short i; + short L; + + L = L_FRAME8k; + 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]; + } + + 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)]; + } + } + 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];*/ + } + + 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)]; + } + } + + return; +} + +/*--------------------------------------------------------------------------* + * Windowing_2nd() + * + * + *--------------------------------------------------------------------------*/ + +static void Windowing_2nd_NB( + float *ImdctOutWin, /* o : Output */ + const float *ImdctOut, /* i : Input */ + const float *win /* i : Window */ +) +{ + short i; + short L; + + L = L_FRAME8k; + 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]; + } + + for (i = 0; i < N_ZERO_NB; i++) + { + ImdctOutWin[L + i] = -ImdctOut[L/2 - 1 - i]; + } + + for (i = N_ZERO_NB; i < L/2; i++) + { + ImdctOutWin[L + i] = -ImdctOut[L/2 - 1 - i] * win[L - 1 - i]; + } + + return; +} + +/*--------------------------------------------------------------------------* + * common_overlapping() + * + * + *--------------------------------------------------------------------------*/ + +static void common_overlapping( + float *auOut, /* i : Input */ + float *ImdctOutWin, /* o : Output */ + float *OldauOut, /* i : Window */ + short end1, /* i : Decay */ + short offset1, + short start2, + short end2, + short offset_i2, + short offset2 +) +{ + short i; + + /* Common Overlapping */ + for (i=0 ; i < end1; i++) + { + auOut[i] = ImdctOutWin[i+N_ZERO_NB] + OldauOut[i+offset1]; + } + for (i=start2 ; i < end2; i++) + { + auOut[i+offset2] = ImdctOutWin[i+offset_i2]; + } + + return; +} + + +/*--------------------------------------------------------------------------* + * Smoothing_vector() + * + * + *--------------------------------------------------------------------------*/ + +static void Smoothing_vector_NB( + const float OldauOutnoWin[], /* i : Input vector 1 */ + const float ImdctOutWin[], /* i : Input vector 2 */ + const float SmoothingWin[], /* i : Smoothing window */ + float auOut[], /* o : Output vector that contains vector 1 .* vector 2 */ + const short ol_size /* i : Overlap size */ +) +{ + short i; + float weight; + + for (i=0 ; i < ol_size; i++) + { + weight = SmoothingWin[i]; + auOut[i] = (OldauOutnoWin[i]*(1.f-weight)) + (ImdctOutWin[i]*weight); + } + + return; +} + +/*--------------------------------------------------------------------------* + * Smoothing_vector_scaledown() + * + * + *--------------------------------------------------------------------------*/ + +static void Smoothing_vector_scaledown_NB( + const float OldauOutnoWin[], /* i : Input vector 1 */ + const float ImdctOutWin[], /* i : Input vector 2 */ + const float SmoothingWin[], /* i : Smoothing window */ + float auOut[], /* o : Output vector that contains vector 1 .* vector 2 */ + const short ol_size /* i : Overlap size */ +) +{ + short i; + float weight; + + for (i=0 ; i < ol_size; i++) + { + weight = SmoothingWin[i]; + auOut[i] = (OldauOutnoWin[i]*(1.f-weight)) + (ImdctOutWin[i]*SCALE_DOWN_3dB*weight); + } + + return; +} + +/*--------------------------------------------------------------------------* + * Scaledown() + * + * + *--------------------------------------------------------------------------*/ + +static void Scaledown( + float x[], /* i : Input vector */ + float y[], /* o : Output vector that contains vector 1 .* vector 2 */ + float scale_v, + const short N /* i : Overlap size */ +) +{ + short i; + + for(i=0; inbLostCmpt==1)&&(st->phase_mat_flag==1)&&(st->phase_mat_next==0) ) + { + if (FEC_phase_matching(st, wtda_audio, out, st->old_out, st->old_out_pha) ) + { + window_ola( wtda_audio, out, st->old_out, output_frame, st->tcx_cfg.tcx_last_overlap_mode, st->tcx_cfg.tcx_curr_overlap_mode, st->prev_bfi, st->oldHqVoicing, st->oldgapsynth ); + st->phase_mat_next = 0; + } + else + { + st->phase_mat_next = 1; + } + } + else if((st->prev_bfi == 1)&&(st->bfi == 0) &&(st->phase_mat_next == 1)) + { + FEC_phase_matching_nextgood( wtda_audio, out, st->old_out, st->old_out_pha, mean_en_high); + st->phase_mat_next = 0; + } + else if((st->prev_bfi == 1)&&(st->bfi == 1) &&(st->phase_mat_next == 1)) + { + FEC_phase_matching_burst( wtda_audio, out, st->old_out, st->old_out_pha, st->prev_oldauOut); + st->phase_mat_next = 1; + } + else + { + if(st->bfi == 0 && st->prev_bfi == 1) + { + if((st->stat_mode_out==1) || (st->diff_energydiff_energyoldIMDCTout, st->old_out, st->old_bfi_cnt> 1 ? 1: 0, N_LEAD_NB); + } + else if(st->old_bfi_cnt > 1) + { + Next_good_after_burst_erasures( wtda_audio, out, st->old_out, N_LEAD_NB ); + } + else + { + window_ola( wtda_audio, out, st->old_out, output_frame, st->tcx_cfg.tcx_last_overlap_mode, st->tcx_cfg.tcx_curr_overlap_mode, st->prev_bfi, st->oldHqVoicing, st->oldgapsynth ); + } + } + else /* if(st->bfi == 1) */ + { + if( (st->stat_mode_out==1) || (st->diff_energyoldIMDCTout, st->old_out, output_frame, st->prev_oldauOut, N_LEAD_NB) ) + { + window_ola( wtda_audio, out, st->old_out, output_frame, st->tcx_cfg.tcx_last_overlap_mode, st->tcx_cfg.tcx_curr_overlap_mode, st->prev_bfi, st->oldHqVoicing, st->oldgapsynth ); + } + } + else + { + window_ola( wtda_audio, out, st->old_out, output_frame, st->tcx_cfg.tcx_last_overlap_mode, st->tcx_cfg.tcx_curr_overlap_mode, st->prev_bfi, st->oldHqVoicing, st->oldgapsynth ); + } + } + + st->phase_mat_next = 0; + } + + return; +} + + +/*--------------------------------------------------------------------------*/ +/* Function Next_good_after_burst_erasures */ +/* ~~~~~~~~~~~~~~~~~~~~ */ +/* */ +/* Windowing, Overlap and Add */ +/*--------------------------------------------------------------------------*/ +/* float ImdctOut[] (i) input */ +/* short auOut[] (o) output audio */ +/* float OldauOut[] (i/o) audio from previous frame */ +/* short ol_size (i) overlap size */ +/* short L (i) length */ +/*--------------------------------------------------------------------------*/ + +void Next_good_after_burst_erasures( + const float *ImdctOut, + float *auOut, + float *OldauOut, + const short ol_size +) +{ + float ImdctOutWin[2*L_FRAME8k]; + short i, L; + float win_NB[L_FRAME8k + 25]; + + L = L_FRAME8k; + for(i=0; i +#include "wmc_auto.h" +#include "options.h" +#include "rom_dec.h" +#include "rom_com.h" +#include "cnst.h" +#include "prot.h" +#include "assert.h" + + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ + +#define FEC_MAX 512 +#define FEC_NB_PULSE_MAX 20 +#define FEC_FFT_MAX_SIZE 512 +#define FEC_DCIM_FILT_SIZE_MAX 60 + +#define PHASE_DITH (PI2) + +#define DELTA_CORR 6 /* Range for phase correction around peak */ +#define THRESH_TR_dB 10.0f +#define THRESH_TR_LIN (float)pow(10.0f,THRESH_TR_dB/10.0f) +#define THRESH_TR_LIN_INV (float)pow(10.0f,-THRESH_TR_dB/10.0f) +#define MAX_INCREASE_GRPOW 0.0f /* maximum amplification in case of transients */ +#define MAX_INCREASE_GRPOW_LIN (float)pow(10.0f,MAX_INCREASE_GRPOW/10.0f) + +#define PHASE_DITH_SCALE (float)pow(2.0,-16.0) /* for scaling random short values to +/- pi */ + +#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 BETA_MUTE_FAC 0.5f /* attenuation factor per additional bad frame */ + +#define LGW32k 7 +#define LGW16k 6 +#define LGW48k LGW32k+1 /* Use the same frequency groups as for SWB + 1 */ + +#define L_TRANA_LOG32k 8 +#define L_TRANA_LOG16k 7 + +#define PFIND_SENS 0.97f /* peakfinder sensitivity */ + +/*---------------------------------------------------------------------* + * Local function + *---------------------------------------------------------------------*/ + +short rand_phase( const short seed, float *sin_F, float *cos_F ); + + +/*-------------------------------------------------------------------* + * mult_rev2() + * + * Multiplication of two vectors second vector is multiplied in reverse order + *-------------------------------------------------------------------*/ + +static void mult_rev2( + const float x1[], /* i : Input vector 1 */ + const float x2[], /* i : Input vector 2 */ + float y[], /* o : Output vector that contains vector 1 .* vector 2 */ + const short N /* i : Vector length */ +) +{ + short i,j ; + + for (i=0,j=N-1 ; i square magnitude spectrum */ + const short N /* i : Vector lenght */ +) +{ + short i, j; + + for (i = 1, j = N-1; i < N/2; i++, j--) + { + x[i] = x[i]*x[i] + x[j]*x[j]; + } + + x[0] *= x[0]; + x[N/2] *= x[N/2]; + + return; +} + +/*------------------------------------------------------------------* + * rand_phase() + * + * randomized phase in form of sin and cos components + *------------------------------------------------------------------*/ + +short rand_phase( + const short seed, + float *sin_F, + float *cos_F +) +{ + const float *sincos = sincos_t_ext + 128; + short seed2 = seed; + own_random(&seed2); + + if (seed2 & 0x40) + { + *sin_F = sincos[seed2 >> 8]; + } + else + { + *sin_F = -sincos[seed2 >> 8]; + } + + if (seed2 & 0x80) + { + *cos_F = sincos[-(seed2 >> 8)]; + } + else + { + *cos_F = -sincos[-(seed2 >> 8)]; + } + + return seed2; +} + +/*------------------------------------------------------------------* + * trans_ana() + * + * Transient analysis + *------------------------------------------------------------------*/ + +static void trans_ana( + const float *xfp, /* i : Input signal */ + float *mag_chg, /* i/o: Magnitude modification */ + float *ph_dith, /* i/o: Phase dither */ + float *mag_chg_1st, /* i/o: per band magnitude modifier for transients */ + const short output_frame, /* i : Frame length */ + const short time_offs, /* i : Time offset */ + const float est_mus_content, /* i : 0.0=speech_like ... 1.0=Music (==st->env_stab ) */ + const short last_fec, /* i : signal that previous frame was concealed with fec_alg*/ + float *alpha, /* o : Magnitude modification factors for fade to average */ + float *beta, /* o : Magnitude modification factors for fade to average */ + float *beta_mute, /* o : Factor for long-term mute */ + float Xavg[LGW_MAX] /* o : Frequency group average gain to fade to */ +) +{ + const float *w_hamm; + float grp_pow_chg, att_val, att_degree; + float xfp_left[L_TRANA48k], xfp_right[L_TRANA48k]; + float gr_pow_left[LGW_MAX], gr_pow_right[LGW_MAX]; + const float *xfp_; + short Ltrana, Ltrana_2, Lprot, LtranaLog = 0, Lgw, k, burst_len; + short att_always[LGW_MAX]; /* fixed attenuation per frequency group if set to 1*/ + short burst_phdith_thresh = BURST_PHDITH_THRESH; /* speech settings */ + short burst_att_thresh = BURST_ATT_THRESH ; + float att_per_frame = ATT_PER_FRAME; + short burst_phdith_rampup_len = BURST_PHDITH_RAMPUP_LEN; + short tr_dec[LGW_MAX]; + + /* check burst error */ + burst_len = time_offs/output_frame + 1; + + set_s(att_always,0,LGW_MAX); + *ph_dith = 0.0f; + + /* softly shift attenuation just a bit later for estimated "stable" music_content */ + burst_phdith_thresh = BURST_PHDITH_THRESH+(short)(est_mus_content*1.0f + 0.5f); + burst_att_thresh = BURST_ATT_THRESH + (short)(est_mus_content*1.0f + 0.5f); + att_per_frame = ATT_PER_FRAME - (short)(est_mus_content*1.0f + 0.5f); /* only slighty less att for music */ + att_per_frame *=0.1f; + + if ( burst_len > burst_phdith_thresh ) + { + /* increase degree of dither */ + *ph_dith = PHASE_DITH * min(1.0f,((float)burst_len - (float)burst_phdith_thresh)/(float)burst_phdith_rampup_len); + } + + att_degree = 0; + if (burst_len > burst_att_thresh) + { + set_s(att_always,1,LGW_MAX); + + /* increase degree of attenuation */ + if( burst_len - burst_att_thresh <= PH_ECU_MUTE_START ) + { + att_degree = (float)(burst_len - burst_att_thresh) * att_per_frame; + } + else + { + att_degree = (float) PH_ECU_MUTE_START * att_per_frame + (burst_len - burst_att_thresh - PH_ECU_MUTE_START) * 6.0206f; + } + } + + Lprot = ( 2* output_frame * 4)/ 5; /* 4/5==1024/1280, keep mult within short */ + Ltrana = Lprot/QUOT_LPR_LTR; + Ltrana_2 = Ltrana/2; + + if (output_frame == L_FRAME48k) + { + w_hamm = w_hamm48k_2; + Lgw = LGW48k; + } + else if (output_frame == L_FRAME32k) + { + w_hamm = w_hamm32k_2; + LtranaLog = L_TRANA_LOG32k; + Lgw = LGW32k; + } + else + { + w_hamm = w_hamm16k_2; + LtranaLog = L_TRANA_LOG16k; + Lgw = LGW16k; + } + + if (burst_len <= 1 || (burst_len == 2 && last_fec) ) + { + set_f(alpha,1.0f,LGW_MAX); + set_f(beta,0.0f,LGW_MAX); + *beta_mute = BETA_MUTE_FAC_INI; + + /* apply hamming window */ + v_mult( xfp, w_hamm, xfp_left, Ltrana_2 ); + mult_rev2( xfp+Ltrana_2, w_hamm, xfp_left+Ltrana_2, Ltrana_2 ); + + xfp_ = xfp + Lprot - Ltrana; + v_mult( xfp_, w_hamm, xfp_right, Ltrana_2 ); + mult_rev2( xfp_+Ltrana_2, w_hamm, xfp_right+Ltrana_2, Ltrana_2 ); + + /* spectrum */ + if (output_frame == L_FRAME48k) + { + fft3(xfp_left,xfp_left,Ltrana); + fft3(xfp_right,xfp_right,Ltrana); + } + else + { + fft_rel(xfp_left,Ltrana,LtranaLog); + fft_rel(xfp_right,Ltrana,LtranaLog); + } + + /* square representation */ + fft_spec2(xfp_left,Ltrana); + fft_spec2(xfp_right,Ltrana); + + /* band powers in frequency groups + exclude bin at 0 and at EVS_PI from calculation */ + xfp_left[Ltrana_2] = 0.0f; + xfp_right[Ltrana_2] = 0.0f; + } + + for ( k = 0; k < Lgw; k++ ) + { + if (burst_len <= 1 || (burst_len == 2 && last_fec) ) + { + gr_pow_left[k] = sum_f(xfp_left +gw[k],gw[k+1]-gw[k]); + gr_pow_right[k] = sum_f(xfp_right+gw[k],gw[k+1]-gw[k]); + + /* check if transient in any of the bands */ + gr_pow_left[k] += FLT_MIN; /* otherwise div by zero may occur */ + gr_pow_right[k] += FLT_MIN; + + Xavg[k] = sqrt(0.5f*(gr_pow_left[k]+gr_pow_right[k])/(float)(gw[k+1]-gw[k])); + + grp_pow_chg = gr_pow_right[k] / gr_pow_left[k]; + + /* dither phase in case of transient */ + /* separate transition detection and application of forced burst dithering */ + tr_dec[k] = (grp_pow_chg > THRESH_TR_LIN) || (grp_pow_chg < THRESH_TR_LIN_INV); + + /* magnitude modification */ + if ( tr_dec[k] || att_always[k]) + { + att_val = min(MAX_INCREASE_GRPOW_LIN,grp_pow_chg); + att_val = (float)sqrt(att_val); + mag_chg_1st[k] = att_val; + mag_chg[k] = att_val; + } + else + { + mag_chg_1st[k] = 1.0f; + mag_chg[k] = 1.0f; + } + } + else + { + if( burst_len < OFF_FRAMES_LIMIT ) + { + mag_chg[k] = mag_chg_1st[k] * (float)pow(10.0,-att_degree/20.0); + } + else + { + mag_chg[k] = 0; + } + if (burst_len > BETA_MUTE_THR) + { + *beta_mute *= BETA_MUTE_FAC; + } + alpha[k] = mag_chg[k]; + beta[k] = sqrt(1.0f - SQR(alpha[k])) **beta_mute; + if (k>=LGW32k-1) + { + beta[k] *=0.1f; + } + else if (k>=LGW16k-1) + { + beta[k] *=0.5f; + } + } + } + + return; +} + +/*------------------------------------------------------------------* + * peakfinder() + * + * Peak-picking algorithm + *------------------------------------------------------------------*/ + +static void peakfinder( + const float *x0, /* i : vector from which the maxima will be found */ + const short len0, /* i : length of input vector */ + short *plocs, /* o : the indicies of the identified peaks in x0 */ + short *cInd, /* o : number of identified peaks */ + const float sel /* i : The amount above surrounding data for a peak to be identified */ +) +{ + float minMag, tempMag, leftMin; + float dx0[L_PROT48k_2], x[L_PROT48k_2+1], peakMag[MAX_PLOCS]; + short k, i, len, tempLoc = 0, foundPeak, ii, xInd; + short *ind, indarr[L_PROT48k_2+1], peakLoc[MAX_PLOCS]; + + ind = indarr; + + /* Find derivative */ + v_sub(x0+1,x0,dx0,len0-1); + + /* This is so we find the first of repeated values */ + for (i=0; i 2) + { + /* Set initial parameters for loop */ + tempMag = minMag; + foundPeak = 0; + leftMin = minMag; + + /* Deal with first point a little differently since tacked it on + Calculate the sign of the derivative since we taked the first point + on it does not necessarily alternate like the rest. */ + + /* The first point is larger or equal to the second */ + if (x[0] >= x[1]) + { + ii = -1; + if (x[1] >= x[2]) /* x[1] is not extremum -> overwrite with x[0] */ + { + x[1] = x[0]; + ind[1] = ind[0]; + ind++; + len--; + } + } + else /* First point is smaller than the second */ + { + ii = 0; + if (x[1] < x[2]) /* x[1] is not extremum -> overwrite with x[0] */ + { + x[1] = x[0]; + ind[1] = ind[0]; + ind++; + len--; + } + } + + *cInd = 0; + + /* Loop through extrema which should be peaks and then valleys */ + while (ii < len-1) + { + ii++; /* This is a peak */ + + /*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 (foundPeak) + { + tempMag = minMag; + foundPeak = 0; + } + + /* Make sure we don't iterate past the length of our vector */ + if (ii == len-1) + { + break; /* We assign the last point differently out of the loop */ + } + + /* Found new peak that was larger than temp mag and selectivity larger + than the minimum to its left. */ + if ((x[ii] > tempMag) && (x[ii] > leftMin + sel)) + { + tempLoc = ii; + tempMag = x[ii]; + } + + ii++; /* Move onto the valley */ + + /* Come down at least sel from peak */ + if (!foundPeak && (tempMag > sel + x[ii])) + { + foundPeak = 1; /* We have found a peak */ + leftMin = x[ii]; + peakLoc[*cInd] = tempLoc; /* Add peak to index */ + peakMag[*cInd] = tempMag; + (*cInd)++; + } + else if (x[ii] < leftMin) /* New left minimum */ + { + leftMin = x[ii]; + } + } + + /* Check end point */ + if (x[len-1] > tempMag && x[len-1] > leftMin + sel) + { + peakLoc[*cInd] = len-1; + peakMag[*cInd] = x[len-1]; + (*cInd)++; + } + else if (!foundPeak && tempMag > minMag) /* Check if we still need to add the last point */ + { + peakLoc[*cInd] = tempLoc; + peakMag[*cInd] = tempMag; + (*cInd)++; + } + + /* Create output */ + for (i=0; i<*cInd; i++) + { + plocs[i] = ind[peakLoc[i]]; + } + } + else /* This is a monotone function where an endpoint is the only peak */ + { + xInd = (x[0] > x[1]) ? 0 : 1; + peakMag[0] = x[xInd]; + if (peakMag[0] > minMag + sel) + { + plocs[0] = ind[xInd]; + *cInd=1; + } + else + { + *cInd=0; + } + } + + return; +} + +/*-------------------------------------------------------------------* + * imax() + * + * Get interpolated maximum position + *-------------------------------------------------------------------*/ + +static float imax(const float *y) +{ + float posi, y1, y2,y3,y3_y1,y2i; + /* Seek the extrema of the parabola P(x) defined by 3 consecutive points so that P([-1 0 1]) = [y1 y2 y3] */ + float ftmp_den1,ftmp_den2; + y1 = y[0]; + y2 = y[1]; + y3 = y[2]; + y3_y1 = y3-y1; + ftmp_den1 = (y1+y3-2*y2); + ftmp_den2 = (4*y2 - 2*y1 - 2*y3); + + if( ftmp_den2==0.0f || ftmp_den1==0.0f ) + { + return (0.0f); /* early exit with left-most value */ + } + + y2i = -0.125f * SQR(y3_y1) /(ftmp_den1) + y2; + /* their corresponding normalized locations */ + posi = y3_y1/(ftmp_den2); + + /* Interpolated maxima if locations are not within [-1,1], calculated extrema are ignored */ + if (posi >= 1.0f || posi <= -1.0f) + { + posi = y3 > y1 ? 1.0f : -1.0f; + } + else + { + if (y1 >= y2i) + { + posi = (y1 > y3) ? -1.0f : 1.0f; + } + else if (y3 >= y2i) + { + posi = 1.0f; + } + } + + return posi + 1.0f; +} + + +/*-------------------------------------------------------------------* + * spec_ana() + * + * Spectral analysis + *-------------------------------------------------------------------*/ + +static void spec_ana( + const float *prevsynth, /* i : Input signal */ + short *plocs, /* o : The indicies of the identified peaks */ + float *plocsi, /* o : Interpolated positions of the identified peaks */ + short *num_plocs, /* o : Number of identified peaks */ + float *X_sav, /* o : Stored fft spectrum */ + const short output_frame, /* i : Frame length */ + const short bwidth /* i : Encoded bandwidth index */ +) +{ + short i, Lprot, LprotLog2=0, hamm_len2=0, Lprot2_1, m; + const float *w_hamm = NULL; + float xfp[L_PROT48k]; + float Xmax, Xmin, sel; + short stop_band_start; + short stop_band_length; + + Lprot = 2*output_frame * L_PROT32k / 1280; + Lprot2_1 = Lprot/2+1; + + if (output_frame == L_FRAME48k) + { + w_hamm = w_hamm_sana48k_2; + hamm_len2 = L_PROT_HAMM_LEN2_48k; + } + else if (output_frame == L_FRAME32k) + { + w_hamm = w_hamm_sana32k_2; + hamm_len2 = L_PROT_HAMM_LEN2_32k; + LprotLog2 = 10; + } + else + { + w_hamm = w_hamm_sana16k_2; + hamm_len2 = L_PROT_HAMM_LEN2_16k; + LprotLog2 = 9; + } + + /* Apply hamming-rect window */ + v_mult(prevsynth,w_hamm,xfp,hamm_len2); + mvr2r(prevsynth+hamm_len2,xfp+hamm_len2,Lprot - 2*hamm_len2); + mult_rev2(prevsynth + Lprot - hamm_len2,w_hamm,xfp + Lprot - hamm_len2,hamm_len2); + + /* Spectrum */ + if (output_frame == L_FRAME48k) + { + fft3(xfp,xfp,Lprot); + } + else + { + fft_rel(xfp,Lprot,LprotLog2); + } + + /* Apply zeroing of non-coded FFT spectrum */ + if (output_frame > inner_frame_tbl[bwidth]) + { + stop_band_start = 128 << bwidth; + stop_band_length = Lprot - (stop_band_start << 1); + stop_band_start = stop_band_start + 1; + set_f( xfp + stop_band_start, 0, stop_band_length ); + } + + mvr2r(xfp,X_sav,Lprot); + + /* Magnitude representation */ + fft_spec2(xfp, Lprot); + + for (i=0; i 0) + { + delta_tmp = (plocs[m] - plocs[m-1] - 1)/2; + if (delta_tmp < DELTA_CORR) + { + delta_corr_dn = delta_tmp; + } + } + + if (m < *num_plocs-1 ) + { + delta_tmp = (plocs[m+1] - plocs[m] - 1)/2; + if ( delta_tmp < DELTA_CORR ) + { + delta_corr_up = delta_tmp; + } + } + + /* Input Xph */ + while ( i < plocs[m]-delta_corr_dn ) + { + *seed = own_random(seed); + + if (*seed & 0x40) + { + sin_F = sincos[*seed >> 8]; + } + else + { + sin_F = -sincos[*seed >> 8]; + } + + if (*seed & 0x80) + { + cos_F = sincos[-(*seed >> 8)]; + } + else + { + cos_F = -sincos[-(*seed >> 8)]; + } + + tmp = (X[i] * cos_F - X[im_ind] * sin_F); + X[im_ind] = (X[i] * sin_F + X[im_ind] * cos_F); + if (alpha[k] < 1.0f) + { + *seed = rand_phase(*seed,&sin_F,&cos_F); + X[i] = alpha[k] * tmp + beta[k] * Xavg[k] * cos_F; + X[im_ind] = alpha[k] * X[im_ind] + beta[k] * Xavg[k] * sin_F; + } + else + { + X[i] = mag_chg[k] * tmp; + X[im_ind] *= mag_chg[k]; + } + i++; + im_ind--; + if (i >= gwlpr[k+1]) + { + k++; + } + } + + e = plocs[m] + delta_corr_up; + if (e > Lprot/2 - 1) + { + e = Lprot/2 - 1; + } + + Xph = corr_phase[m]; + Xph_short = (short)(((long)(Xph * 512/EVS_PI)) % 32768) & 0x03ff; + if (Xph_short >= 512) + { + sin_F = -sincos_t_ext[Xph_short-512]; + if (Xph_short < 768) + { + cos_F = -sincos_t_ext[Xph_short-512+256]; + } + else + { + cos_F = sincos_t_ext[-Xph_short+1024+256]; + } + } + else + { + sin_F = sincos_t_ext[Xph_short]; + if (Xph_short < 256) + { + cos_F = sincos_t_ext[Xph_short+256]; + } + else + { + cos_F = -sincos_t_ext[-Xph_short+256+512]; + } + } + + while ( i <= e ) + { + mag_chg_local = mag_chg[k]; + + if( ph_dith != 0.0f ) + { + /* Call phase randomization only when needed */ + Xph = corr_phase[m]; + *seed = own_random(seed); + Xph += *seed * ph_dith * PHASE_DITH_SCALE; /* where ph_dith is 0..2PI, or -2PI (in transient), bin phase scaling factor from trans_ana */ + + if( ph_dith > 0.0f ) + { + /* up to 6 dB additional att of peaks in non_transient longer bursts, (when peak phase is randomized) */ + /* 0.5~= sqrt((float)pow(10.0,-6/10.0)); ph_dith= 0..2pi,--> scale=1.0 ...5 */ + mag_chg_local *= 0.5f + (1.0f-(1.0f/PHASE_DITH)*ph_dith)*0.5f; + } + + Xph_short = (short)((int)(Xph * 512/EVS_PI) & 0x03ff); + + if (Xph_short >= 512) + { + sin_F = -sincos_t_ext[Xph_short-512]; + if (Xph_short < 768) + { + cos_F = -sincos_t_ext[Xph_short-512+256]; + } + else + { + cos_F = sincos_t_ext[-Xph_short+1024+256]; + } + } + else + { + sin_F = sincos_t_ext[Xph_short]; + if (Xph_short < 256) + { + cos_F = sincos_t_ext[Xph_short+256]; + } + else + { + cos_F = -sincos_t_ext[-Xph_short+256+512]; + } + } + } + + tmp = (X[i] * cos_F - X[im_ind] * sin_F); + X[im_ind] = (X[i] * sin_F + X[im_ind] * cos_F); + if (alpha[k] < 1.0f) + { + float alpha_local = mag_chg_local; + float beta_local = beta_mute * sqrt(1.0f - SQR(alpha_local)); + if (k>=LGW32k-1) + { + beta_local *=0.1f; + } + else if (k>=LGW16k-1) + { + beta_local *=0.5f; + } + + *seed = rand_phase(*seed,&sin_F,&cos_F); + X[i] = alpha_local * tmp + beta_local * Xavg[k] * cos_F; + X[im_ind] = alpha_local * X[im_ind] + beta_local * Xavg[k] * sin_F; + } + else + { + X[i] = mag_chg_local * tmp; + X[im_ind] *= mag_chg_local; + } + + i++; + im_ind--; + if (i >= gwlpr[k+1]) + { + k++; + } + } + } + + while ( i < Lprot/2 ) + { + *seed = own_random(seed); + + if (*seed & 0x40) + { + sin_F = sincos[*seed >> 8]; + } + else + { + sin_F = -sincos[*seed >> 8]; + } + + if (*seed & 0x80) + { + cos_F = sincos[-(*seed >> 8)]; + } + else + { + cos_F = -sincos[-(*seed >> 8)]; + } + + + tmp = (X[i] * cos_F - X[im_ind] * sin_F); + X[im_ind] = (X[i] * sin_F + X[im_ind] * cos_F); + if (alpha[k] < 1.0f) + { + *seed = rand_phase(*seed,&sin_F,&cos_F); + X[i] = alpha[k] * tmp + beta[k] * Xavg[k] * cos_F; + X[im_ind] = alpha[k] * X[im_ind] + beta[k] * Xavg[k] * sin_F; + im_ind--; + } + else + { + X[i] = mag_chg[k] * tmp; + X[im_ind--] *= mag_chg[k]; + } + i++; + + if (i >= gwlpr[k+1]) + { + k++; + } + } + + return; +} + +/*-------------------------------------------------------------------------- + * rec_wtda() + * + * Windowing and TDA of reconstructed frame + *--------------------------------------------------------------------------*/ + +static void rec_wtda( + float *X, /* i : FFT spectrum */ + float *ecu_rec, /* o : Reconstructed frame in tda domain */ + const short output_frame, /* i : Frame length */ + const short Lprot, /* i : Prototype frame length */ + const float fs +) +{ + float old_wtda[L_FRAME48k],xinit[L_FRAME48k],xsubst_[2*L_FRAME48k]; + short timesh; + short xf_len; + short i; + float *p_ecu; + float g; + float tbl_delta; + + /* extract reconstructed frame with aldo window */ + set_f(xsubst_,0.0f,output_frame-Lprot/2); + mvr2r(X,xsubst_+output_frame-Lprot/2,Lprot); + set_f(xsubst_+output_frame+Lprot/2,0.0f,output_frame-Lprot/2); + + /* Smoothen onset of ECU frame */ + xf_len = (short)((float)output_frame*N_ZERO_MDCT_NS/FRAME_SIZE_NS) - (output_frame - Lprot/2); + p_ecu = xsubst_ + (output_frame - Lprot/2); + tbl_delta = 64.0/xf_len; /* 64 samples = 1/4 cycle in sincos_t */ + for ( i = 0; i < xf_len; i++, p_ecu++ ) + { + g = sincos_t[((short)(i * tbl_delta))]; + g *= g; + *p_ecu = g * (*p_ecu); + } + + timesh = NS2SA(fs, 10000000L - PH_ECU_ALDO_OLP2_NS); + set_f( xinit, 0, timesh ); + mvr2r( xsubst_, xinit+timesh, output_frame-timesh ); + + set_f( old_wtda,0,output_frame); + + /* warm up old_wtda */ + wtda( xinit, ecu_rec, old_wtda, ALDO_WINDOW, ALDO_WINDOW, output_frame ); + wtda( xsubst_+output_frame-timesh, ecu_rec, old_wtda, ALDO_WINDOW, ALDO_WINDOW, output_frame ); + + return; +} + + +/*-------------------------------------------------------------------------- + * rec_frame() + * + * Frame reconstruction + *--------------------------------------------------------------------------*/ + +static void rec_frame( + float *X, /* i : FFT spectrum */ + float *ecu_rec, /* o : Reconstructed frame in tda domain */ + const short output_frame /* i : Frame length */ +) +{ + short Lprot, LprotLog2=0; + float fs; + + fs = (float)output_frame*50.0f; + Lprot = 2*output_frame * L_PROT32k / 1280; + + if (output_frame == L_FRAME48k) + { + LprotLog2 = 9; + } + else if (output_frame == L_FRAME32k) + { + LprotLog2 = 10; + } + else + { + LprotLog2 = 9; + } + + /* extend spectrum and IDFT */ + if (output_frame == L_FRAME48k) + { + ifft3( X, X, Lprot ); + } + else + { + ifft_rel( X, Lprot, LprotLog2 ); + } + + rec_wtda( X, ecu_rec, output_frame, Lprot, fs ); + + return; +} + + +/*-------------------------------------------------------------------------- + * fir_dwn() + * + * + *--------------------------------------------------------------------------*/ + +static void fir_dwn( + const float x[], /* i : input vector */ + const float h[], /* i : impulse response of the FIR filter */ + float y[], /* o : output vector (result of filtering) */ + const short L, /* i : input vector size */ + const short K, /* i : order of the FIR filter (K+1 coefs.) */ + const short decimation /* i : decimation */ +) +{ + float s; + short i, j, k, mmax; + + k = 0; + + /* do the filtering */ + for ( i = K/2; i < L; i += decimation ) + { + s = x[i] * h[0]; + + if ( i < K ) + { + mmax = i; + } + else + { + mmax = K; + } + + for ( j = 1; j <= mmax; j++ ) + { + s += h[j] * x[i-j]; + } + + y[k] = s; + k++; + } + + for ( ; i < L+K/2; i += decimation ) + { + s = 0; + + for (j = i-L+1; j <= K; j++) + { + s += h[j] * x[i-j]; + } + + y[k] = s; + k++; + } + + return; +} + + +/*-------------------------------------------------------------------------- + * fec_ecu_pitch() + * + * + *--------------------------------------------------------------------------*/ + +static void fec_ecu_pitch( + const float *prevsynth, + float *prevsynth_LP, + const short L, + short *N, + float *min_corr, + short *decimatefator, + const short HqVoicing +) +{ + short i,filt_size; + float accA,accB,accC,Ryy; + short delay_ind,k,cb_start,cb_end,tmp_short,Lon20; + float Asr_LP[FEC_DCIM_FILT_SIZE_MAX+1]; + + switch(L) + { + case L_FRAME48k: + *decimatefator=6; + filt_size=60; + mvr2r(Asr_LP48,Asr_LP,filt_size+1); + break; + case L_FRAME32k: + *decimatefator=4; + filt_size=40; + mvr2r(Asr_LP32,Asr_LP,filt_size+1); + break; + case L_FRAME16k: + *decimatefator=2; + filt_size=20; + mvr2r(Asr_LP16,Asr_LP,filt_size+1); + break; + default: + *decimatefator=2; + filt_size=40; + mvr2r(Asr_LP16,Asr_LP,filt_size+1); + break; + } + + /* We need to inverse the ALDO window */ + + /* Resampling to work at 8Khz */ + fir_dwn( prevsynth,Asr_LP,prevsynth_LP,2*L,filt_size,*decimatefator ); /* resampling without delay */ + + Lon20=(short) ((L/20)/ *decimatefator); + + /* Correlation analysis */ + *min_corr=0; + accC=0; + for (k = 0; k < 6*Lon20; k++) + { + accC+=prevsynth_LP[34*Lon20+k]*prevsynth_LP[34*Lon20+k]; + } + + if (HqVoicing==1) + { + cb_start=0; + cb_end=33*Lon20; + } + else + { + cb_start=0; + cb_end=28*Lon20; + } + + tmp_short=34*Lon20; + accB=0; + delay_ind=cb_start; + for (i=cb_start; i *min_corr ) + { + *min_corr = Ryy; + delay_ind = i; + } + + if ( HqVoicing == 0 && *min_corr > 0.95f ) + { + break; + } + } + + *N = 40*Lon20-delay_ind-6*Lon20; + + return; +} + + +/*-------------------------------------------------------------------------- + * fec_ecu_dft() + * + * + *--------------------------------------------------------------------------*/ + +static void fec_ecu_dft( + const float *prevsynth_LP, /* i: */ + const short N, /* i: */ + float *Tfr, /* o: */ + float *Tfi, /* o: */ + float *sum_Tf_abs, /* o: */ + float *Tf_abs, /* o: */ + short *Nfft /* o: */ +) +{ + float target[2*L_FRAME8k],tmp; + short i, Lon20,tmp_short,N_LP,k; + + Lon20 = (short)160/20; + + for (i=0; iLon20*10 || HqVoicing ) + { + PL=1; + } + while(cpt<=N/2-1-2) + { + if(Tf_abs[cpt]>old && Tf_abs[cpt]>new_s) + { + glued=cpt; + + for (i=glued; immax) + { + mmax=Tf_abs[pulses[k]]; + indmax=pulses[k]; + } + } + cumsum += Tf_abs[indmax]; + + if (HqVoicing || cumsumtime_offs */ + *time_offs = 32767 ; /* continued muting will ensure that the now fixed seeds are not creating tones */ + } + + trans_ana( prevsynth + 2*output_frame-Lprot, mag_chg, &ph_dith, mag_chg_1st, + output_frame, *time_offs, env_stab, 0, alpha, beta, beta_mute, Xavg ); /* 1.0 stable-music, 0.0 speech-like */ + } + + mvr2r( X_sav, X, Lprot ); + + /* seed for own_rand2 */ + seed = *time_offs; + if (*num_p > 0) + { + seed += plocs[*num_p-1]; + } + + subst_spec( 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( X, ecu_rec, output_frame ); + + return; +} + + +/*-------------------------------------------------------------------------- + * hq_ecu() + * + * Main routine for HQ ECU + *--------------------------------------------------------------------------*/ + +void hq_ecu( + const float *prevsynth, /* i : buffer of previously synthesized signal */ + float *ecu_rec, /* o : reconstructed frame in tda domain */ + short *time_offs, /* i/o: Sample offset for consecutive frame losses*/ + float *X_sav, /* i/o: Stored spectrum of prototype frame */ + short *num_p, /* i/o: Number of identified peaks */ + short *plocs, /* i/o: Peak locations */ + float *plocsi, /* i/o: Interpolated peak locations */ + const float env_stab, /* i : Envelope stability parameter */ + short *last_fec, /* i/o: Flag for usage of pitch dependent ECU */ + const short ph_ecu_HqVoicing, /* i : HQ Voicing flag */ + short *ph_ecu_active, /* i : Phase ECU active flag */ + float *gapsynth, /* o : Gap synthesis */ + const short prev_bfi, /* i : indicating burst frame error */ + const short old_is_transient[2], /* i : flags indicating previous transient frames*/ + float *mag_chg_1st, /* i/o: per band magnitude modifier for transients*/ + float Xavg[LGW_MAX], /* i/o: Frequency group average gain to fade to */ + float *beta_mute, /* o : Factor for long-term mute */ + const short output_frame, /* i : frame length */ + Decoder_State *st /* i/o: decoder state structure */ +) +{ + short N; + float corr = 0.0f; + short decimatefactor; + float prevsynth_LP[2*L_FRAME8k]; + + /* find pitch and R value */ + if (!(output_frame < L_FRAME16k) ) + { + fec_ecu_pitch( 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.0f; + decimatefactor=4; + N=output_frame/4; + } + + if ((st->total_brate >= 48000 && ( output_frame >= L_FRAME16k && !prev_bfi && (!old_is_transient[0] || old_is_transient[1] ) && + (ph_ecu_HqVoicing || ( ((st->env_stab_plc > 0.5) && ( corr < 0.6)) || (st->env_stab_plc < 0.5 && (corr > 0.85 )))))) || + (st->total_brate < 48000 && ( ( ph_ecu_HqVoicing || corr > 0.85 ) && !prev_bfi && (!old_is_transient[0] || old_is_transient[1]) )) ) + { + fec_alg( prevsynth+NS2SA(output_frame*50,ACELP_LOOK_NS/2-PH_ECU_LOOKAHEAD_NS), prevsynth_LP, ecu_rec, output_frame, N, decimatefactor, ph_ecu_HqVoicing, gapsynth, &st->ni_seed_forfec ); + *last_fec = 1; + *ph_ecu_active = 0; + *time_offs = output_frame; + } + else + { + hq_phase_ecu( prevsynth, ecu_rec, time_offs, X_sav, num_p, plocs, plocsi, env_stab, last_fec, + prev_bfi, old_is_transient, mag_chg_1st, Xavg, beta_mute, st->bwidth, output_frame ); + + *last_fec = 0; + *ph_ecu_active = 1; + } + + return; +} diff --git a/lib_dec/FEC_adapt_codebook.c b/lib_dec/FEC_adapt_codebook.c new file mode 100644 index 000000000..5e42f66bf --- /dev/null +++ b/lib_dec/FEC_adapt_codebook.c @@ -0,0 +1,462 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_dec.h" +#include "prot.h" + + +/*------------------------------------------------------------------------- + * FEC_synchro_exc() + * + * Perform resynchronisation of the last glottal pulse in voiced frame lost + *------------------------------------------------------------------------*/ + +static short FEC_synchro_exc( /* o : do_WI flag */ + const short L_frame, /* i : length of the frame */ + float *exc, /* i/o: exc vector to modify */ + const short desire_puls_pos, /* i : Pulse position send by the encoder */ + const short true_puls_pos, /* i : Present pulse location */ + const short Old_pitch /* i : Pitch use to create temporary adaptive codebook */ +) +{ + float exc_tmp[L_FRAME16k+L_SUBFR], min_energy, *pt_exc,*pt_exc1, ftmp, fact; + short i, j, point_to_remove, point_to_add = -1, nb_min; + short min_pos[L_FRAME16k/PIT_MIN_DOUBLEEXTEND], points_by_pos[L_FRAME16k/PIT_MIN_DOUBLEEXTEND], total_point, tmp_len; + short *pt_pos, pos, start_search, tmp16; + short remaining_len; + + /* Init */ + for( i=0; i= 65536*65536.0f ) + { + 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 + * --------------------------------------------------------------------*/ + + if(nb_min == 1 || abs(point_to_remove) == 1) + { + nb_min = 1; + points_by_pos[0] = (short)abs(point_to_remove); + } + else + { + /* First position */ + fact = (float)abs(point_to_remove) / (nb_min*nb_min); + + total_point = (short)(fact+0.5); + points_by_pos[0] = total_point; + + for (i = 2; i <= nb_min; i++) + { + points_by_pos[i-1] = (short)(fact*(i*i) - total_point+0.5) ; + total_point += points_by_pos[i-1]; + + /* ensure a constant increase */ + if (points_by_pos[i-1] < points_by_pos[i-2]) + { + tmp16 = points_by_pos[i-2]; + points_by_pos[i-2] = points_by_pos[i-1]; + points_by_pos[i-1] = tmp16; + } + } + } + + /* -------------------------------------------------------------------- + * 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; + } + + pt_exc = exc_tmp; + pt_exc1 = exc; + + i = 0; + pt_pos = min_pos + nb_min - 1; + if ( point_to_add > 0 ) /* add some points */ + { + remaining_len = L_frame; + + for (i = 0; i < nb_min; i++) + { + /* Copy section */ + if(i == 0) + { + /* Compute len to copy */ + tmp_len = *pt_pos; + } + else + { + /* Compute len to copy */ + tmp_len = *pt_pos - *(pt_pos+1) - points_by_pos[i-1]; + } + + mvr2r( pt_exc1, pt_exc, tmp_len); + remaining_len -= tmp_len; + pt_exc1 += tmp_len; + pt_exc += tmp_len; + + /* add some points */ + ftmp = -(*pt_exc1/20); + for (j=0; j PIT_MAX && L_frame == L_FRAME ) + { + P0 = PIT_MAX; /* Should never be the case, however... */ + } + else if ( P0 > PIT16k_MAX && L_frame == L_FRAME16k ) + { + P0 = PIT16k_MAX; /* Should never be the case, however... */ + } + set_f( exc_tmp, 0, L_frame+ MODE1_L_FIR_FER); /* Reset excitation vector */ + + /*--------------------------------------------* + * Find LP filter impulse response energy + *--------------------------------------------*/ + + set_f( h1, 0, L_subfr ); /* Find the impulse response */ + set_f( mem, 0, M ); + h1[0] = 1.0f; + syn_filt(Aq, M, h1, h1, L_subfr, mem, 0); + enr_LP = dotp( h1, h1, L_subfr ) + 0.01f; /* Find the impulse response energy */ + + /*------------------------------------------------------------------------------------------* + * Construct the harmonic part as a train of low-pass filtered pulses + *------------------------------------------------------------------------------------------*/ + + pt_exc = exc_tmp + L_frame- 1 - MODE1_L_FIR_FER/2 - P0; /* beginning of the 1st pulse */ + pt_end = exc_tmp + onset_len; + + len = (short)(pt_exc - pt_end); + if( len > MODE1_L_FIR_FER ) + { + 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] += h_low[i]; /* As it is lp filtered, the E is somewhat lower */ + } + } + else + { + for( i=0; i< len; i++ ) + { + /* The filter response would have E=1 in full band. */ + pt_exc[i] -= h_low[i]; /* As it is lp filtered, the E is somewhat lower */ + } + } + + gain = (float)sqrt(1.5*enr_q / enr_LP); /* divide by LP filter E, scale by transmitted E */ + gain *= 0.96f; + for( i=0; i< L_frame; i++ ) + { + exc_tmp[i] *= gain; + } + + mvr2r(&exc_tmp[L_frame - L_EXC_MEM], exc, L_EXC_MEM); + + return; +} + +short FEC_enhACB( + const short L_frame, /* i : frame length */ + const short last_L_frame, /* i : frame length of last frame */ + float *exc_io, /* i/o : adaptive codebook memory */ + const short new_pit, /* i : decoded first frame pitch */ + const short puls_pos, /* i : decoder position of the last glottal pulses decoded in the previous frame */ + const float bfi_pitch /* i : pitch used for concealment */ +) +{ + short Tc, P0, sign, pit_search; + short Tlist[10], Terr, diff_pit, dist_Plast; + float ftmp; + float exc[L_FRAME16k + L_SUBFR]; + short do_WI = 1; + + set_f(exc, 0.0f, L_FRAME16k - L_EXC_MEM); + set_f(exc+L_FRAME16k, 0.0f, L_SUBFR); + mvr2r(exc_io, exc + L_FRAME16k - L_EXC_MEM, L_EXC_MEM); + + Tc = (short)bfi_pitch; + mvr2r(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; + sign = 0; + if (P0 < 0) + { + sign = 1; + P0 = -P0; + } + + if( L_frame == L_FRAME ) + { + if( P0>PIT_MAX ) + { + P0 = PIT_MAX; /* Should never be the case, however... */ + } + } + else /* L_frame == L_FRAME16k */ + { + if( P0>PIT16k_MAX ) + { + P0 = PIT16k_MAX; /* Should never be the case, however... */ + } + } + + /*---------------------------------------------------------------------------------- + * Find the position of the first the maximum(minimum) lp_filtered pulse + * <----- Mem --->|<--------------------- L_frame ------------>|<----- L_SUBFR --->| + * |<-------pit_search----> | | + *----------------------------------------------------------------------------------*/ + + pit_search = Tc; + + Tlist[0] = findpulse( L_frame, exc+L_frame-pit_search , pit_search,DEC, &sign); + + Terr = (short) abs(pit_search-Tlist[0]-P0); + + dist_Plast = Tc-Tlist[0]; + + Tlist[1] = findpulse( L_frame, exc+L_frame-pit_search , pit_search+L_SUBFR,DEC, &sign); + + if(Terr > abs(Tlist[1]-Tc + P0)) + { + dist_Plast = Tc-Tlist[1]; + Terr = (short)abs(Tlist[1]-Tc + P0); + } + + diff_pit = (short)abs(new_pit - Tc); + ftmp = (float) (int)((float)L_frame/(float)Tc+0.5); + + if ( Terr <= ftmp * diff_pit + && Terr != 0 /* If Terr = 0, no resynchronization required */ + && Terr < L_SUBFR) /* prevent catastrophy search */ + { + /* perform excitation resynchronization here */ + do_WI = FEC_synchro_exc( L_frame, exc, P0, dist_Plast, Tc ); + mvr2r( exc + L_FRAME16k - L_EXC_MEM, exc_io, L_EXC_MEM ); + } + else + { + do_WI = 0; + } + + if( last_L_frame != L_FRAME16k ) + { + /* This is essential in case of bit rate switching + FEC*/ + do_WI = 0; + } + + return do_WI; +} diff --git a/lib_dec/FEC_clas_estim.c b/lib_dec/FEC_clas_estim.c new file mode 100644 index 000000000..6a2967f6c --- /dev/null +++ b/lib_dec/FEC_clas_estim.c @@ -0,0 +1,796 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include "cnst.h" +#include "options.h" +#include "prot.h" +#include "rom_com.h" +#include "stat_dec.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define K_COR_DEC 0.8547f /* <-0.29, 0.88> */ +#define C_COR_DEC 0.2479f + +#define K_TILT_DEC 0.8333f /* <-0.35, 0.85> */ +#define C_TILT_DEC 0.2917f + +#define K_ZC_DEC -0.04f /* <63, 38> */ +#define C_ZC_DEC 2.52f + +#define K_ENR_DEC 0.04f /* <-14, 11> */ +#define C_ENR_DEC 0.56f + +#define K_PC_DEC -0.0357f /* <45, 17> */ +#define C_PC_DEC 1.6071f + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static float calculate_zero_crossings( const float *synth, const short L_frame ); + +static float calculate_pitch_synchr_norm_correlation( const float *pitch, const float *synth, const short L_frame, const short L_subfr ); + +static float calculate_spectral_tilt( const float *synth, const short nbSubfr, const short L_subfr ); + +static short calculate_classification_result( short const last_good, float fmerit1, float const ener, short const codec_mode ); + +static void FEC_ClassifierCore( const float *synth, const float *pitch, short const L_frame, const short codec_mode, short *clas, float *lp_speech, float *frame_ener, + float *ener, float *enern, float *class_para, const float LTP_Gain, const int narrowBand, const SIGNAL_CLASSIFIER_MODE mode ); + +static short FEC_dec_class( Decoder_State *st, const long core_brate, const short coder_type, float *enr_q, const short last_good ); + +static void FEC_classificationMusic( const short coder_type, short *decision_hyst, short *clas ); + + +/*------------------------------------------------------------------------* + * calculate_zero_crossings() + * + * + *------------------------------------------------------------------------*/ + +static float calculate_zero_crossings( + const float *synth, + const short L_frame +) +{ + short i; + float zc_frame; + + zc_frame = 0.f; + + for ( i = 0; i < L_frame; ++i ) + { + if ( (synth[i] <= 0.0f) && (synth[i-1] > 0.0f) ) + { + zc_frame += 1.0f; + } + } + + /* Renormalization for 12.8kHz core*/ + zc_frame *= 256.0f / (float)L_frame; + + return zc_frame; +} + +/*------------------------------------------------------------------------* + * calculate_pitch_synchr_norm_correlation() + * + * + *------------------------------------------------------------------------*/ + +static float calculate_pitch_synchr_norm_correlation( + const float *pitch, + const float *synth, + const short L_frame, + const short L_subfr +) +{ + short T0, pos; + short j, i; + float cor_max[16] = {0.f}; + float enr1t, enr2t, voicing; + + T0 = (short) pitch[3]; + + if ( T0 > (3 * (L_subfr / 2) )) + { + T0 = (short) ( 0.5f * ( pitch[2] + pitch[3]) + 0.5f ); + } + + pos = L_frame; + j = 0; + + while ( pos > (L_frame/L_subfr==4? 3*L_subfr: 4*L_subfr) ) + { + pos -= T0; + + cor_max[j] = dotp( &synth[pos], &synth[pos-T0], T0); + enr1t = dotp( &synth[pos-T0], &synth[pos-T0], T0); + enr2t = dotp( &synth[pos], &synth[pos], T0); + + cor_max[j] *= inv_sqrt( enr1t * enr2t + 0.1f ); + + + if ( (pos - T0) < (L_frame - L_subfr) ) + { + T0 = (short) ( 0.5f * ( pitch[2] + pitch[3] ) + 0.5f ); + } + j++; + } + + voicing = cor_max[0]; + + for ( i = 1; i < j; ++i ) + { + voicing += cor_max[i]; + } + + if( j > 1 ) + { + voicing /= j; + } + + return voicing; +} + + +/*------------------------------------------------------------------------* + * calculate_spectral_tilt() + * + * + *------------------------------------------------------------------------*/ + +static float calculate_spectral_tilt( + const float *synth, + const short nbSubfr, + const short L_subfr +) +{ + short i; + float tilt; + + float enr1t = 0.0f; + float enr2t = 0.0f; + float const* pt1 = synth + L_subfr; + float const* pt2 = synth + L_subfr - 1; + + for ( i = 0; i < nbSubfr-1; ++i ) + { + enr1t += dotp( pt1, pt1, L_subfr ); + enr2t += dotp( pt1, pt2, L_subfr ); + + pt1 += L_subfr; + pt2 += L_subfr; + } + + tilt = enr2t / ( enr1t + 0.1f ); + + return tilt; +} + +/*------------------------------------------------------------------------* + * calculate_classification_result() + * + * + *------------------------------------------------------------------------*/ +static short calculate_classification_result( + short const last_good, + float fmerit1, + float const ener, + short const codec_mode +) +{ + short result = UNVOICED_CLAS; + + switch ( last_good ) + { + case VOICED_CLAS: + case ONSET: + case SIN_ONSET: + case VOICED_TRANSITION: + + if ( fmerit1 < 0.39f ) + { + result = UNVOICED_CLAS; + } + else if ( fmerit1 < 0.63f && (codec_mode == MODE2 || ener < -15.0f) ) + { + result = VOICED_TRANSITION; + } + else + { + result = VOICED_CLAS; + } + break; + + case UNVOICED_CLAS: + case UNVOICED_TRANSITION: + case INACTIVE_CLAS: /* relevant for MODE2 only */ + + if ( fmerit1 > 0.56f ) + { + result = ONSET; + } + else if ( fmerit1 > 0.45f ) + { + result = UNVOICED_TRANSITION; + } + else + { + result = UNVOICED_CLAS; + } + break; + } + + return result; +} + + +/*------------------------------------------------------------------------* + * FEC_ClassifierCore() + * + * + *------------------------------------------------------------------------*/ + +static void FEC_ClassifierCore( + const float *synth, + const float *pitch, /* i : pitch values for each subframe */ + short const L_frame, /* i : length of the frame */ + const short codec_mode, /* i : codec mode */ + short *clas, /* i/o: frame classification */ + float *lp_speech, /* i/o: long term active speech energy average */ + float *frame_ener, /* o : */ + float *ener, /* o : */ + float *enern, /* o : */ + float *class_para, /* o : classification para. fmerit1 */ + const float LTP_Gain, /* i : */ + const int narrowBand, /* i : */ + const SIGNAL_CLASSIFIER_MODE mode /* i : */ +) +{ + float zc_frame; + float tiltn, corn, zcn, pcn, fmerit1, tilt; + float voicing; + float pc = 0.0f; + + /*------------------------------------------------------------------------* + * Compute the zero crossing rate for all subframes + *------------------------------------------------------------------------*/ + + zc_frame = calculate_zero_crossings(synth, L_frame); + + /*------------------------------------------------------------------------* + * Compute the normalized correlation pitch-synch at the end of the frame + *------------------------------------------------------------------------*/ + + voicing = calculate_pitch_synchr_norm_correlation(pitch, synth, L_frame, L_SUBFR); + + /*------------------------------------------------------------------------* + * Compute pitch coherence + *------------------------------------------------------------------------*/ + + pc = 0; /* just to remove MSVC warnings */ + if (codec_mode == MODE1 || !(LTP_Gain != -1.0f && mode == CLASSIFIER_TCX) ) + { + pc = (float) fabs( pitch[3] + pitch[2] - pitch[1] - pitch[0] ) * 256.0f / (float)L_frame; + } + + /*------------------------------------------------------------------------* + * Compute spectral tilt + *------------------------------------------------------------------------*/ + + tilt = calculate_spectral_tilt(synth, L_frame/L_SUBFR, L_SUBFR ); + + /*------------------------------------------------------------------------* + * Compute pitch-synchronous energy at the frame end + *------------------------------------------------------------------------*/ + + *ener = frame_energy( L_frame, pitch, synth, *lp_speech, frame_ener ); + + /*------------------------------------------------------------------------* + * transform parameters between 0 & 1 + * find unique merit function + *------------------------------------------------------------------------*/ + + *enern = K_ENR_DEC **ener + C_ENR_DEC; + tiltn = K_TILT_DEC * tilt + C_TILT_DEC; + corn = K_COR_DEC * voicing + C_COR_DEC; + zcn = K_ZC_DEC * zc_frame + C_ZC_DEC; + + if ( codec_mode == MODE2 && LTP_Gain != -1.0f && mode == CLASSIFIER_TCX ) + { + pcn = LTP_Gain * C_PC_DEC; + } + else + { + pcn = K_PC_DEC * pc + C_PC_DEC; + } + + if( pcn > 1.0f ) + { + pcn = 1.0f; + } + else if( pcn < 0.0f ) + { + pcn = 0.0f; + } + + fmerit1 = (1.0f / 6.0f ) * ( tiltn + 2.0f * corn + zcn + pcn + *enern ); + + if( codec_mode == MODE2 && narrowBand ) + { + fmerit1 *= 0.9f; + } + + /*------------------------------------------------------------------------* + * frame classification + *------------------------------------------------------------------------*/ + + if( codec_mode == MODE1 ) + { + *class_para = fmerit1; + } + *clas = calculate_classification_result(*clas, fmerit1, *ener, codec_mode); + + return; +} + + +/*------------------------------------------------------------------------* + * FEC_clas_estim() + * + * Estimation of frame class, if not available in the bitstream + *------------------------------------------------------------------------*/ + +void FEC_clas_estim( + const float *syn, + const float *pitch, /* i : pitch values for each subframe */ + const short L_frame, /* i : length of the frame */ + const short coder_type, /* i : coder type */ + const short codec_mode, /* i : codec mode */ + float *mem_syn_clas_estim, /* i/o: memory of the synthesis signal for frame class estimation */ + short *clas, /* i/o: frame classification */ + float *lp_speech, /* i/o: long term active speech energy average */ + long const bitrate, /* i : Decoded bitrate */ + short const Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + short *decision_hyst, /* i/o: hysteresis of the music/speech decision */ + short *locattack, /* i/o: detection of attack (mainly to localized speech burst) */ + short *UV_cnt, /* i/o: number of consecutives frames classified as UV */ + float *LT_UV_cnt, /* i/o: long term consecutives frames classified as UV */ + float *Last_ener, /* i/o: last_energy frame */ + short *amr_io_class, /* i/o: classification for AMR-WB IO mode */ + float *lt_diff_etot, /* i/o: long-term total energy variation */ + float *class_para, /* o : classification para. fmerit1 */ + const float LTP_Gain, /* i : */ + const int narrowBand, /* i : */ + const SIGNAL_CLASSIFIER_MODE mode,/* i : */ + const int bfi, /* i : */ + const float preemph_fac, /* i : */ + const int tcxonly, /* i : */ + const int last_core_brate /* i : last core bitrate */ +) +{ + float diff_ener; + float mean_diff; + short i; + float ftmp_c, fcorr, dev; + float frame_ener = 0.0f; + float ener = 0.0f; + float enern = 0.0f; + float tmp; + float old_synth[L_SYN_CLAS_ESTIM], *synth; + + /* After Rate Switching st->last_core is reset to 0. Check for last_core_brate is needed */ + if((last_core_brate == SID_1k75 || last_core_brate == ACELP_6k60 || last_core_brate == ACELP_8k85 + || last_core_brate == ACELP_12k65 || last_core_brate == ACELP_14k25 || last_core_brate == ACELP_15k85 + || last_core_brate == ACELP_18k25 || last_core_brate == ACELP_19k85 || last_core_brate == ACELP_23k05 + || last_core_brate == ACELP_23k85) && !Opt_AMR_WB && codec_mode == MODE2 + && L_frame > L_FRAME) + { + int oldLenClasBuff, newLenClasBuff; + oldLenClasBuff = L_SYN_MEM_CLAS_ESTIM * L_FRAME/L_frame; + newLenClasBuff = L_SYN_MEM_CLAS_ESTIM; + 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; /* Set pointer to current frame */ + mvr2r( mem_syn_clas_estim, old_synth, L_SYN_MEM_CLAS_ESTIM ); /* Copy old synthesis into local buffer */ + mvr2r( syn, synth, L_frame ); /* Copy current synthesis into local buffer */ + + /* TCX outputs non-pre-speech */ + if( codec_mode == MODE2 && mode == CLASSIFIER_TCX ) + { + tmp = syn[-1]; + preemph(synth, preemph_fac, L_frame, &tmp); + } + + /* 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) */ + if ((codec_mode == MODE1 && ( bitrate < ACELP_11k60 || coder_type <= UNVOICED || Opt_AMR_WB)) || + (codec_mode == MODE2 && bfi!=1 && !tcxonly )) + { + + /*------------------------------------------------------------------------* + * classification decision depending on coder_type information + *------------------------------------------------------------------------*/ + + if( coder_type == UNVOICED ) + { + *clas = UNVOICED_CLAS; + } + else if( coder_type == VOICED ) + { + *clas = VOICED_CLAS; + } + else if( coder_type == INACTIVE && !Opt_AMR_WB) + { + *clas = INACTIVE_CLAS; + } + else + { + /*------------------------------------------------------------------------* + * GC, TC and AC frames + *------------------------------------------------------------------------*/ + + FEC_ClassifierCore( synth, pitch, L_frame, codec_mode, clas, lp_speech, &frame_ener, &ener, + &enern, class_para, LTP_Gain, narrowBand, mode ); + } + + /*------------------------------------------------------------------------* + * Overwrite classification decision in case of music + *------------------------------------------------------------------------*/ + + if( codec_mode == MODE1 ) + { + FEC_classificationMusic( coder_type, decision_hyst, clas ); + } + + /*---------------------------------------------------------------------------------* + * Measure energy on active voice frames (to improve FEC performance) + *---------------------------------------------------------------------------------*/ + + if ( *clas == VOICED_CLAS ) + { + if ( ( codec_mode == MODE2 && coder_type == VOICED ) || + ( codec_mode == MODE1 && ( Opt_AMR_WB || (coder_type != GENERIC && coder_type != TRANSITION ) ) ) ) + { + enern = frame_energy( L_frame, pitch, synth, *lp_speech, &frame_ener ); + } + + *lp_speech = 0.99f * *lp_speech + 0.01f * frame_ener; + } + + if( codec_mode == MODE1 ) + { + /*---------------------------------------------------------------------------------* + * Overwrite classification decision to UNVOICED_CLAS in case of INACTIVE frame + *---------------------------------------------------------------------------------*/ + + if( coder_type == INACTIVE && *clas != INACTIVE_CLAS ) + { + *clas = UNVOICED_CLAS; + } + + /*---------------------------------------------------------------------------------* + * Classification refinement to improve noise coding (only in AMR-WB IO mode) + *---------------------------------------------------------------------------------*/ + + if( Opt_AMR_WB ) + { + *locattack = 0; + + + if( *clas == UNVOICED_CLAS + && coder_type != INACTIVE + ) + { + /* unvoiced signal but not silence */ + if( *lp_speech <= 40 ) + { + *UV_cnt = 16; + } + else + { + *UV_cnt -= 8; + } + } + else if ( + coder_type != INACTIVE + ) + { + /* neither unvoiced nor clean silence */ + (*UV_cnt)++; + } + + if( *UV_cnt > 300 ) + { + *UV_cnt = 300; + } + else if( *UV_cnt < 0 ) + { + *UV_cnt = 0; + } + + /* Update long-term average number of frames between UNVOICED */ + if( coder_type == INACTIVE ) + { + /* tends to speech if no activity */ + *LT_UV_cnt = 0.95f * *LT_UV_cnt; + + if ( *UV_cnt > 125 ) + { + *UV_cnt = 125; + } + } + else + { + *LT_UV_cnt = 0.9f * *LT_UV_cnt + 0.1f * *UV_cnt; + } + + /*-----------------------------------------------------------------------------* + * 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 = ener - *Last_ener; + *Last_ener = ener; + *amr_io_class = *clas; + + if( *LT_UV_cnt > LT_UV_THR && diff_ener < 12.0f ) + { + *amr_io_class = AUDIO_CLAS; + } + + if( (diff_ener > 6.0f && *clas == AUDIO_CLAS) || (diff_ener > 9.0f) ) + { + *locattack = 1; + } + + /*------------------------------------------------------------------------* + * Compute statistical deviation of long-term energy variation and + * overwrite classification, if needed + *------------------------------------------------------------------------*/ + + if( coder_type != INACTIVE ) + { + /* calculate mean energy variation of past MAX_LT frames */ + mean_diff = 0.0f; + for (i = 1; i 5.0f ) + { + *amr_io_class = *clas; + *UV_cnt = (short)(80 + *UV_cnt*0.2f); + } + } + } + } + } + + /* update the memory of synthesis for frame class estimation */ + mvr2r( old_synth + L_frame, mem_syn_clas_estim, L_SYN_MEM_CLAS_ESTIM ); + + return; +} + + +/*------------------------------------------------------------------------* + * FEC_dec_class() + * + * Decode class and energy information + *------------------------------------------------------------------------*/ + +static short FEC_dec_class( + Decoder_State *st, /* i/o: decoder state structure */ + const long bitrate, /* i : core bitrate */ + const short coder_type, /* i : coder type */ + float *enr_q, /* i : decoded energy */ + const short last_good /* i : Last good FEC classification */ +) +{ + short clas, tmpS; + + clas = ONSET; + + if( coder_type != VOICED ) + { + /* decode the class */ + tmpS = (short)get_next_indice( st, FEC_BITS_CLS ); + + if( tmpS == 0 ) + { + clas = UNVOICED_CLAS; + } + else if( tmpS == 1 ) + { + if( last_good >= VOICED_TRANSITION ) + { + clas = VOICED_TRANSITION; + } + else + { + clas = UNVOICED_TRANSITION; + } + } + else if( tmpS == 2 ) + { + clas = VOICED_CLAS; + } + } + else + { + clas = VOICED_CLAS; + } + + /* decode the energy */ + if( bitrate > ACELP_13k20 && coder_type != TRANSITION && coder_type < AUDIO ) + { + tmpS = (short)get_next_indice( st, FEC_BITS_ENR ); + + /* convert from logarithmic to linear domain (the range is 0 : 1.55 : 96 dB) */ + *enr_q = (float)pow( 10.0f, ( (float)tmpS * FEC_ENR_STEP ) / 10.0f ); + } + + return clas; +} + + +/*------------------------------------------------------------------------* + * FEC_classificationMusic() + * + * + *------------------------------------------------------------------------*/ + +static void FEC_classificationMusic( + const short coder_type, /* i : coder type */ + short *decision_hyst, /* i/o: hysteresis of the music/speech decision */ + short *clas /* i/o: frame classification */ +) +{ + if( coder_type == AUDIO ) + { + (*decision_hyst) += 4; + } + else + { + (*decision_hyst)--; + } + + if( coder_type == INACTIVE ) + { + *decision_hyst -= 10; + } + + if( *decision_hyst > 200 ) + { + *decision_hyst = 200; + } + else if( *decision_hyst < 0 ) + { + *decision_hyst = 0; + } + + if( *decision_hyst > 16 && *clas < VOICED_CLAS && coder_type == AUDIO ) + { + *clas = VOICED_CLAS; + } + + return; +} + + +/*------------------------------------------------------------------------* + * FEC_pos_dec() + * + * Decode class, energy and last glottal pulse position at higher bitrates + * ( last glottal pulse position is encoded only in GENERIC frames ) + *------------------------------------------------------------------------*/ + +short FEC_pos_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const short coder_type, /* i : coder type */ + const short last_good, /* i : last good classification */ + short *last_pulse_pos, /* o : last glotal pulse position in the lost ACB */ + short *clas, /* o : decoded classification */ + float *enr_q, /* o : decoded energy */ + const long core_brate /* i : decoded bitrate */ +) +{ + short pitch_index, T0, T0_frac, T0_min, T0_max; + short bit_pos_pitch_index, nBits; + + T0 = 0; + if( coder_type > UNVOICED ) + { + /* decode the clas and energy information */ + if( coder_type < AUDIO ) + { + *clas = FEC_dec_class( st, core_brate, coder_type, enr_q, last_good ); + + if( coder_type == GENERIC && *clas == VOICED_CLAS && ( last_good <= UNVOICED_CLAS || last_good == INACTIVE_CLAS) ) + { + *clas = SIN_ONSET; + } + } + + if( coder_type == GENERIC && core_brate > ACELP_24k40 ) + { + nBits = 0; + if( coder_type != AUDIO ) + { + /* find the number of bits */ + nBits = ACB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ(core_brate, coder_type, 0, 0)]; + } + + bit_pos_pitch_index = 71; /* 64 kbps WB,SWB and FB*/ + + if( core_brate <= ACELP_32k ) + { + bit_pos_pitch_index = 72; /* 32 kbp, WB*/ + if (st->bwidth > WB) + { + bit_pos_pitch_index = 73; /* 32 kbp, SWB, FB*/ + } + } + /* retrieve the pitch index */ + pitch_index = (short)get_indice( st, bit_pos_pitch_index, nBits ); + + /* decode pitch period */ + T0_min = PIT_MIN; + T0_max = PIT_MAX; + pit16k_Q_dec( pitch_index, 10, 1, &T0, &T0_frac, &T0_min, &T0_max, &st->BER_detect ); + + /* decode last pulse position */ + *last_pulse_pos = (short)get_next_indice( st, FEC_BITS_POS ); + + /* respect the sign */ + if (*last_pulse_pos >= 128) + { + *last_pulse_pos = -(*last_pulse_pos & 0x7F); + } + + if ( T0 >= 128 ) + { + *last_pulse_pos *= 2; + } + + if( st->BER_detect ) + { + *last_pulse_pos = 0; + } + } + } + + return T0; +} diff --git a/lib_dec/FEC_lsf_estim.c b/lib_dec/FEC_lsf_estim.c new file mode 100644 index 000000000..8d9f07149 --- /dev/null +++ b/lib_dec/FEC_lsf_estim.c @@ -0,0 +1,57 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * FEC_lsf_estim() + * + * - LSP calculation + * - A(z) calculation + *-------------------------------------------------------------------*/ + +void FEC_lsf2lsp_interp( + Decoder_State *st, /* i/o: Decoder static memory */ + const short L_frame, /* i : length of the frame */ + float *Aq, /* o : calculated A(z) for 4 subframes */ + float *lsf, /* o : estimated LSF vector */ + float *lsp /* o : estimated LSP vector */ +) +{ + /* convert LSFs to LSPs */ + if ( st->Opt_AMR_WB ) + { + isf2isp( lsf, lsp, M, INT_FS_12k8 ); + } + else + { + if( L_frame == L_FRAME ) + { + lsf2lsp( lsf, lsp, M, INT_FS_12k8 ); + } + else /* L_frame == L_FRAME16k */ + { + lsf2lsp( lsf, lsp, M, INT_FS_16k ); + } + } + + /*----------------------------------------------------------------------* + * Interpolate LSP vector and find A(z) + *----------------------------------------------------------------------*/ + + if ( st->Opt_AMR_WB ) + { + int_lsp( L_frame, st->lsp_old, lsp, Aq, M, interpol_isp_amr_wb, 1 ); + } + else + { + int_lsp( L_frame, st->lsp_old, lsp, Aq, M, interpol_frac_12k8, 0 ); + } + + return; +} diff --git a/lib_dec/FEC_pitch_estim.c b/lib_dec/FEC_pitch_estim.c new file mode 100644 index 000000000..e0f949aa0 --- /dev/null +++ b/lib_dec/FEC_pitch_estim.c @@ -0,0 +1,57 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + + +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" + + +/*------------------------------------------------------------------------* + * FEC_pitch_estim() + * + * Estimation of pitch for FEC + *------------------------------------------------------------------------*/ + +void FEC_pitch_estim( + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short last_core, /* i : last core */ + const short L_frame, /* i : length of the frame */ + const short clas, /* i : current frame classification */ + const short last_good, /* i : last good clas information */ + const float pitch_buf[], /* i : Floating pitch for each subframe */ + const float old_pitch_buf[], /* i : buffer of old subframe pitch values */ + float *bfi_pitch, /* i/o: update of the estimated pitch for FEC */ + short *bfi_pitch_frame, /* o : frame length when pitch was updated */ + short *upd_cnt, /* i/o: update counter */ + const short coder_type /* i : coder_type */ +) +{ + if( last_core == HQ_CORE ) + { + *bfi_pitch = pitch_buf[(L_frame/L_SUBFR)-1]; + *bfi_pitch_frame = L_frame; + *upd_cnt = MAX_UPD_CNT; + } + + if( (clas == VOICED_CLAS && last_good >= VOICED_TRANSITION) || (Opt_AMR_WB && clas == VOICED_CLAS) ) + { + /* update pitch for FEC if pitch is coherent */ + if( ( (pitch_buf[3] < 1.4f * pitch_buf[1]) && (pitch_buf[3] > 0.7f * pitch_buf[1]) && + (pitch_buf[1] < 1.4f * old_pitch_buf[2*NB_SUBFR-1]) && (pitch_buf[1] > 0.7f * old_pitch_buf[2*NB_SUBFR-1]) && + (L_frame == L_FRAME) ) || + ( (pitch_buf[3] < 1.4f * pitch_buf[1]) && (pitch_buf[3] > 0.7f * pitch_buf[1]) && + (pitch_buf[1] < 1.4f * old_pitch_buf[2*NB_SUBFR16k-1]) && (pitch_buf[1] > 0.7f * old_pitch_buf[2*NB_SUBFR16k-1]) && + (L_frame == L_FRAME16k) ) || ( coder_type == TRANSITION ) ) + { + *bfi_pitch = pitch_buf[(L_frame/L_SUBFR)-1]; + *bfi_pitch_frame = L_frame; + *upd_cnt = 0; + } + } + + return; +} diff --git a/lib_dec/FEC_scale_syn.c b/lib_dec/FEC_scale_syn.c new file mode 100644 index 000000000..b88042b85 --- /dev/null +++ b/lib_dec/FEC_scale_syn.c @@ -0,0 +1,409 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" + +#define SCLSYN_LAMBDA 0.3f + +/*-------------------------------------------------------------------* + * FEC_scale_syn() + * + * Smooth speech energy evolution when recovering after erasure(s) + *-------------------------------------------------------------------*/ + +void FEC_scale_syn( + const short L_frame, /* i : length of the frame */ + short clas, /* i/o: frame classification */ + const short last_good, /* i: last good frame classification */ + float *synth, /* i/o: synthesized speech at Fs = 12k8 Hz */ + const float *pitch, /* i: pitch values for each subframe */ + float enr_old, /* i: energy at the end of previous frame */ + float enr_q, /* i: transmitted energy for current frame */ + const short coder_type, /* i: coder type */ + const short LSF_Q_prediction, /* i : LSF prediction mode */ + short *scaling_flag, /* i/o: flag to indicate energy control of syn */ + float *lp_ener_FEC_av, /* i/o: averaged voiced signal energy */ + float *lp_ener_FEC_max, /* i/o: averaged voiced signal energy */ + const short bfi, /* i: current frame BFI */ + const long total_brate, /* i: total bitrate */ + const short prev_bfi, /* i: previous frame BFI */ + const long last_core_brate, /* i: previous frame core bitrate */ + float *exc, /* i/o: excitation signal without enhancement */ + float *exc2, /* i/o: excitation signal with enhancement */ + const float Aq[], /* i: LP filter coefs */ + float *old_enr_LP, /* i/o: LP filter E of last good voiced frame */ + const float *mem_tmp, /* i: temp. initial synthesis filter states */ + float *mem_syn, /* o: initial synthesis filter states */ + int avoid_lpc_burst_on_recovery, /* i : if true the excitation energy is limited if LP has big gain */ + short force_scaling /* i: force scaling */ +) +{ + short i; + float enr1, enr2, gain1, gain2; + float scaling, ener_max, enr2_av, enr2_max; + float enr_LP; + float h1[L_FRAME/2], tilt, rr0, rr1, pitch_dist, mean_pitch; + short k; + + gain2 = 0.0f; + gain1 = 0.0f; + scaling = 1.0f; + enr_LP = 0.0f; + + /*-----------------------------------------------------------------* + * Find the synthesis filter impulse response on voiced + *-----------------------------------------------------------------*/ + + if( clas >= VOICED_TRANSITION && clas < INACTIVE_CLAS ) + { + if( L_frame == L_FRAME ) + { + enr_LP = enr_1_Az( Aq+(NB_SUBFR-1)*(M+1), L_SUBFR ); + } + else /* L_frame == L_FRAME16k */ + { + enr_LP = enr_1_Az( Aq+(NB_SUBFR16k-1)*(M+1), L_SUBFR ); + } + } + + /*-----------------------------------------------------------------* + * Define when to scale the synthesis + *-----------------------------------------------------------------*/ + + if( bfi ) + { + *scaling_flag = 1; /* Always check synthesis on bad frames */ + } + else if( prev_bfi ) + { + if( ( LSF_Q_prediction == AUTO_REGRESSIVE ) || ( LSF_Q_prediction == MOVING_AVERAGE ) ) + { + *scaling_flag = 2; /* Decoded LSFs affected */ + } + else if( coder_type != TRANSITION ) + { + *scaling_flag = 1; /* SN, but not TC mode - LSF still affected by the interpolation */ + } + else + { + *scaling_flag = 0; /* LSF still possibly affected due to interpolation */ + } + scaling = 1.5f; + } + else + { + if( (LSF_Q_prediction == AUTO_REGRESSIVE) && (*scaling_flag == 2) ) + { + *scaling_flag = 2; /* Continue with energy control till the end of AR prediction */ + } + else if( *scaling_flag > 0 ) + { + (*scaling_flag)--; /* If scaling flag was equal to 2, add one control frame to account for the LSF interpolation */ + } + scaling = 2.0f; + } + + /*-----------------------------------------------------------------* + * Find the energy/gain at the end of the frame + *-----------------------------------------------------------------*/ + + fer_energy( L_frame, clas, synth, pitch[(L_frame>>6)-1], &enr2, L_frame ); + + if( bfi || (total_brate == ACELP_7k20) || (total_brate == ACELP_8k00) ) + { + /* previous frame erased and no TC frame */ + if( *scaling_flag > 0 ) + { + enr2 += 0.01f; + + if( bfi ) /* In all bad frames, limit the gain to 1 */ + { + gain2 = (float)sqrt( enr_old / enr2 ); + if( gain2 > 1.0f ) + { + gain2 = 1.0f; + } + + /* find the energy/gain at the beginning of the frame */ + fer_energy( L_frame, clas, synth, pitch[0], &enr1, 0 ); + + enr1 += 0.1f; + gain1 = (float)sqrt( enr_old / enr1 ); + if( gain1 > 1.0f ) + { + gain1 = 1.0f; + } + } + else /* good frame */ + { + if( enr_q == 0 ) /* If E info (FEC protection bits) is not available in the bitstream */ + { + enr_q = enr2; + + set_f( h1, 0.0f, L_FRAME/2 ); + h1[0] = 1.0f; + syn_filt( Aq+(3*(M+1)), M, h1, h1, L_FRAME/2, h1+(M+1), 0 ); + rr0 = dotp( h1, h1, L_FRAME/2-1 ) + 0.001f; + rr1 = dotp( h1, h1+1, L_FRAME/2-1 ); + tilt = rr1 / rr0; + + pitch_dist = 0.0f; + mean_pitch = pitch[0]; + for( k=0; k<(NB_SUBFR - 1); k++ ) + { + pitch_dist += abs((short)(pitch[k+1]+0.5f)-(short)(pitch[k]+0.5f)); + mean_pitch += pitch[k+1]; + } + pitch_dist /= (float)(NB_SUBFR-1); + mean_pitch /= (float)(NB_SUBFR); + + if( ( tilt > 0.7f ) && /* HF resonnant filter */ + ( (pitch_dist > 8.0f) || (mean_pitch < PIT_MIN) ) && /* pitch unstable or very short */ + ( (prev_bfi) || ( (coder_type == GENERIC) && (LSF_Q_prediction == AUTO_REGRESSIVE) ) ) ) + { + if( enr_q > scaling * enr_old ) + { + enr_q = scaling * enr_old; + } + } + else + { + if( (clas <= VOICED_TRANSITION) || (clas >= INACTIVE_CLAS) ) + { + ener_max = *lp_ener_FEC_av; + } + else + { + ener_max = *lp_ener_FEC_max; + } + + if( enr_old > ener_max ) + { + ener_max = enr_old; + } + if( enr_q > scaling * ener_max ) + { + enr_q = scaling * ener_max; + } + } + } + + gain2 = (float)sqrt( enr_q / enr2 ); + + + /*-----------------------------------------------------------------* + * Find the energy/gain at the beginning of the frame to ensure smooth transition after erasure(s) + *-----------------------------------------------------------------*/ + + if( ( (last_good >= VOICED_TRANSITION && last_good < INACTIVE_CLAS && (clas == UNVOICED_CLAS || clas == INACTIVE_CLAS)) || + last_core_brate == SID_1k75 || last_core_brate == SID_2k40 || last_core_brate == FRAME_NO_DATA ) && prev_bfi ) + { + /* voiced -> unvoiced signal transition */ + /* CNG -> active signal transition */ + gain1 = gain2; + } + else + { + /* find the energy at the beginning of the frame */ + fer_energy( L_frame, clas, synth, pitch[0], &enr1, 0 ); + + enr1 += 0.1f; + gain1 = (float)sqrt( enr_old / enr1 ); + if( gain1 > 1.2f ) + { + /* prevent clipping */ + gain1 = 1.2f; + } + + /* prevent amplifying the unvoiced or inactive part of the frame in case an offset is followed by an onset */ + if( clas == ONSET && gain1 > gain2 && prev_bfi ) + { + gain1 = gain2; + } + } + + enr2 = enr_q; /* 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 ); + for( i=0; i 0.7f ) && /* HF resonnant filter */ + ( (clas == UNVOICED_CLAS) || (clas == INACTIVE_CLAS) ) ) ) /* unvoiced classification */ + { + if( enr_q > scaling * enr_old ) + { + enr_q = scaling * enr_old; + } + } + else if( last_good >= VOICED_TRANSITION && last_good < INACTIVE_CLAS && clas >= VOICED_TRANSITION && clas < INACTIVE_CLAS ) + { + /* voiced -> voiced recovery */ + if( (*old_enr_LP != 0.0f) && (enr_LP > 2 * *old_enr_LP) ) + { + enr_q /= enr_LP; + enr_q *= 2* *old_enr_LP; + } + else if (avoid_lpc_burst_on_recovery && enr_LP > 20.0f) + { + enr_q *= sqrt(20.0f / enr_LP); + } + } + + if( (last_good >= VOICED_TRANSITION && last_good < INACTIVE_CLAS && clas >= VOICED_TRANSITION && clas < INACTIVE_CLAS ) + || force_scaling) + { + if( enr_q > enr_old ) + { + enr_q = (1 - SCLSYN_LAMBDA) * enr_old + SCLSYN_LAMBDA * enr_q; + } + } + } + + gain2 = (float)sqrt( enr_q / enr2 ); + + /* do not allow E increase if enr_q index == 0 (lower end Q clipping) */ + if( enr_q < 1.1f ) + { + if( gain2 > 1.0f ) + { + gain2 = 1.0f; + } + } + else + { + if( gain2 > 1.2f ) + { + gain2 = 1.2f; + } + } + + /*-----------------------------------------------------------------* + * Find the energy/gain at the beginning of the frame to ensure smooth transition after erasure(s) + *-----------------------------------------------------------------*/ + + if( clas == SIN_ONSET ) + { + /* allow only slow increase */ + gain1 = 0.5f * gain2; + } + else if( (last_good >= VOICED_TRANSITION && last_good < INACTIVE_CLAS && (clas == UNVOICED_CLAS || clas == INACTIVE_CLAS)) || + last_core_brate == SID_1k75 || last_core_brate == SID_2k40 || last_core_brate == FRAME_NO_DATA ) + { + /* voiced -> unvoiced signal transition */ + /* CNG -> active signal transition */ + gain1 = gain2; + } + else + { + /* find the energy at the beginning of the frame */ + fer_energy( L_frame, clas, synth, pitch[0], &enr1, 0 ); + + enr1 += 0.1f; + gain1 = (float)sqrt( enr_old / enr1 ); + if( gain1 > 1.2f ) + { + /* prevent clipping */ + gain1 = 1.2f; + } + if (avoid_lpc_burst_on_recovery && (enr_LP > 20.0f) && (enr_LP <= 2 * *old_enr_LP) && (gain1 > 1.0f)) + { + gain1 = 1.0f; + } + + /* prevent amplifying the unvoiced or inactive part of the frame in case an offset is followed by an onset */ + if( clas == ONSET && gain1 > gain2 ) + { + gain1 = gain2; + } + } + + /*-----------------------------------------------------------------* + * Smooth the energy evolution by exponentially evolving from gain1 to gain2 + *-----------------------------------------------------------------*/ + + gain2 *= ( 1.0f - AGC ); + for( i=0; i= VOICED_TRANSITION && clas < INACTIVE_CLAS) ) + { + if( clas == VOICED_TRANSITION ) + { + enr2_av = enr2; + fer_energy( L_frame, VOICED_CLAS, synth, pitch[(L_frame>>6)-1], &enr2_max, L_frame ); + } + else + { + enr2_max = enr2; + fer_energy( L_frame, UNVOICED_CLAS, synth, pitch[(L_frame>>6)-1], &enr2_av, L_frame ); + } + + *lp_ener_FEC_av = 0.05f * enr2_av + 0.95f * *lp_ener_FEC_av; + *lp_ener_FEC_max = 0.05f * enr2_max + 0.95f * *lp_ener_FEC_max; + } + + /*-----------------------------------------------------------------* + * Update the LP filter energy for voiced frames + *-----------------------------------------------------------------*/ + + if( clas >= VOICED_TRANSITION && clas < INACTIVE_CLAS ) + { + *old_enr_LP = enr_LP; + } + + + return; +} diff --git a/lib_dec/LD_music_post_filter.c b/lib_dec/LD_music_post_filter.c new file mode 100644 index 000000000..676f4683a --- /dev/null +++ b/lib_dec/LD_music_post_filter.c @@ -0,0 +1,702 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define MAX_SNR1 45.0f +#define INV_MAX_SNR (1.f / (MAX_SNR1-1.0f)) /* max. SNR considered for noise subtraction in voiced segments */ +#define MAX_SNR_SNR1 (MAX_SNR1 * INV_MAX_SNR) /* 45 * (1 / (MAX_SNR1-1)) */ + + +#define BIN_1KHZ (short)(1000.f/BIN_16kdct) +#define BIN_2KHZ (short)(2000.f/BIN_16kdct) +#define BIN_4KHZ (short)(4000.f/BIN_16kdct) + +#define MAX_GN_R 0.2f +#define ALPH 1.00f +#define BET (1.925f-ALPH) +#define MAXX 5 + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static void spectrum_mod_dct( float data[], const float lf_E[], float lf_EO[], + const float noiseE[], const float minGain, float lp_gbin[], + const short music_flag, short min_band, const float MAX_GN, const short max_band ); + +static void analy_sp_dct( const float dct_in[], float dct_buf[], float *fr_bands, float *lf_E, float *etot ); + +static void find_enr_dct( const float data[], float band[], float *ptE, float *Etot, const short min_band, + const short max_band, float *Bin_E, const float bin_freq ); + +/*------------------------------------------------------------------------* + * LD_music_post_filter() + * + * Music post-filter + *------------------------------------------------------------------------*/ + +void LD_music_post_filter +( + const float dtc_in[], /* i : input synthesis */ + float dtc_out[], /* o : output synthesis */ + const long core_brate, /* i : core bitrate */ + short *last_music_flag, /* i/o : Previous music detection ouptut */ + float *thresh, /* i/o : Detection thresold */ + short *nb_thr_1, /* i/o : Number of consecutives frames of level 1 */ + short *nb_thr_3, /* i/o : Number of consecutives frames of level 3 */ + float *lt_diff_etot, /* i/o : Long term total energy variation */ + float *mem_etot, /* i/o : Total energy memory */ + const float min_ns_gain, /* i : minimum gain for inter-harm noise red. */ + float bckr[], /* i/o : per band bckgnd. noise energy estimate */ + float lf_EO[], /* i/o : old per bin E for previous half frame */ + float lp_gbin[], /* i/o : smoothed suppression gain, per FFT bin */ + float *filt_lfE, /* i : post filter weighting coefficient */ + short *last_nonfull_music,/* i : Number of frames sinces la "speech like" frame */ + const short coder_type /* i : Coder type : -1 in case of IO */ + ,const short Last_coder_type /* i : last Coder type */ +) +{ + float DCT_buf[DCT_L_POST]; + float fr_bands[MBANDS_GN_LD]; + float lf_E[VOIC_BINS_HR]; + float etot, ftmp; + short i, j, k; + short min_band = 0; + float local_min_gain = min_ns_gain; + short music_flag2 = 0; + float max_val; + float max_ovf_2k, max_ovf_4k, max_ovf_6k; + float min_g_2k, min_g_4k, min_g_6k; + float m_ave, old_ftmp; + float old_ftmp_1; + float tmp_lfE[DCT_L_POST]; + float MAX_GN = MAX_GN_R; + short MAX_band = MBANDS_GN_LD; + + /*------------------------------------------------------------------------* + * Frequency analysis + *------------------------------------------------------------------------*/ + + analy_sp_dct( dtc_in, DCT_buf, fr_bands, lf_E, &etot ); + + /*------------------------------------------------------------------------* + * Find signal classification + *------------------------------------------------------------------------*/ + + music_flag2 = stab_est( etot, lt_diff_etot, mem_etot, + nb_thr_3, nb_thr_1, thresh, last_music_flag, 1 ); + + if ( core_brate < ACELP_6k60 || Last_coder_type != AUDIO ) + { + /* do not perform music improvement on SID frames */ + music_flag2 = 0; + } + + if( music_flag2 < 4 ) + { + *last_nonfull_music = 0; + } + else + { + (*last_nonfull_music)++; + } + + *last_nonfull_music = min( 51, *last_nonfull_music ); + + /*------------------------------------------------------------------------* + * Remapping of bands + * Section to "remap" the minimal band and the minimum gain for our needs + *------------------------------------------------------------------------*/ + + if( music_flag2 > 3) + { + min_band = 2; + local_min_gain = 0.25119f; + } + else if( music_flag2 == 3) + { + min_band = 3; + local_min_gain = 0.25119f; + } + else if( music_flag2 == 2) + { + min_band = 4; + local_min_gain = 0.35481f; + } + else if( music_flag2 == 1) + { + min_band = 4; + local_min_gain = 0.50119f; + } + + min_band += 4; + + MAX_GN = 0.1f; + if( core_brate > ACELP_9k60 ) + { + /* overshoot not allowed, since GSC already matches the energy */ + MAX_GN = 0.0f; + } + + if( coder_type == AUDIO ) + { + /* with GSC we know for sure that we are in music */ + min_band = 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; + for (i = 0; i < MBANDS_GN_LD; i++) + { + m_ave = 0.0f; + max_val = 0.0f; + + for( k=j; k < mfreq_bindiv_LD[i]+j; k++ ) + { + m_ave += lf_E[k]; + max_val = max(max_val, lf_E[k]); + } + + m_ave -= max_val; + m_ave /= mfreq_bindiv_LD[i] - 1; + + bckr[i] = m_ave*sc_qnoise[i]; + j += mfreq_bindiv_LD[i]; + } + + 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]; + + ftmp = lf_E[0]*m_ave+BET; + ftmp *= ftmp; + ftmp *= ftmp; + ftmp *= ftmp; + ftmp = min(ftmp, MAXX); + old_ftmp = ftmp; + + ftmp = lf_E[1]*m_ave+BET; + ftmp *= ftmp; + ftmp *= ftmp; + ftmp *= ftmp; + ftmp = min(ftmp, MAXX); + old_ftmp_1 = ftmp; + tmp_lfE[0] = 0.5f*old_ftmp + 0.5f*ftmp; + + for(i = 1; i < DCT_L_POST-1; i++) + { + tmp_lfE[i] = 0.333f*old_ftmp + 0.333f*old_ftmp_1; + old_ftmp = old_ftmp_1; + ftmp = lf_E[i+1]*m_ave+BET; + ftmp *= ftmp; + ftmp *= ftmp; + ftmp *= ftmp; + old_ftmp_1 = min(ftmp, MAXX); + tmp_lfE[i] += 0.333f * old_ftmp_1; + } + + ftmp = lf_E[i] * m_ave + BET; + ftmp *= ftmp; + ftmp *= ftmp; + ftmp *= ftmp; + ftmp = min(ftmp, MAXX); + tmp_lfE[i] = 0.5f * old_ftmp + 0.5f * ftmp; + + for(i = 0; i < BIN_4KHZ; i++) + { + filt_lfE[i] = tmp_lfE[i] * 0.05f + 0.95f * filt_lfE[i]; + } + + for(; i < DCT_L_POST; i++) + { + filt_lfE[i] = tmp_lfE[i] * 0.15f + 0.85f * 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( coder_type == AUDIO ) + { + MAX_band = 16; + } + + spectrum_mod_dct( DCT_buf, lf_E, lf_EO, bckr, local_min_gain, lp_gbin, music_flag2, min_band, MAX_GN, MAX_band ); + + i = 0; + if( music_flag2 >= 1 ) + { + for(i = 0; i < BIN_1KHZ; i++) + { + ftmp = min(1.0f, filt_lfE[i]); + DCT_buf[i] *= ftmp; + } + } + + if( *last_nonfull_music > 40 ) + { + max_ovf_2k = 1.25f; + max_ovf_4k = 1.5f; + max_ovf_6k = 1.5f; + + min_g_2k = 0.0f; + min_g_4k = 0.0f; + min_g_6k = 0.0f; + + if( coder_type == AUDIO ) + { + max_ovf_2k = 1.0f; + max_ovf_4k = 1.1f; + max_ovf_6k = 1.25f; + + min_g_2k = 0.75f; + min_g_4k = 0.5f; + min_g_6k = 0.5f; + + if( core_brate > ACELP_9k60 ) + { + max_ovf_4k = 1.0f; + max_ovf_6k = 1.15f; + + min_g_2k = 0.925f; + min_g_4k = 0.825f; + min_g_6k = 0.75f; + } + } + else if( core_brate >= ACELP_12k65 ) + { + max_ovf_2k = 1.0f; + max_ovf_4k = 1.25f; + + if( core_brate > ACELP_15k85 ) + { + max_ovf_4k = 1.0f; + max_ovf_6k = 1.25f; + + min_g_2k = 0.75f; + min_g_4k = 0.5f; + min_g_6k = 0.5f; + } + } + + for(; i < BIN_2KHZ; i++) + { + ftmp = min(max_ovf_2k, filt_lfE[i]); + ftmp = max(min_g_2k, ftmp); + DCT_buf[i] *= ftmp; + } + + for(; i < BIN_4KHZ; i++) + { + ftmp = min(max_ovf_4k, filt_lfE[i]); + ftmp = max(min_g_4k, ftmp); + DCT_buf[i] *= ftmp; + } + + if( coder_type != AUDIO || 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++) + { + ftmp = min(max_ovf_6k, filt_lfE[i]); + ftmp = max(min_g_6k, ftmp); + DCT_buf[i] *= ftmp; + } + } + } + else if( *last_nonfull_music > 25 ) + { + /* When unsure on content type only slight clean-up allowed, no overshoot allowed */ + for(; i < DCT_L_POST; i++) + { + ftmp = min(1.f, filt_lfE[i]); + DCT_buf[i] *= ftmp; + } + } + + /* reconstruction of the enhanced synthesis */ + mvr2r( DCT_buf, dtc_out, DCT_L_POST ); +} + +/*---------------------------------------------------------------------------* + * spectrum_mod_dct() + * + * spectrum enhancement according to the output of signal_type_clas() + *---------------------------------------------------------------------------*/ + +static void spectrum_mod_dct( + float data[], /* i/o: DCT spectrum */ + const float lf_E[], /* i: per bin E for first 46 bins (without DC) */ + float lf_EO[], /* i/o: old per bin E for previous half frame */ + const float noiseE[], /* i: per band background noise energy estimate */ + const float minGain, /* i: minimum suppression gain */ + float lp_gbin[], /* i/o: Smoothed suppression gain, per FFT bin */ + const short music_flag, /* i: music ? 1:0 */ + short min_band, + const float MAX_GN, + const short MAX_band +) +{ + float maxNoise; + float binE[VOIC_BINS_HR]; + float gain, minE; + float freq; + float slope; + float inv_noise[MBANDS_GN_LD]; + float *pt_gbin, alpha, tmpN; + short i, cnt; + float *pt; + float tmp, shift; + const float *pt2; + + gain = 0.0f; + + /*-----------------------------------------------------------------* + * Compute the inverse of noise + *-----------------------------------------------------------------*/ + + for (i=0; i<=MBANDS_GN_LD-1; i++) + { + inv_noise[i] = 1.0f / noiseE[i]; + } + + /*----------------------------------------------------------------------* + * Perform noise reduction for 1 frames + *----------------------------------------------------------------------*/ + + for (i=0; i < VOIC_BINS_HR; i++) + { + binE[i] = 0.3f * lf_EO[i] + 0.7f * lf_E[i]; + } + mvr2r(lf_E, lf_EO, VOIC_BINS_HR); /* update */ + + /*----------------------------------------------------------------------* + * Find the maximum noise in a critical band + *----------------------------------------------------------------------*/ + + maxNoise = 0.0f; + for (i=0; i<=MBANDS_GN_LD-1; i++) + { + set_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( maxNoise <= 10.0f) + { + minE = .5625f; + } + else + { + minE = minGain*minGain; + } + + pt2 = binE; + freq = 0; + + pt_gbin = lp_gbin; + tmp = INV_MAX_SNR; + slope = tmp - tmp * minE; + shift = MAX_SNR_SNR1 * minE - tmp; + for (i=0; i < min_band; i++) + { + for (; freq <= mfreq_loc_LD[i]; freq += BIN_16kdct) + { + pt2++; + pt++; + *pt_gbin++ = 1.0f; + } + } + + /*-----------------------------------------------------------------* + * Per Frequency MODE1_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/*MBANDS_GN_LD*/; i++) + { + + tmp = INV_MAX_SNR_tab[i]; + slope = tmp - tmp * minE; + shift = MAX_SNR_SNR1_tab[i] * minE - tmp; + + tmpN = slope * inv_noise[i]; + tmp = 0.0f; + cnt = 0; + while (freq <= mfreq_loc_LD[i]) + { + gain = 1.0f; + + if (noiseE[i] >= 0.5f) /* Do not alter if noise E very low */ + { + gain = tmpN **pt2 + shift; /* limits: [x,y] = {[1, minE], [MAX_SNR1, 1]}, */ + } + + pt2++; + + if (gain < minE) + { + gain = minE; + } + + if (gain > 1.0f+MAX_GN) + { + gain = 1.0f+MAX_GN; + } + + /* the gain smoothing control: stronger lp filtering for lower gains */ + alpha = 1.0f - (float)sqrt(gain); + + *pt_gbin = gain + alpha **pt_gbin; + *pt++ *= *pt_gbin; + cnt++; + freq += BIN_16kdct; + pt_gbin++; + } + } + } + else + { + freq = BIN_16kdct; + pt_gbin = lp_gbin; + for (i=0; i < MBANDS_GN_LD; i++) + { + for (; freq <= mfreq_loc_LD[i]; freq += BIN_16kdct) + { + *pt_gbin = 0.9f* *pt_gbin + 0.1f; + pt_gbin++; + } + } + } + + return; +} + +/*----------------------------------------------------------------------------------* + * analy_sp_dct() + * + * Spectral analysis of the current synthesized frame + *----------------------------------------------------------------------------------*/ + +static void analy_sp_dct( + const float dct_in[], /* i: input DCT spectrum */ + float dct_buf[], /* i: output DCT spectrum */ + float *fr_bands, /* o: energy in critical frequency bands */ + float *lf_E, /* o: per bin E for first... */ + float *etot /* o: total input energy */ +) +{ + float Bin_E[DCT_L_POST]; + + *etot = 0.0f; + mvr2r( dct_in, dct_buf, DCT_L_POST ); + + /*-----------------------------------------------------------------* + * Windowing + * Compute spectrum + * find energy per critical frequency band and total energy in dB + *-----------------------------------------------------------------*/ + + find_enr_dct( dct_buf, fr_bands, lf_E, etot, 0, MBANDS_GN_LD, Bin_E, BIN_16kdct ); + + /* find average log total energy over both half-frames */ + *etot = 10.0f * (float)log10(*etot) - 3.0103f; + + 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 + *------------------------------------------------------------------------*/ + +void find_enr_dct( + const float data[], /* i : fft result, for the format see fft_rel.c */ + float band[], /* o : per band energy */ + float *ptE, /* o : per bin energy for low frequencies */ + float *Etot, /* o : total energy */ + const short min_band, /* i : minimum critical band */ + const short max_band, /* i : maximum critical band */ + float *Bin_E, /* o : Per bin energy */ + const float bin_freq /* i : Number of frequency bins */ +) +{ + short i, cnt; + float freq, tmp; + const float *ptR; + + ptR = &data[0]; /* pointer to first real coefficient */ + freq = 0; + for( i=0; i < max_band; i++ ) + { + band[i] = 0.0f; + cnt = 0; + while( freq <= mfreq_loc_LD[i] ) + { + /* energy */ + *ptE = *ptR **ptR; + + /* normalization - corresponds to FFT normalization by 2/L_FFT */ + *ptE *= 1.0f / (DCT_L_POST); + + *Bin_E = *ptE; + Bin_E++; + band[i] += *ptE++; + ptR++; + + freq += bin_freq; + cnt++; + } + + /* normalization per frequency bin */ + band[i] /= cnt; + + if ( band[i] < E_MIN ) + { + band[i] = E_MIN; + } + } + + /*-----------------------------------------------------------------* + * Find the total energy over the input bandwidth + *-----------------------------------------------------------------*/ + + tmp = *Etot; + for( i = min_band; i <= NB_LIMIT_BAND; i++ ) + { + /* total channel energy */ + tmp += band[i]; + } + + *Etot = tmp; + + return; +} + +/*------------------------------------------------------------------------* + * Prep_music_postP() + * + * Performs the steps needed to do the music post processing + *------------------------------------------------------------------------*/ + +void Prep_music_postP( + float exc_buffer_in[], /* i/o: excitation buffer */ + float dct_buffer_out[], /* o : DCT output buffer */ + float filt_lfE[], /* i/o: long term spectrum energy */ + const short last_core, /* i : last core */ + const float *pitch_buf, /* i : current frame pitch information */ + float *LDm_enh_lp_gbin /* o : smoothed suppression gain, per bin FFT */ +) +{ + short i; + float *pt1; + const float *pt2; + short s_pit, fr_pit; + + s_pit = (short)(pitch_buf[3]); + fr_pit = (short)((pitch_buf[3] - s_pit) * 4.0f); + + /*------------------------------------------------------------* + * Extrapolation of the last future part and windowing + *------------------------------------------------------------*/ + + if( last_core == HQ_CORE ) + { + set_f( filt_lfE, 1.0f, DCT_L_POST ); + set_f( LDm_enh_lp_gbin, 1.0f, VOIC_BINS_HR ); + pt1 = exc_buffer_in + OFFSET2 - 1; + pt2 = pt1 + (short)(pitch_buf[0] + 0.5f); + for( i = 0; i < OFFSET2; i++ ) + { + *pt1 = *pt2; + pt1--; + pt2--; + } + } + + pt1 = exc_buffer_in + DCT_L_POST - OFFSET2; + pred_lt4( pt1, pt1, s_pit, fr_pit, OFFSET2, inter4_2, L_INTERPOL2, PIT_UP_SAMP ); + + pt2 = post_dct_wind; + for( i = 0; i < OFFSET2; i++ ) + { + *pt1 *= *pt2; + pt1++; + pt2++; + } + + pt1 = exc_buffer_in; + pt2--; + for( i = 0; i < OFFSET2; i++ ) + { + *pt1 *= *pt2; + pt1++; + pt2--; + } + + edct( exc_buffer_in, dct_buffer_out, DCT_L_POST ); + + return; +} + +/*------------------------------------------------------------------------* + * Post_music_postP() + * + * Going back from frequency to time domain from the enhanced spectrum + * to retreive the aligned excitation and redo the synthesis + *------------------------------------------------------------------------*/ + +void Post_music_postP( + float dct_buffer_in[], /* i/o: excitation buffer */ + float exc_buffer_out[], /* o : DCT output buffer */ + float *exc2, /* i/o: Current excitation to be overwriten */ + const float *mem_tmp, /* i : previous frame synthesis memory */ + float *st_mem_syn2, /* i/o: current frame synthesis memory */ + const float *Aq, /* i : LPC filter coefficients */ + float *syn /* i/o: 12k8 synthesis */ +) +{ + edct( dct_buffer_in, exc_buffer_out, DCT_L_POST ); + + mvr2r( exc_buffer_out + OFFSET2, exc2, L_FRAME ); + mvr2r( mem_tmp, st_mem_syn2, M ); + + syn_12k8( L_FRAME, Aq, exc2, syn, st_mem_syn2, 1 ); + + return; +} diff --git a/lib_dec/TonalComponentDetection.c b/lib_dec/TonalComponentDetection.c new file mode 100644 index 000000000..948213203 --- /dev/null +++ b/lib_dec/TonalComponentDetection.c @@ -0,0 +1,777 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#define _USE_MATH_DEFINES +#include "wmc_auto.h" + +#include +#include +#include +#include "options.h" +#include "prot.h" +#include "cnst.h" +#include "stat_com.h" + +#define WMC_TOOL_SKIP + + +/***********************************************************************************/ +/* forward declaration for local functions, see implementation at end of this file */ +/***********************************************************************************/ + +static void calcPseudoSpec(float const * mdctSpec, unsigned int nSamples, float floorPowerSpectrum, float * powerSpec); +static void getEnvelope(unsigned int nSamples, float const * powerSpec, float F0, float * envelope, float * smoothedSpectrum); +static void GetF0(unsigned int const nSamples, unsigned int const nSamplesCore, float const * const powerSpectrum, float const pitchLag, float * const pOrigF0, float * const pF0); +static void findStrongestHarmonics(unsigned int nSamples, float const * powerSpectrum, float F0, unsigned int nTotalHarmonics, unsigned int * pHarmonicIndexes, unsigned int * pnHarmonics); +static void CorrectF0(unsigned int const * pHarmonicIndexes, unsigned int nHarmonics, float * pF0); +static void findCandidates(unsigned int nSamples, const float * MDCTSpectrum, float * thresholdModificationNew, float floorPowerSpectrum /* i: lower limit for power spectrum bins */ ); +static void modifyThreshold(int i, float F0, float threshold, float * thresholdModification); +static void modifyThresholds(float F0, float origF0, float * thresholdModification); +static void RefineThresholdsUsingPitch(unsigned int nSamples, unsigned int nSamplesCore, float const * powerSpectrum, float lastPitchLag, float currentPitchLag, float * pF0, float * thresholdModification); +static void findTonalComponents(unsigned short int * indexOfTonalPeak, unsigned short int * lowerIndex, unsigned short int * upperIndex, unsigned int *numIndexes, unsigned int nSamples, const float * powerSpectrum, float F0, float const * 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(unsigned short int indexOfTonalPeak[], + unsigned short int lowerIndex[], + unsigned short int upperIndex[], + unsigned int * pNumIndexes, + float lastPitchLag, float currentPitchLag, + float const lastMDCTSpectrum[], + float const scaleFactors[], + float const secondLastPowerSpectrum[], + unsigned int nSamples + ,unsigned int nSamplesCore + ,float floorPowerSpectrum /* i: lower limit for power spectrum bins */ + ) +{ + float F0; + float thresholdModification[L_FRAME_MAX]; + float * const pScaledMdctSpectrum = thresholdModification; + + + /* Convert from 16 bit to 32 bit */ + mvr2r(lastMDCTSpectrum, pScaledMdctSpectrum, nSamples); + mdct_noiseShaping(pScaledMdctSpectrum, nSamplesCore, scaleFactors); + v_multc(pScaledMdctSpectrum + nSamplesCore, scaleFactors[FDNS_NPTS-1], pScaledMdctSpectrum + nSamplesCore, nSamples - nSamplesCore ); + + /* Find peak candidates in the last frame. */ + findCandidates(nSamples, pScaledMdctSpectrum, 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(unsigned short int indexOfTonalPeak[], + unsigned short int lowerIndex[], + unsigned short int upperIndex[], + float phaseDiff[], + float phases[], unsigned int * pNumIndexes, + float lastPitchLag, float currentPitchLag, + float const lastMDCTSpectrum[], + float const scaleFactors[], + float const secondLastPowerSpectrum[], + unsigned int nSamples + ,unsigned int nSamplesCore + ,float floorPowerSpectrum /* i: lower limit for power spectrum bins */ + ) +{ + unsigned short int newIndexOfTonalPeak[MAX_NUMBER_OF_IDX]; + unsigned short int newLowerIndex[MAX_NUMBER_OF_IDX]; + unsigned short int newUpperIndex[MAX_NUMBER_OF_IDX]; + unsigned int newNumIndexes, nPreservedPeaks; + unsigned int iNew, iOld, j; + float * pOldPhase, * pNewPhase; + + DetectTonalComponents(newIndexOfTonalPeak, + newLowerIndex, + newUpperIndex, + &newNumIndexes, + lastPitchLag, + currentPitchLag, + lastMDCTSpectrum, + scaleFactors, + secondLastPowerSpectrum, + nSamples, + nSamplesCore, + floorPowerSpectrum ); + + nPreservedPeaks = 0; + iNew = 0; + 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 */ + while ((iNew < newNumIndexes) && (indexOfTonalPeak[iOld] >= newUpperIndex[iNew])) + { + ++iNew; + } + if ((iNew < newNumIndexes) && (indexOfTonalPeak[iOld] > newLowerIndex[iNew])) + { + newIndexOfTonalPeak[nPreservedPeaks] = indexOfTonalPeak[iOld]; + newLowerIndex[nPreservedPeaks] = lowerIndex[iOld]; + newUpperIndex[nPreservedPeaks] = upperIndex[iOld]; + phaseDiff[nPreservedPeaks] = phaseDiff[iOld]; + for (j = lowerIndex[iOld]; j <= upperIndex[iOld]; j++) + { + *pNewPhase++ = *pOldPhase++; + } + ++nPreservedPeaks; + } + else + { + pOldPhase += upperIndex[iOld]-lowerIndex[iOld]+1; + } + } + for (iNew = 0; iNew < nPreservedPeaks; iNew++) + { + indexOfTonalPeak[iNew] = newIndexOfTonalPeak[iNew]; + lowerIndex[iNew] = newLowerIndex[iNew]; + upperIndex[iNew] = newUpperIndex[iNew]; + } + *pNumIndexes = nPreservedPeaks; + +} + +/***************************************************** +---------------- private functions ------------------- +******************************************************/ + +static void calcPseudoSpec(float const * mdctSpec, + unsigned int nSamples, + float floorPowerSpectrum, + float * powerSpec) +{ + unsigned int k; + float x; + + for (k = 1; k <= nSamples-2; k++) + { + x = (mdctSpec[k+1] - mdctSpec[k-1]); /* An MDST estimate */ + x = mdctSpec[k] * mdctSpec[k] + x * x; + powerSpec[k] = max(floorPowerSpectrum, x); + } + powerSpec[0] = 0.5f*powerSpec[1]; + powerSpec[nSamples-1] = 0.5f*powerSpec[nSamples-2]; + +} + +static void getEnvelope(unsigned int nSamples, + float const * powerSpec, + float F0, + float * envelope, + float * smoothedSpectrum) +{ + unsigned int nFilterLength, nHalfFilterLength, nSecondHalfFilterLength, n1, n2; + unsigned int i; + double sum; /* double is required to avoid precision problems in the optimized version. */ + + + if (F0 == 0) + { + nFilterLength = 15; + } + else if (F0 <= 10.0f) + { + nFilterLength = 11; + } + else if (F0 >= 22.0f) + { + /* 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; + } + else + { + nFilterLength = 1+2*(int)(F0/2); + } + nHalfFilterLength = nFilterLength/2; + n1 = nHalfFilterLength+1; + nSecondHalfFilterLength = nFilterLength-nHalfFilterLength; + n2 = nSecondHalfFilterLength-1; + + assert((nFilterLength >= 7) && (nFilterLength <= 23) && (nFilterLength %2 == 1)); + + sum = 0; + for (i = 0; i < n2; i++) + { + sum += LEVEL_ABOVE_ENVELOPE*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 += LEVEL_ABOVE_ENVELOPE*powerSpec[i+n2]; + /* 1/(i+nSecondHalfFilterLength) needs to be stored in a table for each filter length */ + envelope[i] = (float)sum / (i+nSecondHalfFilterLength); + } + sum /= nFilterLength; /* 1/nFilterLength is from a table */ + /* No need for PTR_INIT for powerSpec[i+n2] as we continue from the previous loop */ + for (i = n1; i < nSamples-n2; i++) + { + sum += LEVEL_ABOVE_ENVELOPE*(powerSpec[i+n2]-powerSpec[i-n1])/nFilterLength; /* LEVEL_ABOVE_ENVELOPE/nFilterLength is from a table */ + envelope[i] = (float)sum; + } + sum *= nFilterLength; + /* No need for PTR_INIT for powerSpec[i-n1] as we continue from the previous loop */ + for (i = nSamples-n2; i < nSamples; i++) + { + sum -= LEVEL_ABOVE_ENVELOPE*powerSpec[i-n1]; + /* 1/(nSamples-(i-nHalfFilterLength)) needs to be stored in a table for each filter length */ + envelope[i] = (float)sum / (nSamples-(i-nHalfFilterLength)); + } + for (i = 1; i < nSamples-1; i++) + { + smoothedSpectrum[i] = 0.75f*powerSpec[i-1]+powerSpec[i]+0.75f*powerSpec[i+1]; + } + smoothedSpectrum[0] = powerSpec[0]+0.75f*powerSpec[1]; + smoothedSpectrum[nSamples-1] = 0.75f*powerSpec[nSamples-2]+powerSpec[nSamples-1]; + + +} + +static void GetF0(unsigned int const nSamples, /*i*/ + unsigned int const nSamplesCore, /*i*/ + float const * const powerSpectrum, /*i*/ + float const pitchLag, /*i*/ + float * const pOrigF0, /*i/o*/ + float * const pF0) /*i/o*/ +{ + float halfPitchLag; + unsigned int rgiStrongHarmonics[MAX_PEAKS_FROM_PITCH]; + unsigned int nTotalHarmonics, nStrongHarmonics; + + + assert(LAST_HARMONIC_POS_TO_CHECK <= nSamplesCore); + + /* Use only F0 >= 100 Hz */ + if ((pitchLag > 0) && (pitchLag <= 0.5f*nSamplesCore)) + { + halfPitchLag = 0.5f*pitchLag; + *pF0 = nSamplesCore/halfPitchLag; + *pOrigF0 = *pF0; + if (nSamples < 2*LAST_HARMONIC_POS_TO_CHECK) + { + nTotalHarmonics = (unsigned int)(nSamples/(*pF0)); + } + else + { + nTotalHarmonics = (int)(2*LAST_HARMONIC_POS_TO_CHECK/(*pF0)); /* For correcting F0 we go 2 times the last harmonic position that will be used */ + } + + /* 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 + { + *pF0 = 0; + *pOrigF0 = 0; + } + +} + +/* This is very fast with almost ordered vectors. */ +static void sort(unsigned int *in, unsigned int n) +{ + int i; + unsigned int j, tempr; + + for (i = n-2; i >= 0; i--) + { + tempr = in[i]; + for (j = i+1; (j < n) && (tempr > in[j]); j++ ) + { + in[j-1] = in[j]; + /* (tempr > r[j]) */ + } + in[j-1] = tempr; + } + +} + +static void findStrongestHarmonics(unsigned int nSamples, float const * powerSpectrum, float F0, unsigned int nTotalHarmonics, unsigned int * pHarmonicIndexes, unsigned int * pnHarmonics) +{ + float peaks[MAX_PEAKS_FROM_PITCH], smallestPeak; + unsigned int nPeaksToCheck, nPeaks, iSmallestPeak; + unsigned int i, l, k; + (void)nSamples; + + nPeaks = 0; + iSmallestPeak = 0; + smallestPeak = FLT_MAX; + nPeaksToCheck = min(nTotalHarmonics, MAX_PEAKS_FROM_PITCH+1); + for (i = 1; i < nPeaksToCheck; i++) + { + float newPeak; + k = (int)(i*F0); + assert(k > 0 && k < 2*LAST_HARMONIC_POS_TO_CHECK && k < nSamples); + newPeak = powerSpectrum[k]; + peaks[nPeaks] = newPeak; + pHarmonicIndexes[nPeaks] = i; + if (newPeak <= smallestPeak) + { + iSmallestPeak = nPeaks; + smallestPeak = newPeak; + } + ++nPeaks; + } + for (; i < nTotalHarmonics; i++) + { + float newPeak; + k = (int)(i*F0); + assert(k > 0 && k < 2*LAST_HARMONIC_POS_TO_CHECK && k < nSamples); + newPeak = powerSpectrum[k]; + if (newPeak > smallestPeak) + { + peaks[iSmallestPeak] = newPeak; + pHarmonicIndexes[iSmallestPeak] = i; + smallestPeak = newPeak; + for (l = 0; l < MAX_PEAKS_FROM_PITCH; l++) + { + if (peaks[l] <= smallestPeak) + { + iSmallestPeak = l; + smallestPeak = peaks[l]; + } + } + } + } + sort(pHarmonicIndexes, nPeaks); + *pnHarmonics = nPeaks; + +} + +/* Use new F0, for which harmonics are most common in pHarmonicIndexes */ +static void CorrectF0(unsigned int const * pHarmonicIndexes, + unsigned int nHarmonics, + float * pF0) +{ + unsigned int i; + float F0; + unsigned int diff[MAX_PEAKS_FROM_PITCH-1], sortedDiff[MAX_PEAKS_FROM_PITCH-1]; + unsigned int iMostCommonDiff, nMostCommonDiff, nSameDiff, iMult; + + F0 = *pF0; + if (F0 > 0 && nHarmonics > 0) + { + for (i = 0; i < nHarmonics-1; i++) + { + diff[i] = pHarmonicIndexes[i+1]-pHarmonicIndexes[i]; + sortedDiff[i] = diff[i]; + } + sort(sortedDiff, nHarmonics-1); + iMostCommonDiff = sortedDiff[0]; + nSameDiff = 1; + i = 1; + if (sortedDiff[0]*pHarmonicIndexes[0] == 1) + { + /* Find how many distances between peaks have length 1 */ + for (; i < nHarmonics-1; i++) + { + if (sortedDiff[i] == 1) + { + ++nSameDiff; + } + } + } + nMostCommonDiff = nSameDiff; + + /* 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 (nSameDiff < 3) + { + + /* Find the most common difference */ + for (i = nSameDiff; i < nHarmonics-1; i++) + { + if (sortedDiff[i] == sortedDiff[i-1]) + { + ++nSameDiff; + } + else + { + if (nSameDiff > nMostCommonDiff) + { + nMostCommonDiff = nSameDiff; + iMostCommonDiff = sortedDiff[i-1]; + } + else + { + if ((nSameDiff == nMostCommonDiff) && (abs((int)iMostCommonDiff-(int)pHarmonicIndexes[0]) > abs((int)sortedDiff[i-1]-(int)pHarmonicIndexes[0]))) + { + nMostCommonDiff = nSameDiff; + iMostCommonDiff = sortedDiff[i-1]; + } + } + nSameDiff = 1; + } + } + if (nSameDiff > nMostCommonDiff) + { + nMostCommonDiff = nSameDiff; + iMostCommonDiff = sortedDiff[nHarmonics-2]; + } + } + + /* If there are enough peaks at the same distance */ + if (nMostCommonDiff >= MAX_PEAKS_FROM_PITCH/2) + { + iMult = 1; + for (i = 0; i < nHarmonics-1; i++) + { + if (diff[i] == iMostCommonDiff) + { + iMult = pHarmonicIndexes[i]; + break; + } + /* for rare cases of octave mismatch or missing harmonics */ + if ((i < nHarmonics-2) && (diff[i] == diff[i+1]) && (diff[i]+diff[i+1] == iMostCommonDiff)) + { + iMult = pHarmonicIndexes[i]; + break; + } + } + + /* If the real F0 is much higher than the original F0 from the pitch */ + if (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 = iMostCommonDiff*F0; + } + 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 if ((iMostCommonDiff > 1) || (nMostCommonDiff < 3)) + { + /* Not enough peaks at the same distance => don't use the pitch. */ + F0 = 0; + } + *pF0 = F0; + } + +} + +static void modifyThreshold(int i, + float F0, + float threshold, + float * thresholdModification) +{ + float harmonic, fractional, twoTimesFract; + int k; + + harmonic = i*F0; + k = (int)harmonic; + fractional = harmonic - k; /* Fractional part of the i*F0 */ + twoTimesFract = 2.0f*fractional; /* threshold if the centar of the peek is between k-1 and k, threshold+2 if the centar of the peek is between k and k+1 */ + thresholdModification[k] = threshold; + thresholdModification[k-1] = threshold + twoTimesFract; + thresholdModification[k+1] = threshold + 2.0f - twoTimesFract; + +} + +static void modifyThresholds(float F0, + float origF0, + float * thresholdModification) +{ + int i, nHarmonics; + + + + if ((F0 == 0) && (origF0 > 0)) + { + nHarmonics = min(MAX_PEAKS_FROM_PITCH, (int)(LAST_HARMONIC_POS_TO_CHECK/origF0)); + for (i = 1; i <= nHarmonics; i++) + { + modifyThreshold(i, origF0, 0.7f, thresholdModification); + } + } + else if ((F0 > 0) && (origF0 > 0)) + { + nHarmonics = min(MAX_PEAKS_FROM_PITCH, (int)(LAST_HARMONIC_POS_TO_CHECK/F0)); + + for (i = (int)(F0/origF0+0.5f); i > 0; i--) + { + modifyThreshold(i, origF0, 0.35f, thresholdModification); + } + for (i = 1; i <= nHarmonics; i++) + { + modifyThreshold(i, F0, 0.35f, thresholdModification); + } + } + +} + +static void findCandidates(unsigned int nSamples, + const float * MDCTSpectrum, + float * thresholdModificationNew + ,float floorPowerSpectrum /* i: lower limit for power spectrum bins */ + ) +{ + float powerSpectrum[L_FRAME_MAX]; + float envelope[L_FRAME_MAX]; + float smoothedSpectrum[L_FRAME_MAX]; + unsigned int upperIdx, lowerIdx; + unsigned int k, j; + + calcPseudoSpec(MDCTSpectrum, nSamples, floorPowerSpectrum, powerSpectrum); + getEnvelope(nSamples, powerSpectrum, 0, envelope, smoothedSpectrum); + + set_f( thresholdModificationNew, UNREACHABLE_THRESHOLD, nSamples); + for (k = GROUP_LENGTH/2 ; k <= nSamples - (GROUP_LENGTH-GROUP_LENGTH/2); k++) + { + if (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. */ + float biggerNeighbor; + biggerNeighbor = max(powerSpectrum[k-1], powerSpectrum[k+1]); + if (powerSpectrum[k] >= biggerNeighbor) + { + /* Find the right foot */ + for (upperIdx = k+1; upperIdx < nSamples-1; upperIdx++) + { + if (powerSpectrum[upperIdx] < powerSpectrum[upperIdx+1]) + { + /* Side lobes may increase for certain ammount */ + if (ALLOWED_SIDE_LOBE_FLUCTUATION*powerSpectrum[upperIdx] < powerSpectrum[upperIdx+1]) + { + break; + } + /* Check for further decrease after a side lobe increase */ + for (j = upperIdx+1; j < nSamples-1; j++) + { + if (powerSpectrum[j] < ALLOWED_SIDE_LOBE_FLUCTUATION*powerSpectrum[j+1]) + { + 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 (2.0f*powerSpectrum[upperIdx+1]*powerSpectrum[j] > powerSpectrum[upperIdx]*powerSpectrum[upperIdx]) + { + break; + } + upperIdx = j-1; /* Reinitialize pointers due to the change of upperIdx */ + } + } + /* left foot */ + for (lowerIdx = k-1; lowerIdx > 0; lowerIdx--) + { + if (powerSpectrum[lowerIdx] < powerSpectrum[lowerIdx-1]) + { + /* Side lobes may increase for certain ammount */ + if (ALLOWED_SIDE_LOBE_FLUCTUATION*powerSpectrum[lowerIdx] < powerSpectrum[lowerIdx-1]) + { + break; + } + /* Check for further decrease after a side lobe increase */ + for (j = lowerIdx-1; j > 0; j--) + { + if (powerSpectrum[j] < ALLOWED_SIDE_LOBE_FLUCTUATION*powerSpectrum[j-1]) + { + 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 (2.0f*powerSpectrum[lowerIdx-1]*powerSpectrum[j] > powerSpectrum[lowerIdx]*powerSpectrum[lowerIdx]) + { + break; + } + lowerIdx = j+1; /* Reinitialize pointers due to the change of lowerIdx */ + } + } + + /* Check if there is a bigger peak up to the next peak foot */ + for (j = max(GROUP_LENGTH/2, lowerIdx); j <= min(upperIdx, nSamples - (GROUP_LENGTH-GROUP_LENGTH/2)); j++) + { + if (powerSpectrum[j] > powerSpectrum[k]) + { + k = j; /* PTR_INIT for powerSpectrum[k] */ + } + } + + /* Modify thresholds for the following frame */ + for (j = k-1; j < k+2; j++) + { + if (smoothedSpectrum[j] > envelope[j]) + { + thresholdModificationNew[j] = SMALL_THRESHOLD; + } + else + { + thresholdModificationNew[j] = BIG_THRESHOLD; + } + } + /* Jump to the next foot of the peak. */ + k = upperIdx; /* Reinitialize pointers due to the change of k */ + } + } + } + +} + +static void RefineThresholdsUsingPitch(unsigned int nSamples, + unsigned int nSamplesCore, + float const * powerSpectrum, + float lastPitchLag, + float currentPitchLag, + float * pF0, + float * thresholdModification) +{ + int pitchIsStable; + float origF0; + + pitchIsStable = (fabs(lastPitchLag-currentPitchLag) < 0.25f); + if (pitchIsStable) + { + GetF0(nSamples, + nSamplesCore, + powerSpectrum, lastPitchLag, &origF0, pF0); + modifyThresholds(*pF0, origF0, thresholdModification); + } + else + { + *pF0 = 0; + } + +} + +static void findTonalComponents(unsigned short int * indexOfTonalPeak, /* OUT */ + unsigned short int * lowerIndex, /* OUT */ + unsigned short int * upperIndex, /* OUT */ + unsigned int * numIndexes, /* OUT */ + unsigned int nSamples, /* IN */ + const float * powerSpectrum, /* IN */ + float F0, /* IN */ + float const * thresholdModification) /* IN */ +{ + float envelope[L_FRAME_MAX]; + float smoothedSpectrum[L_FRAME_MAX]; + + unsigned int nrOfFIS; + unsigned int upperIdx, lowerIdx, lowerBound; + unsigned int k, j; + + getEnvelope(nSamples, powerSpectrum, F0, envelope, smoothedSpectrum); + nrOfFIS = 0; + lowerBound = 0; + for (k = GROUP_LENGTH/2 ; k <= nSamples - (GROUP_LENGTH-GROUP_LENGTH/2); k++) + { + if (smoothedSpectrum[k] > envelope[k]*thresholdModification[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. */ + float biggerNeighbor; + biggerNeighbor = max(powerSpectrum[k-1], powerSpectrum[k+1]); + if (powerSpectrum[k] >= biggerNeighbor) + { + /* Find the right foot */ + for (upperIdx = k+1; upperIdx < nSamples-1; upperIdx++) + { + if (powerSpectrum[upperIdx] < powerSpectrum[upperIdx+1]) + { + /* Side lobes may increase for certain ammount */ + if (ALLOWED_SIDE_LOBE_FLUCTUATION*powerSpectrum[upperIdx] < powerSpectrum[upperIdx+1]) + { + break; + } + /* Check for further decrease after a side lobe increase */ + for (j = upperIdx+1; j < nSamples-1; j++) + { + if (powerSpectrum[j] < ALLOWED_SIDE_LOBE_FLUCTUATION*powerSpectrum[j+1]) + { + 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 (2.0f*powerSpectrum[upperIdx+1]*powerSpectrum[j] > powerSpectrum[upperIdx]*powerSpectrum[upperIdx]) + { + break; + } + upperIdx = j-1; /* Reinitialize pointers due to the change of upperIdx */ + } + } + /* left foot */ + for (lowerIdx = k-1; lowerIdx > lowerBound; lowerIdx--) + { + if (powerSpectrum[lowerIdx] < powerSpectrum[lowerIdx-1]) + { + /* Side lobes may increase for certain ammount */ + if (ALLOWED_SIDE_LOBE_FLUCTUATION*powerSpectrum[lowerIdx] < powerSpectrum[lowerIdx-1]) + { + break; + } + /* Check for further decrease after a side lobe increase */ + for (j = lowerIdx-1; j > 0; j--) + { + if (powerSpectrum[j] < ALLOWED_SIDE_LOBE_FLUCTUATION*powerSpectrum[j-1]) + { + 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 (2.0f*powerSpectrum[lowerIdx-1]*powerSpectrum[j] > powerSpectrum[lowerIdx]*powerSpectrum[lowerIdx]) + { + break; + } + lowerIdx = j+1; /* Reinitialize pointers due to the change of lowerIdx */ + } + } + lowerBound = upperIdx; + + /* Check if there is a bigger peak up to the next peak foot */ + for (j = max(GROUP_LENGTH/2, lowerIdx); j <= min(upperIdx, nSamples - (GROUP_LENGTH-GROUP_LENGTH/2)); j++) + { + if (powerSpectrum[j] > powerSpectrum[k]) + { + k = j; /* PTR_INIT for powerSpectrum[k] */ + } + } + + assert((nrOfFIS == 0) || (indexOfTonalPeak[nrOfFIS-1] < k)); + lowerIndex[nrOfFIS] = k-GROUP_LENGTH/2; + upperIndex[nrOfFIS] = k+(GROUP_LENGTH-GROUP_LENGTH/2-1); + if ((nrOfFIS > 0) && (lowerIndex[nrOfFIS] <= upperIndex[nrOfFIS-1])) + { + int m = (k+indexOfTonalPeak[nrOfFIS-1])/2; + upperIndex[nrOfFIS-1] = m; + lowerIndex[nrOfFIS] = m+1; + } + indexOfTonalPeak[nrOfFIS++] = k; + if (nrOfFIS == MAX_NUMBER_OF_IDX) + { + break; + } + /* Jump to the next foot of the peak. */ + k = upperIdx; /* Reinitialize pointers due to the change of k */ + } + } + } + *numIndexes = nrOfFIS; + +} diff --git a/lib_dec/acelp_core_dec.c b/lib_dec/acelp_core_dec.c new file mode 100644 index 000000000..1ae9900bd --- /dev/null +++ b/lib_dec/acelp_core_dec.c @@ -0,0 +1,920 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * acelp_core_dec() + * + * ACELP core decoder + *-------------------------------------------------------------------*/ + +void acelp_core_dec( + Decoder_State *st, /* i/o: decoder state structure */ + float synth[], /* o : synthesis */ + float bwe_exc_extended[], /* i/o: bandwidth extended excitation */ + float *voice_factors, /* o : voicing factors */ + float old_syn_12k8_16k[], /* o : intermediate ACELP synthesis at 12.8kHz or 16kHz to be used by SWB BWE */ + short coder_type, /* i : coder type */ + short sharpFlag, /* i : formant sharpening flag */ + float pitch_buf[NB_SUBFR16k], /* o : floating pitch for each subframe*/ + short *unbits, /* o : number of unused bits */ + short *sid_bw /* o : 0-NB/WB, 1-SWB SID */ +) +{ + float old_exc[L_EXC_DEC], *exc; /* excitation signal buffer */ + float syn_tmp[L_FRAME16k+L_SUBFR], *syn; /* synthesis signal buffer */ + short output_frame; /* frame length at output sampling freq. */ + float lsf_new[M]; /* LSFs at the end of the frame */ + float lsp_new[M]; /* LSPs at the end of the frame */ + float lsp_mid[M]; /* LSPs in the middle of the frame */ + float Aq[NB_SUBFR16k*(M+1)]; /* A(q) quantized for the 4 subframes */ + float old_exc2[L_FRAME16k + L_EXC_MEM], *exc2; /* total excitation buffer */ + float mem_tmp[M]; /* temporary synthesis filter memory */ + float enr_q; /* E information for FER protection */ + float tmp_noise; /* Long term temporary noise energy */ + float Es_pred; /* predicted scaled innov. energy */ + float FEC_pitch; /* FEC pitch */ + float old_bwe_exc[((PIT16k_MAX + (L_FRAME16k+1) + L_SUBFR16k) * 2)]; /* excitation buffer */ + float *bwe_exc; /* Excitation for SWB TBE */ + short i, int_fs; + short tc_subfr; + short allow_cn_step; + float temp_buf[L_FRAME16k + L_SYN_MEM]; + short last_pulse_pos; + short T0_tmp; + short do_WI; + float dct_buffer[DCT_L_POST]; + float exc_buffer[DCT_L_POST]; + float dct_exc_tmp[L_FRAME16k]; + float bpf_error_signal[L_FRAME16k]; + short nb_bits; /* number of bits */ + int indice; /* parameter indices to write */ + float gain_buf[NB_SUBFR16k]; + float q_env[20]; + float exc3[L_FRAME16k]; + float syn1_tmp[L_FRAME16k+2], *syn1; + float *realBuffer[CLDFB_NO_COL_MAX], *imagBuffer[CLDFB_NO_COL_MAX]; + float realBufferTmp[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + float imagBufferTmp[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + short LSF_Q_prediction; /* o : LSF prediction mode */ + float tmpF; + + /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ + for( i=0; ioutput_Fs / 50); + + st->bpf_off = 0; + if( st->last_core == HQ_CORE ) + { + /* in case of HQ->ACELP switching, do not apply BPF */ + st->bpf_off = 1; + + /* in case of core switching, rest post-filter memories */ + st->pfstat.on = 0; + + /* reset the GSC pre echo energy threshold in case of switching */ + st->Last_frame_ener = (float)MAX_32; + } + + if( st->prev_bfi > 0 ) + { + /* reset the GSC pre echo energy threshold in case of FEC */ + st->Last_frame_ener = (float)MAX_32; + } + + st->clas_dec = st->last_good; + enr_q = 0.0f; + Es_pred = 0.0f; + tmp_noise = 0.0f; + + mvr2r(st->old_exc, old_exc, L_EXC_MEM_DEC ); + exc = old_exc + L_EXC_MEM_DEC; + mvr2r( st->old_exc2, old_exc2, L_EXC_MEM ); + exc2 = old_exc2 + L_EXC_MEM; + mvr2r( st->old_bwe_exc, old_bwe_exc, PIT16k_MAX * 2); + bwe_exc = old_bwe_exc + PIT16k_MAX * 2; + + last_pulse_pos = 0; + do_WI = 0; + st->GSC_noisy_speech = 0; + st->relax_prev_lsf_interp = 0; + set_zero( gain_buf, NB_SUBFR16k ); + + if( st->L_frame == L_FRAME ) + { + st->gamma = GAMMA1; + st->preemph_fac = PREEMPH_FAC; + int_fs = INT_FS_12k8; + } + else + { + st->gamma = GAMMA16k; + st->preemph_fac = PREEMPH_FAC_16k; + int_fs = INT_FS_16k; + } + + /* reset post-filter in case of switching */ + if( st->pfstat.on == 0 ) + { + st->pfstat.reset = 1; + } + + /*----------------------------------------------------------------* + * Updates in case of internal sampling rate switching + *----------------------------------------------------------------*/ + + if( st->last_L_frame != st->L_frame && st->last_core != HQ_CORE ) + { + if( st->pfstat.on != 0 ) + { + short mem_syn_r_size_old, mem_syn_r_size_new; + + mem_syn_r_size_old = (short)(1.25*st->last_L_frame/20.f); + mem_syn_r_size_new = (short)(1.25*st->L_frame/20.f); + 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 ); + } + + /* convert quantized LSP vector */ + st->rate_switching_reset = lsp_convert_poly( st->lsp_old, st->L_frame, 0 ); + + /* convert old quantized LSF vector */ + lsp2lsf( st->lsp_old, st->lsf_old, M, int_fs ); + + /* FEC - update adaptive LSF mean vector */ + mvr2r( st->lsf_old, st->lsfoldbfi1, M ); + mvr2r( st->lsf_old, st->lsfoldbfi0, M ); + mvr2r( st->lsf_old, st->lsf_adaptive_mean, M ); + + /* Reset LPC mem */ + if( st->sr_core == 16000 ) + { + mvr2r( GEWB2_Ave, st->mem_AR, M ); + } + else + { + mvr2r( GEWB_Ave, st->mem_AR, M ); + } + set_zero( st->mem_MA, M ); + + /* update synthesis filter memories */ + synth_mem_updt2( st->L_frame, st->last_L_frame, st->old_exc, st->mem_syn_r, st->mem_syn2, NULL, DEC ); + mvr2r( st->old_exc, old_exc, L_EXC_MEM_DEC ); + mvr2r( st->mem_syn2, st->mem_syn1, M ); + mvr2r( st->mem_syn2, st->mem_syn3, M ); + + } + + /* update buffer of old subframe pitch values */ + if( st->last_L_frame != st->L_frame ) + { + if( st->L_frame == L_FRAME ) + { + if( st->last_L_frame == L_FRAME32k ) + { + tmpF = (float)12800/(float)32000; + } + else if( st->last_L_frame == 512 ) + { + tmpF = (float)12800/(float)25600; + } + else /* st->last_L_frame == L_FRAME16k */ + { + tmpF = (float)12800/(float)16000; + } + + for( i=NB_SUBFR16k-NB_SUBFR; iold_pitch_buf[i-1] = tmpF * st->old_pitch_buf[i]; + } + + for( i=2*NB_SUBFR16k-NB_SUBFR; i<2*NB_SUBFR16k; i++ ) + { + st->old_pitch_buf[i-2] = tmpF * st->old_pitch_buf[i]; + } + } + else + { + + if( st->last_L_frame == L_FRAME32k ) + { + tmpF = (float)16000/(float)32000; + } + else if( st->last_L_frame == 512 ) + { + tmpF = (float)16000/(float)25600; + } + else /* st->last_L_frame == L_FRAME12k8 */ + { + tmpF = (float)16000/(float)12800; + } + + for( i=2*NB_SUBFR-1; i>=NB_SUBFR; i-- ) + { + st->old_pitch_buf[i+2] = tmpF * st->old_pitch_buf[i]; + } + st->old_pitch_buf[NB_SUBFR+1] = st->old_pitch_buf[NB_SUBFR+2]; + + for( i=NB_SUBFR-1; i>=0; i-- ) + { + st->old_pitch_buf[i+1] = tmpF * st->old_pitch_buf[i]; + } + st->old_pitch_buf[0] = st->old_pitch_buf[1]; + } + } + + if( st->bfi_pitch_frame != st->L_frame ) + { + if( st->L_frame == L_FRAME ) + { + if( st->bfi_pitch_frame == L_FRAME32k ) + { + tmpF = (float)12800/(float)32000; + } + else if( st->bfi_pitch_frame == 512 ) + { + tmpF = (float)12800/(float)25600; + } + else /* st->bfi_pitch_frame == L_FRAME16k */ + { + tmpF = (float)12800/(float)16000; + } + st->bfi_pitch *= tmpF; + st->bfi_pitch_frame = L_FRAME; + } + else + { + if( st->bfi_pitch_frame == L_FRAME32k ) + { + tmpF = (float)16000/(float)32000; + } + else if( st->bfi_pitch_frame == 512 ) + { + tmpF = (float)16000/(float)25600; + } + else /* st->bfi_pitch_frame == L_FRAME12k8 */ + { + tmpF = (float)16000/(float)12800; + } + st->bfi_pitch *= tmpF; + st->bfi_pitch_frame = L_FRAME16k; + } + } + + if( st->last_bwidth == NB && st->bwidth != NB && st->ini_frame != 0 ) + { + st->rate_switching_reset = 1; + } + + /*----------------------------------------------------------------------* + * GOOD frame + *----------------------------------------------------------------------*/ + + if( !st->bfi ) + { + + /*----------------------------------------------------------------* + * Decoding of TC subframe clasification + *----------------------------------------------------------------*/ + + tc_subfr = -1; + if( coder_type == TRANSITION ) + { + tc_subfr = tc_classif( st, st->L_frame ); + } + + /*----------------------------------------------------------------* + * Decoding of inactive CNG frames + *----------------------------------------------------------------*/ + + if ( st->core_brate == FRAME_NO_DATA || st->core_brate == SID_2k40 ) + { + /* decode CNG parameters */ + if( st->cng_type == LP_CNG ) + { + CNG_dec( st, st->L_frame, Aq, st->core_brate, lsp_new, lsf_new, &allow_cn_step, sid_bw, q_env ); + + /* comfort noise generation */ + CNG_exc( st->core_brate, st->L_frame, &st->Enew, &st->cng_seed, exc, exc2, &st->lp_ener, st->last_core_brate, + &st->first_CNG, &(st->cng_ener_seed), bwe_exc, allow_cn_step, &st->last_allow_cn_step, st->num_ho, + q_env, st->lp_env, st->old_env, st->exc_mem, st->exc_mem1, sid_bw, &st->cng_ener_seed1, exc3 ,st->Opt_AMR_WB ); + } + else + { + if( st->core_brate == SID_2k40 ) + { + FdCng_decodeSID( st ); + *sid_bw = 0; + } + + generate_comfort_noise_dec( NULL, NULL, st ); + + FdCng_exc( st->hFdCngDec->hFdCngCom, &st->CNG_mode, st->L_frame, st->lsp_old, st->first_CNG, st->lspCNG, Aq, lsp_new,lsf_new, exc, exc2, bwe_exc ); + + mvr2r( exc2, exc3, st->L_frame ); + } + + /* update past excitation signals for LD music post-filter */ + mvr2r( st->dct_post_old_exc + L_FRAME, st->dct_post_old_exc, DCT_L_POST-L_FRAME-OFFSET2 ); + mvr2r( exc2, st->dct_post_old_exc + (DCT_L_POST-L_FRAME-OFFSET2), L_FRAME ); + + /* synthesis at 12.8kHz sampling rate */ + syn_12k8( st->L_frame, Aq, exc2, syn, st->mem_syn2, 1 ); + syn_12k8( st->L_frame, Aq, exc3, syn1, st->mem_syn3, 1 ); + + /* reset the decoder */ + CNG_reset_dec( st, pitch_buf, voice_factors ); + + /* update st->mem_syn1 for ACELP core switching */ + mvr2r( st->mem_syn3, st->mem_syn1, M ); + + /* update old synthesis for classification */ + mvr2r( syn1 + st->L_frame - L_SYN_MEM_CLAS_ESTIM, st->mem_syn_clas_estim, 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]; + } + + /* save and delay synthesis to be used by SWB BWE */ + save_old_syn( st->L_frame, syn1, old_syn_12k8_16k, st->old_syn_12k8_16k, st->preemph_fac, &st->mem_deemph_old_syn ); + } + /*----------------------------------------------------------------* + * Decoding of all other frames + *----------------------------------------------------------------*/ + + else + { + /*-----------------------------------------------------------------* + * After CNG period, use the most up-to-date LSPs + *-----------------------------------------------------------------*/ + + if( st->last_core_brate == FRAME_NO_DATA || st->last_core_brate == SID_2k40 ) + { + mvr2r( st->lspCNG, st->lsp_old, M ); + + lsp2lsf( st->lspCNG, st->lsf_old, M, int_fs ); + } + + /*-----------------------------------------------------------------* + * Reset higher ACELP pre-quantizer in case of switching + *-----------------------------------------------------------------*/ + + if( !st->use_acelp_preq ) + { + st->mem_preemp_preQ = 0.0f; + st->last_nq_preQ = 0; + } + st->use_acelp_preq = 0; + + /*-----------------------------------------------------------------* + * LSF de-quantization and interpolation + *-----------------------------------------------------------------*/ + + lsf_dec( st, tc_subfr, st->L_frame, coder_type, st->bwidth, Aq, &LSF_Q_prediction, lsf_new, lsp_new, lsp_mid ); + + /*-----------------------------------------------------------------* + * FEC - first good frame after lost frame(s) (possibility to correct the ACB) + *-----------------------------------------------------------------*/ + + if( st->core_brate >= ACELP_11k60 ) + { + last_pulse_pos = 0; + + /* decode the last glottal pulse position */ + T0_tmp = FEC_pos_dec( st, coder_type, st->last_good, &last_pulse_pos, &st->clas_dec, &enr_q, st->core_brate ); + + if( st->last_core != HQ_CORE || (st->last_core == HQ_CORE && st->last_con_tcx) ) + { + if( st->clas_dec == SIN_ONSET && last_pulse_pos != 0 && st->prev_bfi == 1 ) + { + FEC_SinOnset( old_exc+L_EXC_MEM_DEC-L_EXC_MEM, last_pulse_pos, T0_tmp, enr_q, Aq, st->L_frame); + } + else if( (coder_type == GENERIC || coder_type == VOICED) && last_pulse_pos != 0 && st->old_bfi_cnt == 1 && output_frame == L_FRAME16k ) + { + do_WI = FEC_enhACB(st->L_frame, st->last_L_frame, old_exc+L_EXC_MEM_DEC-L_EXC_MEM, T0_tmp, last_pulse_pos, st->bfi_pitch ); + } + } + } + + /*------------------------------------------------------------* + * In case of first frame after an erasure and transition from voiced to unvoiced or inactive + * redo the LPC interpolation + *------------------------------------------------------------*/ + + if( st->stab_fac == 0 && st->old_bfi_cnt > 0 && st->clas_dec != VOICED_CLAS && st->clas_dec != ONSET && st->relax_prev_lsf_interp == 0 ) + { + int_lsp4( st->L_frame, st->lsp_old, lsp_mid, lsp_new, Aq, M, 2 ); + } + + /*---------------------------------------------------------------* + * Decoding of the scaled predicted innovation energy + *---------------------------------------------------------------*/ + + if( ( coder_type != UNVOICED && coder_type != AUDIO && coder_type != INACTIVE && !(st->core_brate <= ACELP_8k00 && coder_type != TRANSITION) ) + || (coder_type == INACTIVE && st->total_brate >= ACELP_32k) ) + { + nb_bits = Es_pred_bits_tbl[BIT_ALLOC_IDX(st->core_brate, coder_type, -1, -1)]; + indice = (short)get_next_indice( st, nb_bits ); + Es_pred_dec( &Es_pred, indice, nb_bits, 0 ); + } + + /*------------------------------------------------------------* + * Decode excitation according to coding type + *------------------------------------------------------------*/ + + if( st->nelp_mode_dec ) + { + /* SC-VBR - NELP frames */ + decod_nelp( st, coder_type, &tmp_noise, pitch_buf, exc, exc2, voice_factors, bwe_exc, st->bfi, gain_buf ); + } + else if( coder_type == UNVOICED ) + { + /* UNVOICED frames */ + decod_unvoiced( st, Aq, coder_type, &tmp_noise, pitch_buf, voice_factors, exc, exc2, bwe_exc, gain_buf ); + } + else if( st->ppp_mode_dec ) + { + /* SC-VBR - PPP frames */ + decod_ppp( st, Aq, pitch_buf, exc, exc2, voice_factors, bwe_exc, gain_buf, st->bfi ); + } + else if( coder_type == TRANSITION ) + { + decod_tran( st, st->L_frame, tc_subfr, Aq, coder_type, Es_pred, pitch_buf, voice_factors, exc, exc2, bwe_exc, unbits, sharpFlag, gain_buf ); + } + else if( coder_type == AUDIO || ( coder_type == INACTIVE && st->core_brate <= ACELP_24k40 ) ) + { + /* AUDIO and INACTIVE frames (coded by GSC technology) */ + decod_audio( st, dct_exc_tmp, Aq, coder_type, &tmp_noise, pitch_buf, voice_factors, exc, exc2, bwe_exc, lsf_new, gain_buf ); + } + else + { + /* GENERIC, VOICED and INACTIVE frames (coded by AVQ technology) */ + decod_gen_voic( st, st->L_frame, sharpFlag, Aq, coder_type, Es_pred, do_WI, pitch_buf, voice_factors, exc, exc2, bwe_exc, unbits, gain_buf ); + } + + /* synthesis for ACELP core switching and SWB BWE */ + syn_12k8( st->L_frame, Aq, exc, temp_buf, st->mem_syn1, 1 ); + + /* save and delay synthesis to be used by SWB BWE */ + save_old_syn( st->L_frame, temp_buf, old_syn_12k8_16k, st->old_syn_12k8_16k, st->preemph_fac, &st->mem_deemph_old_syn ); + + /*-----------------------------------------------------------------* + * Apply energy matching when switching to inactive frames + *-----------------------------------------------------------------*/ + + inact_switch_ematch( exc2, dct_exc_tmp, st->lt_ener_per_band, coder_type, st->L_frame, st->core_brate, st->bfi, st->last_core, st->last_codec_mode ); + + /*------------------------------------------------------------* + * Decode information and modify the excitation signal of stationary unvoiced frames + *------------------------------------------------------------*/ + + if( st->nelp_mode_dec != 1 ) + { + stat_noise_uv_dec( st, coder_type, lsp_new, lsp_mid, Aq, exc2 ); + } + + /*------------------------------------------------------------* + * 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 */ + mvr2r( st->dct_post_old_exc + L_FRAME, st->dct_post_old_exc, DCT_L_POST-L_FRAME-OFFSET2 ); + mvr2r( exc2, st->dct_post_old_exc + (DCT_L_POST-L_FRAME-OFFSET2), L_FRAME ); + mvr2r( st->dct_post_old_exc, exc_buffer, DCT_L_POST-OFFSET2 ); + + if( coder_type == AUDIO && !st->GSC_noisy_speech ) + { + /* Extrapolation of the last future part, windowing and high resolution DCT transform */ + Prep_music_postP( exc_buffer, dct_buffer, st->filt_lfE, st->last_core, pitch_buf, st->LDm_enh_lp_gbin ); + + /* LD music post-filter */ + LD_music_post_filter( dct_buffer, dct_buffer, st->core_brate, &st->LDm_last_music_flag, + st->LDm_thres, &st->LDm_nb_thr_1, &st->LDm_nb_thr_3, st->LDm_lt_diff_etot, + &st->LDm_mem_etot, st->LDm_enh_min_ns_gain, st->LDm_bckr_noise, st->LDm_enh_lf_EO, + st->LDm_enh_lp_gbin, st->filt_lfE, &st->last_nonfull_music, AUDIO, st->last_coder_type ); + + /* Inverse DCT transform, retrieval of the aligned excitation, re-synthesis */ + mvr2r( st->mem_syn2, mem_tmp, M ); + Post_music_postP( dct_buffer, exc_buffer, exc2, st->mem_syn2, st->mem_syn2, Aq, syn ); + } + else + { + /* Core synthesis at 12.8kHz or 16kHz */ + mvr2r( st->mem_syn2, mem_tmp, M ); + syn_12k8( st->L_frame, Aq, exc2, syn, st->mem_syn2, 1 ); + + for( i = 0; i < DCT_L_POST; i++ ) + { + st->filt_lfE[i] = 0.3f + 0.7f * st->filt_lfE[i]; + } + } + + /*------------------------------------------------------------* + * FEC - Estimate the classification information + *------------------------------------------------------------*/ + + FEC_clas_estim( syn, pitch_buf, st->L_frame, coder_type, st->codec_mode, st->mem_syn_clas_estim, &st->clas_dec, + &st->lp_ener_bfi, st->core_brate, st->Opt_AMR_WB, &st->decision_hyst, NULL, NULL, NULL, + NULL, NULL, NULL, temp_buf, 0, 0, 0, + 0, 0, 0, st->last_core_brate ); + + /*------------------------------------------------------------* + * FEC - Estimate pitch + *------------------------------------------------------------*/ + + FEC_pitch_estim( st->Opt_AMR_WB, st->last_core, st->L_frame, st->clas_dec, st->last_good, pitch_buf, st->old_pitch_buf, + &st->bfi_pitch, &st->bfi_pitch_frame, &st->upd_cnt, coder_type ); + + /*------------------------------------------------------------* + * 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( st->L_frame, st->clas_dec, st->last_good, syn, pitch_buf, st->enr_old, enr_q, coder_type, + LSF_Q_prediction, &st->scaling_flag, &st->lp_ener_FEC_av, &st->lp_ener_FEC_max, st->bfi, + st->total_brate, st->prev_bfi, st->last_core_brate, exc, exc2, Aq, &st->old_enr_LP, mem_tmp, st->mem_syn2, + st->last_con_tcx && (st->L_frameTCX_past != st->L_frame) && (st->last_core != 0), 0 ); + + /* estimate the pitch-synchronous speech energy per sample to be used when normal operation recovers */ + if( (st->total_brate == ACELP_7k20) || (st->total_brate == ACELP_8k00) ) + { + fer_energy( st->L_frame, st->clas_dec, syn, pitch_buf[((st->L_frame)>>6)-1], &st->enr_old, st->L_frame ); + } + } + + } /* End of GOOD FRAME */ + /*----------------------------------------------------------------* + * BAD frame + *----------------------------------------------------------------*/ + + else + { + /* SC-VBR */ + if( st->last_nelp_mode_dec == 1 ) + { + st->nelp_mode_dec = 1; + } + + /* long burst frame erasures */ + if( st->nbLostCmpt > 5 && st->clas_dec >= VOICED_CLAS && st->clas_dec < INACTIVE_CLAS ) + { + st->last_good = VOICED_TRANSITION; + } + + /* LSF estimation and A(z) calculation */ + lsf_dec_bfi( MODE1, lsf_new, st->lsf_old, st->lsf_adaptive_mean, NULL, st->mem_MA, st->mem_AR, + st->stab_fac, st->last_coder_type, st->L_frame, st->last_good, + st->nbLostCmpt, 0, NULL, NULL, NULL, st->Last_GSC_pit_band_idx, st->Opt_AMR_WB, st->bwidth ); + + FEC_lsf2lsp_interp( st, st->L_frame, Aq, lsf_new, lsp_new ); + + if( st->nelp_mode_dec == 1 ) + { + /* SC-VBR */ + decod_nelp( st, coder_type, &tmp_noise, pitch_buf, exc, exc2, voice_factors, bwe_exc, st->bfi, gain_buf ); + FEC_pitch = pitch_buf[3]; + } + else + { + /* calculation of excitation signal */ + FEC_exc_estim( st, st->L_frame, exc, exc2, dct_exc_tmp, pitch_buf, voice_factors, &FEC_pitch, bwe_exc, lsf_new, &tmp_noise ); + + tmp_noise = st->lp_gainc; + + /* SC-VBR */ + st->prev_gain_pit_dec = st->lp_gainp; + } + + /* synthesis for ACELP core switching and SWB BWE */ + syn_12k8( st->L_frame, Aq, exc, temp_buf, st->mem_syn1, 1 ); + + /* save and delay synthesis to be used by SWB BWE */ + save_old_syn( st->L_frame, temp_buf, old_syn_12k8_16k, st->old_syn_12k8_16k, st->preemph_fac, &st->mem_deemph_old_syn ); + + /* Apply energy matching when switching to inactive frames */ + inact_switch_ematch( exc2, dct_exc_tmp, st->lt_ener_per_band, coder_type, st->L_frame, st->core_brate, st->bfi, st->last_core, st->last_codec_mode ); + + /* update past excitation signals for LD music post-filter */ + mvr2r( st->dct_post_old_exc + L_FRAME, st->dct_post_old_exc, DCT_L_POST-L_FRAME-OFFSET2 ); + mvr2r( exc2, st->dct_post_old_exc + (DCT_L_POST-L_FRAME-OFFSET2), L_FRAME ); + + /* synthesis at 12k8 Hz sampling rate */ + if( (st->total_brate == ACELP_7k20) || (st->total_brate == ACELP_8k00) ) + { + mvr2r( st->mem_syn2, mem_tmp, M ); + } + syn_12k8( st->L_frame, Aq, exc2, syn, st->mem_syn2, 1 ); + + /* update buffer for classifier */ + mvr2r( exc2 + st->L_frame - L_EXC_MEM, st->old_exc2, L_EXC_MEM ); + mvr2r( syn + st->L_frame - L_EXC_MEM, st->old_syn2, L_EXC_MEM ); + mvr2r( syn + st->L_frame - L_SYN_MEM_CLAS_ESTIM, st->mem_syn_clas_estim, 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]; + } + /* Update circular buffer, keep last energy difference unchanged */ + for (i = 1; iLDm_lt_diff_etot[i-1] = st->LDm_lt_diff_etot[i]; + } + + /*------------------------------------------------------------* + * FEC - Smooth the speech energy evolution when recovering after a BAD frame + * (smoothing is performed in the excitation domain and signal is resynthesized after) + *------------------------------------------------------------*/ + + if( (st->total_brate == ACELP_7k20) || (st->total_brate == ACELP_8k00) ) + { + FEC_scale_syn( st->L_frame, st->clas_dec, st->last_good, syn, pitch_buf, st->enr_old, enr_q, coder_type, + LSF_Q_prediction, &st->scaling_flag, &st->lp_ener_FEC_av, &st->lp_ener_FEC_max, st->bfi, + st->total_brate, st->prev_bfi, st->last_core_brate, exc, exc2, Aq, &st->old_enr_LP, mem_tmp, st->mem_syn2, + st->last_con_tcx && (st->L_frameTCX_past != st->L_frame) && (st->last_core != 0), 0 ); + } + + /* estimate the pitch-synchronous speech energy per sample to be used when normal operation recovers */ + fer_energy( st->L_frame, st->last_good, syn, FEC_pitch, &st->enr_old, st->L_frame ); + + if( st->nelp_mode_dec !=1 ) + { + /* modify the excitation signal of stationary unvoiced frames */ + stat_noise_uv_mod( coder_type, 0, st->lsp_old, lsp_new, lsp_new, Aq, exc2, 1, &st->ge_sm, &st->uv_count, &st->act_count, + st->lspold_s, &st->noimix_seed, &st->min_alpha, &st->exc_pe, st->core_brate, st->bwidth ); + } + /* SC-VBR */ + st->FadeScale = st->FadeScale*0.75; + } + + + if( st->L_frame == L_FRAME ) + { + mvr2r( Aq+2*(M+1), st->cur_sub_Aq, (M+1) ); + } + else + { + mvr2r( Aq+3*(M+1), st->cur_sub_Aq, (M+1) ); + } + + /*--------------------------------------------------------* + * Apply NB postfilter in case of 8kHz output + *--------------------------------------------------------*/ + + if( st->last_bwidth == NB ) + { + if( st->bwidth == NB ) + { + st->pfstat.on = 1; + nb_post_filt( st->L_frame, L_SUBFR, &(st->pfstat), &st->psf_lp_noise, tmp_noise, syn, Aq, pitch_buf, coder_type, st->BER_detect, 0 ); + } + else + { + st->pfstat.on = 0; + nb_post_filt( st->L_frame, L_SUBFR, &(st->pfstat), &st->psf_lp_noise, tmp_noise, syn, Aq, pitch_buf, AUDIO, st->BER_detect, 0 ); + } + } + else + { + st->psf_lp_noise = st->lp_noise; + } + + /*------------------------------------------------------------------* + * Perform fixed deemphasis through 1/(1 - g*z^-1) + *-----------------------------------------------------------------*/ + + /* update old synthesis buffer - needed for ACELP internal sampling rate switching */ + mvr2r( syn + st->L_frame - L_SYN_MEM, st->mem_syn_r, L_SYN_MEM ); + deemph( syn, st->preemph_fac, st->L_frame, &(st->mem_deemph) ); + AGC_dec(syn, st->agc_mem2, st->L_frame); + + mvr2r( syn+st->L_frame/2, st->old_syn_Overl, st->L_frame/2 ); + mvr2r( syn+st->L_frame-M-1, st->syn, M+1 ); + + + /*------------------------------------------------------------------* + * Formant post-filter + *-----------------------------------------------------------------*/ + + if( st->last_bwidth>=WB && st->core_brate > ACELP_24k40 && st->core_brate <= ACELP_32k ) + { + mvr2r( syn, temp_buf + L_SYN_MEM, L_FRAME16k ); + + st->pfstat.on = 1; + formant_post_filt( &(st->pfstat), temp_buf + L_SYN_MEM, Aq, syn, L_FRAME16k, L_SUBFR, st->lp_noise, st->total_brate, 0 ); + } + else if( st->last_bwidth >= WB ) + { + if( st->pfstat.on ) + { + mvr2r( st->pfstat.mem_pf_in+L_SYN_MEM-M, temp_buf, M ); + mvr2r( syn, temp_buf+M, L_SUBFR ); + residu ( Aq, M, temp_buf+M,temp_buf+M+L_SUBFR, L_SUBFR ); + syn_filt ( Aq, M, temp_buf+M+L_SUBFR, temp_buf, L_SUBFR, st->pfstat.mem_stp+L_SYN_MEM-M, 0 ); + scale_st ( syn, temp_buf, &st->pfstat.gain_prec, L_SUBFR, -1 ); + mvr2r( temp_buf, syn, L_SUBFR/2 ); + blend_subfr2( temp_buf + L_SUBFR/2, syn + L_SUBFR/2, syn + L_SUBFR/2 ); + + } + st->pfstat.on = 0; + } + + /*----------------------------------------------------------------* + * Comfort noise addition + *----------------------------------------------------------------*/ + + if( st->flag_cna || (st->cng_type == FD_CNG && st->total_brate <= ACELP_32k) || (st->cng_type == LP_CNG && st->core_brate <= SID_2k40) ) + { + /*VAD only for non inactive frame*/ + st->VAD = st->VAD && (coder_type != INACTIVE); + + /*Noisy speech detector*/ + noisy_speech_detection( st->VAD, syn, st->hFdCngDec->hFdCngCom->frameSize, st->hFdCngDec->msNoiseEst, st->hFdCngDec->psize_shaping, + st->hFdCngDec->nFFTpart_shaping, &(st->hFdCngDec->lp_noise), &(st->hFdCngDec->lp_speech), &(st->hFdCngDec->hFdCngCom->flag_noisy_speech) ); + + st->hFdCngDec->hFdCngCom->likelihood_noisy_speech = 0.99f*st->hFdCngDec->hFdCngCom->likelihood_noisy_speech + 0.01f*(float)st->hFdCngDec->hFdCngCom->flag_noisy_speech; + st->lp_noise = st->hFdCngDec->lp_noise; + + /*Noise estimate*/ + ApplyFdCng( syn, realBuffer, imagBuffer, st->hFdCngDec, st->m_frame_type, st, 0, + ( coder_type == AUDIO && !st->GSC_noisy_speech ) ); + + /* CNA: Generate additional comfort noise to mask potential coding artefacts */ + if( st->flag_cna && coder_type != AUDIO ) + { + generate_masking_noise( syn, st->hFdCngDec->hFdCngCom, st->hFdCngDec->hFdCngCom->frameSize, 0 ); + } + else if( st->flag_cna && coder_type == AUDIO && st->last_core == ACELP_CORE && st->last_coder_type != AUDIO ) + { + v_multc( st->hFdCngDec->hFdCngCom->olapBufferSynth2+5*st->hFdCngDec->hFdCngCom->frameSize/4, (float)(st->hFdCngDec->hFdCngCom->fftlen/2), temp_buf, st->hFdCngDec->hFdCngCom->frameSize/2); + v_add( temp_buf, syn, syn, st->hFdCngDec->hFdCngCom->frameSize/2); + } + } + + if( st->flag_cna == 0 && st->L_frame == L_FRAME16k && st->last_flag_cna == 1 && ( (st->last_core == ACELP_CORE && st->last_coder_type != AUDIO) || st->last_core == AMR_WB_CORE) ) + { + v_multc( st->hFdCngDec->hFdCngCom->olapBufferSynth2+5*st->L_frame/4, 256.f, temp_buf, st->L_frame/2 ); + v_add( temp_buf, syn, syn, st->L_frame/2 ); + } + + if( st->flag_cna == 0 || coder_type == AUDIO ) + { + set_f( st->hFdCngDec->hFdCngCom->olapBufferSynth2, 0.f, st->hFdCngDec->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->cldfbAna->no_channels * st->cldfbAna->no_col) != st->L_frame ) + { + resampleCldfb( st->cldfbAna, st->L_frame*50 ); + resampleCldfb( st->cldfbBPF, st->L_frame*50 ); + + if( st->ini_frame > 0 ) + { + st->cldfbSyn->bandsToZero = st->cldfbSyn->no_channels - st->cldfbAna->no_channels; + } + } + + if( st->L_frame != st->last_L_frame && st->last_codec_mode != MODE2 ) + { + if( st->L_frame == L_FRAME ) + { + retro_interp5_4( st->pst_old_syn ); + } + else if( st->L_frame == L_FRAME16k ) + { + retro_interp4_5( syn, st->pst_old_syn ); + } + } + + /* bass post-filter */ + bass_psfilter( st->Opt_AMR_WB, syn, st->L_frame, pitch_buf, st->pst_old_syn, &st->pst_mem_deemp_err, &st->pst_lp_ener, st->bpf_off, st->stab_fac, + &st->stab_fac_smooth, st->mem_mean_pit, st->Track_on_hist, st->vibrato_hist, &st->psf_att, coder_type, bpf_error_signal ); + + /* analysis of the synthesis at internal sampling rate */ + cldfbAnalysis( syn, realBuffer, imagBuffer, -1, st->cldfbAna ); + + /* analysis and add the BPF error signal */ + addBassPostFilter( bpf_error_signal, st->bpf_off? 0:-1, realBuffer, imagBuffer, st->cldfbBPF ); + + /* set output mask for upsampling */ + if( st->bwidth == NB ) + { + /* set NB mask for upsampling */ + st->cldfbSyn->bandsToZero = st->cldfbSyn->no_channels - 10; + } + else if( st->cldfbSyn->bandsToZero != st->cldfbSyn->no_channels - st->cldfbAna->no_channels ) + { + /* in case of BW switching, re-init to default */ + st->cldfbSyn->bandsToZero = st->cldfbSyn->no_channels - st->cldfbAna->no_channels; + } + + /*WB/SWB-FD_CNG*/ + if( ( st->core_brate == FRAME_NO_DATA || st->core_brate == SID_2k40 ) && ( st->cng_type == FD_CNG ) && ( st->hFdCngDec->hFdCngCom->numCoreBands < st->cldfbSyn->no_channels ) ) + { + generate_comfort_noise_dec_hf( realBuffer,imagBuffer, st ); + + if( st->hFdCngDec->hFdCngCom->regularStopBand < st->cldfbSyn->no_channels ) + { + st->cldfbSyn->bandsToZero = st->cldfbSyn->no_channels - st->hFdCngDec->hFdCngCom->regularStopBand; + } + else + { + st->cldfbSyn->bandsToZero = 0; + } + } + + /* synthesis of the combined signal */ + cldfbSynthesis( realBuffer, imagBuffer, synth, -1, st->cldfbSyn ); + + /* save synthesis - needed in case of core switching */ + mvr2r( synth, st->previoussynth, output_frame ); + + /*-----------------------------------------------------------------* + * Bandwidth extension 6kHz-7kHz (only for 16kHz input signals) + *-----------------------------------------------------------------*/ + + if( (st->L_frame == L_FRAME && st->bwidth != NB && output_frame >= L_FRAME16k && + ( st->extl == -1 || st->extl == SWB_CNG || (st->extl == WB_BWE && st->extl_brate == 0 && coder_type != AUDIO) ) ) ) + { + hf_synth( st->core_brate, output_frame, Aq, exc2, syn, synth, &st->seed2, st->mem_hp400, + st->mem_syn_hf, st->mem_hf, st->delay_syn_hf, st->mem_hp_interp ); + } + else + { + hf_synth_reset( &st->seed2, st->mem_hf, st->mem_syn_hf, st->mem_hp400, st->mem_hp_interp, st->delay_syn_hf ); + } + + /*-----------------------------------------------------------------* + * Populate parameters for SWB TBE + *-----------------------------------------------------------------*/ + + if( ( !st->bfi && st->prev_bfi) || (st->last_vbr_hw_BWE_disable_dec == 1 && st->vbr_hw_BWE_disable_dec == 0) || ((st->extl == SWB_TBE || st->extl == WB_TBE || st->extl == FB_TBE)&& st->last_extl != SWB_TBE && st->last_extl != WB_TBE && st->last_extl != FB_TBE) ) + { + st->bwe_non_lin_prev_scale = 0.0f; + set_f( st->old_bwe_exc_extended, 0.0f, NL_BUFF_OFFSET ); + } + + if( !st->ppp_mode_dec ) + { + non_linearity( bwe_exc, bwe_exc_extended, st->old_bwe_exc_extended, L_FRAME32k, &st->bwe_non_lin_prev_scale, coder_type, voice_factors, st->L_frame ); + } + + if( st->core_brate == FRAME_NO_DATA || st->core_brate == SID_2k40 ) + { + st->bwe_non_lin_prev_scale = 0.0f; + } + + /*----------------------------------------------------------------------* + * Updates + *----------------------------------------------------------------------*/ + + updt_dec( st, st->L_frame, coder_type, old_exc, pitch_buf, Es_pred, Aq, lsf_new, lsp_new, voice_factors, old_bwe_exc, gain_buf ); + + if( st->core_brate > SID_2k40 ) + { + /* update CNG parameters in active frames */ + cng_params_upd( lsp_new, exc, st->L_frame, &st->ho_circ_ptr, st->ho_ener_circ, + &st->ho_circ_size, st->ho_lsp_circ, DEC, st->ho_env_circ, NULL, + NULL, NULL, st->last_active_brate ); + + /* Set 16k LSP flag for CNG buffer */ + st->ho_16k_lsp[st->ho_circ_ptr] = (st->L_frame == L_FRAME ? 0 : 1 ); + } + + return; +} diff --git a/lib_dec/acelp_core_switch_dec.c b/lib_dec/acelp_core_switch_dec.c new file mode 100644 index 000000000..59330ac37 --- /dev/null +++ b/lib_dec/acelp_core_switch_dec.c @@ -0,0 +1,561 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ + +static void decod_gen_voic_core_switch( Decoder_State *st, const short L_frame, const short sharpFlag, const float *Aq, + const short coder_type, float *exc, const long core_brate ); + +/*-------------------------------------------------------------------* + * acelp_core_switch_dec() + * + * ACELP core decoder in the first ACELP->HQ switching frame + *-------------------------------------------------------------------*/ + +void acelp_core_switch_dec( + Decoder_State *st, /* i/o: decoder state structure */ + float *synth_subfr_out, /* o : synthesized ACELP subframe */ + float *tmp_synth_bwe, /* o : synthesized ACELP subframe BWE */ + const short output_frame, /* i : input frame legth */ + const short core_switching_flag,/* i : core switching flag */ + float *mem_synth /* o : synthesis to overlap */ +) +{ + short i, delta, L_frame_for_cs, decode_bwe; + short d1m, ind1, fdelay, gapsize; + long cbrate; + float synth_intFreq[2*L_SUBFR]; + float old_exc[L_EXC_DEC], *exc; + float tmp_mem2[2*L_FILT48k], gain; + float hb_synth_tmp[NS2SA(48000, 10000000L)]; + const float *hp_filter; + float Aq[2*(M+1)]; + float bpf_error_signal[2*L_SUBFR]; + float *realBuffer[CLDFB_NO_COL_MAX_SWITCH], *imagBuffer[CLDFB_NO_COL_MAX_SWITCH]; + float realBufferTmp[CLDFB_NO_COL_MAX_SWITCH][CLDFB_NO_CHANNELS_MAX], imagBufferTmp[CLDFB_NO_COL_MAX_SWITCH][CLDFB_NO_CHANNELS_MAX]; + + /*----------------------------------------------------------------* + * Initializations + *----------------------------------------------------------------*/ + + /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ + for( i=0; iold_Aq_12_8, Aq, M+1 ); + mvr2r( st->old_Aq_12_8, Aq + (M+1), M+1 ); + + set_f(mem_synth, 0, NS2SA(16000, DELAY_CLDFB_NS)+2 ); + + /* set multiplication factor according to the sampling rate */ + delta = 1; + if( output_frame == L_FRAME32k ) + { + delta = 2; + } + else if( output_frame == L_FRAME48k ) + { + delta = 3; + } + + /*----------------------------------------------------------------* + * set switching frame bit-rate + *----------------------------------------------------------------*/ + + if( core_switching_flag && st->last_L_frame == st->last_L_frame_ori && (st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE) ) + { + exc = old_exc + L_EXC_MEM_DEC; + mvr2r(st->old_exc, old_exc, L_EXC_MEM_DEC ); + + if( st->last_L_frame == L_FRAME ) + { + if( st->core_brate > ACELP_24k40 ) + { + cbrate = ACELP_24k40; + } + else + { + cbrate = st->core_brate; + } + + L_frame_for_cs = L_FRAME; + } + else + { + if( st->core_brate <= ACELP_8k00 ) + { + cbrate = ACELP_8k00; + } + else if( st->core_brate <= ACELP_14k80 ) + { + cbrate = ACELP_14k80; + } + else + { + cbrate = min(st->core_brate, ACELP_22k60 ); + } + + L_frame_for_cs = L_FRAME16k; + } + + /*----------------------------------------------------------------* + * Excitation decoding + *----------------------------------------------------------------*/ + + decod_gen_voic_core_switch( st, L_frame_for_cs, 0, Aq, GENERIC, exc, cbrate ); + + /*----------------------------------------------------------------* + * synthesis, deemphasis, postprocessing and resampling + *----------------------------------------------------------------*/ + + /* synthesis and deemphasis */ + syn_12k8( 2*L_SUBFR, Aq, exc, synth_intFreq, st->mem_syn2, 1 ); + + if( st->pfstat.on && st->last_bwidth == NB ) + { + float tmp_noise, pitch_buf_tmp[2]; + tmp_noise = 0; + + for( i=0; i<2; i++ ) + { + pitch_buf_tmp[i] = L_SUBFR; + } + + nb_post_filt( 2*L_SUBFR, L_SUBFR, &(st->pfstat), &tmp_noise, 0, synth_intFreq, Aq, pitch_buf_tmp, AUDIO, st->BER_detect, 0 ); + } + + if( L_frame_for_cs == L_FRAME ) + { + deemph( synth_intFreq, PREEMPH_FAC, 2*L_SUBFR, &st->mem_deemph ); + } + else + { + deemph( synth_intFreq, PREEMPH_FAC_16k, 2*L_SUBFR, &st->mem_deemph ); + } + + AGC_dec( synth_intFreq, st->agc_mem2, 2*L_SUBFR ); + + if( st->pfstat.on && st->last_bwidth != NB ) + { + mvr2r( st->pfstat.mem_pf_in+L_SYN_MEM-M, bpf_error_signal, M ); /*bpf_error_signal used as temporary buffer*/ + mvr2r( synth_intFreq, bpf_error_signal+M, L_SUBFR ); + residu( Aq, M, bpf_error_signal+M,old_exc, L_SUBFR ); + syn_filt( Aq, M, old_exc, bpf_error_signal, L_SUBFR, st->pfstat.mem_stp+L_SYN_MEM-M, 0 ); + scale_st( synth_intFreq, bpf_error_signal, &st->pfstat.gain_prec, L_SUBFR, -1 ); + mvr2r( 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->pfstat.on = 0; + + if( st->flag_cna ) + { + generate_masking_noise( synth_intFreq, st->hFdCngDec->hFdCngCom, 2*L_SUBFR, 0 ); + } + + /*----------------------------------------------------------------* + * Resample to the output sampling rate (8/16/32/48 kHz) + * Bass post-filter + *----------------------------------------------------------------*/ + + /* bass post-filter */ + bass_psfilter( st->Opt_AMR_WB, synth_intFreq, 2*L_SUBFR, NULL, st->pst_old_syn, + &st->pst_mem_deemp_err, &st->pst_lp_ener, st->bpf_off, st->stab_fac, &st->stab_fac_smooth, + st->mem_mean_pit, st->Track_on_hist, st->vibrato_hist, &st->psf_att, GENERIC, bpf_error_signal ); + + /* CLDFB analysis of the synthesis at internal sampling rate */ + cldfb_save_memory( st->cldfbAna ); + cldfbAnalysis( synth_intFreq, realBuffer, imagBuffer, NS2SA(50*L_frame_for_cs, SWITCH_GAP_LENGTH_NS+DELAY_CLDFB_NS), st->cldfbAna ); + cldfb_restore_memory( st->cldfbAna ); + + /* CLDFB analysis and add the BPF error signal */ + cldfb_save_memory( st->cldfbBPF ); + addBassPostFilter( bpf_error_signal, st->bpf_off? 0: NS2SA(50*L_frame_for_cs, SWITCH_GAP_LENGTH_NS+DELAY_CLDFB_NS), realBuffer, imagBuffer, st->cldfbBPF ); + cldfb_restore_memory( st->cldfbBPF ); + + /* CLDFB synthesis of the combined signal */ + cldfb_save_memory( st->cldfbSyn ); + cldfbSynthesis( realBuffer, imagBuffer, synth_subfr_out, NS2SA(st->output_Fs, SWITCH_GAP_LENGTH_NS+DELAY_CLDFB_NS), st->cldfbSyn ); + cldfb_restore_memory( st->cldfbSyn ); + + mvr2r( 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 ); /* need for switching (-2 is due to 0 delay filtering) */ + + /*----------------------------------------------------------------* + * BWE decoding + *----------------------------------------------------------------*/ + + decode_bwe = 0; + if( !((inner_frame_tbl[st->bwidth] == L_FRAME16k && st->last_L_frame == L_FRAME16k) || inner_frame_tbl[st->bwidth] == L_FRAME8k) ) + { + /* Decoding of BWE */ + d1m = (short)get_next_indice(st, AUDIODELAYBITS); + ind1 = (short)get_next_indice(st, NOOFGAINBITS1); + gain = usdequant( ind1, MINVALUEOFFIRSTGAIN, DELTAOFFIRSTGAIN ); + decode_bwe = 1; + } + + + + if( decode_bwe && !((output_frame == L_FRAME16k && st->last_L_frame == L_FRAME16k) || output_frame == L_FRAME8k) ) + { + set_f( tmp_mem2, 0, 2*L_FILT48k ); + + hp_filter = hp16000_48000; + fdelay = 48; + if( st->output_Fs == 16000 ) + { + if( st->last_L_frame == L_FRAME ) + { + hp_filter = hp12800_16000; + fdelay = 20; + } + } + else if( st->output_Fs == 32000 ) + { + + if( st->last_L_frame == L_FRAME ) + { + hp_filter = hp12800_32000; + fdelay = 40; + } + else + { + hp_filter = hp16000_32000; + fdelay = 32; + } + } + else if( st->last_L_frame == L_FRAME ) + { + hp_filter = hp12800_48000; + fdelay = 60; + } + + /* safety check in case of bit errors */ + i = MAX_D1M_16k; + if( st->last_L_frame == L_FRAME ) + { + i = MAX_D1M_12k8; + } + + if( d1m >= i ) + { + d1m = i - 1; + gain = 0; /* force muting */ + st->BER_detect = 1; + } + + i = NS2SA(st->output_Fs, FRAME_SIZE_NS-ACELP_LOOK_NS-DELAY_BWE_TOTAL_NS); + mvr2r( st->old_synth_sw, hb_synth_tmp, i ); + set_f( hb_synth_tmp + i, 0, NS2SA(st->output_Fs, 10000000L) - i ); + fir( hb_synth_tmp, hp_filter, hb_synth_tmp, tmp_mem2, output_frame>>1, fdelay, 0 ); /* put the 40 past samples into the memory */ + set_f( tmp_synth_bwe, 0, SWITCH_MAX_GAP ); + + gapsize = delta * (NS2SA(16000,SWITCH_GAP_LENGTH_NS)); + for( i=0; iHQ switching frame in case of BAD frame + *-------------------------------------------------------------------*/ + +void acelp_core_switch_dec_bfi( + Decoder_State *st, /* i/o: decoder state structure */ + float synth_out[], /* o : synthesis */ + const short coder_type /* i : coder type */ +) +{ + short i; + float old_exc[L_EXC_DEC], *exc; /* excitation signal buffer */ + float syn[L_FRAME16k]; /* synthesis signal buffer */ + float lsf_new[M]; /* LSFs at the end of the frame */ + float lsp_new[M]; /* LSPs at the end of the frame */ + float Aq[NB_SUBFR16k*(M+1)]; /* A(q) quantized for the 4 subframes */ + float old_exc2[L_FRAME16k + L_EXC_MEM], *exc2; /* total excitation buffer */ + float tmp_noise; /* Long term temporary noise energy */ + float FEC_pitch; /* FEC pitch */ + float old_bwe_exc[((PIT16k_MAX + (L_FRAME16k+1) + L_SUBFR16k) * 2)]; /* excitation buffer */ + float *bwe_exc; /* Excitation for SWB TBE */ + float tmp_float[NBPSF_PIT_MAX]; + float tmp_float2[M]; + float tmp_float3; + float tmp_float4[L_TRACK_HIST]; + short tmp_float5[L_TRACK_HIST]; + short tmp_float6[L_TRACK_HIST]; + float tmp_float7; + float voice_factors[NB_SUBFR16k]; + float pitch_buf[NB_SUBFR16k]; + float *realBuffer[CLDFB_NO_COL_MAX_SWITCH_BFI], *imagBuffer[CLDFB_NO_COL_MAX_SWITCH_BFI]; + float realBufferTmp[CLDFB_NO_COL_MAX_SWITCH_BFI][CLDFB_NO_CHANNELS_MAX], imagBufferTmp[CLDFB_NO_COL_MAX_SWITCH_BFI][CLDFB_NO_CHANNELS_MAX]; + + /*----------------------------------------------------------------* + * Initialization + *----------------------------------------------------------------*/ + + /* initialize CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ + for( i=0; ibpf_off = 1; + st->clas_dec = st->last_good; + tmp_noise = 0.0f; + + mvr2r( st->old_exc, old_exc, L_EXC_MEM_DEC ); + exc = old_exc + L_EXC_MEM_DEC; + mvr2r( st->old_exc2, old_exc2, L_EXC_MEM ); + exc2 = old_exc2 + L_EXC_MEM; + mvr2r( st->old_bwe_exc, old_bwe_exc, PIT16k_MAX * 2); + bwe_exc = old_bwe_exc + PIT16k_MAX * 2; + st->GSC_noisy_speech = 0; + st->relax_prev_lsf_interp = 0; + + /* SC-VBR */ + if( st->last_nelp_mode_dec == 1 ) + { + st->nelp_mode_dec = 1; + } + + mvr2r( st->mem_AR, tmp_float, M ); + mvr2r( st->mem_MA, tmp_float2, M ); + + /* LSF estimation and A(z) calculation */ + lsf_dec_bfi( MODE1, lsf_new, st->lsf_old, st->lsf_adaptive_mean, NULL, st->mem_MA, st->mem_AR, + st->stab_fac, st->last_coder_type, st->L_frame, st->last_good, + st->nbLostCmpt, 0, NULL, NULL, NULL, st->Last_GSC_pit_band_idx, st->Opt_AMR_WB, st->bwidth ); + + FEC_lsf2lsp_interp( st, st->L_frame, Aq, lsf_new, lsp_new ); + + mvr2r( tmp_float, st->mem_AR, M ); + mvr2r( tmp_float2, st->mem_MA, M ); + + /*----------------------------------------------------------------* + * Excitation decoding + *----------------------------------------------------------------*/ + + if( st->nelp_mode_dec == 1 ) + { + /* SC-VBR */ + decod_nelp( st, coder_type, &tmp_noise, pitch_buf, exc, exc2, voice_factors, bwe_exc, st->bfi, tmp_float2 ); + FEC_pitch = pitch_buf[3]; + } + else + { + tmp_float[0] = st->bfi_pitch; + tmp_float[1] = (float)st->bfi_pitch_frame; + tmp_float[2] = st->lp_gainp; + tmp_float[3] = st->lp_gainc; + tmp_float[4] = st->upd_cnt; + tmp_float[5] = st->seed; + + /* calculation of excitation signal */ + FEC_exc_estim( st, st->L_frame, exc, exc2, syn /* dummy buffer */, pitch_buf, voice_factors, &FEC_pitch, bwe_exc, lsf_new, &tmp_noise ); + + st->seed = (short)tmp_float[5]; + st->bfi_pitch = tmp_float[0]; + st->bfi_pitch_frame = (short)tmp_float[1]; + st->lp_gainp = tmp_float[2]; + st->lp_gainc = tmp_float[3]; + st->upd_cnt = (short)tmp_float[4]; + } + + /*------------------------------------------------------------------* + * Synthesis + *-----------------------------------------------------------------*/ + + mvr2r( st->mem_syn2, tmp_float, M ); + syn_12k8( st->L_frame, Aq, exc2, syn, tmp_float, 1 ); + + tmp_float[0] = st->enr_old; + fer_energy( st->L_frame, st->last_good, syn, FEC_pitch, tmp_float, st->L_frame ); + + /*------------------------------------------------------------------* + * Perform fixed deemphasis through 1/(1 - g*z^-1) + *-----------------------------------------------------------------*/ + + mvr2r( &(st->mem_deemph), tmp_float, 1 ); + if( st->L_frame == L_FRAME ) + { + deemph( syn, PREEMPH_FAC, L_FRAME, tmp_float ); + } + else + { + deemph( syn, PREEMPH_FAC_16k, L_FRAME16k, tmp_float ); + } + + /*----------------------------------------------------------------* + * Bass post-filter + *----------------------------------------------------------------*/ + + st->bpf_off = 1; + mvr2r( st->pst_old_syn, tmp_float, NBPSF_PIT_MAX ); + tmp_float3 = st->stab_fac_smooth; + mvr2r( st->mem_mean_pit, tmp_float4, L_TRACK_HIST ); + mvs2s( st->Track_on_hist, tmp_float5, L_TRACK_HIST ); + mvs2s( st->vibrato_hist, tmp_float6, L_TRACK_HIST ); + tmp_float7 = st->psf_att; + + /* apply bass post-filter */ + bass_psfilter( st->Opt_AMR_WB, syn, st->L_frame, pitch_buf, tmp_float, &st->pst_mem_deemp_err, &st->pst_lp_ener, st->bpf_off, + st->stab_fac, &tmp_float3, tmp_float4, tmp_float5, tmp_float6, &tmp_float7, coder_type, old_exc /* tmp buffer */ ); + + /*----------------------------------------------------------------* + * Resampling to the output sampling frequency + *----------------------------------------------------------------*/ + + /* CLDFB analysis of the synthesis at internal sampling rate */ + cldfb_save_memory( st->cldfbAna ); + cldfbAnalysis ( syn, realBuffer, imagBuffer, st->L_frame/2, st->cldfbAna ); + cldfb_restore_memory( st->cldfbAna ); + + /* CLDFB synthesis of the combined signal */ + cldfb_save_memory( st->cldfbSyn ); + cldfbSynthesis ( realBuffer, imagBuffer, synth_out, st->output_Fs*0.01, st->cldfbSyn ); + cldfb_restore_memory( st->cldfbSyn ); + + return; +} + + +/*-------------------------------------------------------------------* + * decod_gen_voic_core_switch() + * + * Decode excitation signal in teh first ACELP->HQ switching frame + *-------------------------------------------------------------------*/ + +static void decod_gen_voic_core_switch( + Decoder_State *st, /* i/o: decoder static memory */ + const short L_frame, /* i : length of the frame */ + const short sharpFlag, /* i : flag for formant sharpening */ + const float *Aq, /* i : LP filter coefficient */ + const short coder_type, /* i : coding type */ + float *exc, /* i/o: adapt. excitation exc */ + const long core_brate /* i : switching frame bit-rate */ +) +{ + short T0, T0_frac, T0_min, T0_max;/* integer pitch variables */ + float gain_pit; /* pitch gain */ + float gain_code; /* gain/normalized gain of the algebraic excitation */ + float norm_gain_code; /* normalized gain of the algebraic excitation */ + float gain_inov; /* Innovation gain */ + float voice_fac; /* voicing factor */ + float code[L_SUBFR]; /* algebraic codevector */ + float pitch; /* pointer to floating pitch */ + short i; /* tmp variables */ + short pitch_limit_flag; + float tmpF; + + /* initializations */ + if( L_frame == L_FRAME ) + { + T0_max = PIT_MAX; + T0_min = PIT_MIN; + } + else /* L_frame == L_FRAME16k */ + { + T0_max = PIT16k_MAX; + T0_min = PIT16k_MIN; + } + + /*----------------------------------------------------------------------* + * Decode pitch lag + *----------------------------------------------------------------------*/ + + pitch = pit_decode( st, core_brate, 0, L_frame, 0, coder_type, &pitch_limit_flag, &T0, &T0_frac, &T0_min, &T0_max, L_SUBFR ); + + /*--------------------------------------------------------------* + * Find the adaptive codebook vector. + *--------------------------------------------------------------*/ + + pred_lt4( &exc[0], &exc[0], T0, T0_frac, L_SUBFR+1, inter4_2, L_INTERPOL2, PIT_UP_SAMP ); + + /*--------------------------------------------------------------* + * LP filtering of the adaptive excitation + *--------------------------------------------------------------*/ + + lp_filt_exc_dec( st, MODE1, core_brate,0, coder_type, 0, L_SUBFR, L_frame, 0, exc ); + + /*--------------------------------------------------------------* + * Innovation decoding + *--------------------------------------------------------------*/ + + inov_decode( st, core_brate, 0, L_frame, coder_type, sharpFlag, 0, -1, Aq, st->tilt_code, pitch, code ); + + /*--------------------------------------------------------------* + * Gain decoding + * Estimate spectrum tilt and voicing + *--------------------------------------------------------------*/ + + if( L_frame == L_FRAME ) + { + gain_dec_mless( st, core_brate, L_frame, TRANSITION, 0, -1, code, st->old_Es_pred, &gain_pit, &gain_code, &gain_inov, &norm_gain_code ); + } + else + { + gain_dec_mless( st, core_brate, L_frame, coder_type, 0, -1, code, st->old_Es_pred, &gain_pit, &gain_code, &gain_inov, &norm_gain_code ); + } + + st->tilt_code = est_tilt( exc, gain_pit, code, gain_code, &voice_fac, L_SUBFR, 0 ); + + /*----------------------------------------------------------------------* + * Find the total excitation + *----------------------------------------------------------------------*/ + + if( st->prev_bfi ) + { + gain_code = min( gain_code, 0.5f*gain_code+0.5f*st->lp_gainc ); + } + + for( i = 0; i < L_SUBFR; i++ ) + { + tmpF = gain_pit * exc[i]; + exc[i] = tmpF + gain_code * code[i]; + } + + /*-----------------------------------------------------------------* + * long term prediction on the 2nd sub frame + *-----------------------------------------------------------------*/ + + pred_lt4( &exc[L_SUBFR], &exc[L_SUBFR], T0, T0_frac, L_SUBFR+1, inter4_2, L_INTERPOL2, PIT_UP_SAMP ); + + for( i = 0; i < L_SUBFR; i++ ) + { + exc[i+L_SUBFR] *= gain_pit; + } + + return; +} diff --git a/lib_dec/amr_wb_dec.c b/lib_dec/amr_wb_dec.c new file mode 100644 index 000000000..a8e63bf13 --- /dev/null +++ b/lib_dec/amr_wb_dec.c @@ -0,0 +1,867 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + + +/*------------------------------------------------------------------* + * amr_wb_dec() + * + * AMR-WB decoder + *------------------------------------------------------------------*/ + +void amr_wb_dec( + Decoder_State *st, /* i/o: decoder state structure */ + float *output /* o : synthesis output */ +) +{ + short i; + short vad_flag; + short coder_type; + float ftmp; + float old_exc[L_EXC_DEC], *exc; /* excitation signal buffer */ + float syn_tmp[L_FRAME+2], *syn; /* synthesis signal buffer */ + float synth_out[L_FRAME48k]; /* synthesis output */ + short output_frame; /* frame length at output sampling freq. */ + float lsf_new[M]; /* LSFs at the end of the frame */ + float lsp_new[M]; /* LSPs at the end of the frame */ + float Aq[NB_SUBFR*(M+1)]; /* A(q) quantized for the 4 subframes */ + float exc2[L_FRAME]; /* total excitation buffer */ + float mem_tmp[M]; /* temporary synthesis filter memory */ + float pitch_buf[NB_SUBFR]; /* floating pitch for each subframe */ + float enr_q; /* E information for FER protection */ + float tmp_noise; /* Long term temporary noise energy */ + float FEC_pitch; /* FEC pitch */ + float dummy_buf[L_FRAME32k]; /* dummy buffer - no usage */ + short allow_cn_step; + short locattack, amr_io_class; + short tmps; + float xsp_tmp[M]; + float tmp_buffer[L_FRAME48k]; + float dct_buffer[DCT_L_POST]; + float frame_e; + float exc_buffer[DCT_L_POST]; + float class_para; + float voice_factors[NB_SUBFR]; + short hf_gain[NB_SUBFR]; + short delay_comp; + short nZeros; + float tmp; + short last_core_ori; + short sid_bw = 0; + float bpf_error_signal[L_FRAME]; + float ng_ener; + float gain_buf[NB_SUBFR16k]; + float q_env[20]; + float exc3[L_FRAME]; + float *realBuffer[CLDFB_NO_COL_MAX], *imagBuffer[CLDFB_NO_COL_MAX]; + float realBufferTmp[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], imagBufferTmp[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + short flag_cna; + short waveadj_rec = 0; + + push_wmops("amr_wb_dec"); + + /*------------------------------------------------------------------* + * Initialization + *------------------------------------------------------------------*/ + + syn_tmp[0] = 0; + syn_tmp[1] = 0; + syn = syn_tmp+2; + + for( i=0; iuse_partial_copy = 0; + st->rf_flag = 0; + st->rf_flag_last = 0; + + st->L_frame = L_FRAME; + st->nb_subfr = NB_SUBFR; + st->core = AMR_WB_CORE; + st->core_brate = st->total_brate; + st->extl = -1; + st->bwidth = WB; + coder_type = GENERIC; + output_frame = (short)(st->output_Fs / 50); /* frame length of the input signal */ + + st->bpf_off = 0; + if( st->last_core == HQ_CORE ) + { + st->bpf_off = 1; + st->pfstat.on = 0; + } + st->igf = 0; + + st->sr_core = st->L_frame*50; + st->fscale_old = st->fscale; + st->fscale = sr2fscale(st->sr_core); + + /* Initialization in case that the first frame is the good received AMR-WB (IO) frame */ + if( st->ini_frame == 0 ) + { + st->last_core = AMR_WB_CORE; + mvr2r( mean_isf_amr_wb, st->lsf_old, M ); + isf2isp( st->lsf_old, st->lsp_old, M, INT_FS_12k8 ); + } + + /* Updates in case of EVS primary mode -> AMR-WB IO mode switching */ + if( st->last_core != AMR_WB_CORE ) + { + updt_IO_switch_dec( output_frame, st ); + } + + /* Updates in case of HQ -> AMR-WB IO switching */ + core_switching_pre_dec( st, output_frame ); + + last_core_ori = st->last_core; + set_s( hf_gain, 0, NB_SUBFR ); + + enr_q = 0.0f; + tmp_noise = 0.0f; + amr_io_class = UNVOICED_CLAS; + + mvr2r( st->old_exc, old_exc, L_EXC_MEM_DEC ); + exc = old_exc + L_EXC_MEM_DEC; + + /* reset post-filter in case of switching */ + if( st->pfstat.on == 0 ) + { + st->pfstat.reset = 1; + } + + if( st->bfi ) + { + st->nbLostCmpt++; + } + else + { + st->nbLostCmpt = 0; + } + + /* PLC: [TCX: Fade-out-recovery] + * PLC: overlapping part needs to be attenuated for first good frame */ + if (!st->bfi && st->prev_bfi && (st->last_codec_mode == MODE2) && (st->last_core_bfi == TCX_20_CORE || st->last_core_bfi == TCX_10_CORE)) + { + v_multc( st->old_out, st->plcInfo.recovery_gain, st->old_out, st->L_frameTCX ); + } + + /*-----------------------------------------------------------------* + * switching from ACELP@16k core to AMR-WB IO mode + *-----------------------------------------------------------------*/ + + st->rate_switching_reset = 0; + + if( st->last_core != AMR_WB_CORE && st->last_L_frame == L_FRAME16k && st->last_core != HQ_CORE ) + { + /* in case of switching, do not apply BPF */ + st->bpf_off = 1; + if( st->pfstat.on != 0 ) + { + short mem_syn_r_size_old, mem_syn_r_size_new; + + mem_syn_r_size_old = (short)(1.25*st->last_L_frame/20.f); + mem_syn_r_size_new = (short)(1.25*st->L_frame/20.f); + 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 ); + } + + /* convert old quantized LSP vector */ + st->rate_switching_reset = lsp_convert_poly( st->lsp_old, L_FRAME, 1 ); + + /* convert old quantized LSF vector */ + lsp2lsf( st->lsp_old, st->lsf_old, M, INT_FS_12k8 ); + + /* FEC - update adaptive LSF mean vector */ + mvr2r( st->lsf_old, st->lsfoldbfi1, M ); + mvr2r( st->lsf_old, st->lsfoldbfi0, M ); + mvr2r( st->lsf_old, st->lsf_adaptive_mean, M ); + + /* Reset LPC mem */ + mvr2r( GEWB_Ave, st->mem_AR, M ); + set_zero( st->mem_MA, M ); + + /* update synthesis filter memories */ + synth_mem_updt2( L_FRAME, st->last_L_frame, st->old_exc, st->mem_syn_r, st->mem_syn2, NULL, DEC ); + mvr2r( st->old_exc, old_exc, L_EXC_MEM_DEC ); + mvr2r( st->mem_syn2, st->mem_syn1, M ); + mvr2r( st->mem_syn2, st->mem_syn3, M ); + + /* LSP -> ISP */ + mvr2r( stable_ISP, xsp_tmp, M ); + lsp2isp( st->lsp_old, st->lsp_old, xsp_tmp, M ); + + } + + /* update buffer of old subframe pitch values */ + if( st->last_L_frame != L_FRAME ) + { + if( st->last_L_frame == L_FRAME32k ) + { + tmp = (float)12800/(float)32000; + } + else if( st->last_L_frame == 512 ) + { + tmp = (float)12800/(float)25600; + } + else /* st->last_L_frame == L_FRAME16k */ + { + tmp = (float)12800/(float)16000; + } + + for( i=NB_SUBFR16k-NB_SUBFR; iold_pitch_buf[i-1] = tmp * st->old_pitch_buf[i]; + } + + for( i=2*NB_SUBFR16k-NB_SUBFR; i<2*NB_SUBFR16k; i++ ) + { + st->old_pitch_buf[i-2] = tmp * st->old_pitch_buf[i]; + } + } + + if( st->bfi_pitch_frame != L_FRAME ) + { + if( st->bfi_pitch_frame == L_FRAME32k ) + { + tmp = (float)12800/(float)32000; + } + else if( st->bfi_pitch_frame == 512 ) + { + tmp = (float)12800/(float)25600; + } + else /* st->bfi_pitch_frame == L_FRAME16k */ + { + tmp = (float)12800/(float)16000; + } + + st->bfi_pitch *= tmp; + st->bfi_pitch_frame = L_FRAME; + } + + + if( st->last_core != AMR_WB_CORE ) + { + /* reset the unvoiced/audio signal improvement memories */ + isp2a( st->lsp_old, st->old_Aq, M ); + mvr2r( st->old_Aq, st->old_Aq + (M+1), M+1 ); + mvr2r( st->old_Aq, st->old_Aq + 2*(M+1), M+1 ); + mvr2r( st->old_Aq, st->old_Aq + 3*(M+1), M+1 ); + } + + if( st->last_bwidth == NB && st->ini_frame != 0 ) + { + st->rate_switching_reset = 1; + } + + /*----------------------------------------------------------------------* + * GOOD frame + *----------------------------------------------------------------------*/ + + if( !st->bfi ) + { + /*----------------------------------------------------------------* + * Processing of FRAME_NO_DATA frames + * Decoding of SID frames + *----------------------------------------------------------------*/ + + if ( st->core_brate == FRAME_NO_DATA || st->core_brate == SID_1k75 ) + { + /* decode CNG parameters */ + CNG_dec( st, L_FRAME, Aq, st->core_brate, lsp_new, lsf_new, &allow_cn_step, &sid_bw, q_env ); + + /* comfort noise generation */ + CNG_exc( st->core_brate, L_FRAME, &st->Enew, &st->cng_seed, exc, exc2, &st->lp_ener, st->last_core_brate, + &st->first_CNG, &st->cng_ener_seed, dummy_buf, allow_cn_step, &st->last_allow_cn_step, st->num_ho, + q_env, st->lp_env, st->old_env, st->exc_mem, st->exc_mem1, &sid_bw, &st->cng_ener_seed1, exc3, st->Opt_AMR_WB ); + + set_f( voice_factors, 1.0f, NB_SUBFR ); + class_para = 0.0f; + + if ( st->first_CNG == 0 ) + { + st->first_CNG = 1; + } + + /* update past excitation signals for LD music post-filter */ + mvr2r( st->dct_post_old_exc + L_FRAME, st->dct_post_old_exc, DCT_L_POST-L_FRAME-OFFSET2 ); + mvr2r( exc2, st->dct_post_old_exc + (DCT_L_POST-L_FRAME-OFFSET2), L_FRAME ); + + /* synthesis at 12k8 Hz sampling rate */ + syn_12k8( L_FRAME, Aq, exc2, syn, st->mem_syn2, 1 ); + syn_12k8( st->L_frame, Aq, exc2, dummy_buf, st->mem_syn3, 1 ); + + /* reset the decoder */ + CNG_reset_dec( st, pitch_buf, dummy_buf+L_FRAME ); + + /* update st->mem_syn1 for ACELP core switching */ + mvr2r( st->mem_syn3, st->mem_syn1, M ); + if( output_frame != L_FRAME8k ) + { + frame_e = 10.0f * (float) log10( dotp( syn, syn, L_FRAME ) / (float) L_FRAME ); + st->psf_lp_noise = 0.99f * st->psf_lp_noise + 0.01f * frame_e; + } + + /* update old synthesis for classification */ + mvr2r( syn + L_FRAME - L_SYN_MEM_CLAS_ESTIM, st->mem_syn_clas_estim, 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]; + } + + vad_flag = 0; + } + + /*----------------------------------------------------------------* + * Decoding of all other frames + *----------------------------------------------------------------*/ + + else + { + /*-----------------------------------------------------------------* + * After CNG period, use the most up-to-date ISPs + *-----------------------------------------------------------------*/ + + if( st->last_core_brate == FRAME_NO_DATA || st->last_core_brate == SID_1k75 ) + { + mvr2r( st->lspCNG, st->lsp_old, M ); + isp2isf( st->lspCNG, st->lsf_old, M, INT_FS_12k8 ); + set_f( old_exc, 0, L_EXC_MEM_DEC ); + } + + /*------------------------------------------------------------* + * Extracts VAD information from the bitstream in AMR-WB IO mode + *------------------------------------------------------------*/ + + vad_flag = (short)get_next_indice( st, 1 ); + + if( vad_flag == 0 ) + { + coder_type = INACTIVE; + } + else + { + coder_type = GENERIC; + } + + /*-----------------------------------------------------------------* + * ISF de-quantization and interpolation + *-----------------------------------------------------------------*/ + + isf_dec_amr_wb( st, Aq, lsf_new, lsp_new ); + + /*------------------------------------------------------------* + * Decode excitation + *------------------------------------------------------------*/ + + decod_amr_wb( st, Aq, pitch_buf, exc, exc2, hf_gain, voice_factors, gain_buf ); + + /* synthesis for ACELP core switching and SWB BWE */ + syn_12k8( L_FRAME, Aq, exc, tmp_buffer, st->mem_syn1, 1 ); + + /*------------------------------------------------------------* + * Update long-term energies for FEC + * Update ISP vector for CNG + *------------------------------------------------------------*/ + + if( coder_type == INACTIVE ) + { + if( st->unv_cnt > 20 ) + { + ftmp = st->lp_gainc * st->lp_gainc; + st->lp_ener = 0.7f * st->lp_ener + 0.3f * ftmp; + for( i=0; ilspCNG[i] = (float)(0.9f * st->lspCNG[i] + 0.1f * lsp_new[i]); + } + } + else + { + st->unv_cnt++; + } + } + else + { + st->unv_cnt = 0; + } + + /*------------------------------------------------------------* + * Save filter memory in case the synthesis is redone after scaling + * Core synthesis at 12k8 Hz + *------------------------------------------------------------*/ + + mvr2r( st->mem_syn2, mem_tmp, M ); + syn_12k8( L_FRAME, Aq, exc2, syn, st->mem_syn2, 1 ); + + /*------------------------------------------------------------* + * FEC - Estimate the classification information + *------------------------------------------------------------*/ + + FEC_clas_estim( syn, pitch_buf, st->L_frame, coder_type, st->codec_mode, st->mem_syn_clas_estim, &st->clas_dec, + &st->lp_ener_bfi, st->core_brate, st->Opt_AMR_WB, &st->decision_hyst, &locattack, &st->UV_cnt, + &st->LT_UV_cnt, &st->Last_ener, &amr_io_class, st->lt_diff_etot, &class_para, 0, 0, 0, + 0, 0, 0, st->last_core_brate ); + + /* update past excitation signals for LD music post-filter */ + mvr2r( st->dct_post_old_exc + L_FRAME, st->dct_post_old_exc, DCT_L_POST-L_FRAME-OFFSET2 ); + mvr2r( exc2, st->dct_post_old_exc + (DCT_L_POST-L_FRAME-OFFSET2), L_FRAME ); + mvr2r( st->dct_post_old_exc, exc_buffer, DCT_L_POST-OFFSET2 ); + + if( output_frame != L_FRAME8k ) + { + if ( coder_type == INACTIVE ) + { + frame_energy( L_FRAME, pitch_buf, syn, 0.0f, &frame_e ); + st->psf_lp_noise = 0.99f * st->psf_lp_noise + 0.01f * frame_e; + } + } + + if( amr_io_class != UNVOICED_CLAS && coder_type != INACTIVE && st->psf_lp_noise < 15.0f ) + { + short tmp_coder_type = AUDIO; + if( st->last_coder_type == INACTIVE || st->last_coder_type == UNVOICED ) + { + tmp_coder_type = INACTIVE; + } + /* Extrapolation of the last future part, windowing and high resolution DCT transform */ + Prep_music_postP( exc_buffer, dct_buffer, st->filt_lfE, st->last_core, pitch_buf, st->LDm_enh_lp_gbin ); + + /* LD music post-filter */ + LD_music_post_filter( dct_buffer, dct_buffer, st->core_brate, &st->LDm_last_music_flag, + st->LDm_thres, &st->LDm_nb_thr_1, &st->LDm_nb_thr_3, st->LDm_lt_diff_etot, + &st->LDm_mem_etot, st->LDm_enh_min_ns_gain, st->LDm_bckr_noise, st->LDm_enh_lf_EO, + st->LDm_enh_lp_gbin, st->filt_lfE, &st->last_nonfull_music, -1, tmp_coder_type ); + + /* Inverse DCT transform, retrieval of the aligned excitation, re-synthesis */ + Post_music_postP( dct_buffer, exc_buffer, exc2, mem_tmp, st->mem_syn2, Aq, syn ); + } + else + { + /*------------------------------------------------------------* + * Improvement for unvoiced and audio signals + *------------------------------------------------------------*/ + + improv_amr_wb_gs( amr_io_class, coder_type, st->core_brate, &st->seed_tcx, st->old_Aq, st->mem_syn2, st->lt_voice_fac, + locattack, Aq, exc2, mem_tmp, syn, pitch_buf, st->Last_ener, st->rate_switching_reset, st->last_coder_type ); + + for( i = 0; i < DCT_L_POST; i++ ) + { + st->filt_lfE[i] = 0.3f + 0.7f * st->filt_lfE[i] ; + } + } + + /*------------------------------------------------------------* + * FEC - Estimate pitch + *------------------------------------------------------------*/ + + FEC_pitch_estim( 1, st->last_core, L_FRAME, st->clas_dec, st->last_good, pitch_buf, st->old_pitch_buf, + &st->bfi_pitch, &st->bfi_pitch_frame, &st->upd_cnt, 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) + *------------------------------------------------------------*/ + + FEC_scale_syn( L_FRAME, st->clas_dec, st->last_good, syn, pitch_buf, st->enr_old, enr_q, -1, + MOVING_AVERAGE, &st->scaling_flag, &st->lp_ener_FEC_av, &st->lp_ener_FEC_max, st->bfi, + st->total_brate, st->prev_bfi, st->last_core_brate, exc, exc2, Aq, &st->old_enr_LP, mem_tmp, st->mem_syn2, + st->last_con_tcx && (st->L_frameTCX_past != st->L_frame) && (st->last_core != 0), 0 ); + + /* estimate the pitch-synchronous speech energy per sample to be used when normal operation recovers */ + fer_energy( L_FRAME, st->clas_dec, syn, pitch_buf[3], &st->enr_old, L_FRAME ); + } + + } /* End of GOOD FRAME */ + + /*----------------------------------------------------------------* + * BAD frame + *----------------------------------------------------------------*/ + + else + { + /* long burst frame erasures */ + if( st->nbLostCmpt > 5 && st->clas_dec >= VOICED_CLAS ) + { + st->last_good = VOICED_TRANSITION; + } + + vad_flag = st->last_vad; + amr_io_class = st->last_good; + class_para = 0.0f; + + /* LSF estimation and A(z) calculation */ + lsf_dec_bfi( MODE1, lsf_new, st->lsf_old, st->lsf_adaptive_mean, NULL, st->mem_MA, st->mem_AR, + st->stab_fac, st->last_coder_type, L_FRAME, st->last_good, + st->nbLostCmpt, 0, NULL, NULL, NULL, st->Last_GSC_pit_band_idx, st->Opt_AMR_WB, st->bwidth ); + + FEC_lsf2lsp_interp( st, L_FRAME, Aq, lsf_new, lsp_new ); + + /* calculation of excitation signal */ + FEC_exc_estim( st, L_FRAME, exc, exc2, tmp_buffer, pitch_buf, voice_factors, &FEC_pitch, dummy_buf, lsf_new, &tmp_noise ); + + /* synthesis for ACELP core switching and SWB BWE */ + syn_12k8( L_FRAME, Aq, exc, tmp_buffer, st->mem_syn1, 1 ); + + /* update past excitation signals */ + mvr2r( st->dct_post_old_exc + L_FRAME, st->dct_post_old_exc, DCT_L_POST-L_FRAME-OFFSET2 ); + mvr2r( exc2, st->dct_post_old_exc + (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[i-1] = st->LDm_lt_diff_etot[i]; + } + /* Filter energies update */ + for( i = 0; i < DCT_L_POST; i++ ) + { + st->filt_lfE[i] = 0.3f + 0.7f * st->filt_lfE[i]; + } + + /* synthesis at 12k8 Hz sampling rate */ + mvr2r( st->mem_syn2, mem_tmp, M ); + syn_12k8( L_FRAME, Aq, exc2, syn, st->mem_syn2, 1 ); + + /* update old synthesis for classification */ + mvr2r( syn + L_FRAME - L_SYN_MEM_CLAS_ESTIM, st->mem_syn_clas_estim, L_SYN_MEM_CLAS_ESTIM ); + + + /*------------------------------------------------------------* + * 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( L_FRAME, st->clas_dec, st->last_good, syn, pitch_buf, st->enr_old, enr_q, -1, + MOVING_AVERAGE, &st->scaling_flag, &st->lp_ener_FEC_av, &st->lp_ener_FEC_max, st->bfi, + st->total_brate, st->prev_bfi, st->last_core_brate, exc, exc2, Aq, &st->old_enr_LP, mem_tmp, st->mem_syn2, + 0,0 ); + + /* estimate the pitch-synchronous speech energy per sample to be used when normal operation recovers */ + fer_energy( L_FRAME, st->last_good, syn, FEC_pitch, &st->enr_old, L_FRAME ); + } + + /*--------------------------------------------------------* + * NB post-filter + *--------------------------------------------------------*/ + + if( output_frame == L_FRAME8k || st->last_bwidth == NB ) + { + if( output_frame == L_FRAME8k ) + { + st->pfstat.on = 1; + nb_post_filt( L_FRAME, L_SUBFR, &(st->pfstat), &st->psf_lp_noise, tmp_noise, syn, Aq, pitch_buf, coder_type, st->BER_detect, 0 ); + } + else + { + st->pfstat.on = 0; + nb_post_filt( L_FRAME, L_SUBFR, &(st->pfstat), &st->psf_lp_noise, tmp_noise, syn, Aq, pitch_buf, AUDIO, st->BER_detect, 0); + } + } + + /*------------------------------------------------------------------* + * Perform fixed deemphasis through 1/(1 - g*z^-1) + *-----------------------------------------------------------------*/ + + /* update old synthesis buffer - needed for ACELP internal sampling rate switching */ + mvr2r( syn + L_FRAME - L_SYN_MEM, st->mem_syn_r, L_SYN_MEM ); + + + deemph( syn, PREEMPH_FAC, L_FRAME, &(st->mem_deemph) ); + AGC_dec( syn, st->agc_mem2, L_FRAME ); + mvr2r( syn+L_FRAME/2, st->old_syn_Overl, L_FRAME/2 ); + mvr2r( syn+L_FRAME-M-1, st->syn, M+1 ); + + /*------------------------------------------------------------------* + * Formant post-filter + *-----------------------------------------------------------------*/ + + mvr2r( syn, tmp_buffer + L_SYN_MEM, L_FRAME ); + + if( output_frame != L_FRAME8k && st->last_bwidth != NB ) + { + st->pfstat.on = 1; + formant_post_filt( &(st->pfstat), tmp_buffer + L_SYN_MEM, Aq, syn, L_FRAME, L_SUBFR, st->psf_lp_noise, st->total_brate, amr_io_class == AUDIO_CLAS ); + } + + /*----------------------------------------------------------------* + * Comfort Noise Addition + *----------------------------------------------------------------*/ + + flag_cna = 0; + if( (st->psf_lp_noise >= 15.f) || (coder_type == INACTIVE) ) + { + /*VAD only for non inactive frame*/ + st->VAD = (st->VAD && (coder_type != INACTIVE)); + + ApplyFdCng( syn, NULL, NULL, st->hFdCngDec, st->m_frame_type, st, 0, 0 ); + + st->hFdCngDec->hFdCngCom->frame_type_previous = st->m_frame_type; + + /*Noisy speech detector*/ + noisy_speech_detection( st->VAD, syn, st->hFdCngDec->hFdCngCom->frameSize, st->hFdCngDec->msNoiseEst, st->hFdCngDec->psize_shaping, + st->hFdCngDec->nFFTpart_shaping, &(st->hFdCngDec->lp_noise), &(st->hFdCngDec->lp_speech), &(st->hFdCngDec->hFdCngCom->flag_noisy_speech)); + + st->hFdCngDec->hFdCngCom->likelihood_noisy_speech = 0.99f*st->hFdCngDec->hFdCngCom->likelihood_noisy_speech + 0.01f*(float)st->hFdCngDec->hFdCngCom->flag_noisy_speech; + st->lp_noise = st->hFdCngDec->lp_noise; + + if( st->flag_cna && (st->psf_lp_noise >= 15.f) ) + { + flag_cna = 1; + generate_masking_noise( syn, st->hFdCngDec->hFdCngCom, st->hFdCngDec->hFdCngCom->frameSize, AMR_WB_CORE ); + } + else if ( st->flag_cna ) + { + generate_masking_noise_update_seed(st->hFdCngDec->hFdCngCom); + } + } + else if ( st->flag_cna ) + { + generate_masking_noise_update_seed(st->hFdCngDec->hFdCngCom); + } + + if( flag_cna == 0 ) + { + if( st->last_flag_cna == 1 && ( (st->last_core == ACELP_CORE && st->last_coder_type != AUDIO) || st->last_core == AMR_WB_CORE) ) + { + v_multc( st->hFdCngDec->hFdCngCom->olapBufferSynth2+5*L_FRAME/4, 256.f, tmp_buffer, L_FRAME/2 ); + v_add( tmp_buffer, syn, syn, L_FRAME/2 ); + } + set_f( st->hFdCngDec->hFdCngCom->olapBufferSynth2, 0.f, L_FRAME*2 ); + } + + /*----------------------------------------------------------------* + * Change the sampling frequency to 8/16/32 kHz + * Bass post-filter + *----------------------------------------------------------------*/ + + /* check if the cldfb works on the right sample rate */ + if( (st->cldfbAna->no_channels * st->cldfbAna->no_col) != L_FRAME ) + { + /* resample to ACELP internal sampling rate */ + resampleCldfb (st->cldfbAna, INT_FS_12k8); + resampleCldfb (st->cldfbBPF, INT_FS_12k8); + + if( st->ini_frame > 0 ) + { + st->cldfbSyn->bandsToZero = st->cldfbSyn->no_channels - st->cldfbAna->no_channels; + } + } + + /* bass post-filter */ + bass_psfilter( st->Opt_AMR_WB, syn, L_FRAME, pitch_buf, st->pst_old_syn, + &st->pst_mem_deemp_err, &st->pst_lp_ener, st->bpf_off, st->stab_fac, &st->stab_fac_smooth, + st->mem_mean_pit, st->Track_on_hist, st->vibrato_hist, &st->psf_att, GENERIC, bpf_error_signal ); + + /* analysis of the synthesis at internal sampling rate */ + cldfbAnalysis( syn, realBuffer, imagBuffer, -1, st->cldfbAna ); + + /* analysis and add the BPF error signal */ + addBassPostFilter( bpf_error_signal, st->bpf_off? 0:-1, realBuffer, imagBuffer, st->cldfbBPF ); + + if( st->cldfbSyn->bandsToZero != st->cldfbSyn->no_channels - st->cldfbAna->no_channels ) + { + /* in case of BW switching, re-init to default */ + st->cldfbSyn->bandsToZero = st->cldfbSyn->no_channels-st->cldfbAna->no_channels; + } + + cldfb_synth_set_bandsToZero( st, realBuffer, imagBuffer, CLDFB_NO_COL_MAX ); + + /* synthesis of the combined signal */ + cldfbSynthesis( realBuffer, imagBuffer, synth_out, -1, st->cldfbSyn ); + + /* save synthesis - needed in case of core switching */ + mvr2r( synth_out, st->previoussynth, output_frame ); + + /*--------------------------------------------------------* + * calculate the average frame energy + *--------------------------------------------------------*/ + + fer_energy( L_FRAME, st->clas_dec, syn, pitch_buf[3], &ng_ener, L_FRAME ); + + /*--------------------------------------------------------* + * optimized for NO_S@-26dBov with street noise @ SNR=25dB + *--------------------------------------------------------*/ + + ng_ener = 10.0f * (float)log10(ng_ener + 0.01f) - 90.3087f + 15; + st->ng_ener_ST = 0.7f * st->ng_ener_ST + 0.3f * ng_ener; + + /*-----------------------------------------------------------------* + * Bandwidth extension 6kHz-8kHz + *-----------------------------------------------------------------*/ + if( output_frame >= L_FRAME16k && ((st->cldfbSyn->bandsToZero - st->cldfbSyn->no_channels + 10 ) != 0 || st->last_flag_filter_NB != 1) ) + { + hf_synth_amr_wb( st->core_brate, output_frame, Aq, exc2, syn, st->mem_syn_hf, st->delay_syn_hf, &st->prev_r, &st->fmerit_w_sm, &amr_io_class, st->mem_hp_interp, + synth_out, class_para, hf_gain, voice_factors, pitch_buf, st->ng_ener_ST, lsf_new, &st->frame_count, &st->ne_min, &st->fmerit_m_sm, &st->voice_fac_amr_wb_hf, + &st->unvoicing, &st->unvoicing_sm, &st->unvoicing_flag, &st->voicing_flag, &st->start_band_old, &st->OptCrit_old ); + } + else + { + hf_synth_amr_wb_reset( &st->seed2, st->mem_syn_hf, st->mem_hp_interp, &st->prev_r, &st->fmerit_w_sm, st->delay_syn_hf, + &st->frame_count, &st->ne_min, &st->fmerit_m_sm, &st->voice_fac_amr_wb_hf, &st->unvoicing, + &st->unvoicing_sm, &st->unvoicing_flag, &st->voicing_flag, &st->start_band_old, &st->OptCrit_old ); + } + /*----------------------------------------------------------------------* + * Updates + *----------------------------------------------------------------------*/ + + updt_dec( st, L_FRAME, coder_type, old_exc, pitch_buf, 0, Aq, lsf_new, lsp_new, voice_factors, dummy_buf, gain_buf ); + + /* update old_Aq[] - needed in improv_amr_wb_gs_fx() */ + mvr2r( Aq, st->old_Aq, NB_SUBFR * (M+1) ); + + if( !st->bfi + && st->prev_bfi + && st->last_total_brate >= HQ_48k + && st->last_codec_mode == MODE2 + && (st->last_core_bfi == TCX_20_CORE || st->last_core_bfi == TCX_10_CORE) + && st->plcInfo.concealment_method == TCX_NONTONAL + && st->plcInfo.nbLostCmpt < 4 ) + { + waveadj_rec = 1; + } + + /* update main codec parameters */ + st->last_core = st->core; + st->last_extl = -1; + st->last_L_frame = L_FRAME; + st->last_core_brate = st->core_brate; + st->last_codec_mode = st->codec_mode; + st->last_bwidth = WB; + st->last_total_brate_ber = st->total_brate; + if( !st->bfi ) + { + st->last_total_brate = st->total_brate; + st->last_good = st->clas_dec; + } + st->last_vad = vad_flag; + st->last_flag_cna = flag_cna; + + /*----------------------------------------------------------------* + * Overlap of ACELP synthesis with old MDCT memory + *----------------------------------------------------------------*/ + + if( st->bfi ) + { + /* calculate another loss frame to fill gap in case of switching frame loss */ + acelp_core_switch_dec_bfi( st, st->fer_samples, coder_type ); + } + + delay_comp = NS2SA(st->output_Fs, DELAY_CLDFB_NS); + if( last_core_ori == HQ_CORE ) + { + nZeros = (short)(NS2SA(st->output_Fs,N_ZERO_MDCT_NS)); + + if( st->prev_bfi && st->HqVoicing ) + { + mvr2r( st->fer_samples, st->old_out+nZeros, NS2SA(st->output_Fs,6000000) ); + } + + /* copy the HQ/ACELP delay synchroniation buffer to the beginning of ACELP frame */ + mvr2r( st->delay_buf_out, synth_out, delay_comp ); + + tmp = 1.0f/(float)NS2SA(st->output_Fs,6000000); + for( i=0; ioutput_Fs,6000000); i++ ) + { + synth_out[i+delay_comp] = (1-tmp*(float)i)*st->old_out[i+nZeros] + tmp*(float)i*synth_out[i+delay_comp]; + } + } + + st->prev_bfi = st->bfi; + st->last_con_tcx = st->con_tcx; + + if( st->core_brate > SID_1k75 ) + { + st->last_active_brate = st->total_brate; + } + + if ( st->core_brate > SID_1k75 && st->first_CNG ) + { + if( st->act_cnt >= BUF_DEC_RATE ) + { + st->act_cnt = 0; + } + + st->act_cnt++; + + if( st->act_cnt == BUF_DEC_RATE && st->ho_hist_size > 0 ) + { + st->ho_hist_size--; + } + + if( ++(st->act_cnt2) >= MIN_ACT_CNG_UPD ) + { + st->act_cnt2 = MIN_ACT_CNG_UPD; + } + } + + st->prev_bws_cnt = 0; + st->bws_cnt = 0; + st->bws_cnt1 = 0; + + /*----------------------------------------------------------------* + * HP filtering + * Final synthesis output + *----------------------------------------------------------------*/ + + /* Delay ACELP synthesis by DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS delay */ + if ( output_frame >= L_FRAME16k ) + { + tmps = NS2SA(st->output_Fs, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS); + mvr2r( synth_out, tmp_buffer, output_frame ); + mvr2r( st->prev_synth_buffer, synth_out, tmps ); + mvr2r( tmp_buffer, synth_out + tmps, output_frame - tmps ); + mvr2r( tmp_buffer + output_frame - tmps, st->prev_synth_buffer, tmps ); + } + + if (waveadj_rec) + { + tmps = 0; + if( output_frame >= L_FRAME16k ) + { + tmps = NS2SA(st->output_Fs, DELAY_BWE_TOTAL_NS); + } + waveform_adj2(st->tonalMDCTconceal.secondLastPcmOut, + synth_out+tmps, + st->plcInfo.data_noise, + &st->plcInfo.outx_new_n1, + &st->plcInfo.nsapp_gain, + &st->plcInfo.nsapp_gain_n, + &st->plcInfo.recovery_gain, st->plcInfo.step_concealgain, + st->plcInfo.Pitch, st->plcInfo.FrameSize, + tmps, st->plcInfo.nbLostCmpt + 1, st->bfi ); + } + + /* HP filter */ + hp20( synth_out, output_frame, st->mem_hp20_out, st->output_Fs ); + + /* save synthesis for core switching */ + mvr2r( synth_out + NS2SA(st->output_Fs,ACELP_LOOK_NS+DELAY_BWE_TOTAL_NS), st->old_synth_sw, NS2SA(st->output_Fs,FRAME_SIZE_NS-ACELP_LOOK_NS-DELAY_BWE_TOTAL_NS) ); + + /* TCX-LTP Postfilter: used in AMR-WB IO to update memories and to avoid discontinuities when the past frame was TCX */ + tcx_ltp_post( st->tcxltp, ACELP_CORE, output_frame, st->L_frame_past, 0, synth_out, NULL, NS2SA( st->output_Fs, TCXLTP_DELAY_NS ), + 0, 0, 0, 0.f, &st->tcxltp_pitch_int_post_prev, &st->tcxltp_pitch_fr_post_prev, &st->tcxltp_gain_post_prev, + &st->tcxltp_filt_idx_prev, st->pit_res_max, &st->pit_res_max_past, 0.f, 0, st->tcxltp_mem_in, st->tcxltp_mem_out, st->total_brate ); + + /* final output of synthesis signal */ + mvr2r( synth_out, output, output_frame ); + + + pop_wmops(); + + return; +} diff --git a/lib_dec/ari_dec.c b/lib_dec/ari_dec.c new file mode 100644 index 000000000..f26647d74 --- /dev/null +++ b/lib_dec/ari_dec.c @@ -0,0 +1,640 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "cnst.h" +#include "prot.h" +#include "stat_com.h" +#include "assert.h" +#include "basop_util.h" + +#define WMC_TOOL_SKIP + + +/*--------------------------------------------------------------- + * Ari decode 14 bits routines + -------------------------------------------------------------*/ + +/** + * \brief Start ArCo decoding + * + * \param[i/o] st + * \param[o] s + * + * \return bit consumption + */ +void ari_start_decoding_14bits(Decoder_State *st,Tastat *s) +{ + long val; + + val = get_next_indice(st, cbitsnew); + + s->low = 0; + s->high = ari_q4new; + s->vobf=val; +} + +/** + * \brief Start ArCo decoding + * + * \param[o] prm + * \param[i] bp + * \param[o] s + * + * \return bit consumption + */ +long ari_start_decoding_14bits_prm(const int *ptr,long bp,Tastat *s) +{ + long val; + long i; + const int *p; + + + + val = 0; + + p=ptr+bp; + for (i=0; ilow = 0; + s->high = ari_q4new; + s->vobf=val; + + bp=bp+i; + + + return bp; +} + + + +/** + * \brief Only for 17 symbols with new extended Tables: + * based on tri's optimization + * based on extended Tables which need less branches for coding + * + * \param[i/o] st + * \param[o] res + * \param[i/o] s + * \param[i] cum_freq + * + * \return bit consumption + */ +void ari_decode_14bits_s17_ext(Decoder_State *st, + int *res, + Tastat *s, + const unsigned short *cum_freq) +{ + unsigned long symbol; + unsigned long low, high, range, value; + unsigned long cum; + unsigned short const *p; + + + + + /* read s->low,high,vobf sequentially */ + low = s->low; + high = s->high; + value = s->vobf; + + range = high-low+1; /* keep: tmp=low-1 */ + cum =((((int) (value-low+1))<cum) p = tmp_p; */ + + /* */ + if(p[8]*range>cum) + { + p+= 8; + } + /* */ + if(p[4]*range>cum) + { + p+= 4; + } + /* */ + if(p[2]*range>cum) + { + p+= 2; + } + /* */ + if(p[1]*range>cum) + { + p+= 1; + if((p==cum_freq+15) && (p[1]*range>cum)) + { + p+=1; + } + } + + symbol = p-cum_freq; + + high = low + mul_sbc_14bits(range,cum_freq[symbol]) - 1; + low += mul_sbc_14bits(range,cum_freq[symbol+1]); + + for (;;) + { + if ( high>=ari_q2new ) + { + if ( low>=ari_q2new ) + { + value -= ari_q2new; + low -= ari_q2new; + high -= ari_q2new; + } + else + { + if ( low>=ari_q1new && highlow = low; + s->high = high; + s->vobf = value; + + *res=symbol; +} + +/** + * \brief Only for 27 symbols with new extended Tables: + * based on tri's optimization + * based on extended Tables which need less branches for coding + * copied from ari_decode_14bits_s17_ext, with changes marked + * + * \param[i/o] st + * \param[o] res + * \param[i/o] s + * \param[i] cum_freq + */ +void ari_decode_14bits_s27_ext(Decoder_State *st, + int *res, + Tastat *s, + const unsigned short *cum_freq) +{ + unsigned long symbol; + unsigned long low, high, range, value; + unsigned long cum; + unsigned long il, ih, im; + + + + + /* read s->low,high,vobf sequentially */ + low = s->low; + high = s->high; + value = s->vobf; + + range = high-low+1; /* keep: tmp=low-1 */ + cum =((((int) (value-low+1))<cum) p = tmp_p; */ + + /* begin change when compared with ari_decode_14bits_s17_ext, + starting with line: if (p[8] * range > cum) { */ + il = 0; + ih = 27; + + /* do a five step binary search, using the interval [il, ih) */ + im = 13; /* (il + ih) >> 1 */ + if (cum_freq[im] * range > cum) + { + il = im; + } + else + { + ih = im; + } + + im = (il + ih) >> 1; + if (cum_freq[im] * range > cum) + { + il = im; + } + else + { + ih = im; + } + + im = (il + ih) >> 1; + if (cum_freq[im] * range > cum) + { + il = im; + } + else + { + ih = im; + } + + im = (il + ih) >> 1; + if (cum_freq[im] * range > cum) + { + il = im; + } + else + { + ih = im; + } + + if (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 = il + 1; /* (il + ih) >> 1 */ + if (cum_freq[im] * range > cum) + { + il = im; + } + } + + symbol = il; + /* end change when compared with ari_decode_14bits_s17_ext, + ending with line: symbol = p - cum_freq; */ + + high = low + mul_sbc_14bits(range,cum_freq[symbol]) - 1; + low += mul_sbc_14bits(range,cum_freq[symbol+1]); + + for (;;) + { + if ( high>=ari_q2new ) + { + if ( low>=ari_q2new ) + { + value -= ari_q2new; + low -= ari_q2new; + high -= ari_q2new; + } + else + { + if ( low>=ari_q1new && highlow = low; + s->high = high; + s->vobf = value; + + *res=symbol; +} + +/** + * \brief Only for decoding one bit with uniform probability: + * based on tri's optimization + * copied from ari_decode_14bits_s17_ext, with changes marked + * the equivalent cum_freq table used is {16384, 8192, 0} + * + * \param[i/o] st + * \param[o] res + * \param[i/o] s + */ +void ari_decode_14bits_bit_ext(Decoder_State *st, + int *res, + Tastat *s + ) +{ + unsigned long symbol; + unsigned long low, high, range, value; + unsigned long cum; + + + + + /* read s->low,high,vobf sequentially */ + low = s->low; + high = s->high; + value = s->vobf; + + range = high-low+1; /* keep: tmp=low-1 */ + cum =((((int) (value-low+1))<cum) p = tmp_p; */ + + /* begin change when compared with ari_decode_14bits_s17_ext, + starting with line: if (p[8] * range > cum) { */ + symbol = 0; + + if ((range << 13) > cum) + { + symbol = 1; + } + + if (symbol == 0) + { + /* high is unchanged */ + low = low + (range >> 1); + } + else + { + high = low + (range >> 1) - 1; + /* low is unchanged */ + } + /* end change when compared with ari_decode_14bits_s17_ext, + ending with line: low += mul_sbc_14bits(range, cum_freq[symbol + 1]); */ + + + for (;;) + { + if ( high>=ari_q2new ) + { + if ( low>=ari_q2new ) + { + value -= ari_q2new; + low -= ari_q2new; + high -= ari_q2new; + } + else + { + if ( low>=ari_q1new && highlow = low; + s->high = high; + s->vobf = value; + + *res=symbol; +} + +/*------------------------------------------------------------------------ + * 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 ) + * + *-------------------------------------------------------------------------*/ +long ari_decode_14bits_pow(const int *ptr, long bp, long bits, int *res, Tastat *s, unsigned base) +{ + unsigned long symbol; + unsigned long low, high, range, value; + unsigned long cum; + Word16 pows[12]; /* "base" to the power of 2, 4, 8,... 2^12 */ + Word16 lowlim, highlim=0, testval; + int k; + + + + low = s->low; + high = s->high + 1; + value = s->vobf; + lowlim = 0; + symbol = 0; + + range = high - low; + + /* the value read from bit-stream */ + assert(value >= low); + cum = ((((int) (value - low)) << stat_bitsnew) + (1 << stat_bitsnew) - 1); + + /* search for the interval where "cum" fits */ + if (((base >> 1) * range) > cum) /* below pow-1 */ + { + pows[0] = testval = base; + /* increase exponent until it is smaller than "cum" */ + for (k=1; k<12; k++) + { + highlim = testval; + pows[k] = mult_r(pows[k-1], pows[k-1]); + move16(); + testval = mult_r(pows[k], base); + if (((testval >> 1) * range) <= cum) /* found! big range is [lowlim,testval], (now narrow it down) */ + { + lowlim = testval; + k--; + symbol = 1<0; k--) + { + testval = mult_r(highlim, pows[k]); + if (((testval >> 1) * range) <= cum) + { + lowlim = testval; + symbol -= 1<<(k-1); + } + else + { + highlim = testval; + } + + + } + highlim >>= 1; + lowlim >>= 1; + } + else /* trivial case, above pow-1, that is, first symbol */ + { + symbol = 0; + lowlim = base >> 1; + highlim = 16384; + } + + + high = low + mul_sbc_14bits(range, highlim); + + low += mul_sbc_14bits(range, lowlim); + + /*ptr init for ptr*/ + for (; bp < bits;) + { + if (high > ari_q2new) + { + if (low >= ari_q2new) + { + value -= ari_q2new; + low -= ari_q2new; + high -= ari_q2new; + } + else + { + if (low >= ari_q1new && high <= ari_q3new) + { + value -= ari_q1new; + low -= ari_q1new; + high -= ari_q1new; + } + else + { + break; + } + } + } + low += low; + high += high; + + value = (value << 1) | ptr[bp++]; + } + + if( !(bp != bits || ! ((s->low == (int) low) && (s->high == (int) high) && (s->vobf == (int) value)) ) ) + { + /* This should not happen except of bit errors. */ + s->high = s->low = 0; + *res = 0; + return -1; + } + + s->low = low; + s->high = high - 1; + s->vobf = value; + + *res = symbol; + + + return bp; +} + + + +/*------------------------------------------------------------------------ + * Function: ari_decode_14bits_sign + * + * Decode a sign with equal probabilities. + *-------------------------------------------------------------------------*/ +long ari_decode_14bits_sign(const int *ptr, long bp, long bits, int *res, Tastat *s) +{ + unsigned long symbol; + unsigned long low, high, range, value; + unsigned long cum; + + + + low = s->low; + high = s->high + 1; + value = s->vobf; + + range = high - low; + + if (bp < bits) + { + assert(value >= low); + cum = ((((int) (value - low)) << stat_bitsnew) + (1 << stat_bitsnew) - 1); + if (8192 * range > cum) + { + symbol = 2; + high = low + (range >> 1); + } + else + { + symbol = 1; + low += range >> 1; + } + + /*ptr init for ptr*/ + for (; bp < bits;) + { + if (high > ari_q2new) + { + if (low >= ari_q2new) + { + value -= ari_q2new; + low -= ari_q2new; + high -= ari_q2new; + } + else + { + if (low >= ari_q1new && high <= ari_q3new) + { + value -= ari_q1new; + low -= ari_q1new; + high -= ari_q1new; + } + else + { + break; + } + } + } + low += low; + high += high; + + value = (value << 1) | ptr[bp++]; + } + } + else + { + cum = value-low; + range >>= 1; + if (range > cum) + { + symbol = 2; + high = low + range; + } + else + { + symbol = 1; + low += range; + } + } + + s->low = low; + s->high = high - 1; + s->vobf = value; + + *res = symbol; + + + return bp; +} diff --git a/lib_dec/ari_hm_dec.c b/lib_dec/ari_hm_dec.c new file mode 100644 index 000000000..fb7e05a21 --- /dev/null +++ b/lib_dec/ari_hm_dec.c @@ -0,0 +1,128 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "cnst.h" +#include "wmc_auto.h" +#include "stl.h" +#include "basop_util.h" +#include +#include +#include "prot.h" +#include "rom_com.h" + +/*-------------------------------------------------------------------* + * DecodeIndex() + * + * + *-------------------------------------------------------------------*/ + +int DecodeIndex( + Decoder_State *st, + int Bandwidth, + int *PeriodicityIndex) +{ + if ((st->tcx_hm_LtpPitchLag > 0) && (st->tcxltp_gain > kLtpHmGainThr)) + { + int LtpPitchIndex = ((st->tcx_hm_LtpPitchLag + (1 << (kLtpHmFractionalResolution - 1))) >> kLtpHmFractionalResolution) - 2; + *PeriodicityIndex = kLtpHmFlag; + *PeriodicityIndex |= get_next_indice(st, NumRatioBits[Bandwidth][LtpPitchIndex]); + ++*PeriodicityIndex; + *PeriodicityIndex |= LtpPitchIndex << 9; + return NumRatioBits[Bandwidth][LtpPitchIndex]; + } + else + { + *PeriodicityIndex = get_next_indice(st, 8); + return 8; + } +} + + +/*-------------------------------------------------------------------* + * tcx_hm_dequantize_gain() + * + * + *-------------------------------------------------------------------*/ + +static int tcx_hm_dequantize_gain( + int coder_type, /* i: GC/VC mode */ + int gain_idx, /* i: quantization index */ + Word16 *gain /* o: dequantized gain (Q11) */ +) +{ + assert(0 <= coder_type && coder_type <= 1); + + /* safety check in case of bit errors */ + if( !(0 <= gain_idx && gain_idx < (1 << kTcxHmNumGainBits)) ) + { + *gain = 0; + return 1; + } + + *gain = qGains[coder_type][gain_idx]; + + return 0; +} + + +/*-------------------------------------------------------------------* + * tcx_hm_decode() + * + * + *-------------------------------------------------------------------*/ + +void tcx_hm_decode( + int L_frame, /* i: number of spectral lines */ + Word32 env[], /* i/o: envelope shape (Q16) */ + int targetBits, /* i: target bit budget */ + int coder_type, /* i: GC/VC mode */ + const int prm_hm[],/* i: HM parameters */ + short LtpPitchLag, /* i: LTP pitch lag or -1 if none */ + float LtpGain, /* i: LTP gain */ + int *hm_bits /* o: bit consumption */ +) +{ + int NumTargetBits, fract_res, lag; + Word16 p[2*kTcxHmParabolaHalfWidth+1], gain; + + *hm_bits = 0; + + if( !(coder_type == VOICED || coder_type == GENERIC) ) + { + /* A bit error was encountered */ + *hm_bits = -1; + return; + } + + NumTargetBits = CountIndexBits( L_frame >= 256, prm_hm[1]) + targetBits; + + if (coder_type == VOICED) + { + NumTargetBits += kTcxHmNumGainBits; + } + *hm_bits = NumTargetBits - targetBits + 1; + + /* Convert the index to lag */ + UnmapIndex( prm_hm[1], L_frame >= 256, LtpPitchLag, (NumTargetBits <= kSmallerLagsTargetBitsThreshold) || (L_frame < 256), &fract_res, &lag ); + + /* Render the harmonic model */ + if( tcx_hm_render( lag, fract_res, LtpGain, p ) ) + { + /* A bit error was encountered */ + *hm_bits = -1; + return; + } + + /* Dequantize gain */ + + if( tcx_hm_dequantize_gain( 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 ); + + return; +} diff --git a/lib_dec/arith_coder_dec.c b/lib_dec/arith_coder_dec.c new file mode 100644 index 000000000..35d4af06d --- /dev/null +++ b/lib_dec/arith_coder_dec.c @@ -0,0 +1,185 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include "basop_util.h" +#include "basop_proto_func.h" + + +/*-------------------------------------------------------* + * tcx_arith_decode() + * + * + *-------------------------------------------------------*/ + +static int tcx_arith_decode( /* o: number of bits consumed */ + int L_frame, /* i: number of spectral lines */ + const Word16 envelope[], /* i: scaled envelope (Q15-e) */ + Word16 envelope_e, /* i: scaled envelope exponent (Q0) */ + int target_bits, /* i: target bit budget */ + const int prm[], /* i: bit-stream */ + float q_spectrum[] /* o: scalar quantized spectrum */ +) +{ + int bp, k, q, s; + Tastat as; + unsigned int exp_k; + Word16 tmp; + + + bp = ari_start_decoding_14bits_prm(prm, 0, &as); + tmp = sub(envelope_e, 1); + + for (k=0; k N_MAX_ARI || (target_bits > (ACELP_13k20/50)) || (target_bits <= 0) ) + { + /* this could happen in case of bit errors */ + st->BER_detect = 1; + L_spec = N_MAX_ARI; + *signaling_bits = 0; + *arith_bits = 0; + set_zero( q_spectrum, L_frame ); + + return; + } + + tcx_cfg = &st->tcx_cfg; + *signaling_bits = 0; + + assert(st->enableTcxLpc); + gamma_w = 1.0f; + gamma_uw = 1.0f/st->gamma; + +#define WMC_TOOL_SKIP + tcx_arith_render_envelope( A_ind, L_frame, L_spec, FL2WORD16(tcx_cfg->preemph_fac), FL2WORD16(gamma_w), FL2WORD16(0.5f*gamma_uw), env ); +#undef WMC_TOOL_SKIP + + if (use_hm) + { + if (prm_hm[0]) + { + tcx_hm_decode( L_spec, env, target_bits, coder_type, prm_hm, tcxltp_pitch, tcxltp_gain, &hm_bits ); + + if (hm_bits < 0) + { + st->BER_detect = 1; + *signaling_bits = 0; + *arith_bits = 0; + set_zero( q_spectrum, L_frame ); + + return; + } + } + else + { + hm_bits = 1; + } + *signaling_bits += hm_bits; + } + + L_spec_core = L_spec; + if (st->igf) + { + L_spec_core = 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 ); + + /* safety check in case of bit errors */ + if( *arith_bits < 0 ) + { + st->BER_detect = 1; + set_zero( q_spectrum, L_frame ); + } + + for (k=L_spec; k +#include "wmc_auto.h" +#include "options.h" +#include "prot.h" +#include "options.h" +#include "cnst.h" + + +/*-----------------------------------------------------------------* + * AVQ_demuxdec() + * + * Demultiplex and decode subvectors using + * split algebraic vector dequantizer based on RE8 latice. + *-----------------------------------------------------------------*/ + +void AVQ_demuxdec( + Decoder_State *st, /* i/o: decoder state structure */ + int xriq[], /* o: decoded subvectors [0..8*Nsv-1] */ + short *nb_bits, /* i/o: number of allocated bits */ + const short Nsv, /* i: number of subvectors */ + short nq_out[] /* i/o: AVQ nq index */ +) +{ + short i,j, bits, order_v; + long I[NSV_MAX]; + int nq[NSV_MAX], *kv, code[8]; + + kv = xriq; /* reuse vector to save memory */ + bits = *nb_bits; + + for(i = 0; i 8 ) + { + /* read the unary code including the stop bit for nq[i] */ + nq[i] = -1; + do + { + (nq[i])++; + + if (5 * nq[i] + 4 == bits) + { + break; + } + } + while ( get_next_indice_1( st ) ); + + if( 5*nq[i]+4 == bits ) /* check the overflow */ + { + bits++; /* overflow stop bit */ + } + + /* check for potential bit errors */ + if( nq[i] > NB_SPHERE ) + { + st->BER_detect = 1; + set_i( xriq, 0, Nsv*8 ); + set_s( nq_out, 0, Nsv ); + *nb_bits = 0; + + return; + } + + bits -= (short)nq[i]; + bits--; /* count the stop bit */ + + if( nq[i] > 0 ) + { + nq[i]++; + } + + /* read codebook indices (rank I and event. Voronoi index kv) */ + if( nq[i] == 0 ) /* Q0 */ + { + /* nothing to read */ + } + else if( nq[i] < 5 ) /* Q2, Q3, Q4 */ + { + I[i] = get_next_indice( st, (short)(4*nq[i]) ); + bits -= (short)(4*nq[i]); + } + else if( nq[i]%2 == 0 ) /* Q4 + Voronoi extensions r=1,2,3,... */ + { + I[i] = get_next_indice( st, 4*4 ); + bits -= 4*4; + order_v = (short)(nq[i]/2) - 2; + + for( j=0; j<8; j++ ) + { + kv[i*8+j] = get_next_indice( st, order_v ); + } + bits -= 8*order_v; + } + else /* Q3 + Voronoi extensions r=1,2,3,... */ + { + I[i] = get_next_indice( st, 4*3 ); + bits -= 4*3; + order_v = (short)(nq[i]/2) - 1; + + for( j=0; j<8; j++ ) + { + kv[i*8+j] = get_next_indice( st, order_v ); + } + bits -= 8*order_v; + } + } + } /* for */ + + /* decode all subvectors */ + for( i=0; i=0; l-- ) + { + nq = indx[l]; /* quantizer number (0,2,3..n) */ + + nk = 0; + n = nq; + + if( nq > 4 ) + { + nk = (nq-3)>>1; + n = nq - nk*2; + } + + /* read n groups of 4-bit for Voronoi index (k[]) */ + for( i=0; i<8; i++) + { + kv[i] = 0; + } + + while( nk-- > 0 ) + { + ival = (indx[pos--] & 0x0F); + ival <<= 4; + ival += (indx[pos--] & 0x0F); + + for( i=7; i>=0; i-- ) + { + kv[i] <<= 1; + kv[i] += (ival & 0x01); + ival >>= 1; + } + } + + /* read n groups of 4-bit for base codebook index (I) */ + I = 0; + while( n-- > 0 ) + { + I <<= 4; + I += (indx[pos--] & 0x0F); + } + + /* multi-rate RE8 decoder */ + re8_dec( nq, I, kv, c ); + + /* write decoded RE8 vector */ + for( i=0; i<8; i++ ) + { + nvecq[(l*8)+i] = c[i]; + } + } + + return; +} diff --git a/lib_dec/bass_psfilter.c b/lib_dec/bass_psfilter.c new file mode 100644 index 000000000..08e83305f --- /dev/null +++ b/lib_dec/bass_psfilter.c @@ -0,0 +1,471 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "prot.h" +#include "cnst.h" +#include "rom_com.h" +#include "options.h" +#include + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ + +#define NBPSF_L_EXTRA 120 + +#define BPF_STOP_STOPBAND_16 16 + + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ + +static short Pit_track( float syn[], short T ); + +/*---------------------------------------------------------------------* + * bass_psfilter_init() + * + * Initialisation of postfiltering variables + *---------------------------------------------------------------------*/ + +void bass_psfilter_init( + float old_syn[], /* o : Old synthesis buffer 1 */ + float *mem_deemph_err, /* o : Error deemphasis memory */ + float *lp_ener /* o : long_term error signal energy */ +) +{ + /* post-filter memories */ + *mem_deemph_err = 0.0f; + *lp_ener = 0.0f; + set_f( old_syn, 0, NBPSF_PIT_MAX ); + + return; +} + +/*---------------------------------------------------------------------* + * bass_psfilter() + * + * Perform low-frequency postfiltering + *---------------------------------------------------------------------*/ + +void bass_psfilter( + const short Opt_AMR_WB, /* i : AMR-WB IO flag */ + const float synth_in[], /* i : input synthesis (at 16kHz) */ + const short L_frame, /* i : length of the last frame */ + const float pitch_buf[], /* i : pitch for every subfr [0,1,2,3] */ + float old_syn[], /* i/o: NBPSF_PIT_MAX */ + float *mem_deemph_err, /* i/o: Error deemphasis memory */ + float *lp_ener, /* i/o: long_term error signal energy */ + const short bpf_off, /* i : do not use BPF when set to 1 */ + float v_stab, /* i : stability factor */ + float *v_stab_smooth, /* i/o: smoothed stability factor */ + float *mem_mean_pit, /* i/o: average pitch memory */ + short *Track_on_hist, /* i/o: History of half frame usage */ + short *vibrato_hist, /* i/o: History of frames declared as vibrato*/ + float *psf_att, /* i/o: Post filter attenuation factor */ + const short coder_type, /* i : coder_type */ + float bpf_noise_buf[] /* o : BPF error signal (at int_fs) */ +) +{ + short i, i_subfr, T; + float gain, alpha, corr, ener; + float syn_buf[NBPSF_PIT_MAX+L_FRAME16k+NBPSF_PIT_MAX], *syn; + float syn2_buf[L_FRAME16k], *syn2; + float err[L_HALFR16k]; + short T_sf[NB_SUBFR16k]; + short nb_subfr, T_update; + float delta_v_stab; + short dist_pit_diff, idx_pit_min, idx_pit_max, vibrato, Track_on; + float loc_pit_max, loc_pit_min, diff_pit; + float TrackOnR, vibratR, alp_tmp; + + Track_on = 0; + T_update = 01; + vibrato = 0; + nb_subfr = L_frame/L_SUBFR; + + /*------------------------------------------------------- + * 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------| + * + *-------------------------------------------------------*/ + + mvr2r( old_syn, syn_buf, NBPSF_PIT_MAX ); + mvr2r( synth_in, syn_buf + NBPSF_PIT_MAX, L_frame ); + + if( !(pitch_buf == NULL || bpf_off) ) + { + for(i = L_TRACK_HIST-1; i > 0; i--) + { + mem_mean_pit[i] = mem_mean_pit[i-1]; + } + + mem_mean_pit[i] = mean( pitch_buf, nb_subfr ); + } + + idx_pit_min = minimum(mem_mean_pit, L_TRACK_HIST, &loc_pit_min); + idx_pit_max = maximum(mem_mean_pit, L_TRACK_HIST, &loc_pit_max); + + dist_pit_diff = (short)abs(idx_pit_max - idx_pit_min); + diff_pit = loc_pit_max-loc_pit_min; + + if( L_frame == L_FRAME16k ) + { + diff_pit *= 0.8f; + } + + if( coder_type != INACTIVE && diff_pit >= 2.0f && diff_pit < 10 && dist_pit_diff>= 3) + { + vibrato = 1; + } + + TrackOnR = (float)sum_s(Track_on_hist,L_TRACK_HIST)/L_TRACK_HIST; + vibratR = (float)sum_s(vibrato_hist,L_TRACK_HIST); + alp_tmp = 1.0f-TrackOnR; + + if( vibrato ) + { + vibratR = vibratR * vibratR * -0.009f + 1.0f; + alp_tmp *= vibratR; + } + + alp_tmp = max( 0.1f, alp_tmp ); + + if( alp_tmp > *psf_att ) + { + *psf_att = 0.05f * alp_tmp + 0.95f * *psf_att; + } + else + { + *psf_att = 0.4f * alp_tmp + 0.6f * *psf_att; + } + + if( pitch_buf == NULL || bpf_off ) + { + /* do not use BPF for HQ core */ + T_update = 80; + set_s( T_sf, 0, 5 ); + syn = &syn_buf[NBPSF_PIT_MAX+L_frame]; + for (i=0; i NBPSF_PIT_MAX ) + { + T_sf[i] = NBPSF_PIT_MAX; + } + } + else + { + if( T_sf[i] > PIT_MAX ) + { + T_sf[i] = PIT_MAX; + } + } + } + + T = T_sf[nb_subfr-1]; + syn = &syn_buf[NBPSF_PIT_MAX+L_frame]; + for( i=0; i=PIT_MIN && Opt_AMR_WB ) + { + T = Pit_track( syn, T ); + + if( T != T_sf[i_subfr/L_SUBFR] ) + { + Track_on = 1; + } + } + + /* symetric pitch prediction : phase is opposite between harmonic */ + for( i=0; i 0.5f) + { + alpha = 0.5f; + } + + alpha *= (*psf_att); + if (alpha > 0.3f && Track_on) + { + alpha = 0.3f; + } + else if (alpha > 0.4f && vibrato ) + { + alpha = 0.4f; + } + + if( alpha < 0.0f ) + { + alpha = 0.0f; + } + + *v_stab_smooth = 0.8f * v_stab + 0.2f * (*v_stab_smooth); + delta_v_stab = (float) fabs(*v_stab_smooth - v_stab); + v_stab = (float) pow(v_stab, 0.5f); + alpha = (1.0f + 0.15f*v_stab - 2.0f*delta_v_stab) * alpha; + + for (i=0; i 0; i-- ) + { + Track_on_hist[i] = Track_on_hist[i-1]; + vibrato_hist[i] = vibrato_hist[i-1]; + } + + Track_on_hist[i] = Track_on; + vibrato_hist[i] = vibrato; + + mvr2r( syn_buf+L_frame, old_syn, NBPSF_PIT_MAX ); + + return; +} + + +/*---------------------------------------------------------------------* + * Pit_track() + * + * Perform pitch tracking and test pitch/2 to avoid continuous pitch doubling + *---------------------------------------------------------------------*/ + +static short Pit_track(/* o : Pitch */ + float syn[], /* i : synthesis [-NBPSF_PIT_MAX..L_HALFR16k] */ + short T /* i : pitch period (>= PIT_MIN) */ +) +{ + short i, T2; + float tmp, corr, ener, cn; + float *v1, *v2; + + /*----------------------------------------------------------------* + * Test pitch/2 to avoid continuous pitch doubling + * (short pitch is limited to PIT_MIN (34 = 376Hz) by the encoder + *----------------------------------------------------------------*/ + + T2 = T>>1; + + v1 = &syn[-NBPSF_L_EXTRA]; + v2 = &syn[-T2-NBPSF_L_EXTRA]; + + ener = 0.01f; + for (i=0; i 0.95f) + { + T = T2; + } + + return(T); +} + + +/*---------------------------------------------------------------------* + * addBassPostFilter() + * + * Add BPF component in cldfb domain + *---------------------------------------------------------------------*/ + +void addBassPostFilter( + const float *harm_timeIn, + int samplesToProcess, + float **rAnalysis, + float **iAnalysis, + HANDLE_CLDFB_FILTER_BANK cldfb +) +{ + float *tmp_R[CLDFB_NO_COL_MAX]; + float *tmp_I[CLDFB_NO_COL_MAX]; + float cldfbBufferReal[CLDFB_NO_COL_MAX][20]; + float cldfbBufferImag[CLDFB_NO_COL_MAX][20]; + short i, b; + int maxBand; + const float *weights; + int nCol = cldfb->no_col; + int nColToProcess = nCol; + int nChan = cldfb->no_channels; + + if( samplesToProcess > -1 ) + { + nColToProcess = ((samplesToProcess + cldfb->no_channels - 1) / cldfb->no_channels); + } + + assert(nCol == 16); + + weights = bpf_weights_16; + + if( nChan > BPF_STOP_STOPBAND_16 ) + { + maxBand = BPF_STOP_STOPBAND_16; + } + else + { + maxBand = nChan; + } + + for (i=0; i < nColToProcess; i++) + { + tmp_R[i] = cldfbBufferReal[i]; + tmp_I[i] = cldfbBufferImag[i]; + } + + /* do the analysis of filtered signal */ + cldfbAnalysis( harm_timeIn, tmp_R, tmp_I, samplesToProcess, cldfb ); + + /* now do the subtraction */ + for( i = 0; i < nColToProcess; i++ ) + { + /* loop over low frequency bands */ + for( b = 0; b < maxBand; b++ ) + { + rAnalysis[i][b] -= weights[b] * tmp_R[i][b]; + iAnalysis[i][b] -= weights[b] * tmp_I[i][b]; + } + } + + return; +} diff --git a/lib_dec/cng_dec.c b/lib_dec/cng_dec.c new file mode 100644 index 000000000..09cda38d2 --- /dev/null +++ b/lib_dec/cng_dec.c @@ -0,0 +1,714 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*---------------------------------------------------------------------* + * Local function + *---------------------------------------------------------------------*/ + +static void shb_CNG_decod( Decoder_State *st, const float *synth, float *shb_synth, const short sid_bw ); + + +/*---------------------------------------------------------------------* + * CNG_dec() + * + * Decoding of CNG parameters + *---------------------------------------------------------------------*/ + +void CNG_dec( + Decoder_State *st, /* i/o: State structure */ + const short L_frame, /* i : length of the frame */ + float Aq[], /* o : LP coefficients */ + const long core_brate, /* i : core bitrate */ + float *lsp_new, /* i/o: current frame LSPs */ + float *lsf_new, /* i/o: current frame LSFs */ + short *allow_cn_step /* o : allow CN step */ + ,short *sid_bw /* i : 0-NB/WB, 1-SWB SID */ + ,float *q_env +) +{ + float step; + short i, enr_index; + short num_bits; + float enr, weights; + short m = 0; + short ptr, j, k; + short m1; + float tmp[HO_HIST_SIZE*M]; + short burst_ho_cnt = 0; + short ll, s_ptr; + float lsf_tmp[M]; + float C[M]; + float max[2]; + short max_idx[2]; + float ftmp; + float lsp_tmp[M]; + float dev; + float max_dev; + float dist; + short env_idx[2]; + float enr1; + float env[NUM_ENV_CNG]; + float tmp_env[HO_HIST_SIZE*NUM_ENV_CNG]; + short LSF_Q_prediction; /* o : LSF prediction mode - just temporary variable in CNG */ + short tmp1; + + /*-----------------------------------------------------------------* + * Decode CNG spectral envelope (only in SID frame) + *-----------------------------------------------------------------*/ + + if ( core_brate == SID_1k75 || core_brate == SID_2k40 ) + { + /* de-quantize the LSF vector */ + if ( st->Opt_AMR_WB ) + { + isf_dec_amr_wb( st, Aq, lsf_new, lsp_new ); + } + else + { + lsf_dec( st, 0, L_frame, INACTIVE, -1, Aq, &LSF_Q_prediction, lsf_new, lsp_new, 0 ); + } + } + else + { + /* Use old LSP vector */ + mvr2r( st->lsp_old, lsp_new, M ); + mvr2r( st->lsf_old, lsf_new, M ); + } + + /* Initialize the CNG spectral envelope in case of the very first CNG frame */ + if( st->first_CNG == 0 ) + + { + mvr2r( st->lsp_old, st->lspCNG, M ); + } + + /*-----------------------------------------------------------------* + * Decode residual signal energy + *-----------------------------------------------------------------*/ + + *allow_cn_step = 0; + if( core_brate == SID_1k75 || core_brate == SID_2k40 ) + { + if( core_brate == SID_2k40 ) + { + step = STEP_SID; + } + else + { + step = STEP_AMR_WB_SID; + } + + /* intialize the energy quantization parameters */ + if( !st->Opt_AMR_WB ) + { + num_bits = 7; + } + else + { + num_bits = 6; + } + + /* decode the energy index */ + enr_index = (short) get_next_indice( st, num_bits ); + + if ( st->last_core_brate <= SID_2k40 || st->prev_bfi==1 ) + { + tmp1 = st->old_enr_index + 20; + } + else + { + tmp1 = st->old_enr_index + 40; + } + if ((enr_index > tmp1) && (st->old_enr_index >= 0)) /* Likely bit error , and not startup */ + { + enr_index = tmp1; + enr_index = min(enr_index, 127); + if (st->Opt_AMR_WB != 0) + { + enr_index = min(enr_index, 63); + } + } + + if ( st->last_core_brate > SID_2k40 && + st->first_CNG != 0 && + st->old_enr_index >= 0 && + enr_index > st->old_enr_index + 1 + ) + { + *allow_cn_step = 1; + } + st->old_enr_index = enr_index; + if ( enr_index == 0 ) + { + enr_index = -5; + } + st->Enew = enr_index / step - 2.0f; + + /* find the new energy value */ + st->Enew = (float)( pow( 2.0, st->Enew ) ); + + /* decode SID type */ + if( core_brate == SID_2k40 ) + { + burst_ho_cnt = (short) get_next_indice( st, 3 ); + + *sid_bw = (short) get_next_indice( st, 1 ); + if ( *sid_bw == 0 ) + { + env_idx[0] = (short) get_next_indice( st, 6 ); + + /* get quantized res_env_details */ + for ( i=0; ibwidth == WB && st->first_CNG && st->L_frame != st->last_CNG_L_frame ) + { + st->ho_hist_size = 0; + } + } + + /*---------------------------------------------------------------------* + * CNG spectral envelope update + * Find A(z) coefficients + *---------------------------------------------------------------------*/ + + if( st->last_core_brate == FRAME_NO_DATA || st->last_core_brate == SID_1k75 || st->last_core_brate == SID_2k40 ) + { + /* Reset hangover counter if not first SID period */ + if( st->core_brate > FRAME_NO_DATA ) + { + st->num_ho = 0; + } + + /* Update LSPs if last SID energy not outlier or insufficient number of hangover frames */ + if( st->num_ho < 3 || st->Enew < 1.5f * st->lp_ener ) + { + for( i=0; ilspCNG[i] = CNG_ISF_FACT * st->lspCNG[i] + (1-CNG_ISF_FACT) * lsp_new[i]; + } + } + } + else + { + /* Update CNG_mode, if allowed */ + if( ( st->Opt_AMR_WB || st->bwidth == WB ) && ( !st->first_CNG || st->act_cnt2 >= MIN_ACT_CNG_UPD ) ) + { + if( st->last_active_brate > ACELP_16k40 ) + { + st->CNG_mode = -1; + } + else if( st->last_active_brate > ACELP_13k20 ) + { + st->CNG_mode = 4; + } + else if( st->last_active_brate > ACELP_9k60 ) + { + st-> CNG_mode = 3; + } + else if( st->last_active_brate > ACELP_8k00 ) + { + st->CNG_mode = 2; + } + else if( st->last_active_brate > ACELP_7k20 ) + { + st->CNG_mode = 1; + } + else + { + st->CNG_mode = 0; + } + } + + /* If first sid after active burst update LSF history from circ buffer */ + burst_ho_cnt = min(burst_ho_cnt, st->ho_circ_size); + st->act_cnt = 0; + s_ptr = st->ho_circ_ptr-burst_ho_cnt+1; + if( s_ptr < 0 ) + { + s_ptr += st->ho_circ_size; + } + + for( ll= (short) burst_ho_cnt ; ll > 0 ; ll-- ) + { + if( ++(st->ho_hist_ptr) == HO_HIST_SIZE ) + { + st->ho_hist_ptr = 0; + } + /* Conversion between 12.8k and 16k LSPs */ + if( ( L_frame == L_FRAME16k && st->ho_16k_lsp[s_ptr] == 0 ) || ( L_frame == L_FRAME && st->ho_16k_lsp[s_ptr] == 1 ) ) + { + lsp_convert_poly( &st->ho_lsp_circ[s_ptr*M], L_frame, 0 ); + } + + /* update circular buffers */ + mvr2r(&(st->ho_lsp_circ[s_ptr*M]), &(st->ho_lsp_hist[st->ho_hist_ptr*M]), M ); + mvr2r(&(st->ho_ener_circ[s_ptr]), &(st->ho_ener_hist[st->ho_hist_ptr]), 1 ); + st->ho_sid_bw = ( st->ho_sid_bw & 0x3fffffffL ) << 1; + mvr2r(&(st->ho_env_circ[s_ptr*NUM_ENV_CNG]), &(st->ho_env_hist[st->ho_hist_ptr*NUM_ENV_CNG]), NUM_ENV_CNG ); + + st->ho_hist_size++; + if (st->ho_hist_size > HO_HIST_SIZE) + { + st->ho_hist_size = HO_HIST_SIZE; + } + + s_ptr++; + + if( s_ptr == st->ho_circ_size ) + { + s_ptr = 0; + } + } + if( st->ho_hist_size > 0) + { + *allow_cn_step |= ( st->ho_ener_hist[st->ho_hist_ptr] > 4.0f * st->lp_ener ); + } + + if ( !*allow_cn_step && st->ho_hist_size > 0 ) + { + ptr = st->ho_hist_ptr; + mvr2r( &(st->ho_lsp_hist[ptr*M]), tmp, M ); + m1 = 0; + if( (st->ho_sid_bw & 0x1L) == 0 ) + { + mvr2r( &st->ho_env_hist[ptr*NUM_ENV_CNG], tmp_env, NUM_ENV_CNG ); + m1 = 1; + } + enr = W_DTX_HO[0] * st->ho_ener_hist[ptr]; + weights = W_DTX_HO[0]; + m = 1; + for( k=1; kho_hist_size; k++ ) + { + ptr--; + if( ptr < 0 ) + { + ptr = HO_HIST_SIZE - 1; + } + + if ( st->ho_ener_hist[ptr] < st->ho_ener_hist[st->ho_hist_ptr] * BUF_H_NRG && + st->ho_ener_hist[ptr] > st->ho_ener_hist[st->ho_hist_ptr] * BUF_L_NRG ) + { + enr += W_DTX_HO[k] * st->ho_ener_hist[ptr]; + weights += W_DTX_HO[k]; + mvr2r( &st->ho_lsp_hist[ptr*M], &tmp[m*M], M ); + if( (st->ho_sid_bw & (0x1L << k)) == 0 ) + { + mvr2r( &st->ho_env_hist[ptr*NUM_ENV_CNG], &tmp_env[m1*NUM_ENV_CNG], NUM_ENV_CNG ); + m1++; + } + m++; + } + } + + enr /= weights; + st->lp_ener = enr; + + set_f( max, 0.0f, 2 ); + set_s( max_idx, 0, 2 ); + + for( i=0; iL_frame == L_FRAME ) + { + lsp2lsf( &tmp[i*M], lsf_tmp, M, INT_FS_12k8 ); + ftmp = 6400.0f / (M+1); + C[i] = (6400.0f - lsf_tmp[M-1] - ftmp) * (6400.0f - lsf_tmp[M-1] - ftmp); + } + else + { + lsp2lsf( &tmp[i*M], lsf_tmp, M, INT_FS_16k ); + ftmp = 8000.0f / (M+1); + C[i] = (8000.0f - lsf_tmp[M-1] - ftmp) * (8000.0f - lsf_tmp[M-1] - ftmp); + } + + C[i] += (lsf_tmp[0] - ftmp) * (lsf_tmp[0] - ftmp); + + for ( j=0; j max[0] ) + { + max[1] = max[0]; + max_idx[1] = max_idx[0]; + max[0] = C[i]; + max_idx[0] = i; + } + else if ( C[i] > max[1] ) + { + max[1] = C[i]; + max_idx[1] = i; + } + } + + if ( m == 1 ) + { + mvr2r( tmp, lsp_tmp, M ); + } + else if ( m < 4 ) + { + for ( i=0; i max_dev ) + { + max_dev = dev; + } + } + + if ( dist > 0.4f || max_dev > 0.1f ) + { + for( i=0; ilspCNG[i] = lsp_tmp[i]; + } + } + else + { + for( i=0; ilspCNG[i] = 0.8f * lsp_tmp[i] + (1-0.8f) * lsp_new[i]; + } + } + if( m1 > 0 ) + { + for ( i=0; ilp_ener; + } + mvr2r(env, st->lp_env, NUM_ENV_CNG); + } + } + else + { + mvr2r( lsp_new, st->lspCNG, M ); /* use newly analyzed parameters */ + } + } + + if( core_brate == SID_1k75 || core_brate == SID_2k40 ) + { + /* Update hangover memory during CNG */ + if ( !*allow_cn_step && (st->Enew < 1.5f * st->lp_ener) ) + { + /* update the pointer to circular buffer of old LSP vectors */ + if( ++(st->ho_hist_ptr) == HO_HIST_SIZE ) + { + st->ho_hist_ptr = 0; + } + + /* update the circular buffer of old LSP vectors with the new LSP vector */ + mvr2r( lsp_new, &(st->ho_lsp_hist[(st->ho_hist_ptr)*M]), M ); + + /* update the hangover energy buffer */ + st->ho_ener_hist[st->ho_hist_ptr] = st->Enew; + if ( core_brate == SID_2k40 && *sid_bw == 0 ) + { + enr1 = (float)log10( st->Enew*L_frame + 0.1f ) / (float)log10( 2.0f ); + for ( i=0; iEnew; + } + st->ho_sid_bw = ( st->ho_sid_bw & 0x3fffffffL ) << 1; + mvr2r( env, &(st->ho_env_hist[(st->ho_hist_ptr)*NUM_ENV_CNG]), NUM_ENV_CNG ); + } + else if( *sid_bw != 0 ) + { + st->ho_sid_bw = ( st->ho_sid_bw & 0x3fffffffL ) << 1; + st->ho_sid_bw |= 0x1L; + } + if(++(st->ho_hist_size) > HO_HIST_SIZE) + { + st->ho_hist_size = HO_HIST_SIZE; + } + } + + /* Update the frame length memory */ + st->last_CNG_L_frame = st->L_frame; + + if( core_brate != SID_1k75 ) + { + st->num_ho = m; + } + } + + if ( st->Opt_AMR_WB ) + { + isp2a( st->lspCNG, Aq, M ); + } + else + { + lsp2a_stab( st->lspCNG, Aq, M ); + } + + for( i=1; icore_brate == FRAME_NO_DATA || st->core_brate == SID_2k40 ) + { + /* SHB SID decoding and CNG */ + if ( st->cng_type == LP_CNG && st->extl == SWB_CNG ) + { + shb_CNG_decod( st, synth, shb_synth, sid_bw ); + } + st->last_vad = 0; + st->burst_cnt = 0; + } + else + { + st->last_vad = 1; + st->burst_cnt++; + if ( st->burst_cnt > 10 ) + { + st->burst_cnt = 0; + } + } + + return; +} + +/*---------------------------------------------------------------------* + * shb_CNG_decod() + * + * Main routine of SHB SID decoding and CNG + *---------------------------------------------------------------------*/ + +static void shb_CNG_decod( + Decoder_State *st, /* i/o: State structure */ + const float *synth, /* i : ACELP core synthesis at 32kHz */ + float *shb_synth, /* o : high-band CNG synthesis */ + const short sid_bw /* i : 0-NB/WB, 1-SWB SID */ +) +{ + short i; + short idx_ener; + float shb_lpcCNG[LPC_SHB_ORDER+1]; + float shb_lspCNG[LPC_SHB_ORDER]; + float excTmp[L_FRAME16k]; + float excSHB[L_FRAME16k]; + float ener_excSHB; + float wb_ener; + float gain; + float shb_syn16k[L_FRAME16k]; + float ftmp; + float step; + float interp; + float ener; + short allow_cn_step=0; + + if( !st->bfi ) + { + if ( st->core_brate == SID_2k40 && sid_bw == 1 ) + { + idx_ener = (short) get_next_indice( st, 4 ); + + if ( idx_ener == 0 ) + { + idx_ener = -15; + } + + /* de-quantization of SHB CNG parameters */ + st->last_shb_cng_ener = ((float)idx_ener/0.9f - 6.0f) * (float)log10(2.0f) * 10.0f; + } + } + + /* SHB spectrum estimation */ + interp = ((float)st->shb_dtx_count)/32; + interp = min( interp, 1.0f ); + for ( i=0; ilsp_shb_prev[i]; + shb_lspCNG[i] += (1 - interp) * st->lsp_shb_prev_prev[i]; + } + + if( st->shb_dtx_count < 1000 ) + { + st->shb_dtx_count++; + } + + lsp2a ( shb_lpcCNG, shb_lspCNG, LPC_SHB_ORDER ); + shb_lpcCNG[0] = 1.0f; + + /* SHB energy estimation */ + wb_ener = 0.001f; + for ( i=0; ifirst_CNG == 0 ) + { + st->wb_cng_ener = wb_ener; + } + if ( fabs(wb_ener - st->wb_cng_ener) > 12.0f ) + { + allow_cn_step = 1; + } + + if ( allow_cn_step == 1 ) + { + st->wb_cng_ener = wb_ener; + } + else + { + ftmp = wb_ener - st->wb_cng_ener; + st->wb_cng_ener += 0.9f * ftmp; + } + if ( st->core_brate == SID_2k40 && sid_bw == 1 && !st->bfi ) + { + st->last_wb_cng_ener = st->wb_cng_ener; + + if ( st->first_CNG == 0 ) + { + st->shb_cng_ener = st->last_shb_cng_ener; + } + } + + gain = st->wb_cng_ener - st->last_wb_cng_ener; + if ( gain > 15 ) + { + gain = 15; + } + step = gain + st->last_shb_cng_ener - st->shb_cng_ener; + if ( allow_cn_step == 1 || st->last_core_brate > SID_2k40 ) + { + st->shb_cng_ener += step; + } + else + { + st->shb_cng_ener += 0.25f * step; + } + /* generate white noise excitation */ + for ( i=0; iswb_cng_seed ); + } + + /* synthesis filtering */ + syn_filt( shb_lpcCNG, LPC_SHB_ORDER, excTmp, excSHB, L_FRAME16k, st->state_lpc_syn , 1 ); + + /* synthesis signal gain shaping */ + ener_excSHB = 0.001f; + for ( i=0; ilast_vad == 1 ) + { + if ( st->burst_cnt > 3 && st->last_core != HQ_CORE ) + { + st->trans_cnt = 5; + } + else + { + st->trans_cnt = 0; + } + } + + if ( st->trans_cnt > 0 ) + { + i = (short)((float)st->trans_cnt / 15.0f * 255); + ener = st->shb_cng_ener + sin_table256[i] * (st->last_shb_ener - st->shb_cng_ener); + st->trans_cnt--; + } + else + { + ener = st->shb_cng_ener; + } + + gain = (float)sqrt( pow(10, 0.1f*ener)*L_FRAME16k/ener_excSHB ); + + for ( i=0; igenSHBsynth_Hilbert_Mem, st->genSHBsynth_state_lsyn_filt_shb_local, st->L_frame, &(st->syn_dm_phase) ); + + if ( st->output_Fs == 48000 ) + { + interpolate_3_over_2_allpass( shb_synth, L_FRAME32k, shb_synth, st->interpol_3_2_cng_dec, allpass_poles_3_ov_2 ); + } + ResetSHBbuffer_Dec( st ); + return; +} diff --git a/lib_dec/core_dec_init.c b/lib_dec/core_dec_init.c new file mode 100644 index 000000000..3c119b5ae --- /dev/null +++ b/lib_dec/core_dec_init.c @@ -0,0 +1,669 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "stat_com.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*-----------------------------------------------------------------------* + * open_decoder_LPD() + * + * Initialization of state variables + *-----------------------------------------------------------------------*/ + +void open_decoder_LPD( + Decoder_State *st, + const int bit_rate, + const int bandwidth +) +{ + short i; + short mdctWindowLength; + short mem_syn_r_size_old; + short mem_syn_r_size_new; + short fscaleFB; + short mdctWindowLengthFB; + short encoderLookahead, encoderLookaheadFB; + + st->total_brate = bit_rate; + st->fscale_old = st->fscale; + st->sr_core = getCoreSamplerateMode2(st->total_brate, bandwidth, st->rf_flag); + st->fscale = sr2fscale(st->sr_core); + fscaleFB = sr2fscale(st->output_Fs); + + /* initializing variables for frame lengths etc. right in the beginning */ + st->L_frame = st->sr_core / 50; + st->L_frameTCX = st->output_Fs / 50; + if (st->ini_frame == 0) + { + st->last_L_frame = st->L_frame_past = st->L_frame; + st->L_frameTCX_past = st->L_frameTCX; + } + + st->tcxonly = getTcxonly(bit_rate); + + /* the TD TCX PLC in MODE1 still runs with 80ms subframes */ + if ( (st->L_frame == L_FRAME16k && st->total_brate <= ACELP_32k) || (st->tcxonly && (st->sr_core == 32000 || st->sr_core == 16000))) + { + st->nb_subfr = NB_SUBFR16k; + } + else + { + st->nb_subfr = NB_SUBFR; + } + st->bits_frame = (int) ( ((float)st->L_frame/(float)st->fscale) * (float)FSCALE_DENOM/128.0f * (float)bit_rate /100.0f +0.49f); + + st->TcxBandwidth = getTcxBandwidth(bandwidth); + st->narrowBand = (bandwidth == NB)? 1: 0; + encoderLookahead = (L_LOOK_12k8*st->fscale)/FSCALE_DENOM; + encoderLookaheadFB = (L_LOOK_12k8*fscaleFB)/FSCALE_DENOM; + + 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 == 0) + { + st->pit_res_max_past = st->pit_res_max; + } + st->pit_max_TCX = st->pit_max * st->output_Fs / st->sr_core; + st->pit_min_TCX = st->pit_min * st->output_Fs / st->sr_core; + + /*Preemphasis param*/ + if (st->fscale < (16000*FSCALE_DENOM)/12800) + { + st->preemph_fac = PREEMPH_FAC; /*NB*/ + } + else if (st->fscale < (24000*FSCALE_DENOM)/12800) + { + st->preemph_fac = PREEMPH_FAC_16k; /*WB*/ + } + else + { + st->preemph_fac = PREEMPH_FAC_SWB; /*SWB*/ + } + + if( st->sr_core==16000 ) + { + st->gamma = GAMMA16k; + } + else + { + st->gamma = GAMMA1; + } + + /* LPC quantization */ + if ( st->sr_core <= 16000 && st->tcxonly==0 ) + { + st->lpcQuantization = 1; + } + else + { + st->lpcQuantization = 0; + } + + if ( st->tcxonly==0 ) + { + st->numlpc = 1; + } + else + { + st->numlpc = 2; + } + + /* Initialize TBE */ + st->prev_coder_type = GENERIC; + set_f( st->prev_lsf_diff, 0.5f, LPC_SHB_ORDER-2 ); + st->prev_tilt_para = 0.0f; + set_zero( st->cur_sub_Aq, M+1 ); + + /*TCX config*/ + st->tcx_cfg.preemph_fac=st->preemph_fac; + st->tcx_cfg.tcx_mdct_window_length_old=st->tcx_cfg.tcx_mdct_window_length; + mdctWindowLength = getMdctWindowLength(st->fscale); + mdctWindowLengthFB = getMdctWindowLength(fscaleFB); + + /* Initialize the TCX MDCT window */ + st->tcx_cfg.tcx_mdct_window_delay = mdctWindowLength; + st->tcx_cfg.tcx_mdct_window_delayFB = mdctWindowLengthFB; + st->tcx_cfg.tcx_mdct_window_length = mdctWindowLength; + st->tcx_cfg.tcx_mdct_window_lengthFB = mdctWindowLengthFB; + + mdct_window_sine( st->tcx_cfg.tcx_mdct_window, st->tcx_cfg.tcx_mdct_window_length ); + mdct_window_sine( st->tcx_cfg.tcx_mdct_windowFB, st->tcx_cfg.tcx_mdct_window_lengthFB ); + set_zero(st->tcx_cfg.tcx_mdct_window + st->tcx_cfg.tcx_mdct_window_length, L_MDCT_OVLP_MAX - st->tcx_cfg.tcx_mdct_window_length); + set_zero(st->tcx_cfg.tcx_mdct_windowFB + st->tcx_cfg.tcx_mdct_window_lengthFB, L_MDCT_OVLP_MAX - st->tcx_cfg.tcx_mdct_window_lengthFB); + + mdct_window_sine( st->tcx_cfg.tcx_mdct_window_half, st->tcx_cfg.tcx_mdct_window_length/2 ); + mdct_window_sine( st->tcx_cfg.tcx_mdct_window_halfFB, st->tcx_cfg.tcx_mdct_window_lengthFB/2 ); + + /* minimum overlap 1.25 ms */ + st->tcx_cfg.tcx_mdct_window_min_length = st->sr_core / 800; + st->tcx_cfg.tcx_mdct_window_min_lengthFB = st->output_Fs / 800; + + mdct_window_sine( st->tcx_cfg.tcx_mdct_window_minimum, st->tcx_cfg.tcx_mdct_window_min_length ); + mdct_window_sine( st->tcx_cfg.tcx_mdct_window_minimumFB, st->tcx_cfg.tcx_mdct_window_min_lengthFB ); + + /*ALDO windows for MODE2*/ + mdct_window_aldo(st->tcx_cfg.tcx_aldo_window_1, st->tcx_cfg.tcx_aldo_window_2, st->L_frame); + mdct_window_aldo(st->tcx_cfg.tcx_aldo_window_1_FB, st->tcx_cfg.tcx_aldo_window_2_FB, NS2SA(st->output_Fs, FRAME_SIZE_NS)); + st->tcx_cfg.tcx_aldo_window_1_trunc = st->tcx_cfg.tcx_aldo_window_1 + NS2SA(st->sr_core, N_ZERO_MDCT_NS); + st->tcx_cfg.tcx_aldo_window_1_FB_trunc = st->tcx_cfg.tcx_aldo_window_1_FB + NS2SA(st->output_Fs, N_ZERO_MDCT_NS); + + /*1.25ms transition window for ACELP->TCX*/ + mdct_window_sine( st->tcx_cfg.tcx_mdct_window_trans, (st->L_frame>>1)-st->tcx_cfg.tcx_mdct_window_length); + mdct_window_sine( st->tcx_cfg.tcx_mdct_window_transFB, (st->L_frameTCX>>1)-st->tcx_cfg.tcx_mdct_window_lengthFB); + + /*Mid-OLA*/ + /*compute minimum length for "half" window: lookahead - 5ms. It must be also multiple of 2*/ + st->tcx_cfg.tcx_mdct_window_half_length = 2*((encoderLookahead-(int)(0.005f*st->sr_core+0.5f))>>1); + st->tcx_cfg.tcx_mdct_window_half_lengthFB = 2*((encoderLookaheadFB-(int)(0.005f*st->output_Fs+0.5f))>>1); + assert( (st->tcx_cfg.tcx_mdct_window_half_length>16) && "Half window can not be large enough!"); + + mdct_window_sine( st->tcx_cfg.tcx_mdct_window_half, st->tcx_cfg.tcx_mdct_window_half_length ); + mdct_window_sine( st->tcx_cfg.tcx_mdct_window_halfFB, st->tcx_cfg.tcx_mdct_window_half_lengthFB ); + if (st->ini_frame == 0) + { + st->tcx_cfg.tcx_last_overlap_mode = st->tcx_cfg.tcx_curr_overlap_mode = ALDO_WINDOW; + } + + /* TCX Offset */ + st->tcx_cfg.tcx_offset = (st->tcx_cfg.tcx_mdct_window_delay>>1); + st->tcx_cfg.tcx_offsetFB = (st->tcx_cfg.tcx_mdct_window_delayFB>>1); + /*<0 rectangular transition with optimized window size = L_frame+L_frame/4*/ + st->tcx_cfg.lfacNext = st->tcx_cfg.tcx_offset - st->L_frame/4; + st->tcx_cfg.lfacNextFB = st->tcx_cfg.tcx_offsetFB - st->L_frameTCX/4; + + /* set number of coded lines */ + st->tcx_cfg.tcx_coded_lines = getNumTcxCodedLines(bandwidth); + + /* TNS in TCX */ + st->tcx_cfg.pCurrentTnsConfig = NULL; + st->tcx_cfg.fIsTNSAllowed = getTnsAllowed( st->total_brate, st->igf ); + + if (st->tcx_cfg.fIsTNSAllowed) + { + InitTnsConfigs( bwMode2fs[bandwidth], st->tcx_cfg.tcx_coded_lines, st->tcx_cfg.tnsConfig, st->hIGFDec.infoIGFStopFreq, st->total_brate ); + } + + resetTecDec( &(st->tecDec) ); + + /* Initialize decoder delay */ + /*Constraint for adaptive BPF, otherwise parameter estimation and post-processing not time aligned*/ + if( st->tcxonly == 0 ) + { + i = st->tcx_cfg.lfacNext>0? st->tcx_cfg.lfacNext: 0; + assert( 0==i ); + } + + st->flag_cna = 0; + if( st->ini_frame == 0 ) + { + st->last_flag_cna = 0; + } + + /* Static vectors to zero */ + if (st->ini_frame == 0) + { + st->last_is_cng = 0; + + st->rate_switching_reset = 0; + set_zero(st->old_syn_Overl, L_FRAME32k/2); + + set_zero(st->syn_Overl_TDAC, L_FRAME32k/2); + set_zero(st->syn_OverlFB, L_FRAME_MAX/2); + set_zero(st->syn_Overl_TDACFB, L_FRAME_MAX/2); + + set_zero(st->syn_Overl, L_FRAME32k/2); + + set_zero(st->old_synth, OLD_SYNTH_INTERNAL_DEC); + + set_zero( st->synth_history, L_PROT48k + L_FRAME_MAX); + + set_zero( st->syn, M+1 ); + + set_zero( st->mem_syn_r, 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 Mode 1/2 switching*/ + if( (st->L_frame != st->last_L_frame) || (st->last_codec_mode == MODE1) ) + { + set_zero(st->old_synth, OLD_SYNTH_INTERNAL_DEC); + } + + /*Compute size of old and new memories*/ + mem_syn_r_size_old=(int)(1.25*st->last_L_frame/20.f); + mem_syn_r_size_new=(int)(1.25*st->L_frame/20.f); + + /*Reset LPC mem*/ + if( (st->L_frame != st->last_L_frame) || (st->last_core == AMR_WB_CORE) || (st->last_core == HQ_CORE) ) + { + set_zero( st->mem_MA, M ); + if( st->sr_core == 16000 ) + { + mvr2r( GEWB2_Ave, st->mem_AR, M ); + } + else + { + mvr2r( GEWB_Ave, st->mem_AR, M ); + } + } + + /*Mode 1/2 switching*/ + if( st->last_codec_mode == MODE1 ) + { + mvr2r( st->lsp_old, st->lspold_uw, M ); + mvr2r( st->lsf_old, st->lsfold_uw, M ); + set_zero( st->syn, M ); + } + if( st->last_core == AMR_WB_CORE ) + { + st->last_core = ACELP_CORE; + st->last_core_bfi = ACELP_CORE; + } + + if( st->last_codec_mode == MODE1 && st->last_core == ACELP_CORE ) + { + /* Switching from Mode 1 ACELP */ + st->last_core_bfi = ACELP_CORE; + + /*PLC*/ + if( st->prev_bfi != 0 ) + { + float *w; + short W1,nz,delay_comp; + + W1 = st->tcx_cfg.tcx_mdct_window_lengthFB; + w = st->tcx_cfg.tcx_mdct_windowFB; + + nz = NS2SA(st->output_Fs, N_ZERO_MDCT_NS); + delay_comp = NS2SA(st->output_Fs, DELAY_CLDFB_NS); /*CLDFB delay*/ + + mvr2r(st->fer_samples+delay_comp, st->syn_OverlFB, st->L_frameTCX/2); + lerp (st->fer_samples+delay_comp, st->syn_Overl , st->L_frame /2, st->L_frameTCX/2); /*ACELP(bfi)->TCX(rect)*/ + /*old_out needed for MODE1 routine and syn_Overl_TDAC for MODE2 routine*/ + set_f(st->old_out, 0, nz); + mvr2r(st->fer_samples+delay_comp, st->old_out+nz,W1); + + for (i = 0; i < W1; i++) + { + st->old_out[i+nz] *= w[W1-1-i]*w[W1-1-i]; + } + set_f(&st->old_out[W1+nz], 0, nz); + + lerp (st->old_out , st->old_outLB , st->L_frame , st->L_frameTCX); + + mvr2r(st->old_out +nz, st->syn_Overl_TDACFB, st->L_frameTCX/2); + nz = NS2SA(st->sr_core, N_ZERO_MDCT_NS); + mvr2r(st->old_outLB+nz, st->syn_Overl_TDAC , st->L_frame /2); + } + } + + if ( st->last_codec_mode == MODE2 && + st->L_frame != st->last_L_frame && + ( ( st->m_frame_type == SID_FRAME && st->last_core > ACELP_CORE ) || + (st->last_core > ACELP_CORE && st->core > ACELP_CORE) || st->prev_bfi ) ) + { + lerp(st->old_outLB, st->old_outLB, st->L_frame, st->last_L_frame); + } + + /* Rate switching */ + if( st->last_codec_mode == MODE1 && st->last_core == HQ_CORE ) + { + /* Switching from MDCT */ + + /*Reset of ACELP memories*/ + st->rate_switching_reset=1; + st->tilt_code = TILT_CODE; + set_zero(st->old_exc, L_EXC_MEM_DEC); + set_zero(st->syn, 1+M); + set_zero(st->mem_syn2, M); + + /*OLA -> zero */ + set_zero(st->old_syn_Overl, L_FRAME32k/2); + set_zero(st->syn_Overl_TDAC, L_FRAME32k/2); + set_zero(st->syn_Overl, L_FRAME32k/2); + set_zero(st->syn_Overl_TDACFB, L_FRAME_MAX/2); + mvr2r(st->old_out+NS2SA(st->output_Fs, N_ZERO_MDCT_NS), st->syn_OverlFB, st->tcx_cfg.tcx_mdct_window_lengthFB); + st->tcx_cfg.last_aldo=1; /*It was previously ALDO*/ + st->tcx_cfg.tcx_curr_overlap_mode = ALDO_WINDOW; + /*OLA for Mode 2 TCX always reset in Mode switching cases*/ + set_f( st->old_outLB, 0, st->L_frame ); + + st->last_core_bfi = TCX_20_CORE; + st->pfstat.on=0; + /* reset CLDFB memories */ + cldfb_reset_memory( st->cldfbAna ); + cldfb_reset_memory( st->cldfbBPF ); + cldfb_reset_memory( st->cldfbSyn ); + } + else if( (st->L_frame!=st->last_L_frame) && (st->L_frame<=L_FRAME16k) && (st->last_L_frame <=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( st->lsp_old, st->L_frame, 0 ); + lsp2a_stab( st->lsp_old, st->old_Aq_12_8, M ); + + lsp2lsf( st->lsp_old, st->lsf_old, M, st->sr_core ); + mvr2r( st->lsp_old, st->lspold_uw, M ); + mvr2r( st->lsf_old, st->lsfold_uw, M ); + + if( !st->last_con_tcx ) + { + synth_mem_updt2( st->L_frame, st->last_L_frame, st->old_exc, st->mem_syn_r, st->mem_syn2, NULL, DEC ); + } + + /*mem of deemphasis stayed unchanged.*/ + } + else if( st->L_frame!=st->last_L_frame ) /* Rate switching involving TCX only modes */ + { + /*Partial reset of ACELP memories*/ + st->rate_switching_reset = 1; + + /*reset partly some memories*/ + st->tilt_code = TILT_CODE; + if( !st->last_con_tcx ) + { + set_zero( st->old_exc, L_EXC_MEM_DEC ); + } + set_zero( st->old_Aq_12_8, 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 ); + mvr2r( st->mem_syn_r+L_SYN_MEM-M, st->mem_syn2, M ); + } + /* update of lsf_old only needed in BASOP */ + /* else if( !st->tcxonly && (st->L_frame == L_FRAME16k) && (st->last_total_brate > ACELP_32k) ) */ + /* { */ + /* lsp2lsf( st->lsp_old, st->lsf_old, M, st->sr_core ); */ + /* } */ + } + + if( st->last_bwidth == NB && st->bwidth != NB && st->ini_frame != 0 ) + { + st->rate_switching_reset=1; + } + + st->old_synth_len = 2*st->L_frame; + st->old_synth_lenFB = 2*st->L_frameTCX; + + /* bass pf reset */ + st->bpf_gain_param = 0; + set_f( st->pst_old_syn, 0, NBPSF_PIT_MAX ); + + /* Formant postfilter */ + if (st->ini_frame == 0) + { + /* do nothing */ + } + else if( st->last_codec_mode == MODE2 ) + { + if( !st->tcxonly ) + { + if( st->pfstat.on ) + { + 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 + { + set_zero( st->pfstat.mem_stp, L_SYN_MEM ); + set_zero( st->pfstat.mem_pf_in, L_SYN_MEM ); + st->pfstat.reset = 1; + st->pfstat.gain_prec = 1.f; + } + } + else if( st->pfstat.on ) + { + 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 mode switching*/ + + /*reset post-filter except for Narrowband*/ + if ( ((short)(st->output_Fs / 50)) != L_FRAME8k ) + { + st->pfstat.reset = 1; + if( st->pfstat.on != 0 ) + { + st->pfstat.reset = 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 + { + /*feed last value old_synth as it is used for pre-emphasis mem*/ + st->old_synth[st->old_synth_len-1]=st->syn[M]; + st->pst_old_syn[NBPSF_PIT_MAX-1]=st->syn[M]; + } + } + + /* lsf and lsp initialization */ + if (st->ini_frame == 0 ) + { + mvr2r( st->lsp_old, st->lspold_uw, M ); + mvr2r( st->lsf_old, st->lsfold_uw, M ); + + set_zero( st->lsf_cng, M ); + } + + st->seed_tcx_plc = 21845; + st->past_gpit = 0.0f; + st->past_gcode = 0.0f; + st->gc_threshold = 0.0f; + + lsf2lsp(st->lsf_cng, st->lspold_cng, M, INT_FS_12k8); + lsp2a_stab(st->lspold_cng, st->Aq_cng, M); + st->plcBackgroundNoiseUpdated = 0; + mvr2r(st->lsf_old, st->lsf_q_cng, M); + mvr2r(st->lsf_old, st->old_lsf_q_cng, M); + mvr2r(st->lsp_old, st->lsp_q_cng, M); + mvr2r(st->lsp_old, st->old_lsp_q_cng, M); + set_zero(st->mem_syn_unv_back, M); + st->last_gain_syn_deemph = 1.f; + + if( st->last_codec_mode == MODE1 || st->ini_frame == 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 = 1.f; + st->conceal_eof_gain = 1.0f; + } + /* Post processing */ + set_zero(st->mem_Aq, NB_SUBFR16k*(M+1)); + + st->lp_ener_bfi = 60.0f; + if( st->ini_frame == 0 ) + { + st->prev_bfi = 0; + st->last_core_bfi = -1; + st->tcxConceal_recalc_exc = 0; + } + st->prev_old_bfi = 0; + + st->noise_filling_index = 0; + + mvr2r(st->lsf_old, st->lsf_adaptive_mean, M); + mvr2r(st->lsf_old, st->lsfoldbfi0, M); + mvr2r(st->lsf_old, st->lsfoldbfi1, M); + + st->clas_dec = UNVOICED_CLAS; + + if (!st->last_con_tcx) + { + st->old_enr_LP = 0.0f; /* LP filter E of last good voiced frame or local LP filter E in TD TCX PLC */ + } + + if (st->prev_bfi) + { + /* calculate energy at the end of the previous frame */ + if( st->core == ACELP_CORE && st->last_core == HQ_CORE ) + { + fer_energy( st->L_frameTCX, UNVOICED_CLAS, st->previoussynth, -1, &st->enr_old, 1 ); + } + } + else + { + st->last_good = UNVOICED_CLAS; /* last good received frame for concealment */ + st->enr_old = 0.0f; /* energy at the end of the previous frame */ + } + st->lp_gainc = 0.0f; + st->lp_gainp = 0.0f; + + st->prev_widow_left_rect = 0; + + st->CngLevelBackgroundTrace_bfi = PLC_MIN_CNG_LEV; + st->NoiseLevelIndex_bfi = PLC_MIN_STAT_BUFF_SIZE-1; + st->CurrLevelIndex_bfi = 0; + st->LastFrameLevel_bfi = PLC_MIN_CNG_LEV; + set_f( st->NoiseLevelMemory_bfi, PLC_MIN_CNG_LEV, PLC_MIN_STAT_BUFF_SIZE); + + st->cummulative_damping_tcx = 1.0f; + st->cummulative_damping = 1.0f; + + for( i=0; i<2*NB_SUBFR16k+2; i++ ) + { + st->old_pitch_buf[i] = (float)st->pit_min; + } + + for( i=0; i<2*NB_SUBFR16k+2; i++ ) + { + st->mem_pitch_gain[i] = 1.f; + } + + st->old_fpitch = (float)st->pit_min; + st->old_fpitchFB = (float)st->pit_min_TCX; + + st->rate_switching_init = 1; + + st->reset_mem_AR = 0; + + /* For phase dispersion */ + set_zero(st->dispMem,8); + + st->voice_fac = -1; /* purely unvoiced */ + + /* TCX-LTP */ + st->tcxltp = getTcxLtp(st->sr_core); + if( st->ini_frame == 0 || st->last_codec_mode == MODE1 ) + { + st->tcxltp_pitch_int = st->pit_max; + st->tcxltp_pitch_fr = 0; + st->tcxltp_last_gain_unmodified = 0.f; + if (st->ini_frame == 0) + { + set_f( st->tcxltp_mem_in, 0.0f, TCXLTP_MAX_DELAY ); + set_f( st->tcxltp_mem_out, 0.0f, L_FRAME48k ); + st->tcxltp_pitch_int_post_prev = 0; + st->tcxltp_pitch_fr_post_prev = 0; + st->tcxltp_gain_post_prev = 0.f; + st->tcxltp_filt_idx_prev = -1; + } + } + + st->pst_mem_deemp_err = 0.0f; + st->tcx_cfg.ctx_hm = getCtxHm(st->total_brate, st->rf_flag); + st->last_ctx_hm_enabled = 0; + + st->tcx_cfg.resq = getResq(st->total_brate); + st->tcx_cfg.sq_rounding = 0.375f; /*deadzone of 1.25->rounding=1-1.25/2 (No deadzone=0.5)*/ + + st->tcx_lpc_shaped_ari = getTcxLpcShapedAri( st->total_brate, bandwidth, st->rf_flag ); + + st->envWeighted = 0; + + if( st->tcxonly ) + { + st->p_bpf_noise_buf = NULL; + } + else + { + st->p_bpf_noise_buf = st->bpf_noise_buf; + } + + if( bandwidth == SWB && (st->total_brate == ACELP_16k40 || st->total_brate == ACELP_24k40) ) + { + st->tec_tfa = 1; + } + else + { + st->tec_tfa = 0; + } + + st->tec_flag = 0; + st->tfa_flag = 0; + + /* needed in decoder to read the bitstream */ + st->enableGplc = 0; + + st->flagGuidedAcelp = 0; + st->T0_4th = L_SUBFR; + st->guidedT0 = st->T0_4th; + + + if( st->total_brate >= HQ_48k ) + { + st->enablePlcWaveadjust = 1; + if( st->ini_frame == 0 || st->last_total_brate < HQ_48k || st->last_codec_mode == MODE1 || st->force_lpd_reset ) + { + concealment_init( st->L_frameTCX, &st->plcInfo ); + } + } + else + { + st->enablePlcWaveadjust = 0; + } + + /* PLC: [TCX: Tonal Concealment] */ + st->tonalMDCTconceal.nScaleFactors = 0; + st->tonalMDCTconceal.nSamples = 0; + st->tonalMDCTconceal.lastPcmOut = 0x0; + st->tonalMDCTconceal.lastBlockData.tonalConcealmentActive = 0; + st->tonalMDCTconceal.lastBlockData.nSamples = 0; + + TonalMDCTConceal_Init( &st->tonalMDCTconceal, + st->L_frameTCX, + st->L_frame, 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; + st->tcxltp_third_last_pitch = st->old_fpitch; + + + if( st->total_brate == ACELP_9k60 || st->total_brate == ACELP_16k40 || st->total_brate == ACELP_24k40 ) + { + st->dec_glr = 1; + } + else + { + st->dec_glr = 0; + } + + st->dec_glr_idx = 0; + + st->enableTcxLpc = 1; + st->VAD = 0; + st->old_gaintcx_bfi=0.0f; + st->tcx_cfg.na_scale = 1.f; + st->tcx_hm_LtpPitchLag = -1; + st->tcxltp_gain = 0.0f; + return; +} diff --git a/lib_dec/core_dec_reconf.c b/lib_dec/core_dec_reconf.c new file mode 100644 index 000000000..dee060a13 --- /dev/null +++ b/lib_dec/core_dec_reconf.c @@ -0,0 +1,151 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "options.h" +#include "prot.h" +#include "rom_com.h" +#include "rom_dec.h" + +/*---------------------------------------------------------------------* + * reconfig_decoder_LPD() + * + * + *---------------------------------------------------------------------*/ + +void reconfig_decoder_LPD( + Decoder_State *st, + int bits_frame, + int bandwidth, + int bitrate, + int L_frame_old +) +{ + short i; + + st->bits_frame = bits_frame; + + if( bandwidth == NB ) + { + st->narrowBand = 1; + } + else if( bandwidth > NB ) + { + 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); + + /* TCX-LTP */ + st->tcxltp = getTcxLtp(st->sr_core); + + /*Scale TCX for non-active frames to adjust loudness with ACELP*/ + st->tcx_cfg.na_scale = 1.f; + + if( bandwidth < SWB && !(st->tcxonly) ) + { + int scaleTableSize = sizeof (scaleTcxTable) / sizeof (scaleTcxTable[0]); + for (i = 0 ; i < scaleTableSize ; i++) + { + if ( (bandwidth == scaleTcxTable[i].bwmode) && + (bitrate >= scaleTcxTable[i].bitrateFrom) && + (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 != 0 ) + { + if( st->fscale!=st->fscale_old + && ! (st->last_codec_mode == MODE1 + && st->last_core == ACELP_CORE + && st->prev_bfi != 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() */ + { + unsigned short newLen; + unsigned short oldLen; + + newLen = st->tcx_cfg.tcx_mdct_window_length; + oldLen = st->tcx_cfg.tcx_mdct_window_length_old; + + if( (st->prev_bfi && st->last_core_bfi == ACELP_CORE) || st->last_core == ACELP_CORE ) + { + newLen = st->L_frame/2; + oldLen = L_frame_old/2; + } + + lerp( st->old_syn_Overl, st->old_syn_Overl, newLen, oldLen ); + lerp( st->syn_Overl, st->syn_Overl, newLen, oldLen ); + + if( st->prev_bfi && st->last_core_bfi == ACELP_CORE ) + { + lerp( st->syn_Overl_TDAC, st->syn_Overl_TDAC, newLen, oldLen ); + } + } + + if (st->L_frame <= L_FRAME16k) + { + if( st->last_L_frame <= L_FRAME16k ) + { + if( st->L_frame!=st->last_L_frame ) + { + unsigned short oldLenClasBuff; + unsigned short newLenClasBuff; + + if( st->L_frame > st->last_L_frame ) + { + oldLenClasBuff = L_SYN_MEM_CLAS_ESTIM * st->last_L_frame/st->L_frame; + newLenClasBuff = L_SYN_MEM_CLAS_ESTIM; + } + else + { + oldLenClasBuff = L_SYN_MEM_CLAS_ESTIM; + newLenClasBuff = L_SYN_MEM_CLAS_ESTIM * st->L_frame/st->last_L_frame; + } + lerp( &st->mem_syn_clas_estim[L_SYN_MEM_CLAS_ESTIM-oldLenClasBuff], &st->mem_syn_clas_estim[L_SYN_MEM_CLAS_ESTIM-newLenClasBuff], newLenClasBuff, oldLenClasBuff ); + } + } + else + { + set_zero( st->mem_syn_clas_estim, L_SYN_MEM_CLAS_ESTIM ); + } + } + } + + st->enableTcxLpc = (st->numlpc == 1) && (st->lpcQuantization == 1) && (bitrate <= LOWRATE_TCXLPC_MAX_BR || st->rf_flag); + + if( st->ini_frame == 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 000000000..765b351fb --- /dev/null +++ b/lib_dec/core_dec_switch.c @@ -0,0 +1,179 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "options.h" +#include "prot.h" +#include "rom_com.h" + + +/*-------------------------------------------------------------* + * mode_switch_decoder_LPD() + * + * + *-------------------------------------------------------------*/ + +void mode_switch_decoder_LPD( + Decoder_State *st, + int bandwidth, + int bitrate, + int frame_size_index +) +{ + int fscale, switchWB, sr_core; + int bSwitchFromAmrwbIO; + int frame_size; + + switchWB = 0; + bSwitchFromAmrwbIO = 0; + if(st->last_core == AMR_WB_CORE) + { + bSwitchFromAmrwbIO = 1; + } + sr_core = getCoreSamplerateMode2(bitrate, bandwidth, st->rf_flag); + fscale = sr2fscale(sr_core); + + /* set number of coded lines */ + st->tcx_cfg.tcx_coded_lines = getNumTcxCodedLines(bandwidth); + + if ( (bandwidth>=WB) && (fscale==(FSCALE_DENOM*16000)/12800) && (fscale == st->fscale) ) + { + if ( ((bitrate > ACELP_32k) && (st->tcxonly==0)) || ((bitrate <= ACELP_32k) && (st->tcxonly==1)) ) + { + switchWB = 1; + } + } + + if( st->last_L_frame > L_FRAME16k && st->total_brate <= ACELP_32k ) + { + switchWB = 1; /*force init when coming from MODE1*/ + } + + st->igf = getIgfPresent(bitrate, bandwidth, st->rf_flag ); + + st->hIGFDec.infoIGFStopFreq = -1; + if( st->igf ) + { + /* switch IGF configuration */ + IGFDecSetMode( &st->hIGFDec, st->total_brate, bandwidth, -1, -1, st->rf_flag ); + } + + if( fscale != st->fscale || switchWB || bSwitchFromAmrwbIO || 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; + st->fscale = fscale; + st->L_frame = st->sr_core / 50; + st->L_frameTCX = st->output_Fs / 50; + + st->tcx_cfg.ctx_hm = getCtxHm(bitrate, st->rf_flag); + st->tcx_cfg.resq = getResq(bitrate); + + st->tcx_lpc_shaped_ari = getTcxLpcShapedAri( bitrate, bandwidth, st->rf_flag ); + + if ( bandwidth == NB ) + { + st->narrowBand = 1; + } + else + { + st->narrowBand = 0; + } + st->TcxBandwidth = getTcxBandwidth(bandwidth); + + st->tcx_cfg.pCurrentTnsConfig = NULL; + st->tcx_cfg.fIsTNSAllowed = getTnsAllowed(st->total_brate, st->igf); + if( st->tcx_cfg.fIsTNSAllowed ) + { + InitTnsConfigs( bwMode2fs[bandwidth], st->tcx_cfg.tcx_coded_lines, st->tcx_cfg.tnsConfig, st->hIGFDec.infoIGFStopFreq, st->total_brate ); + } + } + + frame_size = FrameSizeConfig[frame_size_index].frame_net_bits; + + reconfig_decoder_LPD( st, frame_size, bandwidth, bitrate, st->last_L_frame ); + + if (st->envWeighted && !st->enableTcxLpc) + { + mvr2r(st->lspold_uw, st->lsp_old, M); + mvr2r(st->lsfold_uw, st->lsf_old, M); + st->envWeighted = 0; + } + + /* update PLC LSF memories */ + lsp2lsf( st->lsp_old, st->lsfoldbfi1, M, st->sr_core ); + mvr2r(st->lsfoldbfi1, st->lsfoldbfi0,M); + mvr2r(st->lsfoldbfi1, st->lsf_adaptive_mean,M); + + if( st->igf ) + { + /* reset TBE */ + if( ( st->bwidth == WB && st->last_extl != WB_TBE ) || + ( st->bwidth == SWB && st->last_extl != SWB_TBE ) || + ( st->bwidth == FB && st->last_extl != FB_TBE ) ) + { + TBEreset_dec( st, st->bwidth ); + } + else + { + set_f( st->state_lpc_syn, 0.0f, LPC_SHB_ORDER ); + set_f( st->state_syn_shbexc, 0.0f, L_SHB_LAHEAD ); + set_f( st->mem_stp_swb, 0.0f, LPC_SHB_ORDER ); + set_f( st->mem_zero_swb, 0, LPC_SHB_ORDER ); + st->gain_prec_swb = 1.0f; + } + } + + if( bandwidth == SWB && (st->total_brate == ACELP_16k40 || st->total_brate == ACELP_24k40) ) + { + if(st->tec_tfa == 0) + { + set_zero(st->tecDec.loBuffer, MAX_TEC_SMOOTHING_DEG); + } + st->tec_tfa = 1; + } + else + { + st->tec_tfa = 0; + } + + st->tec_flag = 0; + st->tfa_flag = 0; + + /* needed in decoder to read the bitstream */ + if ( + ( bandwidth == FB && bitrate == ACELP_24k40 ) || + ( bandwidth == WB && bitrate == ACELP_24k40 ) || + ( bandwidth == SWB && bitrate == ACELP_24k40 ) + ) + { + st->enableGplc = 1; + } + else + { + st->enableGplc = 0; + } + + if( st->total_brate == ACELP_9k60 || st->total_brate == ACELP_16k40 || st->total_brate == ACELP_24k40 ) + { + st->dec_glr = 1; + } + else + { + st->dec_glr = 0; + } + + st->dec_glr_idx = 0; + + + return; +} diff --git a/lib_dec/core_switching_dec.c b/lib_dec/core_switching_dec.c new file mode 100644 index 000000000..1ae275c06 --- /dev/null +++ b/lib_dec/core_switching_dec.c @@ -0,0 +1,825 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*---------------------------------------------------------------------* + * core_switching_pre_dec() + * + * Preprocessing/preparation for ACELP/HQ core switching + *---------------------------------------------------------------------*/ + +void core_switching_pre_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const short output_frame /* i : frame length */ +) +{ + short oldLenClasBuff, newLenClasBuff; + + + /* Codec mode switching */ + if( st->last_codec_mode == MODE2 ) + { + mvr2r( st->mem_syn2, st->mem_syn1, M ); + set_f( st->agc_mem2, 0, 2 ); + st->mem_deemph = st->syn[M]; + st->bpf_off = 1; + set_f( st->pst_old_syn, 0, NBPSF_PIT_MAX); + st->pst_mem_deemp_err = 0; + st->psf_lp_noise = st->lp_noise; + + /* reset old HB synthesis buffer */ + if( st->last_L_frame == L_FRAME ) + { + st->old_bwe_delay = NS2SA( st->output_Fs, MAX_DELAY_TBE_NS - DELAY_SWB_TBE_12k8_NS ); + } + else + { + st->old_bwe_delay = NS2SA( st->output_Fs, MAX_DELAY_TBE_NS - DELAY_SWB_TBE_16k_NS ); + } + set_f( st->hb_prev_synth_buffer, 0, NS2SA(48000, DELAY_BWE_TOTAL_NS) ); + + /* reset upd_cnt */ + st->upd_cnt = MAX_UPD_CNT; + st->igf = 0; + + if( st->last_core != ACELP_CORE ) + { + /* reset BWE memories */ + set_f( st->old_bwe_exc, 0, PIT16k_MAX*2 ); + st->bwe_non_lin_prev_scale = 0.0f; + } + + if( st->output_Fs >= 16000 ) + { + hf_synth_reset( &st->seed2, st->mem_hf, st->mem_syn_hf, st->mem_hp400, st->mem_hp_interp, st->delay_syn_hf ); + } + set_f( st->old_syn_12k8_16k, 0, NS2SA(16000, DELAY_FD_BWE_ENC_NS) ); + + set_f( st->prev_env, 0, SFM_N_WB ); + set_f( st->prev_normq, 0, SFM_N_WB ); + + set_f( st->last_ni_gain, 0, BANDS_MAX ); + set_f( st->last_env, 0, BANDS_MAX ); + st->last_max_pos_pulse = 0; + + if( st->output_Fs > 16000 ) + { + set_f( st->prev_coeff_out, 0, L_HQ_WB_BWE ); + } + + /* pre-echo */ + st->pastpre = 0; + /* reset the GSC pre echo energy threshold in case of switching */ + st->Last_frame_ener = (float)MAX_32; + + if( st->last_core == TCX_20_CORE || st->last_core == TCX_10_CORE ) + { + st->last_core = HQ_CORE; + mvr2r( st->FBTCXdelayBuf, st->prev_synth_buffer, NS2SA(st->output_Fs, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS)); + set_f( st->last_ni_gain, 0, BANDS_MAX ); + set_f( st->last_env, 0, BANDS_MAX ); + st->last_max_pos_pulse = 0; + + set_s( st->prev_SWB_peak_pos, 0, SPT_SHORTEN_SBNUM ); + st->prev_frm_hfe2 = 0; + st->prev_stab_hfe2 = 0; + } + + if( st->prev_bfi != 0 ) + { + short delay_comp; + + /*switch off Hq Voicing as it was not uodated in MODE2*/ + st->oldHqVoicing = 0; + st->HqVoicing = 0; + + delay_comp = NS2SA(st->output_Fs, DELAY_CLDFB_NS); + + if( !st->last_con_tcx && st->last_core_bfi == ACELP_CORE && st->core == HQ_CORE ) + { + short i; + float *realBuffer[CLDFB_NO_COL_MAX], *imagBuffer[CLDFB_NO_COL_MAX]; + float realBufferTmp[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], imagBufferTmp[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + + for( i=0; icldfbAna ); + cldfbAnalysis( st->syn_Overl, realBuffer, imagBuffer, delay_comp, st->cldfbAna ); + cldfb_restore_memory( st->cldfbAna ); + + /* CLDFB synthesis of the combined signal */ + cldfb_save_memory( st->cldfbSyn ); + cldfbSynthesis( realBuffer, imagBuffer, st->fer_samples, delay_comp, st->cldfbSyn ); + cldfb_restore_memory( st->cldfbSyn ); + } + + if( !st->last_con_tcx && st->last_core_bfi == ACELP_CORE && st->core == HQ_CORE ) + { + lerp(st->syn_Overl, st->fer_samples+delay_comp,output_frame/2, st->last_L_frame/2); + /*Set to zero the remaining part*/ + set_f( st->fer_samples+delay_comp+output_frame/2, 0, (output_frame/2)-delay_comp); + } + } + + st->use_acelp_preq = 0; + st->reset_mem_AR=0; + } + + /*FEC*/ + if( st->L_frame <= L_FRAME16k ) + { + if( st->last_L_frame <= L_FRAME16k && st->core != HQ_CORE ) + { + if( st->L_frame!=st->last_L_frame ) + { + if (st->L_frame>st->last_L_frame) + { + oldLenClasBuff = L_SYN_MEM_CLAS_ESTIM * st->last_L_frame/st->L_frame; + newLenClasBuff = L_SYN_MEM_CLAS_ESTIM; + } + else + { + oldLenClasBuff = L_SYN_MEM_CLAS_ESTIM; + newLenClasBuff = L_SYN_MEM_CLAS_ESTIM * st->L_frame/st->last_L_frame; + } + lerp( &st->mem_syn_clas_estim[L_SYN_MEM_CLAS_ESTIM-oldLenClasBuff], &st->mem_syn_clas_estim[L_SYN_MEM_CLAS_ESTIM-newLenClasBuff], newLenClasBuff, oldLenClasBuff ); + } + } + else + { + set_zero( st->mem_syn_clas_estim, L_SYN_MEM_CLAS_ESTIM ); + } + } + + /* 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 */ + if( st->core == ACELP_CORE && (st->last_core != ACELP_CORE || st->last_codec_mode == MODE2 ) ) + { + st->last_ppp_mode_dec = 0; + st->last_nelp_mode_dec =0; + } + + /* Handle state reset of stat_noise_uv_mod memory */ + if( st->core == ACELP_CORE && (st->last_core != ACELP_CORE || st->last_codec_mode == MODE2 || st->last_total_brate <= PPP_NELP_2k80 ) ) + { + st->act_count = 3; + st->uv_count = 0; + } + + if( (st->core == ACELP_CORE || st->core == AMR_WB_CORE ) && st->last_core == HQ_CORE ) + { + if( st->L_frame == L_FRAME16k ) + { + mvr2r( TRWB2_Ave, st->lsf_old, M ); /* init of LSP */ + mvr2r( TRWB2_Ave, st->lsfoldbfi1, M ); + mvr2r( TRWB2_Ave, st->lsfoldbfi0, M ); + mvr2r( TRWB2_Ave, st->lsf_adaptive_mean, M ); + lsf2lsp( st->lsf_old, st->lsp_old, M, INT_FS_16k ); + } + else + { + mvr2r( TRWB_Ave, st->lsf_old, M ); /* init of LSP */ + mvr2r( TRWB_Ave, st->lsfoldbfi1, M ); + mvr2r( TRWB_Ave, st->lsfoldbfi0, M ); + mvr2r( TRWB_Ave, st->lsf_adaptive_mean, M ); + lsf2lsp( st->lsf_old, st->lsp_old, M, INT_FS_12k8 ); + } + + set_f( st->agc_mem2, 0, 2 ); + st->mem_deemph = 0; + if( !st->last_con_tcx ) + { + set_f( st->mem_syn2, 0.0f, M ); + } + set_f( st->mem_syn1, 0.0f, M ); + st->bwe_non_lin_prev_scale = 0.0f; + + /* Reset ACELP parameters */ + set_zero( st->mem_MA, M ); + if( st->sr_core == 16000 ) + { + mvr2r( GEWB2_Ave, st->mem_AR, M ); + } + else + { + mvr2r( GEWB_Ave, st->mem_AR, M ); + } + st->tilt_code = 0.0f; + st->gc_threshold = 0.0f; + set_f( st->dispMem, 0, 8 ); + + st->last_coder_type = GENERIC; + + fer_energy( output_frame, UNVOICED_CLAS, st->previoussynth, -1, &st->enr_old, 1 ); + st->lp_gainp = 0.0f; + st->lp_gainc = (float)sqrt( st->lp_ener ); + + + st->last_voice_factor = 0; + st->Last_GSC_noisy_speech_flag = 0; + + /* reset CLDFB memories */ + cldfb_reset_memory( st->cldfbAna ); + cldfb_reset_memory( st->cldfbBPF ); + cldfb_reset_memory( st->cldfbSyn ); + + /* reset TBE memories */ + if( !st->last_con_tcx ) + { + set_f( st->old_exc,0, L_EXC_MEM_DEC ); + } + else if( st->L_frame < L_FRAME16k ) + { + /* resample from 16kHz to 12.8kHZ */ + synth_mem_updt2( st->L_frame, L_FRAME16k, st->old_exc, st->mem_syn_r, st->mem_syn2, NULL, DEC ); + } + + set_f( st->old_bwe_exc, 0, PIT16k_MAX*2 ); + + if( st->output_Fs >= 16000 ) + { + hf_synth_reset( &st->seed2, st->mem_hf, st->mem_syn_hf, st->mem_hp400, st->mem_hp_interp, st->delay_syn_hf ); + } + set_f( st->old_syn_12k8_16k, 0, NS2SA(16000, DELAY_FD_BWE_ENC_NS) ); + } + + if( st->core == HQ_CORE && (st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE) ) + { + set_f( st->prev_env, 0, SFM_N_WB ); + set_f( st->prev_normq, 0, SFM_N_WB ); + + set_f( st->last_ni_gain, 0, BANDS_MAX ); + set_f( st->last_env, 0, BANDS_MAX ); + st->last_max_pos_pulse = 0; + + set_s( st->prev_SWB_peak_pos, 0, SPT_SHORTEN_SBNUM ); + st->prev_frm_hfe2 = 0; + st->prev_stab_hfe2 = 0; + + if( st->output_Fs > 16000 ) + { + set_f( st->prev_coeff_out, 0, L_HQ_WB_BWE ); + } + + set_f( st->old_out, 0, output_frame ); + } + + /* handle switching cases where preecho_sb was not called in the last frame (memory not up to date) */ + st->pastpre--; + if( st->pastpre <= 0 ) + { + reset_preecho_dec(st); + } + + + if( st->core_brate == FRAME_NO_DATA ) + { + st->VAD = 0; + st->m_frame_type = ZERO_FRAME; + } + else if( st->core_brate <= SID_2k40 ) + { + st->VAD = 0; + st->m_frame_type = SID_FRAME; + } + else + { + st->VAD = 1; + st->m_frame_type = ACTIVE_FRAME; + } + + /*switch on CNA on active frames*/ + if( st->core != AMR_WB_CORE && st->VAD && st->total_brate <= CNA_MAX_BRATE ) + { + st->flag_cna = 1; + } + else if( st->core == AMR_WB_CORE && st->VAD && st->total_brate <= ACELP_8k85 ) + { + st->flag_cna = 1; + } + else if( st->VAD || ((st->cng_type==FD_CNG) && (st->L_frame == L_FRAME16k))) + { + st->flag_cna = 0; + } + + if( st->core == AMR_WB_CORE ) + { + st->cng_type = LP_CNG; + } + + /* Reconfigure CNG */ + if ( st->hFdCngDec && ((st->last_L_frame!=st->L_frame ) || + (st->hFdCngDec->hFdCngCom->frameSize!=st->L_frame) || + st->ini_frame == 0 || st->bwidth != st->last_bwidth)) + { + /* || st->last_core == AMR_WB_CORE || st->last_codec_mode == MODE2)){*/ + if( st->core != AMR_WB_CORE ) + { + configureFdCngDec( st->hFdCngDec, st->bwidth, st->rf_flag==1&& st->total_brate==13200? 9600: st->total_brate, st->L_frame ); + } + else + { + configureFdCngDec( st->hFdCngDec, WB, ACELP_8k00, st->L_frame ); + + if( st->VAD ) + { + st->hFdCngDec->hFdCngCom->CngBitrate = st->total_brate; + } + } + if( st->last_L_frame!=st->L_frame && st->L_frame<=320 && st->last_L_frame<=320 ) + { + lerp( st->hFdCngDec->hFdCngCom->olapBufferSynth2, st->hFdCngDec->hFdCngCom->olapBufferSynth2, st->L_frame*2, st->last_L_frame*2 ); + if( st->total_brate<=SID_2k40 && st->last_total_brate<=SID_2k40 ) + { + lerp( st->hFdCngDec->hFdCngCom->olapBufferSynth, st->hFdCngDec->hFdCngCom->olapBufferSynth, st->L_frame*2, st->last_L_frame*2 ); + if( st->L_frame==L_FRAME ) + { + short n; + for (n=0; n < st->L_frame*2; n++) + { + st->hFdCngDec->hFdCngCom->olapBufferSynth[n] = st->hFdCngDec->hFdCngCom->olapBufferSynth[n]*0.6250f; + } + } + else + { + short n; + for (n=0; n < st->L_frame*2; n++) + { + st->hFdCngDec->hFdCngCom->olapBufferSynth[n] =st->hFdCngDec->hFdCngCom->olapBufferSynth[n]*1.6f; + } + } + } + } + } + + + return; +} + +/*---------------------------------------------------------------------* + * core_switching_post_dec() + * + * Postprocessing for ACELP/HQ core switching + *---------------------------------------------------------------------*/ + +void core_switching_post_dec( + Decoder_State *st, /* i/o: decoder state structure */ + float *synth, /* i/o: output synthesis */ + const short output_frame, /* i : frame length */ + const short core_switching_flag, /* i : ACELP->HQ switching flag */ + const short coder_type /* i : ACELP coder type */ +) +{ + short i, delay_comp, delta; + float tmpF; + float tmpDelta; + float synth_subfr_out[SWITCH_MAX_GAP], synth_subfr_bwe[SWITCH_MAX_GAP]; + float mem_synth[NS2SA(16000, DELAY_CLDFB_NS)+2]; + short nZeros; + + + if( st->core == ACELP_CORE && st->bfi ) + { + acelp_core_switch_dec_bfi( st, st->fer_samples, coder_type ); + } + + /* set multiplication factor according to the sampling rate */ + delta = 1; + if( output_frame == L_FRAME16k ) + { + delta = 2; + } + else if( output_frame == L_FRAME32k ) + { + delta = 4; + } + else if( output_frame == L_FRAME48k ) + { + delta = 6; + } + + /* set delay compensation between HQ synthesis and ACELP synthesis */ + delay_comp = delta * HQ_DELAY_COMP; + + if( st->core == HQ_CORE ) + { + st->use_acelp_preq = 0; + st->mem_deemph_old_syn = 0.0f; + + if( core_switching_flag && st->last_L_frame == st->last_L_frame_ori && (st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE)) + { + acelp_core_switch_dec( st, synth_subfr_out, synth_subfr_bwe, output_frame, core_switching_flag, mem_synth ); + } + + if( core_switching_flag && st->last_core == HQ_CORE && st->prev_bfi ) + { + mvr2r( st->delay_buf_out, synth_subfr_out, delay_comp ); + } + + /* delay HQ synthesis to synchronize with ACELP synthesis */ + mvr2r( synth, synth + delay_comp, output_frame); + mvr2r( st->delay_buf_out, synth, delay_comp ); + mvr2r( synth + output_frame, st->delay_buf_out, delay_comp ); + + if( core_switching_flag && st->last_L_frame == st->last_L_frame_ori && (st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE)) + { + core_switching_OLA( mem_synth, st->last_L_frame, st->output_Fs, synth, synth_subfr_out, synth_subfr_bwe, output_frame, st->bwidth ); + } + else if( core_switching_flag && st->last_core == HQ_CORE && st->prev_bfi ) /* HQ | ACELP | TRANSITION with ACELP frame lost */ + { + nZeros = (short)(NS2SA(st->output_Fs,N_ZERO_MDCT_NS)); + /* Overlapp between old->out[] (stocked in st->fer_samples[]) and good HQ frame on L/2 */ + tmpDelta = 1.0f/(float)(output_frame>>1); + for( i=0; i>1; i++ ) + { + tmpF = (float)i * tmpDelta; + synth[i+delay_comp] = (1-tmpF) * st->fer_samples[i+nZeros] + synth[i+delay_comp] * tmpF; + } + } + else if ( ( !core_switching_flag && st->core == HQ_CORE && (st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE) ) || /* ACELP | TRANSITION | HQ with TRANSITION lost */ + ( core_switching_flag && st->prev_bfi && st->last_L_frame != st->last_L_frame_ori ) ) /* ACELP@12k8 | ACELP@16k | TRANSITION with ACELP@16k lost */ + { + /* Overlapp between CELP estimation (BFI) and good HQ frame on L/2 */ + tmpDelta = 1.0f/(float)(output_frame>>1); + for( i=0; i<(output_frame>>1); i++ ) + { + tmpF = (float)i * tmpDelta; + synth[i] = synth[i] * tmpF + (1-tmpF) * st->fer_samples[i]; + } + } + + st->bwe_non_lin_prev_scale = 0.0; + if ( !(inner_frame_tbl[st->bwidth] == L_FRAME16k && st->core_brate == HQ_32k ) ) + { + set_f( st->prev_env, 0, SFM_N_WB ); + set_f( st->prev_normq, 0, SFM_N_WB ); + } + + mvr2r( synth, st->previoussynth, output_frame ); + + /*Set post-filtering flag to zero*/ + st->pfstat.on = 0; + } + else + { + /* MDCT to ACELP transition */ + if( st->last_core == HQ_CORE ) + { + nZeros = (short)(NS2SA(st->output_Fs,N_ZERO_MDCT_NS)); + mvr2r( st->delay_buf_out, synth, delay_comp ); /* copy the HQ/ACELP delay synchroniation buffer at the beginning of ACELP frame */ + + if(st->prev_bfi && st->HqVoicing) + { + mvr2r( st->fer_samples, st->old_out+nZeros, NS2SA(st->output_Fs,3000000) ); + } + + tmpF = 1.0f/(float)NS2SA(st->output_Fs,3000000); + for( i=0; ioutput_Fs,3000000); i++ ) + { + synth[i+delay_comp] = (1-tmpF*(float)i)*st->old_out[i+nZeros] + tmpF*(float)i*synth[i+delay_comp]; + } + } + + set_f( st->delay_buf_out, 0, HQ_DELTA_MAX*HQ_DELAY_COMP ); + st->oldHqVoicing = 0; + } + + /* reset SWB BWE buffers */ + if ( st->bws_cnt == 0 || ( st->bws_cnt > 0 && coder_type != INACTIVE && coder_type != AUDIO ) ) + { + st->attenu1 = 0.1f; + } + if( ( st->last_extl != SWB_BWE && st->extl == SWB_BWE ) || ( st->last_extl != FB_BWE && st->extl == FB_BWE ) || + ((st->last_core == HQ_CORE || st->last_extl == SWB_TBE) && st->extl < 0 && st->core != HQ_CORE) + || (st->last_core == ACELP_CORE && st->core == ACELP_CORE + && ((st->prev_coder_type != INACTIVE && coder_type != INACTIVE) || (st->prev_coder_type != AUDIO && coder_type == AUDIO)) + && st->bws_cnt >0) + ) + { + set_f(st->old_wtda_swb, 0, output_frame); + + if( st->last_extl != WB_BWE ) + { + st->prev_mode = NORMAL; + } + + st->prev_Energy = 0.0f; + st->prev_L_swb_norm = 8; + st->prev_frica_flag = 0; + set_f( st->mem_imdct, 0, L_FRAME48k ); + st->prev_td_energy = 0.0f; + st->prev_weight = 0.2f; + st->prev_fb_ener_adjust = 0.0f; + } + + /* reset WB BWE buffers */ + if( st->last_extl != WB_BWE && st->extl == WB_BWE ) + { + set_f(st->old_wtda_swb, 0, output_frame); + if ( st->last_extl != SWB_BWE && st->last_extl != FB_BWE ) + { + st->prev_mode = NORMAL; + } + st->prev_Energy_wb = 0.0f; + st->prev_L_swb_norm = 8; + set_f( st->mem_imdct, 0, L_FRAME48k ); + st->prev_flag = 0; + } + + /* reset SWB TBE buffers */ + if( (( st->extl == SWB_TBE || st->extl == FB_TBE || st->extl == SWB_CNG ) && + (st->L_frame != st->last_L_frame || ( st->last_extl != SWB_TBE && st->last_extl != FB_TBE ) || st->last_core == HQ_CORE )) || + ( st->bwidth < st->last_bwidth && st->last_extl != SWB_TBE ) || st->old_ppp_mode + || ((st->prev_coder_type == AUDIO || st->prev_coder_type == INACTIVE) && st->bws_cnt > 0 ) + || (st->bws_cnt == 0 && st->prev_bws_cnt == N_WS2N_FRAMES) + ) + { + swb_tbe_reset( st->mem_csfilt, st->mem_genSHBexc_filt_down_shb, st->state_lpc_syn, + st->syn_overlap, st->state_syn_shbexc, &(st->tbe_demph), &(st->tbe_premph), st->mem_stp_swb, &(st->gain_prec_swb) ); + + /* reset GainShape delay for SWB TBE FEC */ + set_f( st->GainShape_Delay, 0, NUM_SHB_SUBFR/2 ); + + swb_tbe_reset_synth( st->genSHBsynth_Hilbert_Mem, st->genSHBsynth_state_lsyn_filt_shb_local ); + + if( output_frame == L_FRAME16k ) + { + set_f( st->mem_resamp_HB_32k, 0, 2*ALLPASSSECTIONS_STEEP+1 ); /* reset in case that SWB TBE layer is transmitted, but the output is 16kHz sampled */ + } + + set_f(st->int_3_over_2_tbemem_dec, 0.0f, INTERP_3_2_MEM_LEN); + } + else if( (st->extl == SWB_TBE || st->extl == FB_TBE) && + ( (st->last_total_brate != st->total_brate) || (st->last_bwidth != st->bwidth) || + (st->last_codec_mode != MODE1) || (st->rf_flag != st->rf_flag_last) ) ) + { + set_f( st->state_lpc_syn, 0.0f, LPC_SHB_ORDER ); + set_f( st->state_syn_shbexc, 0.0f, L_SHB_LAHEAD ); + set_f( st->mem_stp_swb, 0.0f, LPC_SHB_ORDER ); + set_f( st->mem_zero_swb, 0, LPC_SHB_ORDER ); + st->gain_prec_swb = 1.0f; + } + + /* Interp_3_2 CNG buffers reset */ + if(st->output_Fs == 48000 && ((st->last_core_brate > SID_2k40) && (st->core_brate == FRAME_NO_DATA || st->core_brate == SID_2k40)) ) + { + set_f(st->interpol_3_2_cng_dec, 0.0f, INTERP_3_2_MEM_LEN); + } + + /* reset FB TBE buffers */ + if( (st->L_frame != st->last_L_frame || st->last_extl != FB_TBE ) && st->extl == FB_TBE ) + { + set_f(st->fb_state_lpc_syn, 0, LPC_SHB_ORDER); + st->fb_tbe_demph = 0; + fb_tbe_reset_synth( st->fbbwe_hpf_mem,&st->prev_fbbwe_ratio ); + } + + /* reset WB TBE buffers */ + if( st->last_extl != WB_TBE && st->extl == WB_TBE ) + { + wb_tbe_extras_reset( st->mem_genSHBexc_filt_down_wb2, st->mem_genSHBexc_filt_down_wb3 ); + wb_tbe_extras_reset_synth( st->state_lsyn_filt_shb, st->state_lsyn_filt_dwn_shb, st->mem_resamp_HB ); + + set_f( st->state_syn_shbexc, 0, L_SHB_LAHEAD / 4 ); + set_f( st->syn_overlap, 0, L_SHB_LAHEAD ); + set_f( st->mem_csfilt, 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 ACELP subframe budget +*---------------------------------------------------------------------*/ + +void core_switching_hq_prepare_dec( + Decoder_State *st, /* i/o: encoder state structure */ + short *num_bits, /* i/o: bit budget update */ + const short output_frame /* i : output frame length */ +) +{ + long cbrate; + + if( st->last_core == HQ_CORE && st->prev_bfi ) + { + mvr2r( st->old_out, st->fer_samples, output_frame ); + } + + /* set switching frame bit-rate */ + if( st->last_L_frame == L_FRAME ) + { + if( st->core_brate > ACELP_24k40 ) + { + cbrate = ACELP_24k40; + } + else + { + cbrate = st->core_brate; + } + + /* subtract ACELP switching frame bits */ + if( st->core_brate >= ACELP_11k60 ) + { + (*num_bits)--; /* LP_FLAG bit */ + } + + *num_bits -= ACB_bits_tbl[BIT_ALLOC_IDX(cbrate, GENERIC, 0, 0)]; /* pitch bits*/ + *num_bits -= gain_bits_tbl[BIT_ALLOC_IDX(cbrate, TRANSITION, 0, 0)]; /* gain bits */ + *num_bits -= FCB_bits_tbl[BIT_ALLOC_IDX(cbrate, GENERIC, 0, 0)]; /* FCB bits */ + } + else /* L_frame == L_FRAME16k */ + { + if( st->core_brate <= ACELP_8k00 ) + { + cbrate = ACELP_8k00; + } + else if( st->core_brate <= ACELP_14k80 ) + { + cbrate = ACELP_14k80; + } + else + { + cbrate = min(st->core_brate,ACELP_22k60); + } + + /* subtract ACELP switching frame bits */ + if( st->core_brate >= ACELP_11k60 ) + { + /* subtract one bit for LP filtering flag */ + (*num_bits)--; + } + *num_bits -= ACB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ(cbrate, GENERIC, 0, 0)]; /* pitch bits*/ + *num_bits -= gain_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ(cbrate, GENERIC, 0, 0)]; /* gain bits */ + *num_bits -= FCB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ(cbrate, GENERIC, 0, 0)]; /* FCB bits */ + } + + /* subtract BWE bits */ + if( !( (inner_frame_tbl[st->bwidth] == L_FRAME16k && st->last_L_frame==L_FRAME16k) || inner_frame_tbl[st->bwidth]==L_FRAME8k ) ) + { + *num_bits -= (NOOFGAINBITS1 + AUDIODELAYBITS); + } + + /* reset state of old_out if switching */ + set_f( st->old_out, 0.0f, output_frame ); + + return; + +} + + +/*---------------------------------------------------------------------* + * bandwidth_switching_detect() + * + * Classification for band-width switching + *---------------------------------------------------------------------*/ + +void bandwidth_switching_detect( + Decoder_State *st /* i/o: encoder state structure */ +) +{ + /* update band-width switching counter */ + if( st->bws_cnt1 >= N_NS2W_FRAMES ) + { + st->bws_cnt1 = 0; + } + else if( st->total_brate > ACELP_9k60 && st->last_core_brate < ACELP_9k60 && st->bwidth == SWB && st->last_bwidth == WB ) + { + st->bws_cnt1++; + } + else if( st->bws_cnt1 > 0 ) + { + st->bws_cnt = st->bwidth < st->last_bwidth ? 2*(N_NS2W_FRAMES - st->bws_cnt1)-1 : 0; + st->bws_cnt1 = st->bwidth < st->last_bwidth ? 0 : ((st->bwidth == SWB) ? st->bws_cnt1+1 : 0); + } + + /* update band-width switching counter */ + if( st->bws_cnt >= N_WS2N_FRAMES ) + { + st->bws_cnt = 0; + } + else if( st->total_brate < ACELP_9k60 && st->last_core_brate > ACELP_9k60 && st->bwidth < st->last_bwidth && st->bwidth == WB ) + { + st->bws_cnt++; + } + else if( st->bws_cnt > 0 ) + { + st->bws_cnt1 = st->bwidth > st->last_bwidth ? ((N_WS2N_FRAMES - st->bws_cnt) >> 1) : 0; + st->bws_cnt = st->bwidth > st->last_bwidth ? 0 :(( st->bwidth == WB) ? st->bws_cnt+1 : 0); + } + + return; +} + + +/*---------------------------------------------------------------------* + * bw_switching_pre_proc() + * + * Band-width switching pre-processing + *---------------------------------------------------------------------*/ + +void bw_switching_pre_proc( + Decoder_State *st, /* i/o: decoder state structure */ + const float *old_syn_12k8_16k /* i : ACELP core synthesis at 12.8kHz or 16kHz */ +) +{ + short i; + float syn_dct[L_FRAME]; + + if( st->core == ACELP_CORE ) + { + /*----------------------------------------------------------------------* + * Calculate tilt of the ACELP core synthesis + *----------------------------------------------------------------------*/ + calc_tilt_bwe( old_syn_12k8_16k, &st->tilt_wb, st->L_frame); + /*-------------------------------------------------------------------------------* + * Calculate frequency energy of 0~3.2kHz and 3.2~6.4kHz the ACELP core synthesis + *-------------------------------------------------------------------------------*/ + + edct( old_syn_12k8_16k, syn_dct, L_FRAME ); + + st->enerLL = EPSILON; + for ( i=0; ienerLL += syn_dct[i] * syn_dct[i]; + } + st->enerLL = (float)sqrt(st->enerLL/128); + + st->enerLH = EPSILON; + for (; ienerLH += syn_dct[i] * syn_dct[i]; + } + st->enerLH = (float)sqrt(st->enerLH/128); + } + else + { + if( st->old_is_transient[0] ) + { + st->enerLL = EPSILON; + for ( i=0; i<32; i++ ) + { + st->enerLL += st->t_audio_q[i] * st->t_audio_q[i]; + } + st->enerLL = (float)sqrt(st->enerLL/32); + + st->enerLH = EPSILON; + for (; i<64; i++ ) + { + st->enerLH += st->t_audio_q[i] * st->t_audio_q[i]; + } + st->enerLH = (float)sqrt(st->enerLH/32); + } + else + { + st->enerLL = EPSILON; + for ( i=0; ienerLL += st->t_audio_q[i] * st->t_audio_q[i]; + } + st->enerLL = (float)sqrt(st->enerLL/128); + + st->enerLH = EPSILON; + for (; ienerLH += st->t_audio_q[i] * st->t_audio_q[i]; + } + st->enerLH = (float)sqrt(st->enerLH/128); + } + } + + if( st->last_bwidth == 0 && st->extl <= SWB_CNG ) + { + st->prev_ener_shb = 0.0f; + set_f(st->prev_SWB_fenv, 0, SWB_FENV); + } + else if( ((st->core == ACELP_CORE && st->last_core == HQ_CORE) || (st->core == st->last_core && st->extl != st->last_extl)) && st->last_bwidth >= SWB ) + { + st->attenu1 = 0.1f; + } + if( st->last_core == HQ_CORE || ( st->last_core == ACELP_CORE && !(st->last_extl == WB_TBE || st->last_extl == SWB_TBE || st->last_extl == FB_TBE ) && st->core_brate > ACELP_8k00) ) + { + st->prev_fractive = 0; + } + + return; +} diff --git a/lib_dec/d_gain2p.c b/lib_dec/d_gain2p.c new file mode 100644 index 000000000..04f46bf24 --- /dev/null +++ b/lib_dec/d_gain2p.c @@ -0,0 +1,260 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include "options.h" +#include "typedef.h" +#include "prot.h" +#include "cnst.h" +#include "rom_com.h" + + +/*--------------------------------------------------------------------------* +* Mode2_gain_dec_mless +* +* Decoding of pitch and codebook gains without updating long term energies +*-------------------------------------------------------------------------*/ + +static void Mode2_gain_dec_mless( + int index, /* (i) : index of quantizer */ + float code[], /* (i) : Innovative code vector */ + int lcode, /* (i) : Subframe size */ + float *gain_pit, /* (o) : Quantized pitch gain */ + float *gain_code, /* (o) : Quantized codebook gain */ + float mean_ener, /* (i) : mean_ener defined in open-loop (2 bits) */ + float *past_gpit, /* (i/o): past gain of pitch */ + float *past_gcode, /* (i/o): past energy of code */ + float *gain_inov, /* (o) : un-scaled innovation gain */ + short coder_type /* (i) : coder type for number of bits */ +) +{ + short i; + float ener_code,gcode0; + const Word16 *t_qua_gain; + + ener_code = 0.0f; + + if( coder_type == 0 ) + { + *gain_inov = 1.0f / (float)sqrt( ( dotp( code, code, lcode ) + 0.01f ) / lcode); + } + else + { + ener_code = 0.01f; + + for(i=0; i>5; + index=index&0x1F; + + *gain_code= (float)pow(10.f,(((index*1.25f)-20.f)/20.f))*gcode; + *gain_code2 = (float) (index2*0.25f+0.25f)*(*gain_code*(gcode2/gcode)); + + *past_gcode=*gain_code/ *gain_inov; /*unscaled gain*/ + + return; +} + + +/*---------------------------------------------------------------------* + * decode_acelp_gains + * + * + *---------------------------------------------------------------------*/ + +void decode_acelp_gains( + float *code, + int gains_mode, + float mean_ener_code, + float *gain_pit, + float *gain_code, + int **pt_indice, + float *past_gpit, + float *past_gcode, + float *gain_inov, + int L_subfr, + float *code2, + float *gain_code2 +) +{ + int index = 0; + + index = **pt_indice; + (*pt_indice)++; + + if (((gains_mode > 0) && (gains_mode < 4))) + { + /* EVS 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(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(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); + } + + return; +} diff --git a/lib_dec/dec2t32.c b/lib_dec/dec2t32.c new file mode 100644 index 000000000..4667c367a --- /dev/null +++ b/lib_dec/dec2t32.c @@ -0,0 +1,91 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" + + +/*----------------------------------------------------------------------------------* + * dec_acelp_2t32() + * + * 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. + *----------------------------------------------------------------------------------*/ + +void dec_acelp_2t32( + Decoder_State *st, /* i/o: decoder state structure */ + float code[] /* o: algebraic (fixed) codebook excitation */ +) +{ + short index, i0, i1; + + index = (short) get_next_indice( st, 12 ); + + set_f( code, 0.0f, L_SUBFR ); + + /*-----------------------------------------------------------------* + * decode the positions and signs of pulses and build the codeword + *-----------------------------------------------------------------*/ + + i0 = ((index>>6) & (NB_POS_FCB_2T-1)) * NB_TRACK_FCB_2T; + i1 = ((index & (NB_POS_FCB_2T-1)) * NB_TRACK_FCB_2T) + 1; + code[i0] = -1.0f; + if ((index & 0x800) == 0) + { + code[i0] = 1.0f; + } + + code[i1] = -1.0f; + if ((index & 0x20) == 0) + { + code[i1] = 1.0f; + } + + return; +} + + +/*----------------------------------------------------------------------------------* + * dec_acelp_1t64() + * + * 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. + *----------------------------------------------------------------------------------*/ + +void dec_acelp_1t64( + Decoder_State *st, /* i/o: decoder state structure */ + float code[] /* o: algebraic (fixed) codebook excitation */ +) +{ + short pos, sgn; + + /*-----------------------------------------------------------------* + * decode the positions and signs of pulses and build the codeword + *-----------------------------------------------------------------*/ + + pos = (short)get_next_indice( st, 7 ); + + sgn = -1; + if( pos >= L_SUBFR ) + { + pos -= L_SUBFR; + sgn = 1; + } + + set_f( code, 0.0f, L_SUBFR ); + code[pos] = sgn; + + return; +} diff --git a/lib_dec/dec4t64.c b/lib_dec/dec4t64.c new file mode 100644 index 000000000..5f9572246 --- /dev/null +++ b/lib_dec/dec4t64.c @@ -0,0 +1,740 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static void add_pulses(const short pos[], const short nb_pulse, const short track, float code[]); +static void dec_1p_N1(const long index, const short N, const short offset, short pos[]); +static void dec_2p_2N1(const long index, const short N, const short offset, short pos[]); +static void dec_3p_3N1(const long index, const short N, const short offset, short pos[]); +static void dec_4p_4N1(const long index, const short N, const short offset, short pos[]); +static void dec_4p_4N(const long index, const short N, const short offset, short pos[]); +static void dec_5p_5N(const long index, const short N, const short offset, short pos[]); +static void dec_6p_6N2(const long index, const short N, const short offset, short pos[]); +static int fcb_decode_PI( int code_index, short sector_6p[], int pulse_num ); + +/*----------------------------------------------------------------------------------* + * dec_acelp_4t64() + * + * 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. + *----------------------------------------------------------------------------------*/ + +void dec_acelp_4t64( + Decoder_State *st, /* i/o: decoder state structure */ + short nbbits, /* i : number of bits per codebook */ + float code[], /* o : algebraic (fixed) codebook excitation */ + const short Opt_AMR_WB /* i : flag indicating AMR-WB IO mode */ +) +{ + short i, k, pos[7]; + long L_index; + long ind1[NB_TRACK_FCB_4T], ind2[NB_TRACK_FCB_4T]; + PulseConfig config; + int indexing_indices[6], wordcnt, bitcnt; + + if ( !Opt_AMR_WB ) + { + switch (nbbits) + { + case 20: + config.nb_pulse = 4; + break; + + case 28: + config.nb_pulse = 6; + break; + + case 36: + config.nb_pulse = 8; + break; + + case 43: + config.nb_pulse = 10; + break; + + case 50: + config.nb_pulse = 12; + break; + + case 62: + config.nb_pulse = 16; + break; + + + case 87: + config.nb_pulse = 26; + break; + } + + config.bits = nbbits; + config.codetrackpos = TRACKPOS_FIXED_FIRST; + + + wordcnt = nbbits >> 4; + bitcnt = nbbits & 15; + for ( i = 0; i < wordcnt; i++ ) + { + indexing_indices[i] = get_next_indice( st, 16 ); + } + if ( bitcnt ) + { + indexing_indices[i] = get_next_indice( st, bitcnt ); + } + + D_ACELP_indexing( code, config, NB_TRACK_FCB_4T, indexing_indices, &st->BER_detect ); + } + else + { + for (i=0; i> N) & 1; + + if (i == 1) + { + pos1 += NB_POS_FCB_4T; + } + + pos[0] = pos1; + + return; +} + +/*-------------------------------------------------------* + * dec_2p_2N1() + * + * Decode 2 pulses with 2*N+1 bits: + *-------------------------------------------------------*/ + +void dec_2p_2N1( + const long index, /* i: quantization index */ + const short N, /* i: nb. of bits */ + const short offset, /* i: pulse position offset */ + short pos[] /* o: pulse position */ +) +{ + short i, pos1, pos2; + long mask; + + mask = ((1<> N) & mask) + offset; + i = (short)(index >> (2*N)) & 1; + pos2 = (short)(index & mask) + offset; + if ((pos2 - pos1) < 0) + { + if (i == 1) + { + pos1 += NB_POS_FCB_4T; + } + else + { + pos2 += NB_POS_FCB_4T; + } + } + else + { + if (i == 1) + { + pos1 += NB_POS_FCB_4T; + pos2 += NB_POS_FCB_4T; + } + } + + pos[0] = pos1; + pos[1] = pos2; + + return; +} + +/*-------------------------------------------------------* + * dec_3p_3N1() + * + * Decode 3 pulses with 3*N+1 bits: + *-------------------------------------------------------*/ + +static void dec_3p_3N1( + const long index, /* i: quantization index */ + const short N, /* i: nb. of bits */ + const short offset, /* i : pulse position offset */ + short pos[] /* o : pulse position */ +) +{ + short j; + long idx, mask; + + mask = ((1 << ((2 * N) - 1)) - 1); + idx = index & mask; + j = offset; + + if(((index >> ((2 * N) - 1)) & 1) == 1) + { + j += (1 << (N - 1)); + } + + dec_2p_2N1(idx, N - 1, j, pos); + mask = ((1 << (N + 1)) - 1); + idx = (index >> (2 * N)) & mask; + dec_1p_N1(idx, N, offset, pos + 2); + + return; +} + +/*-------------------------------------------------------* + * dec_4p_4N1() + * + * Decode 4 pulses with 4*N+1 bits: + *-------------------------------------------------------*/ + +static void dec_4p_4N1( + const long index, /* i : quantization index */ + const short N, /* i : nb. of bits */ + const short offset, /* i : pulse position offset */ + short pos[] /* o : pulse position */ +) +{ + short j; + long mask, idx; + + mask = ((1 << ((2 * N) - 1)) - 1); + idx = index & mask; + j = offset; + + if(((index >> ((2 * N) - 1)) & 1) == 1) + { + j += (1 << (N - 1)); + } + + dec_2p_2N1(idx, N - 1, j, pos); + mask = ((1 << ((2 * N) + 1)) - 1); + idx = (index >> (2 * N)) & mask; + dec_2p_2N1(idx, N, offset, pos + 2); + + return; +} + +/*-------------------------------------------------------* + * dec_4p_4N() + * + * Decode 4 pulses with 4*N bits: + *-------------------------------------------------------*/ + +static void dec_4p_4N( + const long index, /* i : quantization index */ + const short N, /* i : nb. of bits */ + const short offset, /* i : pulse position offset */ + short pos[] /* o : pulse position */ +) +{ + short j, n_1; + + n_1 = N - 1; + j = offset + (1 << n_1); + switch((index >> ((4 * N) - 2)) & 3) + { + case 0: + { + if(((index >> ((4 * n_1) + 1)) & 1) == 0) + { + dec_4p_4N1(index, n_1, offset, pos); + } + else + { + dec_4p_4N1(index, n_1, j, pos); + } + break; + } + case 1: + { + dec_1p_N1((index >> ((3 * n_1) + 1)), n_1, offset, pos); + dec_3p_3N1(index, n_1, j, pos + 1); + break; + } + case 2: + { + dec_2p_2N1((index >> ((2 * n_1) + 1)), n_1, offset, pos); + dec_2p_2N1(index, n_1, j, pos + 2); + break; + } + case 3: + { + dec_3p_3N1((index >> (n_1 + 1)), n_1, offset, pos); + dec_1p_N1(index, n_1, j, pos + 3); + break; + } + } + + return; +} + +/*-------------------------------------------------------* + * dec_5p_5N() + * + * Decode 5 pulses with 5*N bits: + *-------------------------------------------------------*/ + +static void dec_5p_5N( + const long index, /* i : quantization index */ + const short N, /* i : nb. of bits */ + const short offset, /* i : pulse position offset */ + short pos[] /* o : pulse position */ +) +{ + short j, n_1; + long idx; + + n_1 = N - 1; + j = offset + (1 << n_1); + idx = (index >> ((2 * N) + 1)); + + if(((index >> ((5 * N) - 1)) & 1) == 0) + { + dec_3p_3N1(idx, n_1, offset, pos); + dec_2p_2N1(index, N, offset, pos + 3); + } + else + { + dec_3p_3N1(idx, n_1, j, pos); + dec_2p_2N1(index, N, offset, pos + 3); + } + + return; +} + +/*-------------------------------------------------------* + * dec_6p_6N2() + * + * Decode 6 pulses with 6*N+2 bits: + *-------------------------------------------------------*/ + +static void dec_6p_6N2( + const long index, /* i : quantization index */ + const short N, /* i : nb. of bits */ + const short offset, /* i : pulse position offset */ + short pos[] /* o : pulse position */ +) +{ + short j, n_1, offsetA, offsetB; + + n_1 = N - 1; + j = offset + (1 << n_1); + offsetA = offsetB = j; + if(((index >> ((6 * N) - 5)) & 1) == 0) + { + offsetA = offset; + } + else + { + offsetB = offset; + } + + switch((index >> ((6 * N) - 4)) & 3) + { + case 0: + { + dec_5p_5N(index >> N, n_1, offsetA, pos); + dec_1p_N1(index, n_1, offsetA, pos + 5); + break; + } + + case 1: + { + dec_5p_5N(index >> N, n_1, offsetA, pos); + dec_1p_N1(index, n_1, offsetB, pos + 5); + break; + } + + case 2: + { + dec_4p_4N(index >> ((2 * n_1) + 1), n_1, offsetA, pos); + dec_2p_2N1(index, n_1, offsetB, pos + 4); + break; + } + + case 3: + { + dec_3p_3N1(index >> ((3 * n_1) + 1), n_1, offset, pos); + dec_3p_3N1(index, n_1, j, pos + 3); + break; + } + } + + return; +} + +/*---------------------------------------------------------------------* + * fcb_decode_class_all_p() + * + * Get the position number and the pulse number on every position + *---------------------------------------------------------------------*/ + +static int fcb_decode_class_all_p( /* o: The index of pulse positions */ + int *code_index, /* i: fcb index information */ + short sector_6p_num[], /* o: Number of pulses for each position */ + int pulse_num, /* i: Number of pulses on a track. */ + int *pos_num /* o: Number of positions which have pulses on the track.*/ +) +{ + int i,j,k; + int mn9; + int pulse_pos_num; + for (i=1; i<=pulse_num; i++) + { + if ((*code_index) < PI_offset[pulse_num][i]) + { + break; + } + } + + (*code_index) -= PI_offset[pulse_num][i-1]; + + pulse_pos_num = pulse_num - i + 2; + j = (*code_index)>>pulse_pos_num; + + k = j/PI_select_table[16][pulse_pos_num]; + mn9 = j - k * PI_select_table[16][pulse_pos_num]; + if ( ( pulse_pos_num < pulse_num ) && ( pulse_pos_num > 1 ) ) + { + for (i=0; i= k; l += 2) + { + ; + } + + if (k > PI_select_table[17-l][temp]) + { + l--; + } + + k = PI_select_table[17-l][temp--] - k ; + pos_vector[i] = (short)(l-1); + } + pos_vector[i] = (short)(l+k); + + return; +} + +/*---------------------------------------------------------------------* + * fcb_decode_PI() + * + * decode fcb pulse index + *---------------------------------------------------------------------*/ + +static int fcb_decode_PI( /* o: return pulse position number */ + int code_index, /* i: fcb index information */ + short sector_6p[], /* o: decoded pulse position */ + int pulse_num /* i: pulse number for the track */ +) +{ + int i,l; + int mn9; + int pulse_pos_num; + short sector_6p_temp[7], sector_6p_num_temp[7]; + short *sector_6p_ptr0; + short *sector_6p_ptr1; + + /*get the position number and the pulse number on every position */ + mn9 = fcb_decode_class_all_p(&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(mn9, sector_6p_temp, pulse_pos_num); + for (i=pulse_pos_num-1; i>=0; i--) + { + sector_6p_temp[i] += ((code_index&0x1)<<4) ; + code_index = 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> 9 ); + joint_index = ( ( idxs[2] << 16 ) + idxs[1] ) >> 2; + + if ( joint_index >= joint_offset) + { + joint_index = joint_index - joint_offset; + } + + ps[0] = joint_index/5472; + ps[1] = joint_index - ps[0]*5472; + fcb_decode_PI(ps[0], pos, 3); + add_pulses(pos, pulsestrack[0], 0, code); + fcb_decode_PI(ps[1], pos, 3); + add_pulses(pos, pulsestrack[1], 1, code); + + dec_2p_2N1(ps[2], 4, 0, pos); + add_pulses(pos, pulsestrack[2], 2, code); + dec_2p_2N1(ps[3], 4, 0, pos); + add_pulses(pos, pulsestrack[3], 3, code); + + return; +} diff --git a/lib_dec/dec_LPD.c b/lib_dec/dec_LPD.c new file mode 100644 index 000000000..90a4ccd3b --- /dev/null +++ b/lib_dec/dec_LPD.c @@ -0,0 +1,783 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "options.h" +#include "prot.h" +#include "rom_com.h" +#include "cnst.h" +#include "basop_proto_func.h" +#include "stat_com.h" + +#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( + float signal_out[], /* output: signal with LPD delay (7 subfrs) */ + float signal_outFB[], + short *total_nbbits, /* i/o: number of bits / decoded bits */ + Decoder_State *st, /* i/o: decoder memory state pointer */ + float *bpf_noise_buf, /* i/o: BPF noise buffer */ + short bfi, /* i : BFI flag */ + short *bitsRead, /* o : number of read bits */ + short *coder_type, /* o : coder type */ + int param[], /* o : buffer of parameters */ + float *pitch_buf, /* i/o: floating pitch values for each subfr*/ + float *voice_factors, /* o : voicing factors */ + float *ptr_bwe_exc /* o : excitation for SWB TBE */ +) +{ + int *prm, param_lpc[NPRM_LPC_NEW]; + float synth_buf[OLD_SYNTH_SIZE_DEC+L_FRAME_PLUS+M]; + float *synth; + float synth_bufFB[OLD_SYNTH_SIZE_DEC+L_FRAME_PLUS+M]; + float *synthFB; + float lsf[(NB_DIV+1)*M], lsp[(NB_DIV+1)*M], lspmid[M], lsfmid[M]; + float Aq[(NB_SUBFR16k+1)*(M+1)]; + int pitch[NB_SUBFR16k]; + float pit_gain[NB_SUBFR16k]; + short i, k; + short past_core_mode; + short L_frame, nb_subfr, L_frameTCX; + Word16 Aind[M+1], lspind[M]; + float tmp_old[M+1], tmp_new[M+1], enr_old, enr_new; + float lspnew_uw[NB_DIV*M], lsfnew_uw[NB_DIV*M]; + float lsf_q_1st_rf[M], lsf_q_rf[M], lsp_q_rf[M]; + float lsp_diff; + short LSF_Q_prediction; /* o : LSF prediction mode */ + short tcx_last_overlap_mode, tcx_current_overlap_mode; + + + /*--------------------------------------------------------------------------------* + * Initializations + *--------------------------------------------------------------------------------*/ + + prm = param; /* to avoid compilation warnings */ + LSF_Q_prediction = -1; /* to avoid compilation warnings */ + enr_old = 0.0f; + enr_new = 0.0f; + + if ( st->use_partial_copy && st->rf_frame_type >= RF_TCXFD && st->rf_frame_type <= RF_TCXTD2 ) + { + bfi = st->bfi; + } + + past_core_mode = st->last_core_bfi; + + /*Adjust bit per frame*/ + if( !bfi ) + { + st->bits_frame_core = st->bits_frame - (*bitsRead); + } + + /* Framing parameters */ + L_frame = st->L_frame; + L_frameTCX = st->L_frameTCX; + nb_subfr = st->nb_subfr; + + /* Initialize pointers */ + synth = synth_buf + st->old_synth_len; + synthFB = synth_bufFB + st->old_synth_lenFB; + mvr2r( st->old_synth, synth_buf, st->old_synth_len ); + mvr2r( st->old_synthFB, synth_bufFB, st->old_synth_lenFB ); + set_zero( synth, L_FRAME_PLUS+M ); + set_zero( synthFB, L_FRAME_PLUS+M ); + + + /*For post-processing (post-filtering+blind BWE)*/ + if( st->tcxonly == 0 ) + { + /* for bass postfilter */ + set_i( pitch, L_SUBFR, nb_subfr ); + set_zero( pit_gain, nb_subfr ); + } + + /* PLC: [Common: Memory update] + * PLC: Update the number of lost frames */ + if( bfi ) + { + st->nbLostCmpt++; + } + + + /*--------------------------------------------------------------------------------* + * BITSTREAM DECODING + *--------------------------------------------------------------------------------*/ + + + if( !bfi ) + { + st->second_last_core = st->last_core; + tcx_last_overlap_mode = st->tcx_cfg.tcx_last_overlap_mode; + tcx_current_overlap_mode = st->tcx_cfg.tcx_curr_overlap_mode; + + dec_prm( coder_type, param, param_lpc, total_nbbits, st, L_frame, bitsRead ); + + if(!st->rate_switching_init && (st->last_codec_mode) == MODE2 && st->BER_detect) + { + *coder_type = st->last_coder_type; + st->last_core = st->second_last_core; + st->tcx_cfg.tcx_last_overlap_mode = tcx_last_overlap_mode; + st->tcx_cfg.tcx_curr_overlap_mode = tcx_current_overlap_mode; + st->bfi = 1; + bfi = 1; + st->flagGuidedAcelp = 0; + st->nbLostCmpt++; + st->core_brate = st->last_core_brate; + st->core = GetPLCModeDecision( st ); + } + } + else + { + if( st->use_partial_copy && st->rf_frame_type >= RF_TCXFD && st->rf_frame_type <= RF_TCXTD2 ) + { + dec_prm( coder_type, param, param_lpc, total_nbbits, st, L_frame, bitsRead ); + } + + if( st->nbLostCmpt > 1 ) + { + st->flagGuidedAcelp = 0; + } + /* PLC: [Common: mode decision] + * PLC: Decide which Concealment to use. Update pitch lags if needed */ + st->core = GetPLCModeDecision( st ); + } + + /* PLC: [Common: Memory update] + * PLC: Update the number of lost frames */ + if( !bfi ) + { + if( st->prev_bfi == 1 ) + { + st->prev_nbLostCmpt = st->nbLostCmpt; + } + else + { + st->prev_nbLostCmpt = 0; + } + + st->nbLostCmpt = 0; + } + + + /*--------------------------------------------------------------------------------* + * LPC PARAMETERS + *--------------------------------------------------------------------------------*/ + + + if( (bfi == 0 ) || ( bfi == 1 && st->use_partial_copy && st->rf_frame_type == RF_TCXFD) ) + { + if(st->use_partial_copy && ( st->rf_frame_type < RF_TCXFD || st->rf_frame_type > RF_TCXTD2)) + { + if( st->envWeighted ) + { + mvr2r( st->lspold_uw, st->lsp_old, M ); + mvr2r( st->lsfold_uw, st->lsf_old, M ); + st->envWeighted = 0; + } + + /* first stage VQ, 8 bits; reuse TCX high rate codebook */ + set_f(lsf_q_1st_rf, 0.0f, M); + vlpc_1st_dec(param_lpc[0], lsf_q_1st_rf, st->sr_core ); + + /* 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 ); + + v_sort( lsf_q_rf, 0, M-1 ); + reorder_lsf( lsf_q_rf, LSF_GAP, M, st->sr_core ); + + /* current n-th ACELP frame and its corresponding partial copy */ + lsf2lsp( lsf_q_rf, lsp_q_rf, M, st->sr_core ); + + /* copy the old and current lsfs and lsps into the lsf[] and lsp[] buffer for interpolation */ + mvr2r(st->lsf_old, &lsf[0], M); + mvr2r(st->lsp_old, &lsp[0], M); + mvr2r(lsf_q_rf, &lsf[M], M); + mvr2r(lsp_q_rf, &lsp[M], M); + lsp_diff = 0.0f; + + for( i = 0; i < M; i++ ) + { + lsp_diff += (float)fabs(lsp[i+M] - lsp[i]); + } + + if( st->core == ACELP_CORE && st->last_core == ACELP_CORE + && lsp_diff < 1.6f && lsp_diff > 0.12f && st->next_coder_type == GENERIC + && !st->prev_use_partial_copy && st->last_coder_type == UNVOICED && st->rf_frame_type >= RF_GENPRED) + { + mvr2r( &lsp[0], &lsp[M], M ); + } + + /* update mem_MA and mem_AR memories */ + lsf_update_memory( st->narrowBand, &lsf[M], st->mem_MA, st->mem_MA ); + mvr2r(&lsf[M], st->mem_AR, M); + + for( k=0; knumlpc; ++k ) + { + mvr2r( &lsp[(k+1)*M], &lspnew_uw[k*M], M ); + mvr2r( &lsf[(k+1)*M], &lsfnew_uw[k*M], M ); + } + } + else if( (st->enableTcxLpc && st->core != ACELP_CORE) || (bfi && st->use_partial_copy && st->rf_frame_type == RF_TCXFD) ) + { + int tcx_lpc_cdk; + + if( bfi && st->use_partial_copy && st->rf_frame_type == RF_TCXFD ) + { + tcx_lpc_cdk = tcxlpc_get_cdk(GENERIC); + } + else + { + tcx_lpc_cdk = tcxlpc_get_cdk(*coder_type); + } + + mvr2r( st->lsf_old, &lsf[0], M ); + mvr2r( st->lsp_old, &lsp[0], M ); + + D_lsf_tcxlpc( param_lpc, &lsf[M], lspind, st->narrowBand, tcx_lpc_cdk, st->mem_MA ); + + lsf2lsp( &lsf[M], &lsp[M], M, st->sr_core ); + + lsf_update_memory( st->narrowBand, &lsf[M], st->mem_MA, st->mem_MA ); + mvr2r(&lsf[M], st->mem_AR, M); + st->envWeighted = 1; + + E_LPC_lsp_unweight( &lsp[M], lspnew_uw, lsfnew_uw, 1.0f/st->gamma ); + } + else + { + if( st->envWeighted ) + { + mvr2r( st->lspold_uw, st->lsp_old, M ); + mvr2r( st->lsfold_uw, st->lsf_old, M ); + st->envWeighted = 0; + } + + /* Unquantize LPC */ + if( st->core == TCX_20_CORE ) + { + lpc_unquantize( st, st->lsf_old, st->lsp_old, lsf, lsp, st->lpcQuantization, param_lpc, st->numlpc, st->core, st->mem_MA, + lspmid, lsfmid, AUDIO, st->acelp_cfg.midLpc, st->narrowBand, &(st->seed_acelp), st->sr_core, + &st->mid_lsf_int, st->prev_bfi, &LSF_Q_prediction, &st->safety_net ); + } + else + { + lpc_unquantize( st, st->lsf_old, st->lsp_old, lsf, lsp, st->lpcQuantization, param_lpc, st->numlpc, st->core, st->mem_MA, + lspmid, lsfmid, *coder_type, st->acelp_cfg.midLpc, st->narrowBand, &(st->seed_acelp), st->sr_core, + &st->mid_lsf_int, st->prev_bfi, &LSF_Q_prediction, &st->safety_net ); + + if( st->prev_use_partial_copy && st->last_core == ACELP_CORE && st->core == ACELP_CORE && st->prev_rf_frame_type >= RF_GENPRED && *coder_type == UNVOICED ) + { + if( st->lpcQuantization && st->acelp_cfg.midLpc ) + { + mvr2r( lspmid, &lsp[0], M ); + mvr2r( &lsp[M], lspmid, M ); + } + } + } + + for( k=0; knumlpc; ++k ) + { + mvr2r( &lsp[(k+1)*M], &lspnew_uw[k*M], M ); + mvr2r( &lsf[(k+1)*M], &lsfnew_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[i] = (st->lsfoldbfi1[i]+st->lsfoldbfi0[i]+lsfnew_uw[k*M+i])/3; + st->lsfoldbfi1[i] = st->lsfoldbfi0[i]; + st->lsfoldbfi0[i] = lsfnew_uw[k*M+i]; + } + } + } + else + { + /* PLC: [LPD: LPC concealment] Conceal the LPC from the lost frame */ + float const* lsfBase; /* base for differential lsf coding */ + + if( st->tcxonly == 0 || st->core < TCX_10_CORE ) + { + st->numlpc = 1; + } + else + { + st->numlpc = 2; + } + + if( st->nbLostCmpt == 1) + { + mvr2r( st->lsf_old, st->old_lsf_q_cng, M ); + mvr2r( st->lsp_old, st->old_lsp_q_cng, M ); + } + + + lsfBase = PlcGetlsfBase( st->lpcQuantization, st->narrowBand, st->sr_core ); + + dlpc_bfi( st->L_frame, lsfnew_uw, st->lsfold_uw, st->last_good, st->nbLostCmpt, st->mem_MA, st->mem_AR, &(st->stab_fac), + st->lsf_adaptive_mean, st->numlpc, st->lsf_cng, st->plcBackgroundNoiseUpdated, st->lsf_q_cng, st->old_lsf_q_cng, lsfBase); + + st->envWeighted = 0; + + mvr2r( st->lspold_uw, lsp, M ); + mvr2r( st->lsfold_uw, lsf, M ); + + for( k = 0; k < st->numlpc; k++ ) + { + mvr2r( &lsfnew_uw[k*M], &lsf[(k+1)*M], M ); + + lsf2lsp( &lsf[(k+1)*M], &lsp[(k+1)*M], M, st->sr_core ); + lsf2lsp( st->lsf_q_cng, st->lsp_q_cng, M, st->sr_core ); + + mvr2r( &lsp[(k+1)*M], &lspnew_uw[k*M], M ); + } + } + + + /*--------------------------------------------------------------* + * Rate switching + *---------------------------------------------------------------*/ + if( st->rate_switching_reset ) + { + mvr2r( &(lsf[M]),&(lsf[0]), M ); + mvr2r( &(lsp[M]),&(lsp[0]), M ); + mvr2r( &(lsf[M]),st->lsf_old, M ); + mvr2r( &(lsp[M]),st->lsp_old, M ); + mvr2r( &(lsf[M]),lsfmid, M ); + mvr2r( &(lsp[M]),lspmid, M ); + lsp2a_stab( st->lsp_old, st->old_Aq_12_8, M ); + } + + if(st->enablePlcWaveadjust) + { + if (st->core == ACELP_CORE) + { + st->tonality_flag = 0; + } + if (bfi) + { + st->plcInfo.nbLostCmpt++; + } + } + + /*--------------------------------------------------------------------------------* + * ACELP + *--------------------------------------------------------------------------------*/ + + + if( (st->prev_bfi!=0) && (bfi==0) && (*coder_type==VOICED) && (st->prev_nbLostCmpt>4) ) + { + st->dec_glr_idx = 1; + st->reset_mem_AR = 1; + } + + if( st->core == ACELP_CORE ) + { + if( !st->tcxonly ) + { + /* Set pointer to parameters */ + prm = param; + + /* Stability Factor */ + if( !bfi ) + { + st->stab_fac = lsf_stab( &lsf[M], &lsf[0], 0, st->L_frame ); + } + + if( !bfi && st->prev_bfi ) + { + /* check if LSP interpolation can be relaxed or if LPC power can be diffused*/ + lsp2a_stab( &lsp[0], tmp_old, M); + enr_old = enr_1_Az( tmp_old, 2*L_SUBFR ); + + lsp2a_stab( &lsp[M], tmp_new, M); + enr_new = enr_1_Az( tmp_new, 2*L_SUBFR ); + } + + if( !bfi && (st->dec_glr_idx == 1 || (!(st->safety_net) && enr_new>=256.f && enr_new > 2*enr_old)) && st->prev_bfi ) + { + RecLpcSpecPowDiffuseLc( &lsp[M], &lsp[0], &lsf[M], st, st->dec_glr_idx == 1 ? 1 : 0 ); + int_lsp( L_frame, &lsp[0], &lsp[M], Aq, M, interpol_frac_12k8, 0 ); + mvr2r( &lsf[M], lsfnew_uw, M ); + } + else + { + /* LPC Interpolation for ACELP */ + if( !bfi && st->acelp_cfg.midLpc ) + { + st->relax_prev_lsf_interp = 0; + + if( st->prev_bfi ) + { + /* check if LSP interpolation can be relaxed */ + if ( enr_new < (0.25f * enr_old) ) + { + /* don't use safety_net as this is getting impacted with lsf_restruct */ + if ( (st->clas_dec == UNVOICED_CLAS) || (st->clas_dec == SIN_ONSET) || (st->clas_dec == INACTIVE_CLAS) || (*coder_type == GENERIC) || (*coder_type == TRANSITION) ) + { + st->relax_prev_lsf_interp = 1; + } + else + { + st->relax_prev_lsf_interp = -1; + } + } + } + + if( st->stab_fac == 0 && st->old_bfi_cnt > 0 && st->clas_dec != VOICED_CLAS && st->clas_dec != ONSET && st->relax_prev_lsf_interp == 0 ) + { + st->relax_prev_lsf_interp = 2; + } + int_lsp4( L_frame, &lsp[0], lspmid, &lsp[M], Aq, M, st->relax_prev_lsf_interp ); + } + else + { + int_lsp( L_frame, &lsp[0], &lsp[M], Aq, M, interpol_frac_12k8, 0 ); + int_lsp( L_frame, st->old_lsp_q_cng, st->lsp_q_cng, st->Aq_cng, M, interpol_frac_12k8, 0 ); + } + } + } + + if( bfi && st->last_core != ACELP_CORE ) + { + /* PLC: [TCX: TD PLC] */ + con_tcx( st, &synthFB[0] ); + lerp(synthFB, synth, st->L_frame, st->L_frameTCX); + st->con_tcx = 1; + set_f( &st->mem_pitch_gain[2], st->lp_gainp, st->nb_subfr); + } + else + { + /* ACELP decoder */ + if (st->L_frame == L_FRAME) + { + mvr2r(Aq+2*(M+1), st->cur_sub_Aq, (M+1)); + } + else + { + mvr2r(Aq+3*(M+1), st->cur_sub_Aq, (M+1)); + } + + if( bfi ) + { + /* PLC: [ACELP: general] + * PLC: Use the ACELP like concealment */ + con_acelp( Aq, st->core_ext_mode, &synth[0], pitch, pit_gain, st->stab_fac, st, pitch_buf, voice_factors, ptr_bwe_exc ); + mvr2r( &st->mem_pitch_gain[2], &st->mem_pitch_gain[st->nb_subfr+2], st->nb_subfr ); + set_zero( &st->mem_pitch_gain[2],st->nb_subfr ); + } + else + { + decoder_acelp( st, *coder_type, prm, Aq, st->acelp_cfg, &synth[0], pitch, pit_gain, st->stab_fac, pitch_buf, voice_factors, LSF_Q_prediction, ptr_bwe_exc ); + + if( st->flagGuidedAcelp > 0 ) + { + st->guidedT0 = max(min(st->T0_4th + st->guidedT0, NBPSF_PIT_MAX), PIT_MIN_16k); + } + + for (i = 0; i < st->nb_subfr; i++) + { + 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 */ + if( st->narrowBand || st->sr_core==12800 || st->sr_core==16000 ) + { + mvr2r( 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 ) + { + st->second_last_tns_active = st->last_tns_active; + st->last_tns_active = 0; + st->tcxltp_last_gain_unmodified = 0.0f; + } + + } + + + + /*--------------------------------------------------------------------------------* + * TCX20 + *--------------------------------------------------------------------------------*/ + + + if( st->core == TCX_20_CORE ) + { + /* Set pointer to parameters */ + prm = param; + + /* Stability Factor */ + if( !bfi ) + { + st->stab_fac = lsf_stab( &lsf[M], &lsf[0], 0, st->L_frame ); + } + + if (st->enableTcxLpc) + { + /* Convert quantized lsp to A */ + lsp2a_stab( &lsp[M], Aq, M ); + } + else + { + if (!st->tcxonly) + { + if( !bfi && st->prev_bfi && !(st->safety_net) && st->rate_switching_reset ) + { + /* diffuse LPC power on rate switching*/ + RecLpcSpecPowDiffuseLc( &lsp[M], &lsp[0], &lsf[M], st, 0 ); + int_lsp( L_frame, &lsp[0], &lsp[M], Aq, M, interpol_frac_12k8, 0 ); + mvr2r( &lsf[M], lsfnew_uw, M ); + } + else + { + /* LPC Interpolation for TCX */ + E_LPC_int_lpc_tcx( &lsp[0], &lsp[M], Aq ); + } + } + else + { + lsp2a_stab( &lsp[M], Aq, M ); + } + } + + if( !bfi && st->tcx_lpc_shaped_ari ) + { + basop_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 ); + + } + + /*--------------------------------------------------------------------------------* + * TCX10 + *--------------------------------------------------------------------------------*/ + + if( st->core == TCX_10_CORE ) + { + prm = NULL; /* just to avoid MSVC warnings */ + + for (k=0; k<2; k++) + { + /* Set pointer to parameters */ + prm = param + (k*DEC_NPRM_DIV); + + /* Stability Factor */ + if( !bfi ) + { + st->stab_fac = lsf_stab( &lsf[(k+1)*M], &lsf[k*M], 0, st->L_frame ); + } + + lsp2a_stab( &lsp[(k+1)*M], Aq, M ); + IGFDecRestoreTCX10SubFrameData( &st->hIGFDec, k ); + + /* TCX decoder */ + decoder_tcx( &st->tcx_cfg, prm, Aq, Aind, L_frame/2, L_frameTCX/2, st->tcx_cfg.tcx_coded_lines/2, + &synth[k*L_frame/2], &synthFB[k*L_frameTCX/2], st, *coder_type, bfi, k, st->stab_fac ); + } + + } + + if (st->core == TCX_10_CORE || st->core == TCX_20_CORE) + { + if( st->enablePlcWaveadjust || /* bfi */ + ( st->last_total_brate >= HQ_48k && /* recovery */ + st->last_codec_mode == MODE2 ) ) + { + /* waveform adjustment */ + concealment_signal_tuning( bfi, st->core, synthFB, &st->plcInfo, st->nbLostCmpt, st->prev_bfi, + st->tonalMDCTconceal.secondLastPcmOut, past_core_mode,st->tonalMDCTconceal.lastPcmOut, st ); + + if( (bfi || st->prev_bfi) && st->plcInfo.Pitch && st->plcInfo.concealment_method == TCX_NONTONAL ) + { + lerp( synthFB, synth, L_frame, L_frameTCX ); + + if( !bfi && st->prev_bfi ) + { + st->plcInfo.Pitch = 0; + } + } + } + + if (!bfi) + { + TonalMDCTConceal_SaveTimeSignal( &st->tonalMDCTconceal, synthFB, L_frameTCX ); + } + + decoder_tcx_post( st, synth, synthFB, Aq, bfi ); + + if( st->core == TCX_20_CORE ) + { + /* LPC Interpolation for BBWE/post-processing */ + if( st->narrowBand || st->sr_core==12800 || st->sr_core==16000 ) + { + int_lsp( L_frame, st->lspold_uw, lspnew_uw, Aq, M, interpol_frac_12k8, 0 ); + mvr2r( Aq, st->mem_Aq, nb_subfr*(M+1) ); + } + } + } + + + /* PLC: [Common: Classification] */ + /* the classifier buffer is always updated if the sr is at + 16000 or below - the classification itself is just performed if(!st->tcxonly ) */ + if( st->sr_core <= 16000 ) + { + if( st->core == TCX_20_CORE || st->core == TCX_10_CORE || (st->tcxonly && st->bfi) ) + { + float pitch_C[4]; + + /* note: the classifier needs the pitch only for tcx_only == 0 , i.e. not for TCX10 */ + pitch_C[0] = pitch_C[1] = pitch_C[2] = pitch_C[3] = (float)floor(st->old_fpitch+0.5f); + + FEC_clas_estim( synth, pitch_C, st->L_frame, st->tcxonly? GENERIC : st->core_ext_mode, st->codec_mode, st->mem_syn_clas_estim, + &st->clas_dec, &st->lp_ener_bfi, st->core_brate, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + st->tcxltp ? st->tcxltp_last_gain_unmodified : -1.0f, st->narrowBand, 1, + bfi, st->preemph_fac, st->tcxonly, st->last_core_brate ); + } + } + + + + + /*--------------------------------------------------------------------------------* + * Updates + *--------------------------------------------------------------------------------*/ + + + if( bfi && st->last_core != ACELP_CORE ) + { + /* Update FEC_scale_syn parameters */ + if (st->tcxltp_gain == 0) + { + fer_energy( L_frame, UNVOICED, synth, L_frame/2, &st->enr_old, L_frame ); + } + else + { + fer_energy( L_frame, st->clas_dec, synth, st->old_fpitch, &st->enr_old, L_frame ); + } + } + + if( !bfi && st->clas_dec >= VOICED_TRANSITION && st->clas_dec < INACTIVE_CLAS) + { + short offset; + + if( st->core == ACELP_CORE ) + { + offset = (st->nb_subfr-1)*(M+1); + } + else + { + /* TCX */ + offset = 0; + } + + /* use latest LPC set */ + st->old_enr_LP = enr_1_Az( Aq+offset, L_SUBFR ); + } + + + /* Update */ + mvr2r( synth_buf+L_frame, st->old_synth, st->old_synth_len ); + mvr2r( st->old_synthFB + L_frameTCX - NS2SA(st->output_Fs, PH_ECU_MEM_NS), st->synth_history, NS2SA(st->output_Fs, PH_ECU_MEM_NS) ); + mvr2r( synth_bufFB+L_frameTCX, st->old_synthFB, st->old_synth_lenFB ); + mvr2r( st->old_out+NS2SA(st->output_Fs,N_ZERO_MDCT_NS), st->old_synthFB+st->old_synth_lenFB, NS2SA(st->output_Fs, PH_ECU_LOOKAHEAD_NS)); + + mvr2r( &lspnew_uw[(st->numlpc-1)*M], st->lspold_uw, M ); + mvr2r( &lsfnew_uw[(st->numlpc-1)*M], st->lsfold_uw, M ); + + if( bfi == 1 ) + { + mvr2r( st->lspold_uw, st->lsp_old, M ); /* for recovery */ + mvr2r( st->lsfold_uw, st->lsf_old, M ); /* for recovery */ + } + else + { + mvr2r( &lsp[st->numlpc*M], st->lsp_old, M ); + mvr2r( &lsf[st->numlpc*M], st->lsf_old, M ); + } + mvr2r( st->lsp_q_cng, st->old_lsp_q_cng, M ); + mvr2r( st->lsf_q_cng, st->old_lsf_q_cng, M ); + + /* Update MODE1 CNG parameters */ + if( !st->tcxonly ) + { + /* update CNG parameters in active frames */ + if ( st->bwidth == NB && st->enableTcxLpc && st->core != ACELP_CORE ) + { + float buf[L_LP], res[L_FRAME], A[M+1], r[M+1], tmp, lsptmp[M]; + assert(st->L_frame==L_FRAME); + mvr2r(synth+L_FRAME-L_LP, buf, L_LP); + tmp = synth[L_FRAME-L_LP-1]; + preemph(buf, st->preemph_fac, L_LP, &tmp); + autocorr( buf, r, M, L_LP, LP_assym_window, 0, 0, 0 ); + lag_wind(r, M, INT_FS_12k8, LAGW_WEAK); + lev_dur( A, r, M, NULL ); + a2lsp_stab( A, lsptmp, &lspnew_uw[0] ); + residu(A, M, buf+L_LP-L_FRAME, res, L_FRAME ); + + cng_params_upd( lsptmp, res, st->L_frame, &st->ho_circ_ptr, st->ho_ener_circ, &st->ho_circ_size, st->ho_lsp_circ, + DEC, st->ho_env_circ, NULL, NULL, NULL, st->last_active_brate ); + } + else + { + cng_params_upd( &lsp[M], st->old_exc+L_EXC_MEM_DEC-st->L_frame, st->L_frame, &st->ho_circ_ptr, st->ho_ener_circ, + &st->ho_circ_size, st->ho_lsp_circ, DEC, st->ho_env_circ, NULL, NULL, NULL, st->last_active_brate ); + } + + /* Set 16k LSP flag for CNG buffer */ + st->ho_16k_lsp[st->ho_circ_ptr] = (st->L_frame == L_FRAME ? 0 : 1 ); + } + + st->last_is_cng = 0; + + /* Postfiltering */ + post_decoder( st, *coder_type, synth_buf, pit_gain, pitch, signal_out, bpf_noise_buf ); + + if( signal_outFB ) + { + mvr2r( synthFB, signal_outFB, L_frameTCX ); + } + + if( st->enablePlcWaveadjust) + { + if(!bfi) + { + st->plcInfo.nbLostCmpt = 0; + } + + if( st->core == ACELP_CORE ) /* may happen only if bfi==1 */ + { + set_state( st->plcInfo.Transient, st->core, MAX_POST_LEN ); + } + } + + + return; +} diff --git a/lib_dec/dec_ace.c b/lib_dec/dec_ace.c new file mode 100644 index 000000000..072ac8cba --- /dev/null +++ b/lib_dec/dec_ace.c @@ -0,0 +1,550 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "prot.h" +#include "options.h" +#include "rom_com.h" + + +/*-------------------------------------------------------------------* + * decoder_acelp() + * + * Decode ACELP frame + *-------------------------------------------------------------------*/ + +void decoder_acelp( + Decoder_State *st, /* i/o: coder memory state */ + const short coder_type, /* i : coder type */ + int prm[], /* i : parameters */ + const float A[], /* i : coefficients NxAz[M+1] */ + ACELP_config acelp_cfg, /* i : ACELP config */ + float synth[], /* i/o: synthesis */ + int *pT, /* o : pitch for all subframe */ + float *pgainT, /* o : pitch gain for all subfr */ + const float stab_fac, /* i : stability of isf */ + float *pitch_buffer, /* i/o: pitch values for each subfr.*/ + float *voice_factors, /* o : voicing factors */ + const short LSF_Q_prediction,/* i : LSF prediction mode */ + float *bwe_exc /* o : excitation for SWB TBE */ +) +{ + short i, i_subfr, L_frame; + int T0, T0_frac, T0_min, T0_min_frac, T0_max, T0_max_frac, T0_res; + float tmp, gain_pit, gain_code, Es_pred; + float code[L_SUBFR]; + float mem_syn[M], *syn, syn_buf[M+L_FRAME16k+L_FRAME16k/2]; + float *exc, exc_buf[L_EXC_MEM_DEC+L_FRAME16k+1]; + float exc2[L_FRAME16k]; + const float *p_A; + float *pt_pitch, pitch_buf[NB_SUBFR16k]; + float gain_inov; + float mem_back[M]; + float h1[L_FRAME16k/4+1]; + float mem[M]; + const float *pA; + float gain_code2; + float code2[L_SUBFR]; + short lp_flag; + int offset; + float error = 0.0f; + float gain_preQ = 0; /* Gain of prequantizer excitation */ + float code_preQ[L_SUBFR]; /* Prequantizer excitation */ + PulseConfig config; + float weights[5]; + + float prev_gain_pit; + float tmp_noise; /* Long term temporary noise energy */ + + float gain_code_tmp; + float gain_pit_tmp; + float gain_code_pre; + + 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 */ + + /*------------------------------------------------------------------------* + * Initializations * + *------------------------------------------------------------------------*/ + + gain_code_pre = 0; + set_f( code_preQ, 0.f, L_SUBFR ); + + gain_pit = 0; + gain_code = 0; + gain_code2 = 0.f; + + prev_gain_pit = 0; + tmp_noise = 0; + + if( st->nb_subfr == NB_SUBFR ) + { + weights[0] = 0.1f; + weights[1] = 0.2f; + weights[2] = 0.3f; + weights[3] = 0.4f; + } + else /*nb_subfr == NB_SUBFR16k */ + { + weights[0] = (float)1/15; + weights[1] = (float)2/15; + weights[2] = (float)3/15; + weights[3] = (float)4/15; + weights[4] = (float)5/15; + } + + st->lp_gainp = 0; + st->lp_gainc = 0; + + + /* Framing parameters */ + L_frame = st->L_frame; + + /*------------------------------------------------------------------------* + * Previous frame is TCX * + *------------------------------------------------------------------------*/ + /* Reset phase dispersion */ + + if( st->last_core_bfi > ACELP_CORE ) + { + set_zero( st->dispMem, 8 ); + } + + /* Update of synthesis filter memories in case of 12k8 core */ + if( st->prev_bfi && st->last_con_tcx && st->L_frame < L_FRAME16k ) + { + synth_mem_updt2( st->L_frame, L_FRAME16k, st->old_exc, st->mem_syn_r, st->mem_syn2, NULL, DEC ); + } + + if( st->last_con_tcx && st->old_enr_LP ) + { + float enr_LP, ratio; + + /* rescale excitation buffer if LPC energies differs too much */ + enr_LP = enr_1_Az( A, L_SUBFR ); + + ratio = st->old_enr_LP/enr_LP; + if (ratio < 0.8) + { + v_multc( st->old_exc, ratio, st->old_exc, L_EXC_MEM_DEC); + } + } + + /*------------------------------------------------------------------------* + * Initialize buffers * + *------------------------------------------------------------------------*/ + + mvr2r( st->mem_syn2, mem_back, M ); + + /* set ACELP synthesis memory */ + mvr2r( st->mem_syn2, mem_syn, M ); + + /* set excitation memory*/ + exc=exc_buf+L_EXC_MEM_DEC; + mvr2r( st->old_exc, exc_buf, L_EXC_MEM_DEC ); + *(exc+L_frame) = 0.f; + + /* Init syn buffer */ + syn = syn_buf + M; + mvr2r( st->mem_syn2, syn_buf, M ); + + /*------------------------------------------------------------------------* + * Fast recovery flag + *------------------------------------------------------------------------*/ + + if( st->prev_bfi && coder_type == VOICED ) + { + /*Force BPF to be applied fully*/ + st->bpf_gain_param = 3; + } + + /*------------------------------------------------------------------------* + * - decode mean_ener_code for gain decoder (d_gain2.c) * + *------------------------------------------------------------------------*/ + + if ( acelp_cfg.nrg_mode > 0 ) + { + Es_pred_dec( &Es_pred, prm[0], acelp_cfg.nrg_bits,acelp_cfg.nrg_mode>1 ); + prm++; + } + else + { + Es_pred = 0.f; + } + + /*------------------------------------------------------------------------* + * 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/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; + pt_pitch = pitch_buf; + + for( i_subfr = 0; i_subfr < L_frame; i_subfr += L_SUBFR ) + { + if( st->use_partial_copy && st->rf_frame_type == RF_NELP ) + { + if( i_subfr == 0 ) + { + decod_nelp( st, UNVOICED, &tmp_noise, pt_pitch, exc, exc2, voice_factors, bwe_exc, 0 /*st->bfi*/, pgainT ); + set_f(pitch_buffer, L_SUBFR, NB_SUBFR); + } + } + else + { + /*-------------------------------------------------------* + * - Decode adaptive codebook. * + *-------------------------------------------------------*/ + + if( st->use_partial_copy && 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 */ + *pt_pitch = 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 */ + if( st->pit_res_max == 6 && !(st->use_partial_copy) ) + { + if ( T0_res == (st->pit_res_max>>1) ) + { + pred_lt4( &exc[i_subfr], &exc[i_subfr], T0, T0_frac<<1, L_SUBFR+1, inter6_2, PIT_L_INTERPOL6_2, PIT_UP_SAMP6 ); + } + else + { + pred_lt4( &exc[i_subfr], &exc[i_subfr], T0, T0_frac, L_SUBFR+1, inter6_2, PIT_L_INTERPOL6_2, PIT_UP_SAMP6 ); + } + } + else + { + if( T0_res == (st->pit_res_max>>1) ) + { + pred_lt4( &exc[i_subfr], &exc[i_subfr], T0, T0_frac<<1, L_SUBFR+1, inter4_2, L_INTERPOL2, PIT_UP_SAMP ); + } + else + { + pred_lt4( &exc[i_subfr], &exc[i_subfr], T0, T0_frac, L_SUBFR+1, inter4_2, L_INTERPOL2, PIT_UP_SAMP ); + } + } + + /* LP filtering of the adaptive excitation*/ + lp_flag = acelp_cfg.ltf_mode; + + if( acelp_cfg.ltf_mode == NORMAL_OPERATION ) + { + lp_flag = *prm; + prm++; + } + + lp_filt_exc_dec( st, MODE2, st->core_brate, 0, coder_type, i_subfr, L_SUBFR, L_frame, lp_flag, exc ); + } + else + { + /* No adaptive codebook (UC) */ + set_zero( exc + i_subfr, L_SUBFR ); + + T0 = L_SUBFR; + T0_frac = 0; + T0_res = 1; + pitch_buf[i_subfr/L_SUBFR] = (float)L_SUBFR; + } + + if( st->igf ) + { + if( st->sr_core == 12800 ) + { + 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; i < L_SUBFR * HIBND_ACB_L_FAC; i++) + { + bwe_exc[i + i_subfr * HIBND_ACB_L_FAC] = bwe_exc[i + i_subfr * HIBND_ACB_L_FAC - offset + (int) error]; + } + error += (float) offset - (float) T0 * HIBND_ACB_L_FAC - 0.25f * HIBND_ACB_L_FAC * (float) T0_frac; + } + else + { + offset = T0 * 2 + (int) ((float) T0_frac * 0.5f + 4 + 0.5f) - 4; + for (i=0; iuse_partial_copy && ( st->rf_frame_type == RF_ALLPRED || ( st->rf_frame_type == RF_GENPRED && ( i_subfr == L_SUBFR || i_subfr == 3*L_SUBFR )) ) ) + { + set_f(code, 0.0f, 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( 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, pitch_buf[i_subfr/L_SUBFR] ); + } + + /*-------------------------------------------------------* + * - Generate Gaussian excitation * + *-------------------------------------------------------*/ + + if( acelp_cfg.gains_mode[i_subfr/L_SUBFR] == 7 && !st->use_partial_copy ) + { + gaus_L2_dec( code2, st->tilt_code, p_A, acelp_cfg.formant_enh_num, &(st->seed_acelp) ); + } + else + { + gain_code2 = 0.f; + set_zero( code2, 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.0f; + } + + if( st->use_partial_copy && st->rf_frame_type == RF_NOPRED ) + { + st->past_gpit = 0.004089f; + } + + /*----------------------------------------------------------* + * Update parameters for the next subframe. * + * - tilt of code: 0.0 (unvoiced) to 0.5 (voiced) * + *----------------------------------------------------------*/ + + st->tilt_code = est_tilt( exc+i_subfr, gain_pit, code, gain_code, &(st->voice_fac), L_SUBFR, acelp_cfg.voice_tilt ); + + pgainT[i_subfr/L_SUBFR] = gain_pit; + + /*-------------------------------------------------------* + * - Find the total excitation. * + *-------------------------------------------------------*/ + + gain_code_tmp = gain_code; + gain_pit_tmp = gain_pit; + if ( st->core == ACELP_CORE && st->last_core == ACELP_CORE && ( st->use_partial_copy || st->prev_use_partial_copy)) + { + if ( i_subfr > 0 && gain_pit > 1.23f && st->prev_tilt_code_dec > 0.2f && st->next_coder_type == VOICED && (st->use_partial_copy || st->prev_use_partial_copy ) ) + { + gain_pit *= (0.8f - i_subfr/640.0f); + } + + else if( !st->prev_use_partial_copy && st->last_coder_type == UNVOICED && st->next_coder_type != UNVOICED && gain_code < gain_code_pre) + { + gain_code = 0.0f; + } + } + + gain_code_pre = gain_code; + st->tilt_code_dec[i_subfr/L_SUBFR] = st->tilt_code; + + for( i = 0; i < L_SUBFR; i++ ) + { + exc2[i+i_subfr] = gain_pit*exc[i+i_subfr]; + exc2[i+i_subfr] += gain_code2*code2[i]; + exc[i+i_subfr] = exc2[i+i_subfr] + gain_code*code[i]; + } + + /*-----------------------------------------------------------------* + * Prepare TBE excitation + *-----------------------------------------------------------------*/ + + gain_code = gain_code_tmp; + gain_pit = gain_pit_tmp; + + if( st->igf != 0 ) + { + prep_tbe_exc( L_frame, i_subfr, gain_pit, gain_code, code, st->voice_fac, &voice_factors[i_subfr/L_SUBFR], + bwe_exc, gain_preQ, code_preQ, T0, coder_type, st->core_brate ); + } + + /*---------------------------------------------------------* + * Enhance the excitation * + *---------------------------------------------------------*/ + + enhancer( MODE2, -1, acelp_cfg.fixed_cdk_index[i_subfr/L_SUBFR], 0, coder_type, L_frame, st->voice_fac, stab_fac, + st->past_gcode, gain_inov, &(st->gc_threshold), code, &exc2[i_subfr], gain_pit, st->dispMem ); + + } /* !RF_NELP frame partial copy */ + + /*----------------------------------------------------------* + * - compute the synthesis speech * + *----------------------------------------------------------*/ + + syn_filt( p_A, M,&exc2[i_subfr], &syn[i_subfr], L_SUBFR, mem_syn, 1 ); + + /*-----------------------------------------------------------------* + * update lp_filtered gains for the case of frame erasure + *-----------------------------------------------------------------*/ + + st->lp_gainp += weights[i_subfr/L_SUBFR] * st->past_gpit; + st->lp_gainc += weights[i_subfr/L_SUBFR] * st->past_gcode; + + /*----------------------------------------------------------* + * - update pitch lag for guided ACELP * + *----------------------------------------------------------*/ + + if( st->enableGplc && (i_subfr/L_SUBFR) == (L_frame/L_SUBFR)-1 ) + { + st->T0_4th = T0; + } + + /*----------------------------------------------------------* + * - Update LPC coeffs * + *----------------------------------------------------------*/ + + p_A += (M+1); + pt_pitch++; + /* 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; iold_lsp_q_cng, st->lsp_q_cng, st->Aq_cng, M, interpol_frac_12k8, 0 ); + + p_A =st->Aq_cng; + if(st->last_good < UNVOICED_TRANSITION ) + { + mvr2r(st->mem_syn2, mem_syn, M ); + } + else + { + set_zero( mem_syn, M ); + } + + for (i_subfr = 0; i_subfr < L_frame; i_subfr += L_SUBFR) + { + syn_filt(p_A, M,&exc[i_subfr], &syn[i_subfr], L_SUBFR, mem_syn, 1); + p_A += (M+1); + } + } + + tmp = 0; + pA = A + (st->nb_subfr-1)*(M+1); + set_zero( h1, L_SUBFR+1 ); + set_zero( mem, M ); + h1[0] = 1.0f; + syn_filt( pA, M,h1, h1, L_SUBFR, mem, 0); /* impulse response of LPC */ + deemph( h1, st->preemph_fac, L_SUBFR, &tmp); /* impulse response of deemph */ + /* impulse response level = gain introduced by synthesis+deemphasis */ + st->last_gain_syn_deemph = (float)sqrt(dotp( h1, h1, L_SUBFR) ); + + /*-----------------------------------------------------------* + * PLC: [ACELP: Fade-out] + * PLC: update the background level + *-----------------------------------------------------------*/ + + /* Do the classification */ + FEC_clas_estim( syn, pitch_buf, st->L_frame, st->core_ext_mode, st->codec_mode, st->mem_syn_clas_estim, &st->clas_dec, + &st->lp_ener_bfi, st->core_brate, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1.0f, + st->narrowBand, 0, + 0, st->preemph_fac, st->tcxonly, st->last_core_brate ); + + /* Update Pitch Lag memory */ + mvr2r( &st->old_pitch_buf[L_frame/L_SUBFR], st->old_pitch_buf, L_frame/L_SUBFR ); + mvr2r( pitch_buf, &st->old_pitch_buf[L_frame/L_SUBFR], L_frame/L_SUBFR ); + + FEC_scale_syn( st->L_frame, st->clas_dec, st->last_good, syn, pitch_buf, st->enr_old, 0, coder_type, + LSF_Q_prediction, &st->scaling_flag, &st->lp_ener_FEC_av, &st->lp_ener_FEC_max, st->bfi, + st->total_brate, st->prev_bfi, st->last_core_brate, exc, exc2, A, &st->old_enr_LP, mem_back, mem_syn + , st->last_con_tcx && (st->L_frameTCX_past != st->L_frame) && (st->last_core != 0) + , (st->clas_dec == ONSET || (st->last_good >= VOICED_TRANSITION && st->last_good < INACTIVE_CLAS) ) ); + + /* update ACELP synthesis memory */ + mvr2r( mem_syn, st->mem_syn2, M ); + mvr2r( syn+L_frame-L_SYN_MEM, st->mem_syn_r, L_SYN_MEM ); + + tmp = st->syn[M]; + deemph( syn, st->preemph_fac, L_frame, &tmp ); + mvr2r( syn+L_frame-(L_frame/2), st->old_syn_Overl, L_frame/2 ); + mvr2r( syn+L_frame-M-1, st->syn, M+1 ); + mvr2r( syn, synth, L_frame ); + + mvr2r( syn, st->old_core_synth, L_frame ); + + + /* update old_exc */ + mvr2r( exc_buf+L_frame, st->old_exc, L_EXC_MEM_DEC ); + + /* Output pitch parameters for bass post-filter */ + for (i_subfr = 0; i_subfr < L_frame; i_subfr += L_SUBFR ) + { + *pT++ = (int)( pitch_buf[i_subfr/L_SUBFR] + 0.5f); + } + + /* Update TCX-LTP */ + st->tcxltp_last_gain_unmodified = 0.f; + + /*Update MODE1*/ + mvr2r( p_A-(M+1), st->old_Aq_12_8, M+1 ); + st->old_Es_pred = 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[(L_frame/L_SUBFR) - 1]; + + return; +} diff --git a/lib_dec/dec_acelp.c b/lib_dec/dec_acelp.c new file mode 100644 index 000000000..f530d88fc --- /dev/null +++ b/lib_dec/dec_acelp.c @@ -0,0 +1,334 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "typedef.h" +#include "prot.h" +#include "rom_com.h" + +#define WMC_TOOL_SKIP + +/*---------------------------------------------------------------------* +* Local functions +*---------------------------------------------------------------------*/ + +static void D_ACELP_decode_arithtrack( float v[], long unsigned s, int p, int trackstep, int tracklen ); + +/*---------------------------------------------------------------------* +* Function D_ACELP_indexing() +* +*---------------------------------------------------------------------*/ + +void D_ACELP_indexing( + Float32 code[], + PulseConfig config, + int num_tracks, + int index[] + ,short *BER_detect +) +{ + int track, pulses, k, pulsestrack[NB_TRACK_FCB_4T]; + long unsigned s; + long unsigned index_n[NB_TRACK_FCB_4T]; + unsigned short trackpos, idxs[MAX_IDX_LEN]; + int restpulses, wordcnt; + + assert(num_tracks == NB_TRACK_FCB_4T); + + wordcnt = (config.bits + 15) >> 4; /* ceil(bits/16) */ + + /* check if some tracks have more pulses */ + restpulses = config.nb_pulse & (num_tracks-1); + + /* cast to short */ + for (k=0; k>2)+1,4); + pulsestrack[trackpos]--; /* this one has less pulses */ + break; + case TRACKPOS_FREE_ONE: + /* Find track with more pulses */ + trackpos = idxs[0] & 3; + longshiftright(idxs,2,idxs,wordcnt,wordcnt); + + /* set number of pulses per track */ + set_i( pulsestrack,(config.nb_pulse>>2),4); + pulsestrack[trackpos]++; /* this one has more pulses */ + break; + case TRACKPOS_FIXED_EVEN: + /* Pulses on even tracks */ + pulsestrack[0] = (config.nb_pulse+1) >> 1; + pulsestrack[1] = 0; + pulsestrack[2] = config.nb_pulse >> 1; + pulsestrack[3] = 0; + break; + case TRACKPOS_FIXED_FIRST: + /* set number of pulses per track */ + set_i( pulsestrack,config.nb_pulse/num_tracks,4); + for (k=0; k>2),4); + pulsestrack[trackpos]++; + trackpos++; + trackpos &= 3; + pulsestrack[trackpos]++; + break; + default: + assert(0); + break; + } + } + else + { + /* set number of pulses per track */ + set_i( pulsestrack,(config.nb_pulse/num_tracks),num_tracks); + } + + if (config.bits == 43) + { + D_ACELP_decode_43bit(idxs, code, pulsestrack); + } + else + { + + fcb_pulse_track_joint_decode(idxs, wordcnt, index_n, pulsestrack, num_tracks); + + for (track=num_tracks-1; track >=1; track--) + { + pulses = pulsestrack[track]; + + if (pulses) + { + s = index_n[track]; + + /* decode state to actual pulse positions on track */ + /*D_ACELP_decode_arithtrack_old(code+track, s, pulses, 4); */ + 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.0f; + } + } + } + s = index_n[0]; + pulses = pulsestrack[0]; + /* safety check in case of bit errors */ + if (s >= pulsestostates[16][pulses-1]) + { + set_f( code, 0.0f, L_SUBFR ); + *BER_detect = 1; + 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.0f; + } + } + } + + return; +} + + +static void D_ACELP_decode_arithtrack( + float v[], + long unsigned s, + int p, + int trackstep, + int tracklen +) +{ + int k; + + for (k=(tracklen)-1; k>= 0; k--) + { + v[k*trackstep] = 0.0f; /* default: there is no pulse here */ + while((p) && (s >= pulsestostates[k][p-1] )) + { + s -= pulsestostates[k][p-1]; + if (v[k*trackstep]) + { + /* there is a pulse here already = sign is known */ + if (v[k*trackstep] > 0.0f) + { + v[k*trackstep]++; /* place one more pulse here */ + } + else + { + v[k*trackstep]--; /* place one more pulse here */ + } + } + else + { + /* this is the first pulse here -> determine sign */ + if (s & 1) + { + v[k*trackstep] = -1.0f; /* place a negative pulse here */ + } + else + { + v[k*trackstep] = +1.0f; /* place a negative pulse here */ + } + s >>= 1; + } + p--; /* one pulse placed, so one less left */ + } + } + + return; +} + + +void fcb_pulse_track_joint_decode(unsigned short *idxs, int wordcnt, long unsigned *index_n, int *pulse_num, int track_num) +{ + int hi_to_low[10] = { 0, 0, 0, 3, 9, 5, 3, 1, 8, 8}; + + unsigned long long index; + int indx_tmp,indx_flag,indx_flag_1; + int track,track_num1,pulse_num0,pulse_num1; + int div_tmp; + int indx_flag_2; + + indx_flag=0; + indx_flag_1=0; + indx_flag_2 = 0; + for (track=0; track < track_num; track++) + { + indx_flag += (pulse_num[track]>>2); + indx_flag_1 += (pulse_num[track]>>1); + indx_flag_2 += (pulse_num[track]>>3); + } + + if (indx_flag >= track_num) + { + hi_to_low[4] = 9; + } + else + { + hi_to_low[4] = 1; + } + + if (indx_flag_2 >= 1) + { + hi_to_low[7] = 9; + } + else + { + hi_to_low[7] = 1; + } + if (indx_flag_1>=track_num) + { + if (indx_flag>=track_num) + { + index = 0; + if (indx_flag_2 >= 1) + { + for (track=(wordcnt-1); track >= 6; track--) + { + index = ( index << 16 ) + idxs[track] ; + } + index_n[3] = ( ((unsigned int)idxs[5]) << 8 ) + ( ( idxs[4] >> 8 ) & 0xff ); + index_n[2] = ( ( ((unsigned int)idxs[4]) << 16 ) + idxs[3] ) & 0xffffffUL; + index_n[1] = ( ((unsigned int)idxs[2]) << 8 ) + ( ( idxs[1] >> 8 ) & 0xff ); + index_n[0] = ( ( ((unsigned int) idxs[1]) << 16 ) + idxs[0] ) & 0xffffffUL; + } + else + { + for (track=(wordcnt-1); track >= track_num; track--) + { + index = ( index << 16 ) + idxs[track] ; + } + for (track=0; track < track_num; track++) + { + index_n[track] = idxs[track]; + } + } + } + else + { + index = 0; + for (track=(wordcnt-1); track >= 2; track--) + { + index = ( index << 16 ) + idxs[track] ; + } + + index_n[3] = idxs[1] & 0xff; + index_n[2] = idxs[1] >> 8; + index_n[1] = idxs[0] & 0xff; + index_n[0] = idxs[0] >> 8; + } + + track_num1 = track_num - 1; + pulse_num1 = pulse_num[track_num1]; + index = ( index << hi_to_low[pulse_num1] ) + ( index_n[track_num1] >> low_len[pulse_num1] ); + for (track=(track_num-1); track > 0; track--) + { + track_num1 = track - 1; + pulse_num0 = pulse_num[track_num1]; + pulse_num1 = pulse_num[track]; + index = ( index << hi_to_low[pulse_num0] ) + ( index_n[track_num1] >> low_len[pulse_num0] ); + + div_tmp = index / indx_fact[pulse_num1]; + indx_tmp = index - div_tmp * indx_fact[pulse_num1]; + index_n[track] = ( index_n[track] & low_mask[pulse_num1]) + ( indx_tmp << low_len[pulse_num1] ); + index = div_tmp; + } + pulse_num1 = pulse_num[0]; + index_n[0] = ( index_n[0] & low_mask[pulse_num1]) + ( index << low_len[pulse_num1] ); + } + else + { + index = 0; + for (track=(wordcnt-1); track >= 0; track--) + { + index = ( index << 16 ) + idxs[track]; + } + for (track=3; track > 0; track--) + { + pulse_num1 = pulse_num[track]; + index_n[track] = index & index_mask_ACELP[pulse_num1]; + index = index >> index_len[pulse_num1]; + } + index_n[0] = index; + } + + return; +} diff --git a/lib_dec/dec_acelp_tcx_main.c b/lib_dec/dec_acelp_tcx_main.c new file mode 100644 index 000000000..cff7d91ea --- /dev/null +++ b/lib_dec/dec_acelp_tcx_main.c @@ -0,0 +1,443 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "stat_dec.h" +#include "prot.h" +#include "rom_com.h" +#include "options.h" + + +/*-------------------------------------------------------------------* +* decode_frame_type() +* +* +*--------------------------------------------------------------------*/ + +static void decode_frame_type +( + Decoder_State *st +) +{ + int frame_size_index, n, total_brate; + + frame_size_index = 0; + total_brate = st->total_brate; + + /* Get Frame Type (NULL,SID,ACTIVE) and Frame Mode (2kbps, 4kbps,...) */ + + if (st->mdct_sw == MODE1) + { + st->m_frame_type = ACTIVE_FRAME; + + for (n=0; ntotal_brate/50) + { + frame_size_index = n; + break; + } + } + + } + else + { + + /* ZERO Frame */ + if( st->total_brate == FRAME_NO_DATA ) + { + st->bwidth = st->last_bwidth; + st->m_frame_type = ZERO_FRAME; + } + + /* SID frame */ + else if( st->total_brate == SID_2k40 ) + { + unsigned short frame_len_indicator; + st->cng_type = get_next_indice(st, 1); + if( st->cng_type != FD_CNG ) + { + st->BER_detect = 1; + st->cng_type = FD_CNG; + } + st->m_frame_type = SID_FRAME; + frame_size_index = 1; + st->bwidth = get_next_indice(st, 2); + + frame_len_indicator = get_next_indice(st, 1); + if( st->bwidth == NB ) + { + if( frame_len_indicator ) + { + st->BER_detect = 1; + } + frame_len_indicator = 0; + } + if( frame_len_indicator == 0 ) + { + st->L_frame = L_FRAME; + st->total_brate = 9600; + } + else + { + st->L_frame = L_FRAME16k; + if ( st->last_total_brate==16400 || st->last_total_brate==24400 ) + { + st->total_brate = st->last_total_brate; + } + else + { + st->total_brate = 16400; + } + } + + for (n=0; ntotal_brate/50) + { + frame_size_index = n; + break; + } + } + } + /* EVS MODES */ + else + { + /* Get Frame mode */ + st->m_frame_type = ACTIVE_FRAME; + + for( n=0; ntotal_brate/50 ) + { + frame_size_index = n; + break; + } + } + + + if (st->rf_flag == 0) + { + /* Get bandwidth mode */ + st->bwidth = get_next_indice(st, FrameSizeConfig[frame_size_index].bandwidth_bits); + st->bwidth += FrameSizeConfig[frame_size_index].bandwidth_min; + } + else + { + st->bwidth += FrameSizeConfig[frame_size_index].bandwidth_min; + } + + if (st->bwidth > FB) + { + st->bwidth = FB; + st->BER_detect = 1; + } + + if (st->bwidth > SWB && st->total_brate < ACELP_16k40) + { + st->bwidth = SWB; + st->BER_detect = 1; + } + + /* Get reserved bit */ + if (FrameSizeConfig[frame_size_index].reserved_bits && st->rf_flag == 0) + { + int dummy = get_next_indice(st, 1); + if (dummy != 0) + { + st->BER_detect = 1; + } + assert( FrameSizeConfig[frame_size_index].reserved_bits == 1); + } + } + } + + st->rate_switching_init = 0; + + if( st->last_codec_mode != MODE2 || !st->BER_detect ) + { + /* Mode or Rate Change */ + if( (st->m_frame_type == ACTIVE_FRAME || st->m_frame_type == SID_FRAME) && ( (st->total_brate != st->last_total_brate) || (st->bwidth!=st->last_bwidth ) || (st->last_codec_mode == MODE1) || (st->rf_flag !=st->rf_flag_last) || st->force_lpd_reset) ) + { + + st->rate_switching_init = 1; + /* Reconf Core */ + mode_switch_decoder_LPD( st, st->bwidth, st->total_brate, frame_size_index ); + + /* Reconf. CLDFB: check if the CLDFB works on the right sample rate */ + if ( (st->cldfbAna->no_channels * st->cldfbAna->no_col) != st->L_frame ) + { + resampleCldfb (st->cldfbAna, (st->L_frame * 50)); + if( st->L_frame <= L_FRAME16k ) + { + resampleCldfb (st->cldfbBPF, (st->L_frame * 50)); + } + } + + if (st->bwidth == NB) + { + short nBand_nb = (8000*st->cldfbSyn->no_channels / st->output_Fs); + st->cldfbSyn->bandsToZero = st->cldfbSyn->no_channels - nBand_nb; + } + else + { + st->cldfbSyn->bandsToZero = 0; + } + + /*Reconf Frequency-domain based CNG*/ + configureFdCngDec( st->hFdCngDec, st->bwidth, st->rf_flag==1&& st->total_brate==13200? 9600: st->total_brate, st->L_frame ); + if ( st->last_L_frame!=st->L_frame && st->L_frame<=320 && st->last_L_frame<=320 ) + { + lerp( st->hFdCngDec->hFdCngCom->olapBufferSynth2, st->hFdCngDec->hFdCngCom->olapBufferSynth2, st->L_frame*2, st->last_L_frame*2 ); + if ( st->m_frame_type==SID_FRAME && st->hFdCngDec->hFdCngCom->frame_type_previous!= ACTIVE_FRAME ) + { + lerp( st->hFdCngDec->hFdCngCom->olapBufferSynth, st->hFdCngDec->hFdCngCom->olapBufferSynth, st->L_frame*2, st->last_L_frame*2 ); + if( st->L_frame==L_FRAME) + { + for (n=0; n < st->L_frame*2; n++) + { + st->hFdCngDec->hFdCngCom->olapBufferSynth[n] = st->hFdCngDec->hFdCngCom->olapBufferSynth[n]*1.25f; + } + } + else + { + for (n=0; n < st->L_frame*2; n++) + { + st->hFdCngDec->hFdCngCom->olapBufferSynth[n] = st->hFdCngDec->hFdCngCom->olapBufferSynth[n]/1.25f; + } + } + } + } + if ( st->bwidth!=st->last_bwidth ) + { + st->hFdCngDec->hFdCngCom->msFrCnt_init_counter = 0; + st->hFdCngDec->hFdCngCom->init_old = FLT_MAX; + } + + if( st->tcxonly ) + { + st->p_bpf_noise_buf = NULL; + } + else + { + st->p_bpf_noise_buf = st->bpf_noise_buf; + } + } + } + + st->total_brate = total_brate; + + return; + +} + + +/*-------------------------------------------------------------------* +* dec_acelp_tcx_frame() +* +* Main decoding function +*--------------------------------------------------------------------*/ + +void dec_acelp_tcx_frame( + Decoder_State *st, /* i/o: encoder state structure */ + short *coder_type, /* o : coder type */ + short *concealWholeFrame, /* i/o: concealment flag */ + float *output, /* o : synthesis */ + float *bpf_noise_buf, /* i/o: BPF noise buffer */ + float *pcmbufFB, + float bwe_exc_extended[], /* i/o: bandwidth extended excitation */ + float *voice_factors, /* o : voicing factors */ + float pitch_buf[] /* o : floating pitch for each subframe */ +) +{ + short i; + int start_bit_pos; + short tmp; + short bitsRead; + int param[DEC_NPRM_DIV*NB_DIV]; + + float old_bwe_exc[(PIT16k_MAX + (L_FRAME16k + 1) + L_SUBFR16k) * 2]; /* excitation buffer */ + float *ptr_bwe_exc; /* pointer to BWE excitation signal in the current frame */ + + + start_bit_pos = st->next_bit_pos; + if( st->rf_flag == 1 ) + { + start_bit_pos -= 2; + } + + /* -------------------------------------------------------------- */ + /* IDENTIFY FRAME TYPE */ + /* -------------------------------------------------------------- */ + + st->m_old_frame_type = st->m_frame_type; + + if( *concealWholeFrame == 0 ) + { + + unsigned char m_frame_type = st->m_frame_type; + short bwidth = st->bwidth; + short cng_type = st->cng_type; + short L_frame = st->L_frame; + long total_brate = st->last_total_brate; + + decode_frame_type( st ); + + st->force_lpd_reset = 0; + + if( (st->last_codec_mode) == MODE2 && (st->BER_detect || (st->prev_bfi && st->m_frame_type == ZERO_FRAME && 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; + st->bwidth = bwidth; + st->cng_type = cng_type; + st->L_frame = L_frame; + if( st->ini_frame != 0 ) + { + st->total_brate = total_brate; + } + + *concealWholeFrame = 1; + st->m_decodeMode = DEC_CONCEALMENT_EXT; + st->BER_detect = 0; + + if( (st->bwidth != st->last_bwidth ) || (st->rf_flag != st->rf_flag_last) || (st->total_brate != st->last_total_brate) ) + { + st->force_lpd_reset = 1; + } + + st->core_brate = st->last_core_brate; + st->bfi = 1; + if(st->ini_frame == 0 ) + { + st->tcx_cfg.tcx_coded_lines = getNumTcxCodedLines(SWB); + } + } + else + { + st->core_brate = st->total_brate; + bpf_noise_buf = st->p_bpf_noise_buf; + } + } + + if( *concealWholeFrame != 0 ) + { + /* add two zero bytes for arithmetic coder flush */ + for( i=0; i<8*2; i++ ) + { + st->bit_stream[i] = 0; + } + } + + + if( !(st->m_frame_type == SID_FRAME || st->m_frame_type == ZERO_FRAME) ) + { + + /* -------------------------------------------------------------- */ + /* DECODE CORE */ + /* -------------------------------------------------------------- */ + + if( *concealWholeFrame ) + { + + tmp = 0; /*to avoid empty counting */ + } + + tmp = st->total_brate/50 - (st->next_bit_pos - start_bit_pos); + + bitsRead = 0; + + /* update old BWE excitation buffer */ + set_f( old_bwe_exc + PIT16k_MAX * 2, 0.f, ((L_FRAME16k + 1) + L_SUBFR16k) * 2 ); + ptr_bwe_exc = old_bwe_exc + PIT16k_MAX * 2; + mvr2r( st->old_bwe_exc, old_bwe_exc, PIT16k_MAX * 2 ); + + /* Decode the LPD data */ + if( st->m_decodeMode == DEC_NO_FRAM_LOSS ) + { + decoder_LPD( output, pcmbufFB, &tmp, st, bpf_noise_buf, 0, + &bitsRead, coder_type, param, pitch_buf, voice_factors, ptr_bwe_exc ); + if( !st->rate_switching_init && (st->last_codec_mode) == MODE2 && !(st->use_partial_copy && st->rf_frame_type >= RF_TCXFD && st->rf_frame_type <= RF_TCXTD2) && st->bfi ) + { + *concealWholeFrame = 1; + st->m_decodeMode = DEC_CONCEALMENT_EXT; + st->BER_detect = 0; + } + + } + else if( st->m_decodeMode == DEC_CONCEALMENT_EXT ) + { + decoder_LPD( output, pcmbufFB, NULL, st, bpf_noise_buf, 1, /* bfi - st->bfi can be 0 here - MODE2 stays in PLC when DTX appears after a loss */ + &bitsRead, coder_type, NULL, pitch_buf, voice_factors, ptr_bwe_exc ); + } + + + if( ( !st->bfi && (st->prev_bfi || st->prev_use_partial_copy )) || ((st->last_vbr_hw_BWE_disable_dec==1) && (st->vbr_hw_BWE_disable_dec==0)) ) + { + st->bwe_non_lin_prev_scale = 0.0f; + set_f( st->old_bwe_exc_extended, 0.0f, NL_BUFF_OFFSET ); + } + + if( st->core == ACELP_CORE && st->igf && st->con_tcx == 0 ) + { + non_linearity( ptr_bwe_exc, bwe_exc_extended, st->old_bwe_exc_extended, L_FRAME32k, &st->bwe_non_lin_prev_scale, *coder_type, voice_factors, st->L_frame ); + + /* update the old BWE exe memory */ + mvr2r( &old_bwe_exc[L_FRAME32k], st->old_bwe_exc, PIT16k_MAX * 2 ); + } + else + { + set_f( st->old_bwe_exc_extended, 0, NL_BUFF_OFFSET ); + set_f( st->old_bwe_exc, 0, PIT16k_MAX * 2 ); /* reset old non_linear exc during igf frames */ + st->bwe_non_lin_prev_scale = 0.0f; + } + + /* for ACELP mode, skip core data to read TD-BWE side info */ + if( (!st->bfi) && st->core == ACELP_CORE && st->total_brate > 0) + { + /* target bs-position "-2", because of earlier "start_bit_pos -= 2;", which are included in "st->rf_target_bits"*/ + /* from "-2" to "-3" as flag-bit not considered in rf_target_bits */ + if (st->rf_flag) + { + get_next_indice_tmp(st, start_bit_pos + st->total_brate/50 - st->rf_target_bits - 3 - get_tbe_bits(st->total_brate, st->bwidth, st->rf_flag) - st->next_bit_pos); + } + else + { + get_next_indice_tmp(st, start_bit_pos + st->total_brate/50 - st->rf_target_bits - get_tbe_bits(st->total_brate, st->bwidth, st->rf_flag) - st->next_bit_pos); + } + tbe_read_bitstream(st); + } + + if( *concealWholeFrame ) + { + /*"LPD dec - All BFI"*/ + + tmp = 0; /*to avoid empty counting */ + } + + /* updates */ + st->last_voice_factor = voice_factors[st->nb_subfr-1]; + st->last_coder_type = *coder_type; + } + else + { + + + if( st->m_frame_type == SID_FRAME ) + { + /* Decode the FD-CNG bitstream */ + FdCng_decodeSID( st ); + } + + /* updates */ + st->last_voice_factor = 0; + st->last_coder_type = INACTIVE; + + + } + + return; +} diff --git a/lib_dec/dec_amr_wb.c b/lib_dec/dec_amr_wb.c new file mode 100644 index 000000000..fae6646a5 --- /dev/null +++ b/lib_dec/dec_amr_wb.c @@ -0,0 +1,125 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + + +/*---------------------------------------------------------------------* + * decod_amr_wb() + * + * Decode excitation signal in AMR-WB IO mode + *---------------------------------------------------------------------*/ + +void decod_amr_wb( + Decoder_State *st, /* i/o: decoder static memory */ + const float *Aq, /* i : LP filter coefficients */ + float *pitch_buf, /* o : floating pitch values for each subframe */ + float *exc, /* i/o: adapt. excitation exc */ + float *exc2, /* i/o: adapt. excitation/total exc */ + short hf_gain[NB_SUBFR], /* o : decoded HF gain */ + float *voice_factors /* o : voicing factors */ + , float *gain_buf +) +{ + short T0, T0_frac, T0_min, T0_max;/* integer pitch variables */ + float gain_pit; /* pitch gain */ + float gain_code; /* gain/normalized gain of the algebraic excitation */ + float norm_gain_code; /* normalized gain of the algebraic excitation */ + float gain_inov; /* Innovation gain */ + float voice_fac; /* voicing factor */ + float code[L_SUBFR]; /* algebraic codevector */ + const float *p_Aq; /* Pointer to frame LP coefficient */ + float *pt_pitch; /* pointer to floating pitch */ + short i_subfr, i; /* tmp variables */ + short pitch_limit_flag; + + /*------------------------------------------------------------------* + * ACELP subframe loop + *------------------------------------------------------------------*/ + + p_Aq = Aq; /* pointer to interpolated LPC parameters */ + pt_pitch = pitch_buf; /* pointer to the pitch buffer */ + st->lt_voice_fac = 0.0f; + pitch_limit_flag = 0; /* always restrained pitch Q range in IO mode */ + + for( i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR ) + { + /*----------------------------------------------------------------------* + * Decode pitch lag + *----------------------------------------------------------------------*/ + + *pt_pitch = pit_decode( st, st->core_brate, 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[i_subfr], &exc[i_subfr], T0, T0_frac, L_SUBFR+1, inter4_2, L_INTERPOL2, PIT_UP_SAMP ); + + /*--------------------------------------------------------------* + * LP filtering of the adaptive excitation + *--------------------------------------------------------------*/ + + lp_filt_exc_dec( st, MODE1, st->core_brate, 1, -1, i_subfr, L_SUBFR, L_FRAME, 0,exc ); + + /*--------------------------------------------------------------* + * Innovation decoding + *--------------------------------------------------------------*/ + + inov_decode( st, st->core_brate, 1, L_FRAME, -1, 0, i_subfr, -1, p_Aq, st->tilt_code, *pt_pitch, code ); + + /*--------------------------------------------------------------* + * Gain decoding + * Estimate spectrum tilt and voicing + *--------------------------------------------------------------*/ + + gain_dec_amr_wb( st, st->core_brate, &gain_pit, &gain_code, st->past_qua_en, &gain_inov, code, &norm_gain_code ); + + /* update LP filtered gains for the case of frame erasures */ + lp_gain_updt( i_subfr, gain_pit, norm_gain_code, &st->lp_gainp, &st->lp_gainc, L_FRAME ); + + st->tilt_code = est_tilt( exc+i_subfr, gain_pit, code, gain_code, &voice_fac, L_SUBFR, 0 ); + + /*----------------------------------------------------------------------* + * Find the total excitation + *----------------------------------------------------------------------*/ + + for (i = 0; i < L_SUBFR; i++) + { + exc2[i+i_subfr] = gain_pit*exc[i+i_subfr]; + exc[i+i_subfr] = exc2[i+i_subfr] + gain_code*code[i]; + } + + /*----------------------------------------------------------------* + * Excitation enhancements + *----------------------------------------------------------------*/ + + enhancer( MODE1, st->core_brate, -1, 1, -1, L_FRAME, voice_fac, st->stab_fac, + norm_gain_code, gain_inov, &st->gc_threshold, code, exc2 + i_subfr, gain_pit, st->dispMem ); + + /*-----------------------------------------------------------------* + * HF gain modification factors at 23.85 kbps + *-----------------------------------------------------------------*/ + + if ( st->core_brate == ACELP_23k85 ) + { + hf_gain[i_subfr/L_SUBFR] = (short)get_next_indice( st,4); + } + + voice_fac = VF_0th_PARAM + VF_1st_PARAM * voice_fac + VF_2nd_PARAM * voice_fac * voice_fac; + voice_factors[i_subfr/L_SUBFR] = min( max(0.0f, voice_fac), 1.0f); + + p_Aq += (M+1); + pt_pitch++; + + st->lt_voice_fac += 0.25f*voice_fac; + gain_buf[i_subfr/L_SUBFR] = gain_pit; + } + + return; +} diff --git a/lib_dec/dec_gen_voic.c b/lib_dec/dec_gen_voic.c new file mode 100644 index 000000000..8cf21d43c --- /dev/null +++ b/lib_dec/dec_gen_voic.c @@ -0,0 +1,268 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + + +/*---------------------------------------------------------------------* + * decod_gen_voic() + * + * Decode generic (GC), voiced (VC) and AMR-WB IO frames + *---------------------------------------------------------------------*/ + +void decod_gen_voic( + Decoder_State *st, /* i/o: decoder static memory */ + const short L_frame, /* i : length of the frame */ + const short sharpFlag, /* i : formant sharpening flag */ + const float *Aq, /* i : LP filter coefficient */ + const short coder_type, /* i : coding type */ + const float Es_pred, /* i : predicted scaled innov. energy */ + const short do_WI, /* i : FEC fast recovery flag */ + float *pitch_buf, /* o : floating pitch values for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *exc, /* i/o: adapt. excitation exc */ + float *exc2, /* i/o: adapt. excitation/total exc */ + float *bwe_exc, /* o : excitation for SWB TBE */ + short *unbits, /* number of unused bits */ + float *gain_buf +) +{ + short T0 = PIT_MIN, T0_frac = 0, T0_min, T0_max;/* integer pitch variables */ + float gain_pit = 0.0f; /* pitch gain */ + float gain_code = 0.0f; /* gain/normalized gain of the algebraic excitation */ + float norm_gain_code = 0.0f; /* normalized gain of the algebraic excitation */ + float gain_inov = 0; /* Innovation gain */ + float gains_mem[2*(NB_SUBFR-1)];/* pitch gain and code gain from previous subframes */ + float voice_fac; /* voicing factor */ + float code[L_SUBFR]; /* algebraic codevector */ + + const float *p_Aq; /* Pointer to frame LP coefficient */ + float *pt_pitch; /* pointer to floating pitch */ + short i_subfr, i; /* tmp variables */ + int offset; + float error = 0.0f; + float gain_preQ = 0; /* Gain of prequantizer excitation */ + float code_preQ[L_SUBFR]; /* Prequantizer excitation */ + float norm_gain_preQ; + short pitch_limit_flag; + + DTFS_STRUCTURE *PREVP, *CURRP; + short shft_prev = 0, shft_curr = 0; + float ph_offset, dummy2[2], out[L_FRAME16k], enratio = 0.0f; + float sp_enratio, curr_spch_nrg, prev_spch_nrg, curr_res_nrg, prev_res_nrg, syn_tmp[L_FRAME16k], mem_tmp[M]; + short harm_flag_acelp; + + /* read harmonicity flag */ + harm_flag_acelp = 0; + if( st->core_brate > ACELP_24k40 && st->core_brate <= ACELP_32k && coder_type == GENERIC ) + { + harm_flag_acelp = (short)get_next_indice( st, 1 ); + } + + /*------------------------------------------------------------------* + * ACELP subframe loop + *------------------------------------------------------------------*/ + + p_Aq = Aq; /* pointer to interpolated LPC parameters */ + pt_pitch = pitch_buf; /* pointer to the pitch buffer */ + norm_gain_preQ = 0.0f; + gain_preQ = 0; + set_f( code_preQ, 0, L_SUBFR ); + + for( i_subfr = 0; i_subfr < L_frame; i_subfr += L_SUBFR ) + { + + /*----------------------------------------------------------------------* + * Decode pitch lag + *----------------------------------------------------------------------*/ + + *pt_pitch = pit_decode( st, st->core_brate, 0, L_frame, i_subfr, coder_type, &pitch_limit_flag, &T0, &T0_frac, &T0_min, &T0_max, L_SUBFR ); + + /*--------------------------------------------------------------* + * Find the adaptive codebook vector + *--------------------------------------------------------------*/ + + pred_lt4( &exc[i_subfr], &exc[i_subfr], T0, T0_frac, L_SUBFR+1, inter4_2, L_INTERPOL2, PIT_UP_SAMP ); + + if( L_frame == L_FRAME ) + { + offset = tbe_celp_exc_offset(T0, T0_frac); + for (i=0; icore_brate, 0, coder_type, i_subfr, L_SUBFR, L_frame, 0, exc ); + + /*-----------------------------------------------------------------* + * Transform-domain contribution decoding (active frames) + *-----------------------------------------------------------------*/ + + if( st->core_brate > ACELP_24k40 && coder_type != INACTIVE ) + { + gain_code = 0.0f; + transf_cdbk_dec( st, st->core_brate, coder_type, harm_flag_acelp, i_subfr, -1, Es_pred, + gain_code, &st->mem_preemp_preQ, &gain_preQ, &norm_gain_preQ, code_preQ, unbits ); + } + + /*--------------------------------------------------------------* + * Innovation decoding + *--------------------------------------------------------------*/ + + inov_decode( st, st->core_brate, 0, L_frame, coder_type, sharpFlag, i_subfr, -1, p_Aq, st->tilt_code,*pt_pitch, code ); + + /*--------------------------------------------------------------* + * Gain decoding + * Estimate spectrum tilt and voicing + *--------------------------------------------------------------*/ + + if ( st->core_brate <= ACELP_8k00 ) + { + gain_dec_lbr( st, st->core_brate, coder_type, i_subfr, code, &gain_pit, &gain_code, &gain_inov, &norm_gain_code, gains_mem ); + } + else if ( st->core_brate > ACELP_32k ) + { + gain_dec_SQ( st, st->core_brate, coder_type, i_subfr, -1, code, Es_pred, &gain_pit, &gain_code, &gain_inov, &norm_gain_code ); + } + else + { + gain_dec_mless( st, st->core_brate, L_frame, coder_type, i_subfr, -1, code, Es_pred, &gain_pit, &gain_code, &gain_inov, &norm_gain_code ); + } + + st->tilt_code = est_tilt( exc+i_subfr, gain_pit, code, gain_code, &voice_fac,L_SUBFR,0 ); + + /*-----------------------------------------------------------------* + * Transform-domain contribution decoding (inactive frames) + *-----------------------------------------------------------------*/ + + if( st->core_brate > ACELP_24k40 && coder_type == INACTIVE ) + { + transf_cdbk_dec( st, st->core_brate, coder_type, 0, i_subfr, -1, Es_pred, gain_code, + &st->mem_preemp_preQ, &gain_preQ, &norm_gain_preQ, code_preQ, unbits ); + } + + /* update LP filtered gains for the case of frame erasures */ + lp_gain_updt( i_subfr, gain_pit, norm_gain_code + norm_gain_preQ, &st->lp_gainp, &st->lp_gainc, L_frame ); + + /*----------------------------------------------------------------------* + * Find the total excitation + *----------------------------------------------------------------------*/ + + for (i = 0; i < L_SUBFR; i++) + { + exc2[i+i_subfr] = gain_pit*exc[i+i_subfr]; + exc[i+i_subfr] = exc2[i+i_subfr] + gain_code*code[i]; + } + + /*-----------------------------------------------------------------* + * Add the ACELP pre-quantizer contribution + *-----------------------------------------------------------------*/ + + if( st->core_brate > ACELP_24k40 ) + { + for ( i = 0; i < L_SUBFR; i++ ) + { + exc2[i+i_subfr] += gain_preQ * code_preQ[i]; + exc[i+i_subfr] += gain_preQ * code_preQ[i]; + } + } + + /*-----------------------------------------------------------------* + * Prepare TBE excitation + *-----------------------------------------------------------------*/ + + prep_tbe_exc( L_frame, i_subfr, gain_pit, gain_code, code, voice_fac, &voice_factors[i_subfr/L_SUBFR], bwe_exc, + gain_preQ, code_preQ, T0, coder_type, st->core_brate ); + + /*----------------------------------------------------------------* + * Excitation enhancements (update of total excitation signal) + *----------------------------------------------------------------*/ + if( st->core_brate > ACELP_32k || coder_type == INACTIVE ) + { + mvr2r( exc+i_subfr, exc2+i_subfr, L_SUBFR ); + } + else + { + enhancer( MODE1, st->core_brate, -1, 0, coder_type, L_frame, voice_fac, st->stab_fac, + norm_gain_code, gain_inov, &st->gc_threshold, code, exc2 + i_subfr, gain_pit, st->dispMem ); + } + + p_Aq += (M+1); + pt_pitch++; + gain_buf[i_subfr/L_SUBFR] = gain_pit; + st->tilt_code_dec[i_subfr/L_SUBFR] = st->tilt_code; + } + + /* FEC fast recovery */ + if ( do_WI ) + { + shft_prev = L_EXC_MEM - (short) rint_new(st->bfi_pitch); + prev_res_nrg = sum2_f( st->old_exc2+shft_prev, (short) rint_new(st->bfi_pitch) ) + 1e-6f; + prev_spch_nrg = sum2_f( st->old_syn2+shft_prev, (short) rint_new(st->bfi_pitch) ) + 1e-6f; + + mvr2r( st->mem_syn2, mem_tmp, M ); + syn_12k8( st->L_frame, Aq, exc2, syn_tmp, mem_tmp, 1 ); + + shft_curr = st->L_frame - (short) rint_new(pitch_buf[NB_SUBFR16k-1]); + curr_res_nrg = sum2_f(exc2+shft_curr, (short) rint_new(pitch_buf[NB_SUBFR16k-1])); + curr_spch_nrg = sum2_f(syn_tmp+shft_curr,(short) rint_new(pitch_buf[NB_SUBFR16k-1])); + + enratio = curr_res_nrg/prev_res_nrg; + sp_enratio = curr_spch_nrg/prev_spch_nrg; + + if ( enratio > 0.25f && + enratio < 15.0f && + sp_enratio > 0.15f && + st->bfi_pitch < 150 && + pitch_buf[NB_SUBFR16k-1] < 150 ) + { + PREVP = DTFS_new(); + CURRP = DTFS_new(); + + DTFS_to_fs( st->old_exc2+shft_prev, (short)rint_new( st->bfi_pitch ), PREVP, (short)st->output_Fs, do_WI ); + DTFS_to_fs( exc2+shft_curr, (short)rint_new( pitch_buf[NB_SUBFR16k-1] ), CURRP, (short)st->output_Fs, do_WI ); + + ph_offset = 0.0f; + WIsyn( *PREVP, CURRP, dummy2, &ph_offset, out, st->L_frame, 1 ); + + mvr2r( out, exc2, st->L_frame); + mvr2r( exc2, exc, st->L_frame); + + /* update bwe_exc for SWB-TBE */ + for (i_subfr = 0; i_subfr < L_frame; i_subfr += L_SUBFR) + { + interp_code_4over2( exc + i_subfr, bwe_exc + (i_subfr*2), L_SUBFR ); + } + + free(PREVP); + free(CURRP); + } + } + + /* SC-VBR */ + st->prev_gain_pit_dec = gain_pit; + + return; +} diff --git a/lib_dec/dec_higher_acelp.c b/lib_dec/dec_higher_acelp.c new file mode 100644 index 000000000..720f5918b --- /dev/null +++ b/lib_dec/dec_higher_acelp.c @@ -0,0 +1,169 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*-----------------------------------------------------------------* + * Transform domain contribution decoding + *-----------------------------------------------------------------*/ + +void transf_cdbk_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : core bitrate */ + const short coder_type, /* i : coding type */ + const short harm_flag_acelp,/* i : harmonic flag for higher rates ACELP */ + const short i_subfr, /* i : subframe index */ + const short tc_subfr, /* i : TC subframe index */ + const float Es_pred, /* i : predicited scaled innovation energy */ + const float gain_code, /* i : innovative excitation gain */ + float *mem_preemp, /* i/o: dequantizer preemhasis memory */ + float *gain_preQ, /* o : prequantizer excitation gain */ + float *norm_gain_preQ,/* o : normalized prequantizer excitation gain */ + float code_preQ[], /* o : prequantizer excitation */ + short *unbits /* o : number of AVQ unused bits */ +) +{ + short i, index, nBits, Nsv; + int x_norm[L_SUBFR]; + float Ecode; + short nq[L_SUBFR/WIDTH_BAND]; + + /*--------------------------------------------------------------* + * Set bit-allocation + *--------------------------------------------------------------*/ + + Nsv = 8; + nBits = AVQ_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ(core_brate, coder_type, i_subfr, TC_SUBFR2IDX_16KHZ(tc_subfr))]; + + /* increase # of AVQ allocated bits by unused bits from the previous subframe */ + nBits += (*unbits); + + /*--------------------------------------------------------------* + * Dequantize prequantizer excitation gain + *--------------------------------------------------------------*/ + + index = (short)get_next_indice( st, G_AVQ_BITS ); + + if( coder_type == INACTIVE ) + { + if( core_brate == ACELP_64k ) + { + *gain_preQ = usdequant( index, G_AVQ_MIN_INACT_64k, G_AVQ_DELTA_INACT_64k ); + } + else if( core_brate == ACELP_48k ) + { + *gain_preQ = usdequant( index, G_AVQ_MIN_INACT_48k, G_AVQ_DELTA_INACT_48k ); + } + else + { + *gain_preQ = usdequant( index, G_AVQ_MIN_INACT, G_AVQ_DELTA_INACT ); + } + + *gain_preQ *= gain_code; + } + else + { + if( core_brate > ACELP_24k40 && core_brate <= ACELP_32k ) + { + *gain_preQ = gain_dequant( index, 0.1f*G_AVQ_MIN, G_AVQ_MAX, G_AVQ_BITS ); + } + else + { + *gain_preQ = gain_dequant( index, G_AVQ_MIN, G_AVQ_MAX, G_AVQ_BITS ); + } + if( Es_pred < 0 ) + { + *gain_preQ *= 0.25f * fabs(Es_pred); + } + else + { + *gain_preQ *= Es_pred; + } + } + + /*--------------------------------------------------------------* + * Encode and multiplex subvectors into bit-stream + *--------------------------------------------------------------*/ + + AVQ_demuxdec( st, x_norm, &nBits, Nsv, nq ); + + /* save # of AVQ unused bits for next subframe */ + *unbits = nBits; + + /*--------------------------------------------------------------* + * iDCT transform + *--------------------------------------------------------------*/ + + set_f( code_preQ, 0.0f, L_SUBFR ); + for( i=0; i ACELP_32k || harm_flag_acelp ) + { + edct2( L_SUBFR, 1, code_preQ, code_preQ, ip_edct2_64, w_edct2_64 ); + } + + /*--------------------------------------------------------------* + * Preemphasise + *--------------------------------------------------------------*/ + + /* in extreme cases at subframe boundaries, lower the preemphasis memory to avoid a saturation */ + if( (nq[7] != 0) && (st->last_nq_preQ - nq[0] > 7) ) + { + *mem_preemp /= 16; + } + + st->last_nq_preQ = nq[7]; + + preemph( code_preQ, FAC_PRE_AVQ, L_SUBFR, mem_preemp ); + + /*--------------------------------------------------------------* + * Compute normalized prequantizer excitation gain for FEC + *--------------------------------------------------------------*/ + + Ecode = (sum2_f( code_preQ, L_SUBFR ) + 0.01f) / L_SUBFR; + + /* somewhat attenuate pre-quantizer normalized gain for FEC */ + *norm_gain_preQ = 0.8f * (*gain_preQ) * (float)sqrt( Ecode ); + + st->use_acelp_preq = 1; + + return; + +} + +/*-----------------------------------------------------------* + * gain_dequant() + * + * Returns decoded gain quantized between the specified + * range using the specified number of levels. + *-----------------------------------------------------------*/ + +float gain_dequant( /* o: decoded gain */ + short index, /* i: quantization index */ + const float min, /* i: value of lower limit */ + const float max, /* i: value of upper limit */ + const short bits /* i: number of bits to dequantize */ +) +{ + float gain, c_min, c_mult; + short levels; + + levels = 1<tilt_code = 0.0f; /* purely unvoiced */ + set_f( st->tilt_code_dec, 0, NB_SUBFR16k ); + st->prev_tilt_code_dec = st->tilt_code; + + st->dispMem[0] = 0; + st->prev_gain_pit_dec = 0.0; + st->dispMem[2] = st->prev_gain_pit_dec; + + for(i=3; i<7; i++) + { + st->dispMem[i] = st->dispMem[i-1]; + } + + set_f(pitch_buf, L_SUBFR, NB_SUBFR); + interp_code_5over2( exc2, bwe_exc, L_FRAME ); + + set_f( voice_factors, 0.0f, NB_SUBFR16k ); + + return; +} diff --git a/lib_dec/dec_pit_exc.c b/lib_dec/dec_pit_exc.c new file mode 100644 index 000000000..53728d41c --- /dev/null +++ b/lib_dec/dec_pit_exc.c @@ -0,0 +1,197 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + + +/*-------------------------------------------------------------------* + * dec_pit_exc() + * + * Decode pitch-only contribution (used by the GSC technology) + *-------------------------------------------------------------------*/ + +void dec_pit_exc( + Decoder_State *st, /* i/o: decoder static memory */ + const short L_frame, /* i : length of the frame */ + const float *Aq, /* i : LP filter coefficient */ + const float Es_pred, /* i : predicted scaled innov. energy */ + float *pitch_buf, /* o : floating pitch values for each subframe */ + float *code, /* o : innovation */ + float *exc, /* i/o: adapt. excitation exc */ + const short nb_subfr, /* i : Number of subframe considered */ + float *gain_buf +) +{ + short T0, T0_frac, T0_min, T0_max;/* integer pitch variables */ + float gain_pit; /* pitch gain */ + float gain_code; /* gain/normalized gain of the algebraic excitation */ + float norm_gain_code; /* normalized gain of the algebraic excitation */ + float gain_inov; /* Innovation gain */ + float voice_fac; /* voicing factor */ + short L_subfr, pit_idx; + const float *p_Aq; /* Pointer to frame LP coefficient */ + float *pt_pitch; /* pointer to floating pitch */ + short i_subfr, i; /* tmp variables */ + short Local_BR, Pitch_BR, Pitch_CT; + short pitch_limit_flag; + short nbits; + float *pt_gain; /* Pointer to floating gain values for each subframe */ + + if( st->GSC_noisy_speech ) + { + Local_BR = ACELP_7k20; + Pitch_CT = GENERIC; + Pitch_BR = ACELP_7k20; + } + else + { + Local_BR = ACELP_7k20; + Pitch_CT = AUDIO; + Pitch_BR = st->core_brate; + } + + gain_code = 0; + pitch_limit_flag = 1; /* always extended pitch Q range */ + + /*------------------------------------------------------------------* + * ACELP subframe loop + *------------------------------------------------------------------*/ + + L_subfr = st->L_frame/nb_subfr; + p_Aq = Aq; /* pointer to interpolated LPC parameters */ + pt_pitch = pitch_buf; /* pointer to the pitch buffer */ + pt_gain = gain_buf; /* pointer to the gain buffer */ + + for ( i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_subfr ) + { + /*----------------------------------------------------------------------* + * Decode pitch lag + *----------------------------------------------------------------------*/ + + *pt_pitch = pit_decode( st, Pitch_BR, 0, L_frame, i_subfr, Pitch_CT, &pitch_limit_flag, &T0, &T0_frac, &T0_min, &T0_max, L_subfr ); + + /*--------------------------------------------------------------* + * Find the adaptive codebook vector. + *--------------------------------------------------------------*/ + + pred_lt4( &exc[i_subfr], &exc[i_subfr], T0, T0_frac, L_subfr+1, inter4_2, L_INTERPOL2, PIT_UP_SAMP ); + + /*--------------------------------------------------------------* + * Innovation decoding + *--------------------------------------------------------------*/ + + if( st->GSC_noisy_speech ) + { + inov_decode( st, Local_BR, 0, L_frame, LOCAL_CT, 1, i_subfr, -1, p_Aq, st->tilt_code, *pt_pitch, code ); + + /*--------------------------------------------------------------* + * Gain decoding + * Estimate spectrum tilt and voicing + *--------------------------------------------------------------*/ + + gain_dec_mless( st, Local_BR, L_frame, LOCAL_CT, i_subfr, -1, code, Es_pred, &gain_pit, &gain_code, &gain_inov, &norm_gain_code ); + + st->tilt_code = est_tilt( exc+i_subfr, gain_pit, code, gain_code, &voice_fac,L_SUBFR,0 ); + } + else + { + nbits = 4; + + set_f(code, 0, L_SUBFR); + gain_code = 0.0f; + st->tilt_code = 0.0f; + + pit_idx = (short)get_next_indice( st, nbits ); + + gain_pit = 0.5853f + dic_gp[pit_idx]; + + if( st->BER_detect ) /* Bitstream is corrupted, use the past pitch gain */ + { + gain_pit = st->lp_gainp; + } + } + + /*----------------------------------------------------------------------* + * Find the total excitation + *----------------------------------------------------------------------*/ + + if( st->GSC_noisy_speech ) + { + for (i = 0; i < L_subfr; i++) + { + exc[i+i_subfr] = gain_pit * exc[i+i_subfr] + gain_code * code[i]; + } + } + else + { + for (i = 0; i < L_subfr; i++) + { + exc[i+i_subfr] = gain_pit * exc[i+i_subfr]; + } + } + + if( L_subfr == 2*L_SUBFR ) + { + p_Aq += 2*(M+1); + pt_pitch++; + *pt_pitch = *(pt_pitch-1); + pt_pitch++; + *pt_gain = gain_pit; + pt_gain++; + *pt_gain = *(pt_gain-1); + pt_gain++; + + if( i_subfr == 0 ) + { + /* update gains for FEC - equivalent to lp_gain_updt() */ + st->lp_gainp = (3.0f/10.0f) * gain_pit; + st->lp_gainc = 0; + } + else + { + /* update gains for FEC - equivalent to lp_gain_updt() */ + st->lp_gainp = (7.0f/10.0f) * gain_pit; + st->lp_gainc = 0; + } + } + else if( L_subfr == 4*L_SUBFR ) + { + pt_pitch++; + *pt_pitch = *(pt_pitch-1); + pt_pitch++; + *pt_pitch = *(pt_pitch-1); + pt_pitch++; + *pt_pitch = *(pt_pitch-1); + pt_pitch++; + *pt_gain = gain_pit; + pt_gain++; + *pt_gain = *(pt_gain-1); + pt_gain++; + *pt_gain = *(pt_gain-1); + pt_gain++; + *pt_gain = *(pt_gain-1); + pt_gain++; + p_Aq += 4*(M+1); + + /* update gains for FEC - equivalent to lp_gain_updt() */ + st->lp_gainp = gain_pit; + st->lp_gainc = 0; + } + else + { + p_Aq += (M+1); + pt_pitch++; + *pt_gain = gain_pit; + pt_gain++; + + lp_gain_updt( i_subfr, gain_pit, 0, &st->lp_gainp, &st->lp_gainc, L_frame ); + } + } + + return; +} diff --git a/lib_dec/dec_post.c b/lib_dec/dec_post.c new file mode 100644 index 000000000..578c3cd28 --- /dev/null +++ b/lib_dec/dec_post.c @@ -0,0 +1,967 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ + +#define FORMAT_POST_FILT_G1 0.75f /*0.75f*/ /*denominator 0.9,0.75,0.15,0.9*/ + + +/*-------------------------------------------------------------------------- + * Local functions + *--------------------------------------------------------------------------*/ + +static void Dec_postfilt( const short L_subfr, PFSTAT *pfstat, const int t0, const float *signal_ptr, const float *coeff, + float *sig_out, const float gamma1, const float gamma2, const float gain_factor, const short disable_hpf ); + +static void pst_ltp( const int t0, const float *ptr_sig_in, float *ptr_sig_pst0, float gain_factor, const short L_subfr ); + +static void search_del( const int t0, const float *ptr_sig_in, int *ltpdel, int *phase, float *num_gltp, float *den_gltp, + float *y_up, int *off_yup, const short L_subfr ); + +static void filt_plt( const float *s_in, const float *s_ltp, float *s_out, const float gain_plt, const short L_subfr ); + +static void compute_ltp_l( const float *s_in, const int ltpdel, const int phase, float *y_up, float *num, float *den, const short L_subfr ); + +static int select_ltp( const float num1, const float den1, const float num2, const float den2 ); + +static void modify_pst_param( const float psf_lp_noise, float *g1, float *g2, const short coder_type, float *gain_factor ); + +static void Dec_formant_postfilt( PFSTAT *pfstat, const float *signal_ptr, const float *coeff, float *sig_out, + const float gamma1, const float gamma2, const short l_subfr ); + +/*--------------------------------------------------------------------------* + * Function Init_post_filter() + * + * Post-filter initialization + *--------------------------------------------------------------------------*/ + +void Init_post_filter( + PFSTAT * pfstat /* i : post-filter state memories */ +) +{ + /* It is off by default */ + pfstat->on = 0; + + /* Reset */ + pfstat->reset = 0; + + /* Initialize arrays and pointers */ + set_zero( pfstat->mem_pf_in, L_SUBFR ); + + /* res2 = A(gamma2) residual */ + set_zero( pfstat->mem_res2, DECMEM_RES2 ); + + /* 1/A(gamma1) memory */ + set_zero( pfstat->mem_stp, L_SUBFR ); + + /* null memory to compute i.r. of A(gamma2)/A(gamma1) */ + set_zero( pfstat->mem_zero, M ); + + /* for gain adjustment */ + pfstat->gain_prec = 1.0f; + + return; +} + + +/*-------------------------------------------------------------------------- + * nb_post_filt() + * + * Main routine to perform post filtering of NB signals + *--------------------------------------------------------------------------*/ + +void nb_post_filt( + const short L_frame, /* i : frame length */ + const short L_subfr, /* i : sub-frame length */ + PFSTAT *pfstat, /* i/o: Post filter related memories */ + float *psf_lp_noise, /* i/o: long term noise energy */ + const float tmp_noise, /* i : noise energy */ + float *synth, /* i/o: synthesis */ + const float *Aq, /* i : LP filter coefficient */ + const float *pitch_buf, /* i : floating pitch for each subframe */ + const short coder_type, /* i : coder_type */ + const short BER_detect, /* i : BER detect flag */ + const short disable_hpf /* i : flag to disabled HPF */ +) +{ + short t0_first, i, j; + const float *p_Aq; + float *pf_in, post_G1, post_G2, gain_factor; + float pf_in_buffer[M+L_FRAME16k]; + + if(!BER_detect) + { + /* update long-term background noise energy during inactive frames */ + if( coder_type == INACTIVE ) + { + *psf_lp_noise = 0.95f * *psf_lp_noise + 0.05f * tmp_noise; + } + } + + /* set post-filter input */ + modify_pst_param( *psf_lp_noise, &post_G1, &post_G2, coder_type, &gain_factor ); + + + if( pfstat->reset ) + { + set_zero( pfstat->mem_res2, DECMEM_RES2 ); + mvr2r( &synth[L_frame-L_SYN_MEM], pfstat->mem_pf_in, L_SYN_MEM ); + mvr2r( &synth[L_frame-L_SYN_MEM], pfstat->mem_stp, L_SYN_MEM ); + pfstat->gain_prec = 1.0f; + pfstat->reset = 0; + return; + } + + pf_in = &pf_in_buffer[M]; + mvr2r( pfstat->mem_pf_in+L_SYN_MEM-M, &pf_in[-M], M ); + mvr2r( synth, pf_in, L_frame ); + mvr2r( &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( coder_type == AUDIO ) + { + post_G1 = 1.f; + post_G2 = 1.f; + gain_factor = 1.f; + } + + /* run the post filter */ + p_Aq = Aq; + for( i=0, j=0; i= LP_NOISE_THRESH ) + { + post_G1 = 0.76f; + } + else if( rate == ACELP_13k20 ) + { + post_G1 = 0.82f; + } + else if( rate == ACELP_16k40 ) + { + post_G1 = 0.80f; + } + else if( rate == ACELP_24k40 || rate == ACELP_32k ) + { + post_G1 = 0.78f; + } + else + { + post_G1 = 0.76f; + } + } + + /* Switch off post-filter*/ + if( off_flag ) + { + post_G1 = post_G2; + } + + /* Reset post filter */ + if( pfstat->reset ) + { + pfstat->reset = 0; + mvr2r( &synth_in[L_frame-L_SYN_MEM], pfstat->mem_pf_in, L_SYN_MEM); + mvr2r( &synth_in[L_frame-L_SYN_MEM], pfstat->mem_stp, L_SYN_MEM ); + pfstat->gain_prec = 1.f; + mvr2r( synth_in,synth_out, L_frame ); + + return; + } + + /* input memory*/ + mvr2r( pfstat->mem_pf_in, synth_in-L_SYN_MEM, L_SYN_MEM); + mvr2r( &synth_in[L_frame-L_SYN_MEM], pfstat->mem_pf_in, L_SYN_MEM); + + /* run the post filter */ + p_Aq = Aq; + for( i_subfr=0; i_subfr 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( + const short L_subfr, /* i : sub-frame length */ + PFSTAT *pfstat, /* i/o: Post filter related memories */ + const int t0, /* i : pitch delay given by coder */ + const float *signal_ptr, /* i : input signal (pointer to current subframe */ + const float *coeff, /* i : LPC coefficients for current subframe */ + float *sig_out, /* o : postfiltered output */ + const float gamma1, /* i : short term postfilt. den. weighting factor*/ + const float gamma2, /* i : short term postfilt. num. weighting factor*/ + const float gain_factor, /* i : Gain Factor */ + const short disable_hpf /* i : flag to disable HPF */ +) +{ + float apond1[M+1]; /* s.t. denominator coeff. */ + float apond2[LONG_H_ST]; + float sig_ltp[L_SUBFR+1]; /* H0 output signal */ + float res2[SIZ_RES2]; + float *sig_ltp_ptr; + float *res2_ptr; + float *ptr_mem_stp; + float parcor0; + + /* Init pointers and restore memories */ + res2_ptr = res2 + DECMEM_RES2; + ptr_mem_stp = pfstat->mem_stp + L_SYN_MEM - 1; + mvr2r( pfstat->mem_res2, res2, DECMEM_RES2 ); + + /* Compute weighted LPC coefficients */ + weight_a( coeff, apond1, gamma1, M ); + weight_a( coeff, apond2, gamma2, M ); + set_f( &apond2[M+1], 0, LONG_H_ST-(M+1) ); + + /* Compute A(gamma2) residual */ + residu( apond2, M, signal_ptr, res2_ptr, L_subfr ); + + /* Harmonic filtering */ + sig_ltp_ptr = sig_ltp + 1; + + if( !disable_hpf ) + { + pst_ltp( t0, res2_ptr, sig_ltp_ptr, gain_factor, L_subfr ); + } + else + { + mvr2r( res2_ptr, sig_ltp_ptr, L_subfr ); + } + + /* Save last output of 1/A(gamma1) */ + /* (from preceding subframe) */ + sig_ltp[0] = *ptr_mem_stp; + + /* Controls short term pst filter gain and compute parcor0 */ + calc_st_filt( apond2, apond1, &parcor0, sig_ltp_ptr, pfstat->mem_zero, L_subfr, -1 ); + + syn_filt( apond1, M,sig_ltp_ptr, sig_ltp_ptr, L_subfr, pfstat->mem_stp+L_SYN_MEM-M, 0 ); + mvr2r( 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, -1 ); + + /* Gain control */ + scale_st( signal_ptr, sig_out, &(pfstat->gain_prec), L_subfr, -1 ); + + /* Update for next subframe */ + mvr2r( &res2[L_subfr], pfstat->mem_res2, DECMEM_RES2 ); + + return; +} + + + +/*---------------------------------------------------------------------------- + * Dec_formant_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 */ + const float *signal_ptr, /* i : input signal (pointer to current subframe */ + const float *coeff, /* i : LPC coefficients for current subframe */ + float *sig_out, /* o : postfiltered output */ + const float gamma1, /* i : short term postfilt. den. weighting factor*/ + const float gamma2, /* i : short term postfilt. num. weighting factor*/ + const short l_subfr /* i : subframe length */ +) +{ + /* Local variables and arrays */ + float apond1[M+1]; /* s.t. denominator coeff. */ + float apond2[LONG_H_ST]; + float res2[L_SUBFR]; + float resynth[L_SUBFR+1]; + float parcor0; + + /* Compute weighted LPC coefficients */ + weight_a( coeff, apond1, gamma1, M ); + weight_a( coeff, apond2, gamma2, M ); + + set_zero( &apond2[M+1], LONG_H_ST-(M+1) ); + + /* Compute A(gamma2) residual */ + residu( apond2, M, signal_ptr, res2, l_subfr ); + + /* Controls short term pst filter gain and compute parcor0 */ + calc_st_filt( apond2, apond1, &parcor0, res2, pfstat->mem_zero, l_subfr, -1 ); + + /* 1/A(gamma1) filtering, mem_stp is updated */ + resynth[0] = *(pfstat->mem_stp + L_SYN_MEM - 1); + + syn_filt( apond1, M,res2, &(resynth[1]), l_subfr, pfstat->mem_stp+L_SYN_MEM-M, 0 ); + + mvr2r( &(resynth[1])+l_subfr-L_SYN_MEM, pfstat->mem_stp, L_SYN_MEM); + + /* Tilt filtering */ + filt_mu( resynth, sig_out, parcor0, l_subfr, -1 ); + + /* Gain control */ + scale_st( signal_ptr, sig_out, &pfstat->gain_prec, l_subfr, -1 ); + + return; +} + + +/*---------------------------------------------------------------------------- + * pst_ltp() + * + * Perform harmonic postfilter + *----------------------------------------------------------------------------*/ + +static void pst_ltp( + const int t0, /* i : pitch delay given by coder */ + const float *ptr_sig_in, /* i : postfilter input filter (residu2) */ + float *ptr_sig_pst0, /* o : harmonic postfilter output */ + float gain_factor, /* i : gain factor */ + const short L_subfr /* i : sub-frame length */ +) +{ + int ltpdel, phase; + float num_gltp, den_gltp; + float num2_gltp, den2_gltp; + float gain_plt; + float y_up[SIZ_Y_UP]; + const float *ptr_y_up; + int off_yup; + + /* Suboptimal delay search */ + search_del( t0, ptr_sig_in, <pdel, &phase, &num_gltp, &den_gltp, y_up, &off_yup, L_subfr ); + + if( num_gltp == 0.0f ) + { + mvr2r( 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_in, ltpdel, phase, ptr_sig_pst0, &num2_gltp, &den2_gltp, L_subfr ); + + if( select_ltp( num_gltp, den_gltp, num2_gltp, den2_gltp ) == 1 ) + { + /* select short filter */ + ptr_y_up = y_up + ((phase - 1) * (L_subfr+1) + off_yup); + } + else + { + /* select long filter */ + num_gltp = num2_gltp; + den_gltp = den2_gltp; + ptr_y_up = ptr_sig_pst0; + } + } + + if( num_gltp >= den_gltp ) + { + /* beta bounded to 1 */ + gain_plt = MIN_GPLT; + } + else + { + gain_plt = den_gltp / (den_gltp + ((float)0.5) * num_gltp); + } + + /* decrease gain in noisy condition */ + gain_plt += ((1.0f-gain_plt)*gain_factor); + + /* filtering by H0(z) = harmonic filter */ + filt_plt( ptr_sig_in, ptr_y_up, ptr_sig_pst0, gain_plt, L_subfr ); + } + + return; +} + +/*---------------------------------------------------------------------------- + * search_del() + * + * Computes best (shortest) integer LTP delay + fine search + *---------------------------------------------------------------------------*/ + +static void search_del( + const int t0, /* i : pitch delay given by coder */ + const float *ptr_sig_in, /* i : input signal (with delay line) */ + int *ltpdel, /* o : delay = *ltpdel - *phase / f_up */ + int *phase, /* o : phase */ + float *num_gltp, /* o : numerator of LTP gain */ + float *den_gltp, /* o : denominator of LTP gain */ + float *y_up, /* o : LT delayed signal if fract. delay*/ + int *off_yup, /* o : offset in y_up */ + const short L_subfr /* i : sub-frame length */ +) +{ + const float *ptr_h; + float tab_den0[F_UP_PST - 1], tab_den1[F_UP_PST - 1]; + float *ptr_den0, *ptr_den1; + const float *ptr_sig_past, *ptr_sig_past0; + const float *ptr1; + int i, n, ioff, i_max; + float ener, num, numsq, den0, den1; + float den_int, num_int; + float den_max, num_max, numsq_max; + int phi_max; + int lambda, phi; + float temp0, temp1; + float *ptr_y_up; + + /*------------------------------------- + * Computes energy of current signal + *-------------------------------------*/ + + ener = 0.0f; + for (i = 0; i < L_subfr; i++) + { + ener += ptr_sig_in[i] * ptr_sig_in[i]; + } + + if (ener < 0.1f) + { + *num_gltp = 0.0f; + *den_gltp = 1.0f; + *ltpdel = 0; + *phase = 0; + + return; + } + + /*------------------------------------- + * Selects best of 3 integer delays + * Maximum of 3 numerators around t0 + *-------------------------------------*/ + + lambda = t0 - 1; + ptr_sig_past = ptr_sig_in - lambda; + num_int = -1.0e30f; + i_max = 0; + + for (i = 0; i < 3; i++) + { + num = 0.0f; + for (n = 0; n < L_subfr; n++) + { + num += ptr_sig_in[n] * ptr_sig_past[n]; + } + if (num > num_int) + { + i_max = i; + num_int = num; + } + ptr_sig_past--; + } + + if (num_int <= 0.0f) + { + *num_gltp = 0.0f; + *den_gltp = 1.0f; + *ltpdel = 0; + *phase = 0; + + return; + } + + /* Calculates denominator for i_max */ + lambda += i_max; + ptr_sig_past = ptr_sig_in - lambda; + den_int = (float) 0.; + for (n = 0; n < L_subfr; n++) + { + den_int += ptr_sig_past[n] * ptr_sig_past[n]; + } + + if (den_int < (float) 0.1) + { + *num_gltp = (float) 0.; + *den_gltp = (float) 1.; + *ltpdel = 0; + *phase = 0; + return; + } + + /*---------------------------------- + * Select best phase around lambda + * Compute y_up & denominators + *----------------------------------*/ + + ptr_y_up = y_up; + den_max = den_int; + ptr_den0 = tab_den0; + ptr_den1 = tab_den1; + ptr_h = tab_hup_s; + ptr_sig_past0 = ptr_sig_in + LH_UP_S - 1 - lambda; /* points on lambda_max+1 */ + + /* loop on phase */ + for (phi = 1; phi < F_UP_PST; phi++) + { + /* Computes criterion for (lambda+1) - phi/F_UP_PST */ + /* and lambda - phi/F_UP_PST */ + ptr_sig_past = ptr_sig_past0; + /* computes y_up[n] */ + for (n = 0; n <= L_subfr; n++) + { + ptr1 = ptr_sig_past++; + temp0 = (float) 0.; + for (i = 0; i < LH2_S; i++) + { + temp0 += ptr_h[i] * ptr1[-i]; + } + ptr_y_up[n] = temp0; + } + + /* compute den0 (lambda+1) and den1 (lambda) */ + /* part common to den0 and den1 */ + temp0 = (float) 0.; + for (n = 1; n < L_subfr; n++) + { + temp0 += ptr_y_up[n] * ptr_y_up[n]; + } + + /* den0 */ + den0 = temp0 + ptr_y_up[0] * ptr_y_up[0]; + *ptr_den0++ = den0; + + /* den1 */ + den1 = temp0 + ptr_y_up[L_subfr] * ptr_y_up[L_subfr]; + *ptr_den1++ = den1; + if (fabs (ptr_y_up[0]) > fabs (ptr_y_up[L_subfr])) + { + if (den0 > den_max) + { + den_max = den0; + } + } + else + { + if (den1 > den_max) + { + den_max = den1; + } + } + ptr_y_up += (L_subfr+1); + ptr_h += LH2_S; + } + if (den_max < 0.1f) + { + *num_gltp = 0.0f; + *den_gltp = 1.0f; + *ltpdel = 0; + *phase = 0; + return; + } + + /* Computation of the numerators */ + /* and selection of best num*num/den */ + /* for non null phases */ + + /* Initialize with null phase */ + num_max = num_int; + den_max = den_int; + numsq_max = num_max * num_max; + phi_max = 0; + ioff = 1; + + ptr_den0 = tab_den0; + ptr_den1 = tab_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++) + { + + /* computes num for lambda+1 - phi/F_UP_PST */ + num = 0.0f; + for (n = 0; n < L_subfr; n++) + { + num += ptr_sig_in[n] * ptr_y_up[n]; + } + if (num < 0.0f) + { + num = 0.0f; + } + numsq = num * num; + + /* selection if num/sqrt(den0) max */ + den0 = *ptr_den0++; + temp0 = numsq * den_max; + temp1 = numsq_max * den0; + if (temp0 > temp1) + { + num_max = num; + numsq_max = numsq; + den_max = den0; + ioff = 0; + phi_max = phi; + } + + /* computes num for lambda_max - phi/F_UP_PST */ + ptr_y_up++; + num = (float) 0.; + for (n = 0; n < L_subfr; n++) + { + num += ptr_sig_in[n] * ptr_y_up[n]; + } + if (num < (float) 0.) + { + num = (float) 0.; + } + numsq = num * num; + + /* selection if num/sqrt(den1) max */ + den1 = *ptr_den1++; + temp0 = numsq * den_max; + temp1 = numsq_max * den1; + if (temp0 > temp1) + { + num_max = num; + numsq_max = numsq; + den_max = den1; + ioff = 1; + phi_max = phi; + } + ptr_y_up += L_subfr; + } + + /*--------------------------------------------------- + * test if normalized crit0[iopt] > THRESHCRIT + *--------------------------------------------------*/ + + if ((num_max == 0.0f) || (den_max <= 0.1f)) + { + *num_gltp = 0.0f; + *den_gltp = 1.0f; + *ltpdel = 0; + *phase = 0; + return; + } + + /* comparison num * num */ + /* with ener * den x THRESCRIT */ + temp1 = den_max * ener * THRESCRIT; + if (numsq_max >= temp1) + { + *ltpdel = lambda + 1 - ioff; + *off_yup = ioff; + *phase = phi_max; + *num_gltp = num_max; + *den_gltp = den_max; + } + else + { + *num_gltp = 0.0f; + *den_gltp = 1.0f; + *ltpdel = 0; + *phase = 0; + } + + return; +} + +/*---------------------------------------------------------------------------- + * filt_plt() + * + * Perform long term postfilter + *----------------------------------------------------------------------------*/ + +static void filt_plt( + const float *s_in, /* i : input signal with past */ + const float *s_ltp, /* i : filtered signal with gain 1 */ + float *s_out, /* o : output signal */ + const float gain_plt, /* i : filter gain */ + const short L_subfr /* i : the length of subframe */ +) +{ + int n; + float gain_plt_1; + + gain_plt_1 = (float) 1. - gain_plt; + + for (n = 0; n < L_subfr; n++) + { + s_out[n] = gain_plt * s_in[n] + gain_plt_1 * s_ltp[n]; + } + + return; +} + +/*---------------------------------------------------------------------------- + * compute_ltp_l() + * + * compute delayed signal, num & den of gain for fractional delay + * with long interpolation filter + *----------------------------------------------------------------------------*/ + +static void compute_ltp_l( + const float *s_in, /* i : input signal with past */ + const int ltpdel, /* i : delay factor */ + const int phase, /* i : phase factor */ + float *y_up, /* o : delayed signal */ + float *num, /* o : numerator of LTP gain */ + float *den, /* o : denominator of LTP gain */ + const short L_subfr /* i : the length of subframe */ +) +{ + const float *ptr_h; + int n, i; + const float *ptr2; + float temp; + + /* Filtering with long filter */ + ptr_h = tab_hup_l + (phase - 1) * LH2_L; + ptr2 = s_in - ltpdel + LH_UP_L; + + /* Compute y_up */ + for (n = 0; n < L_subfr; n++) + { + temp = 0.0f; + for (i = 0; i < LH2_L; i++) + { + temp += ptr_h[i] **ptr2--; + } + y_up[n] = temp; + ptr2 += LH2_L_P1; + } + + /* Compute num */ + *num = 0.0f; + for (n = 0; n < L_subfr; n++) + { + *num += y_up[n] * s_in[n]; + } + + if (*num < 0.0f) + { + *num = 0.0f; + } + + /* Compute den */ + *den = 0.0f; + for (n = 0; n < L_subfr; n++) + { + *den += y_up[n] * y_up[n]; + } + + 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 int select_ltp( /* o : 1 = 1st gain, 2 = 2nd gain */ + const float num1, /* i : numerator of gain1 */ + const float den1, /* i : denominator of gain1 */ + const float num2, /* i : numerator of gain2 */ + const float den2 /* i : denominator of gain2 */ +) +{ + if (den2 == (float) 0.) + { + return (1); + } + + if (num2 * num2 * den1 > num1 * num1 * den2) + { + return (2); + } + else + { + return (1); + } +} + + +/*------------------------------------------------------------------------------------ + * modify_pst_param() + * + * Modify gamma1 and gamma2 values in function of the long-term noise level + *-----------------------------------------------------------------------------------*/ + +static void modify_pst_param( + const float psf_lp_noise, /* i : Long term noise energy */ + float *g1, /* o : Gamma1 used in post filter */ + float *g2, /* o : Gamma2 used in post filter */ + const short coder_type, /* i : coder type */ + float *gain_factor /* o : Gain factor applied in post filtering */ +) +{ + float ftmp; + + if( coder_type != INACTIVE && psf_lp_noise < LP_NOISE_THR ) + { + ftmp = psf_lp_noise*BG1 + CG1; + if( ftmp > POST_G1 ) + { + ftmp = POST_G1; + } + else if( ftmp < POST_G1_MIN ) + { + ftmp = POST_G1_MIN; + } + *g1 = ftmp; + + ftmp = psf_lp_noise*BG2 + CG2; + if( ftmp > POST_G2 ) + { + ftmp = POST_G2; + } + else if( ftmp < POST_G2_MIN ) + { + ftmp = POST_G2_MIN; + } + *g2 = ftmp; + } + else + { + *g1 = POST_G1_NOIS; + *g2 = POST_G2_NOIS; + } + + /* Set gain_factor of the harmonic filtering */ + ftmp = (psf_lp_noise - K_LP_NOISE) * C_LP_NOISE; + + if( ftmp >= 0.25f ) + { + /* the noise is really high */ + *gain_factor = 0.25f; + } + else if ( ftmp < 0 ) + { + *gain_factor = 0.0f; + } + else + { + *gain_factor = ftmp; + } + + return; +} diff --git a/lib_dec/dec_ppp.c b/lib_dec/dec_ppp.c new file mode 100644 index 000000000..3efbe0e60 --- /dev/null +++ b/lib_dec/dec_ppp.c @@ -0,0 +1,70 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" + +/*------------------------------------------------------------------- + * decod_ppp() + * + * PPP decoder + *-------------------------------------------------------------------*/ + +void decod_ppp( + Decoder_State *st, /* i/o: state structure */ + const float Aq[], /* i : 12k8 Lp coefficient */ + float *pitch_buf, /* i/o: floating pitch values for each subframe */ + float *exc, /* i/o: current non-enhanced excitation */ + float *exc2, /* i/o: current enhanced excitation */ + float *voice_factors, /* o : voicing factors */ + float *bwe_exc /* o : excitation for SWB TBE */ + , float *gain_buf + , short bfi +) +{ + short k; + float p_Aq_old[M+1], excQ_ppp[L_FRAME], p_Aq_curr[M], LPC_de_old[M+1]; + float LPC_de_curr[M+1], pitch[NB_SUBFR]; + + /* call voiced decoder at this point */ + for( k=0; klsp_old, p_Aq_old, M ); + + deemph_lpc( p_Aq_curr, p_Aq_old, LPC_de_curr, LPC_de_old + ,0 + ); + + /* last frame-end lpc and curr frame-end lpc */ + ppp_voiced_decoder( st, excQ_ppp, LPC_de_curr, exc, pitch + ,bfi + ); + + st->tilt_code = st->prev_tilt_code_dec; + + mvr2r( excQ_ppp, exc, L_FRAME ); + mvr2r( exc, exc2, L_FRAME ); + + st->dispMem[0] = 2; + st->dispMem[2] = st->prev_gain_pit_dec; + + for(k=3; k<7; k++) + { + st->dispMem[k] = st->dispMem[k-1]; + } + + mvr2r( pitch, pitch_buf, NB_SUBFR ); + + interp_code_5over2( exc2, bwe_exc, L_FRAME ); + set_f( voice_factors, 0.0f, NB_SUBFR16k ); + set_f(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 000000000..e3e1e4dd5 --- /dev/null +++ b/lib_dec/dec_prm.c @@ -0,0 +1,962 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*-----------------------------------------------------------------* + * dec_prm_hm() + * + * + *-----------------------------------------------------------------*/ + +static void dec_prm_hm( + Decoder_State *st, + int *prm_hm, + const short L_frame +) +{ + /* Disable HM for non-GC,VC modes */ + if( st->tcx_cfg.coder_type != VOICED && st->tcx_cfg.coder_type != GENERIC ) + { + prm_hm[0] = 0; + return; + } + + prm_hm[1] = -1; + prm_hm[2] = 0; + + /* Flag */ + prm_hm[0] = get_next_indice(st, 1); + + if (prm_hm[0]) + { + /* Periodicity index */ + DecodeIndex( st, L_frame >= 256, &prm_hm[1] ); + + /* Gain index */ + if( st->tcx_cfg.coder_type == VOICED ) + { + prm_hm[2] = get_next_indice(st, kTcxHmNumGainBits ); + } + } + + return; +} + + +/*-----------------------------------------------------------------* + * Function dec_prm() * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * + * + * SQ is used for TCX modes + * + * decode parameters according to selected mode * + *-----------------------------------------------------------------*/ + +void dec_prm( + short *coder_type, /* o : coder type */ + int param[], /* o : decoded parameters */ + int param_lpc[], /* o : LPC parameters */ + Word16 *total_nbbits, /* i/o : number of bits / decoded bits */ + Decoder_State *st, /* i/o: decoder memory state */ + const int L_frame, + short *bitsRead +) +{ + short j, k, n, sfr; + int *prm; + int lg; + int lgFB; + int start_bit_pos, bits_common; + int acelp_target_bits=-1; + int tmp; + int nTnsParams; + int nTnsBits; + int nb_subfr; + int nbits_tcx; + int ix, j_old, wordcnt, bitcnt; + int hm_size; + int *prms; + CONTEXT_HM_CONFIG hm_cfg; + int indexBuffer[N_MAX+1]; + short flag_ctx_hm; + short ind; + short ltp_mode, gains_mode; + int prm_ltp[LTPSIZE]; + + /*--------------------------------------------------------------------------------* + * INIT + *--------------------------------------------------------------------------------*/ + + hm_cfg.indexBuffer = indexBuffer; + + if (st->mdct_sw == MODE1) + { + start_bit_pos = 0; /* count from frame start */ + + /* Adjust st->bits_frame_core not to subtract MODE2 bandwidth signaling */ + for (n=0; ntotal_brate/50) + { + st->bits_frame_core += FrameSizeConfig[n].bandwidth_bits; + break; + } + } + } + else + { + if( st->rf_flag == 1 ) + { + /*Inherent adjustment to accommodate the compact packing used in the RF mode*/ + start_bit_pos = st->next_bit_pos - 2; + } + else + { + start_bit_pos = st->next_bit_pos; + } + } + + /* Framing parameters */ + nb_subfr = st->nb_subfr; + + /* Initialize pointers */ + prm = param; + + /* Init counters */ + j = 0; + + /* Init LTP data */ + st->tcx_hm_LtpPitchLag = -1; + st->tcxltp_gain = 0.0f; + + + /*--------------------------------------------------------------------------------* + * EVS HEADER + *--------------------------------------------------------------------------------*/ + + /* Modes (ACE_GC, ACE_UC, TCX20, TCX10...) */ + if ( st->tcxonly ) + { + st->core = get_next_indice(st, 1) + 1; + + ind = get_next_indice(st, 2); + st->clas_dec = ONSET; + if( ind == 0 ) + { + st->clas_dec = UNVOICED_CLAS; + } + else if( ind == 1 ) + { + if( st->last_good >= VOICED_TRANSITION ) + { + st->clas_dec = VOICED_TRANSITION; + } + else + { + st->clas_dec = UNVOICED_TRANSITION; + } + } + else if( ind == 2 ) + { + st->clas_dec = VOICED_CLAS; + } + *coder_type = INACTIVE; + st->VAD = 0; + } + else + { + if (st->mdct_sw == MODE1) + { + /* 2 bits instead of 3 as TCX is already signaled */ + st->core = TCX_20_CORE; + st->tcx_cfg.coder_type = get_next_indice(st, 2); + *coder_type = st->tcx_cfg.coder_type; + } + else + { + if (st->mdct_sw_enable == MODE2) + { + if (get_next_indice_1(st)) /* TCX */ + { + tmp = get_next_indice(st, 3); + assert(!(tmp & 4) || !"HQ_CORE encountered in dec_prm"); + st->core = TCX_20_CORE; + st->tcx_cfg.coder_type = tmp; + *coder_type = st->tcx_cfg.coder_type; + } + else /* ACELP */ + { + st->core = ACELP_CORE; + *coder_type = get_next_indice(st, 2); + } + } + else + { + if(st->rf_flag == 1) + { + if( !( st->use_partial_copy ) ) + { + tmp = get_next_indice(st, 1); + if(tmp == 0) + { + st->core = ACELP_CORE; + } + else + { + st->core = TCX_20_CORE; + st->tcx_cfg.coder_type = *coder_type; + } + } + } + else + { + tmp = get_next_indice(st, 3); + if( tmp < ACELP_MODE_MAX ) + { + st->core = ACELP_CORE; + *coder_type = tmp; + } + else + { + st->core = TCX_20_CORE; + st->tcx_cfg.coder_type = tmp-ACELP_MODE_MAX; + *coder_type = st->tcx_cfg.coder_type; + } + } + } + } + + if( st->igf && st->core == ACELP_CORE ) + { + st->bits_frame_core -= get_tbe_bits(st->total_brate, st->bwidth, st->rf_flag ); + } + + if( st->rf_flag ) + { + st->bits_frame_core -= (st->rf_target_bits+1); /* +1 as flag-bit not considered in rf_target_bits */ + } + + /* Inactive frame detection on non-DTX mode */ + if( *coder_type == INACTIVE ) + { + st->VAD = 0; + } + else + { + st->VAD = 1; + } + } + + /*Core extended mode mapping for correct PLC classification*/ + st->core_ext_mode=*coder_type; + if( *coder_type == INACTIVE ) + { + st->core_ext_mode = UNVOICED; + } + + /* Decode previous mode for error concealment */ + if( !(st->core == ACELP_CORE && st->tcx_cfg.lfacNext<=0) && !st->use_partial_copy ) + { + st->last_core_bs = get_next_indice(st, 1); + + /* + 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 == 0) && (st->clas_dec != VOICED_CLAS))) && (st->last_core_bs != st->last_core) ) + { + st->last_core = st->last_core_bs; + } + + /* for TCX 10 force last_core to be TCX since ACELP as previous core is forbidden */ + if(st->core == TCX_10_CORE) + { + st->last_core = TCX_20_CORE; + st->last_core_bs = TCX_20_CORE; + } + } + + if(st->rf_flag && st->use_partial_copy && !st->tcxonly) + { + st->bits_frame_core = st->rf_target_bits; + + /* offset the indices to read the acelp partial copy */ + get_next_indice_tmp(st, start_bit_pos + st->total_brate/50 - st->rf_target_bits - 3 - st->next_bit_pos); + } + + if( !st->use_partial_copy ) + { + int overlap_code; + + /* Set the last overlap mode based on the previous and current frame type and coded overlap mode */ + if ((st->last_core == ACELP_CORE) || (st->last_core == AMR_WB_CORE)) + { + st->tcx_cfg.tcx_last_overlap_mode = TRANSITION_OVERLAP; + } + else if ((st->core == TCX_10_CORE) && (st->tcx_cfg.tcx_curr_overlap_mode == ALDO_WINDOW)) + { + st->tcx_cfg.tcx_last_overlap_mode = FULL_OVERLAP; + } + else if ((st->core != TCX_10_CORE) && (st->tcx_cfg.tcx_curr_overlap_mode == FULL_OVERLAP)) + { + st->tcx_cfg.tcx_last_overlap_mode = ALDO_WINDOW; + } + else + { + st->tcx_cfg.tcx_last_overlap_mode = st->tcx_cfg.tcx_curr_overlap_mode; + } + + /* Set the current overlap mode based on the current frame type and coded overlap mode */ + st->tcx_cfg.tcx_curr_overlap_mode = ALDO_WINDOW; + + if( st->core != ACELP_CORE ) + { + overlap_code = 0; + if (get_next_indice(st, 1)) + { + overlap_code = 2 + get_next_indice(st, 1); + } + assert(MIN_OVERLAP == 2 && HALF_OVERLAP == 3); + st->tcx_cfg.tcx_curr_overlap_mode = overlap_code; + + /*TCX10 : always symmetric windows*/ + if ((st->core == TCX_20_CORE) && (overlap_code == 0) && (st->last_core != ACELP_CORE) && (st->last_core != AMR_WB_CORE)) + { + st->tcx_cfg.tcx_curr_overlap_mode = ALDO_WINDOW; + } + } + + /* SIDE INFO. DECODING */ + if( st->enableGplc ) + { + short pitchDiff; + short bits_per_subfr, search_range; + bits_per_subfr = 4; + search_range = 8; + st->flagGuidedAcelp = get_next_indice(st, 1); + + pitchDiff = 0; + if( st->flagGuidedAcelp ) + { + pitchDiff = get_next_indice(st, bits_per_subfr); + st->guidedT0 = (pitchDiff - search_range); + } + if( pitchDiff==0 && st->flagGuidedAcelp ) + { + st->flagGuidedAcelp = 0; + } + } + else + { + st->flagGuidedAcelp = 0; + } + + if( st->dec_glr ) + { + if( st->core == ACELP_CORE ) + { + st->dec_glr_idx = get_next_indice(st, G_LPC_RECOVERY_BITS); + } + else + { + st->dec_glr_idx = -1; + } + } + } + + /*--------------------------------------------------------------------------------* + * LPC PARAMETERS + *--------------------------------------------------------------------------------*/ + + /* Initialization of LPC Mid flag */ + if( (st->lpcQuantization == 1 && *coder_type == VOICED) || (st->use_partial_copy)) + { + (&(st->acelp_cfg))->midLpc = 0; + } + else + { + (&(st->acelp_cfg))->midLpc = st->acelp_cfg.midLpc_enable; + } + + if( st->use_partial_copy == 0 ) + { + /* Number of sets of LPC parameters (does not include mid-lpc) */ + if ( st->tcxonly==0 || st->core < TCX_10_CORE ) + { + st->numlpc = 1; + } + else + { + st->numlpc = 2; + } + + /* Decode LPC parameters */ + if( st->enableTcxLpc && st->core != ACELP_CORE ) + { + int 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 ); + } + else if( st->lpcQuantization == 1 ) + { + if(st->sr_core == 16000 && *coder_type == VOICED && st->core == ACELP_CORE) + { + lsf_bctcvq_decprm(st, param_lpc); + } + else + { + lsf_msvq_ma_decprm( st, param_lpc, st->core, *coder_type, st->acelp_cfg.midLpc, st->narrowBand, st->sr_core ); + } + } + else + { + assert(0); + } + } + } + else + { + st->numlpc = 1; + + if( st->rf_frame_type == RF_TCXFD ) + { + param_lpc[0] = 0; + param_lpc[1] = get_next_indice(st, lsf_numbits[0]); /* VQ 1 */ + param_lpc[2] = get_next_indice(st, lsf_numbits[1]); /* VQ 2 */ + param_lpc[3] = get_next_indice(st, lsf_numbits[2]); /* VQ 3 */ + } + else if( st->rf_frame_type >= RF_ALLPRED && st->rf_frame_type <= RF_NELP ) + { + /* LSF indices */ + param_lpc[0] = get_next_indice(st, 8); /* VQ 1 */ + param_lpc[1] = get_next_indice(st, 8); /* VQ 2 */ + } + } + + bits_common = st->next_bit_pos - start_bit_pos; + + /*--------------------------------------------------------------------------------* + * ACELP + *--------------------------------------------------------------------------------*/ + + if( st->core == ACELP_CORE && st->use_partial_copy == 0 ) + { + /* Target Bits */ + + /* needed in decoder to read the bitstream */ + acelp_target_bits = st->bits_frame_core - bits_common; + + /*Configure ACELP*/ + tmp = BITS_ALLOC_config_acelp( acelp_target_bits, *coder_type, &(st->acelp_cfg), st->narrowBand, st->nb_subfr ); + if( tmp < 0 ) + { + /* erroneous configuration, resulting from a corrupt bitstream */ + st->BER_detect = 1; + } + + + /* Adaptive BPF (2 bits)*/ + n = ACELP_BPF_BITS[st->acelp_cfg.bpf_mode]; + if( n!=0 ) + { + st->bpf_gain_param = get_next_indice(st, n); + } + else + { + st->bpf_gain_param=(st->acelp_cfg.bpf_mode)*2; + } + + /* Mean energy (2 or 3 bits) */ + n = ACELP_NRG_BITS[st->acelp_cfg.nrg_mode]; + if( n!=0 ) + { + prm[j++] = get_next_indice(st, n); + } + + /* Subframe parameters */ + for( sfr=0; sfracelp_cfg.ltp_mode][sfr]; + + if( n!=0 ) + { + prm[j] = get_next_indice(st, n); + j++; + } + + /* Adaptive codebook filtering (1 bit) */ + if( st->acelp_cfg.ltf_mode == 2 ) + { + prm[j] = get_next_indice(st, 1); + j++; + } + + /* Innovative codebook */ + { + /* Decode pulse positions. */ + j_old = j; + wordcnt = ACELP_FIXED_CDK_BITS(st->acelp_cfg.fixed_cdk_index[sfr])/16; + bitcnt = ACELP_FIXED_CDK_BITS(st->acelp_cfg.fixed_cdk_index[sfr]) & 15; + + /* sanity check - can happen in case of bit errors */ + if ((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; + st->BER_detect = 1; + } + + for (ix = 0; ix < wordcnt; ix++) + { + prm[j] = get_next_indice(st, 16); + j++; + } + + if( bitcnt ) + { + prm[j] = get_next_indice(st, bitcnt); + } + + j = j_old + 8; + } + + /* Gains (5b, 6b or 7b / subfr) */ + n = ACELP_GAINS_BITS[st->acelp_cfg.gains_mode[sfr]]; + prm[j++] = get_next_indice(st, n); + }/*end of subfr loop*/ + } + else if ( st->rf_frame_type >= RF_ALLPRED && st->use_partial_copy ) + { + tmp = 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 ( tmp < 0 ) + { + /* erroneous configuration, resulting from a corrupt bitstream */ + st->BER_detect = 1; + } + + /* rf_frame_type NELP: 7 */ + if(st->rf_frame_type == RF_NELP) + { + /* NELP gain indices */ + st->rf_indx_nelp_iG1 = get_next_indice( st, 5 ); + st->rf_indx_nelp_iG2[0] = get_next_indice( st, 6 ); + st->rf_indx_nelp_iG2[1] = get_next_indice( st, 6 ); + + /* NELP filter selection index */ + st->rf_indx_nelp_fid = get_next_indice( st, 2 ); + + /* tbe gainFr */ + st->rf_indx_tbeGainFr = get_next_indice( st, 5 ); + } + else + { + /* rf_frame_type ALL_PRED: 4, NO_PRED: 5, GEN_PRED: 6*/ + /* ES pred */ + prm[j++] = get_next_indice(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(st, n); + } + + + /*Innovative codebook*/ + if( (st->rf_frame_type == RF_NOPRED) + || ( st->rf_frame_type == RF_GENPRED && (sfr == 0 || 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(st, 7); + j = j + 8; + } + + /* Gains (5b, 6b or 7b / subfr) */ + if( sfr == 0 || sfr == 2) + { + n = ACELP_GAINS_BITS[gains_mode]; + prm[j++] = get_next_indice(st, n); + } + } + st->rf_indx_tbeGainFr = get_next_indice( st, 2 ); + } + } + + /*--------------------------------------------------------------------------------* + * TCX20 + *--------------------------------------------------------------------------------*/ + + if( st->core == TCX_20_CORE && st->use_partial_copy == 0 ) + { + flag_ctx_hm = 0; + + if( st->enablePlcWaveadjust ) + { + st->tonality_flag = get_next_indice(st, 1); + } + + /* TCX Gain = 7 bits */ + prm[j++] = get_next_indice(st, 7); + + /* TCX Noise Filling = NBITS_NOISE_FILL_LEVEL bits */ + prm[j++] = get_next_indice(st, NBITS_NOISE_FILL_LEVEL); + + /* LTP data */ + if ( st->tcxltp || st->sr_core > 25600 ) /* PLC pitch info for HB */ + { + + prm[j] = get_next_indice(st, 1); + if( prm[j] ) + { + prm[j+1] = get_next_indice(st, 9); + prm[j+2] = get_next_indice(st, 2); + } + 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; + st->tcx_hm_LtpPitchLag = ((!st->tcxonly) && (st->tcxltp_pitch_int < L_frame) + ? (((2 * st->L_frame * st->pit_res_max) << kLtpHmFractionalResolution) / (st->tcxltp_pitch_int * st->pit_res_max + st->tcxltp_pitch_fr)) + : -1); + } + + j += 3; + + /* TCX spectral data */ + lg = L_frame; + lgFB = st->tcx_cfg.tcx_coded_lines; + + if( st->last_core_bs == ACELP_CORE ) + { + /* ACE->TCX transition */ + lg += st->tcx_cfg.tcx_offset; + lgFB += lgFB >> 2; + + if( st->tcx_cfg.lfacNext < 0 ) + { + lg -= st->tcx_cfg.lfacNext; + } + } + + /* TNS data */ + nTnsParams = 0; + nTnsBits = 0; + + if( st->tcx_cfg.fIsTNSAllowed ) + { + SetTnsConfig(&st->tcx_cfg, 1, st->last_core_bs == ACELP_CORE); + + ReadTnsData(st->tcx_cfg.pCurrentTnsConfig, st, &nTnsBits, prm+j, &nTnsParams); + + j += nTnsParams; + } + + hm_size = (int)(2.0f*st->TcxBandwidth*(float)lg); + + if( st->tcx_lpc_shaped_ari && st->last_core_bs != ACELP_CORE) + { + dec_prm_hm(st, &prm[j], hm_size ); + } + + nbits_tcx = ( st->bits_frame_core - (st->next_bit_pos - start_bit_pos) ); + + /*Context HM flag*/ + if ( st->tcx_cfg.ctx_hm && (st->last_core_bs != ACELP_CORE) ) + { + prm[j] = get_next_indice(st, 1); + nbits_tcx--; + + if( prm[j] ) + { + int NumIndexBits = DecodeIndex( st, hm_size >= 256, prm+j+1 ); + + flag_ctx_hm=1; + + ConfigureContextHm( + lgFB, + nbits_tcx, + *(prm+j+1), + st->tcx_hm_LtpPitchLag, + &hm_cfg); + + nbits_tcx-=NumIndexBits; + } + } + j += NPRM_CTX_HM; + /* read IGF payload */ + if (st->igf) + { + n = st->next_bit_pos; + + IGFDecReadLevel( &st->hIGFDec, st, (st->last_core_bs == ACELP_CORE)? IGF_GRID_LB_TRAN: IGF_GRID_LB_NORM, 1 ); + + IGFDecReadData( &st->hIGFDec, st, (st->last_core_bs == ACELP_CORE)? IGF_GRID_LB_TRAN: IGF_GRID_LB_NORM, 1 ); + + nbits_tcx -= (st->next_bit_pos - n); + } + + nbits_tcx = ( st->bits_frame_core - (st->next_bit_pos - start_bit_pos) ); + if( st->tcx_lpc_shaped_ari ) + { + prm[j++] = nbits_tcx; /* store length of buffer */ + prms = &prm[j]; + for (ix = 0; ix < nbits_tcx; ix++) + { + prms[ix] = get_next_indice_1(st); + } + for (ix = 0; ix < 32; ix++) + { + prms[ix+nbits_tcx] = 1; + } + j += nbits_tcx; + } + else + { + + st->resQBits[0] = ACcontextMapping_decode2_no_mem_s17_LC( st, prm+j,lgFB, + nbits_tcx, NPRM_RESQ*st->tcx_cfg.resq, flag_ctx_hm ? &hm_cfg : NULL ); + j += lg; + } + } + if( st->rf_frame_type >= RF_TCXFD && st->rf_frame_type <= RF_TCXTD2 && st->use_partial_copy == 1 ) + { + /* classification */ + ind = get_next_indice(st, 2); + st->clas_dec = ONSET; + if( ind == 0 ) + { + st->clas_dec = UNVOICED_CLAS; + } + else if( ind == 1 ) + { + if( st->last_good >= VOICED_TRANSITION ) + { + st->clas_dec = VOICED_TRANSITION; + } + else + { + st->clas_dec = UNVOICED_TRANSITION; + } + } + else if( ind == 2 ) + { + st->clas_dec = VOICED_CLAS; + } + + if( st->rf_frame_type == RF_TCXFD ) + { + /* TCX Gain = 7 bits */ + st->old_gaintcx_bfi = get_next_indice(st, 7); + } + else + { + /* LTP data */ + if( st->tcxltp ) + { + if( st->rf_frame_type == RF_TCXTD2 || st->rf_frame_type == RF_TCXTD1 ) + { + prm_ltp[0] = 1; /* LTP active*/ + prm_ltp[1] = get_next_indice(st, 9); + prm_ltp[2] = 3; /* max ampl. quantizer output (2bits), anyway not used later*/ + + if(!st->prev_bfi) + { + 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; + } + } + } + } + } + + + /*--------------------------------------------------------------------------------* + * TCX10 + *--------------------------------------------------------------------------------*/ + + if( st->core == TCX_10_CORE ) + { + int tcxltp_prm_0 = 0; + int tcxltp_prm_1 = 0; + int tcxltp_prm_2 = 0; + int nbits_igf = 0; + /* read IGF payload */ + if (st->igf) + { + for (k = 0; k < 2; k++) + { + n = st->next_bit_pos; + + IGFDecReadLevel( &st->hIGFDec, st, IGF_GRID_LB_SHORT, k == 0 ? 1 : 0 ); + + IGFDecReadData( &st->hIGFDec, st, IGF_GRID_LB_SHORT, k == 0 ? 1 : 0 ); + + IGFDecStoreTCX10SubFrameData( &st->hIGFDec, k ); + + nbits_igf += st->next_bit_pos - n; + } + } + + for( k = 0; k < 2; k++ ) + { + flag_ctx_hm = 0; + + prm = param + (k*DEC_NPRM_DIV); + j = 0; + nbits_tcx = st->next_bit_pos - start_bit_pos; + + if(st->enablePlcWaveadjust && k) + { + st->tonality_flag = get_next_indice(st, 1); + } + /* TCX Gain = 7 bits */ + prm[j++] = get_next_indice(st, 7); + + /* TCX Noise Filling = NBITS_NOISE_FILL_LEVEL bits */ + prm[j++] = get_next_indice(st, NBITS_NOISE_FILL_LEVEL); + + /* LTP data */ + if( (k == 0) && ( st->tcxltp || (st->sr_core > 25600) ) ) /* PLC pitch info for HB */ + { + prm[j] = get_next_indice(st, 1); + + if( prm[j] ) + { + prm[j+1] = get_next_indice(st, 9); + prm[j+2] = get_next_indice(st, 2); + + tcxltp_prm_0 = prm[j]; + tcxltp_prm_1 = prm[j+1]; + tcxltp_prm_2 = prm[j+2]; + } + + 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; + st->tcx_hm_LtpPitchLag = -1; + j += 3; + } + else + { + prm[j++] = tcxltp_prm_0; + prm[j++] = tcxltp_prm_1; + prm[j++] = tcxltp_prm_2; + } + + + /* TCX spectral data */ + lgFB = st->tcx_cfg.tcx_coded_lines >> 1; + + if( k==0 && st->last_core_bs == ACELP_CORE ) + { + /* ACE->TCX transition */ + lgFB += lgFB >> 1; + } + + /* TNS data */ + nTnsParams = 0; + nTnsBits = 0; + + if( st->tcx_cfg.fIsTNSAllowed ) + { + if((st->last_core_bs == ACELP_CORE) && (k == 0)) + { + st->BER_detect = 1; + st->last_core = TCX_20_CORE; + st->last_core_bs = TCX_20_CORE; + } + SetTnsConfig(&st->tcx_cfg, 0, 0 /*(*last_core == ACELP_CORE) && (k == 0)*/); /* lcm : tnsConfig[0][1] does not exist !!! */ + + ReadTnsData(st->tcx_cfg.pCurrentTnsConfig, st, &nTnsBits, prm+j, &nTnsParams); + + j += nTnsParams; + } + + hm_size = (int)(2.0f*st->TcxBandwidth*(float)lgFB); + + /*compute target bits*/ + nbits_tcx = (( st->bits_frame_core - bits_common - nbits_igf + 1 - k) >> 1 ) - ( (st->next_bit_pos - start_bit_pos) - nbits_tcx); + + /*Context HM flag*/ + if( st->tcx_cfg.ctx_hm && !(st->last_core_bs == ACELP_CORE && k == 0) ) + { + prm[j] = get_next_indice(st, 1); + nbits_tcx--; + + if( prm[j] ) + { + /* Read PeriodicityIndex */ + int NumIndexBits = DecodeIndex( st, hm_size >= 256, prm+j+1 ); + + flag_ctx_hm = 1; + + ConfigureContextHm( + lgFB, + nbits_tcx, + *(prm+j+1), + -1, + &hm_cfg); + + nbits_tcx -= NumIndexBits; + } + } + j += NPRM_CTX_HM; + + st->resQBits[k] = ACcontextMapping_decode2_no_mem_s17_LC( st, prm+j, + lgFB, + nbits_tcx, NPRM_RESQ*st->tcx_cfg.resq, flag_ctx_hm ? &hm_cfg : NULL ); + j += lgFB; + + } /* k, window index */ + } + + + if(!st->use_partial_copy) + { + if (*total_nbbits-bitsRead[0] < (st->next_bit_pos - start_bit_pos)) + { + st->BER_detect = 1; + st->next_bit_pos = start_bit_pos + *total_nbbits - bitsRead[0]; + } + bitsRead[0] = st->next_bit_pos - start_bit_pos; + } + return; +} diff --git a/lib_dec/dec_tcx.c b/lib_dec/dec_tcx.c new file mode 100644 index 000000000..d816a8e3f --- /dev/null +++ b/lib_dec/dec_tcx.c @@ -0,0 +1,1337 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "prot.h" +#include "options.h" +#include "stat_com.h" +#include "cnst.h" + + +/*-----------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------*/ + +static void IMDCT( float *x, float *old_syn_overl, float *syn_Overl_TDAC, float *xn_buf, float *tcx_aldo_window_1_trunc, float *tcx_aldo_window_2, + float *tcx_mdct_window_half, float *tcx_mdct_window_minimum, float *tcx_mdct_window_trans, int tcx_mdct_window_half_length, + int tcx_mdct_window_min_length, int index, int left_rect, int tcx_offset, int overlap, int L_frame, int L_frameTCX, int L_spec_TCX5, + int L_frame_glob, + int frame_cnt, int bfi, float *old_out, short FB_flag, Decoder_State *st, int fullband, float *acelp_zir ); + +/*-----------------------------------------------------------------* + * decoder_tcx() + * + * + *-----------------------------------------------------------------*/ + +void decoder_tcx( + TCX_config *tcx_cfg, /* input: configuration of TCX */ + int prm[], /* input: parameters */ + float A[], /* input: coefficients NxAz[M+1] */ + Word16 Aind[], /* input: frame-independent coefficients Az[M+1] */ + int L_frame_glob, /* input: frame length */ + int L_frameTCX_glob, + int L_spec, + float synth[], /* in/out: synth[-M..L_frame] */ + float synthFB[], + Decoder_State *st, /* in/out: coder memory state */ + const short coder_type, /* input: coder type */ + int bfi, /* input: Bad frame indicator */ + int frame_cnt, /* input: frame counter in the super frame */ + float stab_fac /* input: stability of isf */ +) +{ + short i, index, L_frame, tcx_offset; + short L_frameTCX, tcx_offsetFB; + short firstLine; + float gain_tcx, fac_ns; + float Ap[M+2]; + float x[N_MAX]; + int overlap; + short overlapFB; + short noiseFillingSize; + short noiseTransWidth = MIN_NOISE_FILLING_HOLE; + int tnsSize = 0; /* number of tns parameters put into prm */ + int fUseTns = 0; /* flag that is set if TNS data is present */ + STnsData tnsData; + short left_rect; + float gainlpc2[FDNS_NPTS]; + float gamma1; + float gamma; + short nf_seed = 0; + float gainCompensate = 1.f; + float h1[L_FRAME_MAX/4+1]; + float mem[M]; + float tmp2; + int arith_bits, signaling_bits; + const int *prm_ltp, *prm_tns, *prm_hm, *prm_sqQ, *prm_target; + float xn_buf[L_MDCT_OVLP_MAX+L_FRAME_PLUS+L_MDCT_OVLP_MAX]; + float xn_bufFB[L_MDCT_OVLP_MAX+L_FRAME_PLUS+L_MDCT_OVLP_MAX]; + float acelp_zir[L_FRAME_MAX/2]; + int sum_word32; + short temp_concealment_method = 0; /* to avoid compilation warnings */ + int infoIGFStartLine; + int L_spec_con; + + prm_target = (const int *)NULL; /* just to suppress MSVC warnigs */ + + + /*-----------------------------------------------------------------* + * Initializations + *-----------------------------------------------------------------*/ + + /* Init lengths */ + overlap = tcx_cfg->tcx_mdct_window_length; + overlapFB = tcx_cfg->tcx_mdct_window_lengthFB; + tcx_offset = tcx_cfg->tcx_offset; + tcx_offsetFB = tcx_cfg->tcx_offsetFB; + L_spec_con = L_spec; + gamma1 = st->gamma; + + if (st->enableTcxLpc) + { + gamma1 = 1.0f; + } + + if( bfi ) + { + /* PLC: [TCX: Memory update] + * PLC: Init buffers */ + + assert(st->L_frame_past > 0); + L_frame = st->L_frame_past; + L_frameTCX = st->L_frameTCX_past; + + left_rect = st->prev_widow_left_rect; + + if( left_rect ) + { + tcx_offset = tcx_cfg->lfacNext; + tcx_offsetFB = tcx_cfg->lfacNextFB; + L_spec += st->tcx_cfg.tcx_coded_lines >> 2; + L_spec_con += st->tcx_cfg.tcx_coded_lines >> 2; + } + } + else + { + if ( frame_cnt == 0 && st->last_core == ACELP_CORE ) + { + if (!st->prev_bfi) + { + tcx_cfg->last_aldo = 0; + } + + /* if past frame is ACELP */ + L_frame = L_frame_glob + tcx_offset; + L_frameTCX = L_frameTCX_glob + tcx_offsetFB; + L_spec_con += st->tcx_cfg.tcx_coded_lines >> 2; + assert(tcx_cfg->lfacNext<=0); + L_frame -= tcx_cfg->lfacNext; + L_frameTCX -= tcx_cfg->lfacNextFB; + tcx_offset = tcx_cfg->lfacNext; + tcx_offsetFB = tcx_cfg->lfacNextFB; + + left_rect = 1; + st->prev_widow_left_rect = 1; + } + else + { + L_frame = L_frame_glob; + L_frameTCX = L_frameTCX_glob; + left_rect = 0; + st->prev_widow_left_rect = 0; + } + + if ( frame_cnt == 0 && (st->last_core_bs == ACELP_CORE) ) + { + L_spec += st->tcx_cfg.tcx_coded_lines >> 2; + } + + st->L_frame_past = L_frame; + st->L_frameTCX_past = L_frameTCX; + } + + if( (L_frame == st->L_frame >> 1) && (st->tcxonly) ) + { + IGFDecUpdateInfo( &st->hIGFDec, IGF_GRID_LB_SHORT ); + } + else + { + IGFDecUpdateInfo( &st->hIGFDec, (st->last_core == ACELP_CORE || (left_rect && st->bfi))? IGF_GRID_LB_TRAN: IGF_GRID_LB_NORM ); + } + + if( st->igf == 0 ) + { + if( st->narrowBand == 0 ) + { + /* minimum needed for output with sampling rates lower then the + nominal sampling rate */ + infoIGFStartLine = min(L_frameTCX, L_frame); + } + else + { + infoIGFStartLine = L_frameTCX; + } + } + else + { + infoIGFStartLine = min(st->hIGFDec.infoIGFStartLine,L_frameTCX); + } + + noiseFillingSize = L_spec; + if( st->igf ) + { + noiseFillingSize = st->hIGFDec.infoIGFStartLine; + } + + prm_ltp = &prm[1+NOISE_FILL_RANGES]; + prm_tns = prm_ltp + LTPSIZE; + + /*-----------------------------------------------------------* + * Read TCX parameters * + *-----------------------------------------------------------*/ + + index = 0; + + if( !bfi ) + { + index = prm[0]; + + /* read noise level (fac_ns) */ + st->noise_filling_index = prm[1]; + } + + fac_ns = (float)st->noise_filling_index * 0.75f / (1<fIsTNSAllowed ) + { + fUseTns = DecodeTnsData( tcx_cfg->pCurrentTnsConfig, prm_tns, &tnsSize, &tnsData ); + } + else + { + fUseTns = 0; + } + + prm_hm = prm_tns + tnsSize; + prm_sqQ = prm_hm + NPRM_CTX_HM; + + /*-----------------------------------------------------------* + * Spectrum data * + *-----------------------------------------------------------*/ + + if( !bfi) + { + /*-----------------------------------------------------------* + * Context HM * + *-----------------------------------------------------------*/ + + if(tcx_cfg->ctx_hm && ( (st->last_core_bs != ACELP_CORE) || (frame_cnt > 0) ) ) + { + st->last_ctx_hm_enabled = prm_hm[0]; + { + for (i = 0; i < L_spec; i++) + { + /* no context harmonic model, copy MDCT coefficients to x */ + x[i] = (float)prm_sqQ[i]; + } + } + } + else /* tcx_cfg->ctx_hm == 0 */ + { + if( st->tcx_lpc_shaped_ari ) /* low rates: envelope based arithmetic coder */ + { + prm_target = prm_sqQ; + prm_sqQ = prm_target + 1; + + tcx_arith_decode_envelope( x, L_frame, L_spec, st, coder_type, Aind, st->tcxltp_gain, *prm_target, prm_sqQ, st->last_core_bs != ACELP_CORE, + prm_hm, /* HM parameter area */ st->tcx_hm_LtpPitchLag, &arith_bits, &signaling_bits ,(st->bwidth > WB)? 1: 0 ); + + st->resQBits[frame_cnt] = *prm_target - arith_bits; + + /* Noise filling seed */ + for (i=0; ictx_hm */ + + for( i=L_spec ; i < L_spec_con; i++ ) + { + x[i] = 0.0f; + } + + for( i=L_spec ; i < max(L_frame, L_frameTCX); i++ ) + { + x[i] = 0.0f; + } + + /*-----------------------------------------------------------* + * adaptive low frequency deemphasis. * + *-----------------------------------------------------------*/ + + weight_a( A, Ap, gamma1, M ); + lpc2mdct( Ap, M, gainlpc2 ); + + /* initialize LF deemphasis factors in xn_buf */ + for( i = 0; i < max(L_spec, L_frameTCX); i++ ) + { + xn_buf[i] = 1.0f; + } + + if( !st->tcxonly ) + { + AdaptLowFreqDeemph( x, st->tcx_lpc_shaped_ari, gainlpc2, L_frame, xn_buf /* LF deemphasis factors */ ); + } + } + + st->damping = 0.f; + + if( bfi == 0 ) + { + /*-----------------------------------------------------------* + * Compute global gain * + *-----------------------------------------------------------*/ + + gain_tcx = (float)pow(10.0f, index/28.0f) * (float)sqrt((float)NORM_MDCT_FACTOR / (float)L_spec); + + st->old_gaintcx_bfi = gain_tcx; + + st->cummulative_damping_tcx = 1.0f; + } + else /* bfi = 1 */ + { + /* PLC: [TCX: Fade-out] + * derivation of damping factor */ + if( st->use_partial_copy ) + { + if( st->rf_frame_type == RF_TCXFD ) + { + gain_tcx = (float)pow(10.0f, (int)st->old_gaintcx_bfi/28.0f) * (float)sqrt((float)NORM_MDCT_FACTOR / (float)L_spec); + st->old_gaintcx_bfi = gain_tcx; + } + else + { + gain_tcx = st->old_gaintcx_bfi; + } + + st->damping = 1; + } + else + { + gain_tcx = st->old_gaintcx_bfi; + st->damping = Damping_fact( coder_type, st->nbLostCmpt, st->last_good, stab_fac, &(st->lp_gainp), st->last_core ); + } + + st->cummulative_damping_tcx *= st->damping; + } + + if( bfi ) + { + if( bfi && st->envWeighted ) + { + gamma = st->gamma; + } + else + { + gamma = gamma1; + } + + /* PLC: [TCX: Fade-out] + * PLC: invert LPC weighting in case of PLC */ + if( bfi ) + { + if (st->enableTcxLpc) + { + gamma = st->cummulative_damping_tcx * (st->gamma - 1) + 1; + } + else + { + gamma = st->cummulative_damping_tcx * (gamma1 - 1) + 1; + } + } + + weight_a( A, Ap, gamma, M ); + lpc2mdct( Ap, M, gainlpc2 ); + } + + tmp2 = 0; + set_zero( h1, L_SUBFR+1 ); + set_zero( mem, M ); + h1[0] = 1.0f; + syn_filt( Ap, M,h1, h1, L_SUBFR, mem, 0 ); /* impulse response of LPC */ + deemph( h1, st->preemph_fac, L_SUBFR, &tmp2 ); /* impulse response of deemph */ + + /* impulse response level = gain introduced by synthesis+deemphasis */ + if( !bfi ) + { + st->last_gain_syn_deemph = (float)sqrt(dotp( h1, h1, L_SUBFR) ); + /*for avoiding compiler warnings*/ + st->gainHelper = 1.f; + st->stepCompensate=0.f; + } + else if (TCX_20_CORE == st->core || 1 == frame_cnt ) + { + gainCompensate = st->last_gain_syn_deemph/(float)sqrt(dotp( h1, h1, L_SUBFR) ); + if (st->nbLostCmpt==1) + { + st->stepCompensate = (1.f - gainCompensate)/st->L_frame; + st->gainHelper = 1.f; + } + else + { + st->stepCompensate = (st->last_concealed_gain_syn_deemph - gainCompensate)/st->L_frame; + st->gainHelper = st->last_concealed_gain_syn_deemph; + } + st->last_concealed_gain_syn_deemph = gainCompensate; + } + + /*-----------------------------------------------------------* + * Residual inv. Q. * + *-----------------------------------------------------------*/ + + if (!bfi && tcx_cfg->resq ) + { + if( st->tcx_lpc_shaped_ari ) + { + /* envelope based arithmetic coder */ + const int *prm_resq; + prm_resq = prm_sqQ + *prm_target /* = targetBits */ - st->resQBits[frame_cnt]; + i = tcx_ari_res_invQ_spec( x, L_spec, prm_resq, st->resQBits[frame_cnt], 0, tcx_cfg->sq_rounding, xn_buf /* LF deemphasis factors */ ); + } + else + { + /* context based arithmetic coder */ + i = tcx_res_invQ_gain(&gain_tcx, &prm_sqQ[L_spec], st->resQBits[frame_cnt] ); + tcx_res_invQ_spec( x, L_spec, &prm_sqQ[L_spec], st->resQBits[frame_cnt], i, tcx_cfg->sq_rounding, st->tcxonly ? NULL : xn_buf /* LF deemphasis factors */ ); + } + } + + if( !bfi && st->tcxonly ) + { + if( st->tcxltp && (st->tcxltp_gain > 0.0f) && !fUseTns ) + { + PsychAdaptLowFreqDeemph(x, gainlpc2, NULL); + } + } + + if( !bfi && !st->tcxonly ) + { + /* Replication of ACELP formant enhancement for low rates */ + if (st->bits_frame < 256) + { + tcxFormantEnhancement( xn_buf, gainlpc2, x, L_frame ); + } + } + + /*-----------------------------------------------------------* + * Add gain to the lpc gains * + *-----------------------------------------------------------*/ + + if( st->VAD == 0 ) + { + gain_tcx *= tcx_cfg->na_scale; + } + + v_multc( gainlpc2, gain_tcx, gainlpc2, FDNS_NPTS); + + + /*-----------------------------------------------------------* + * Noise filling. * + *-----------------------------------------------------------*/ + + if( !bfi && (fac_ns > 0.0f) ) + { + float noiseTiltFactor; + + firstLine = tcxGetNoiseFillingTilt( A, L_frame, (st->bits_frame >= 256 && !st->rf_flag), &noiseTiltFactor ); + + if( st->tcxonly ) + { + noiseTransWidth = HOLE_SIZE_FROM_LTP(max(st->tcxltp_gain,(tcx_cfg->ctx_hm && st->last_core != 0) ? 0.3125f*st->last_ctx_hm_enabled : 0)); + + if (L_frame == st->L_frame >> 1) + { + noiseTransWidth = 3; /* minimum transition fading for noise filling in TCX-10 */ + } + } + + if (!st->tcx_lpc_shaped_ari) + { + /* context based arithmetic coder */ + /* noise filling seed */ + for (i = 0; i < L_spec; i++) + { + nf_seed += (short)(abs(prm_sqQ[i]) * i * 2); + } + } + + + tcx_noise_filling( x, nf_seed, firstLine, noiseFillingSize, noiseTransWidth, + L_frame, noiseTiltFactor, fac_ns, (st->igf)? st->hIGFDec.infoTCXNoise: NULL ); + st->seed_tcx_plc = nf_seed; + } + + if( st->enablePlcWaveadjust ) + { + if( bfi ) + { + if( st->nbLostCmpt == 1 ) + { + st->plcInfo.concealment_method = TCX_NONTONAL; + /* tonal/non-tonal decision */ + if (st->plcInfo.Transient[0] == 1 && st->plcInfo.Transient[1] == 1 && st->plcInfo.Transient[2] == 1) + { + sum_word32 = 0; + + for (i = 9; i >= 0; i--) + { + sum_word32 += st->plcInfo.TCX_Tonality[i]; + } + + if (sum_word32 >= 6) + { + st->plcInfo.concealment_method = TCX_TONAL; + } + } + + if (st->tonal_mdct_plc_active) + { + st->plcInfo.concealment_method = TCX_TONAL; + } + } + + if (L_frameTCX > st->L_frameTCX ) + { + st->plcInfo.concealment_method = TCX_TONAL; + } + + temp_concealment_method = st->plcInfo.concealment_method; + + if (st->core == TCX_10_CORE) + { + temp_concealment_method = TCX_TONAL; + } + } + + /* get the starting location of the subframe in the frame */ + if (st->core == TCX_10_CORE) + { + st->plcInfo.subframe = frame_cnt*L_frameTCX_glob; + } + } + + /* PLC: [TCX: Tonal Concealment] */ + /* PLC: [TCX: Fade-out] + * PLC: Fade out to white noise */ + if( !bfi ) + { + TonalMDCTConceal_SaveFreqSignal( &st->tonalMDCTconceal, x, L_frameTCX, L_frame, gainlpc2 ); + } + else + { + if( !st->enablePlcWaveadjust || (temp_concealment_method == TCX_TONAL)) + { + /* set f to 1 to not fade out */ + /* set f to 0 to immediately switch to white noise */ + float f; + float noiseTiltFactor; + + if (st->tcxonly) + { + f = 1.0f; + } + else + { + f = st->cummulative_damping_tcx; + } + + if( (frame_cnt == 0) && (L_frameTCX == st->L_frameTCX >> 1) + && (st->tcxonly) && (!st->tonal_mdct_plc_active) && (st->nbLostCmpt == 1) + && (tcx_cfg->tcx_last_overlap_mode != FULL_OVERLAP) + && (tcx_cfg->tcx_curr_overlap_mode != FULL_OVERLAP) ) + { + float E_2ndlast, E_last; + + E_2ndlast = E_last = EPSILON; + for( i=0; itonalMDCTconceal.lastBlockData.spectralData[i] *st->tonalMDCTconceal.lastBlockData.spectralData[i]; + E_last += st->tonalMDCTconceal.lastBlockData.spectralData[i+1]*st->tonalMDCTconceal.lastBlockData.spectralData[i+1]; + } + tmp2 = E_2ndlast/E_last; + + /* replace higher energy TCX5 frame by lower one to avoid energy fluctuation */ + if( tmp2 > 2 ) + { + for( i=0; itonalMDCTconceal.lastBlockData.spectralData[i] = st->tonalMDCTconceal.lastBlockData.spectralData[i+1]; + } + } + else if( tmp2 < 0.5 ) + { + for( i=0; itonalMDCTconceal.lastBlockData.spectralData[i+1] = st->tonalMDCTconceal.lastBlockData.spectralData[i]; + } + } + } + + noiseTiltFactor = 1.0f; + + tcxGetNoiseFillingTilt( A, L_frame, (st->bits_frame >= 256 && !st->rf_flag), &noiseTiltFactor ); + + TonalMDCTConceal_InsertNoise( &st->tonalMDCTconceal, x, st->tonal_mdct_plc_active, + &st->seed_tcx_plc, noiseTiltFactor, f, infoIGFStartLine ); + + } + } + + if( L_spec < L_frame ) + { + set_zero( x+L_spec, L_frame-L_spec ); + } + else if( L_spec > L_frameTCX ) + { + set_zero( x+L_frameTCX, L_spec-L_frameTCX ); + } + + if( bfi && (!st->enablePlcWaveadjust || (temp_concealment_method == TCX_TONAL)) + && st->igf && (frame_cnt == 0) && (L_frameTCX == st->L_frameTCX >> 1) + && (st->tcxonly) && (!st->tonal_mdct_plc_active) && (st->nbLostCmpt == 1) + && (tcx_cfg->tcx_last_overlap_mode != FULL_OVERLAP) + && (tcx_cfg->tcx_curr_overlap_mode != FULL_OVERLAP) ) + { + IGFDecCopyLPCFlatSpectrum( &st->hIGFDec, x, IGF_GRID_LB_SHORT ); + mvi2i(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) * + *-----------------------------------------------------------*/ + + if( st->igf && ! bfi ) + { + if ((L_frame == st->L_frame >> 1) && (st->tcxonly)) + { + IGFDecCopyLPCFlatSpectrum( &st->hIGFDec, x, IGF_GRID_LB_SHORT ); + } + else + { + IGFDecCopyLPCFlatSpectrum( &st->hIGFDec, x, (st->last_core == ACELP_CORE)? IGF_GRID_LB_TRAN: IGF_GRID_LB_NORM ); + } + } + /* LPC gains already available */ + + if( !st->enablePlcWaveadjust || !bfi || (temp_concealment_method == TCX_TONAL) ) + { + mdct_noiseShaping( x, L_frame, gainlpc2 ); + + if( !bfi ) + { + v_multc( x+L_frame, gainlpc2[FDNS_NPTS-1], x+L_frame, L_spec-L_frame ); + } + + set_zero( x+L_spec, L_frameTCX-L_spec ); + } + + /* PLC: [TCX: Tonal Concealment] */ + if( bfi && st->tonal_mdct_plc_active ) + { + TonalMDCTConceal_Apply( &st->tonalMDCTconceal, x ); + } + + TonalMDCTConceal_UpdateState( &st->tonalMDCTconceal, L_frameTCX, (st->tcxltp_last_gain_unmodified > 0) ? st->old_fpitch : 0, + bfi, bfi && st->tonal_mdct_plc_active ); + + + if( st->enablePlcWaveadjust ) + { + int core; + core = st->core; + + /* spectrum concealment */ + if (bfi && temp_concealment_method == TCX_NONTONAL) + { + concealment_decode( core, x, &st->plcInfo ); + } + + /* update spectrum buffer, tonality flag, etc. */ + concealment_update( bfi, core, st->tonality_flag, x, &st->plcInfo ); + } + + /*-----------------------------------------------------------* + * IGF * + *-----------------------------------------------------------*/ + + if (st->igf && !((L_frame == st->L_frame >> 1) && (st->tcxonly))) + { + /* copy low spectrum to IGF des buffer */ + st->hIGFDec.igfData.igfInfo.nfSeed = (short)(nf_seed * 31821L + 13849L); + + IGFDecApplyMono( &st->hIGFDec, x, (st->last_core == ACELP_CORE || (left_rect && bfi))? IGF_GRID_LB_TRAN: IGF_GRID_LB_NORM, bfi ); + + /* IGF Decoder - All */ + } + + if (st->igf && ((L_frame == st->L_frame >> 1) && (st->tcxonly))) + { + /* copy low spectrum to IGF des buffer */ + st->hIGFDec.igfData.igfInfo.nfSeed = (short)(nf_seed * 31821L + 13849L); + + IGFDecApplyMono( &st->hIGFDec, x, IGF_GRID_LB_SHORT, bfi ); + + /* IGF Decoder - All */ + } + + index = tcx_cfg->tcx_last_overlap_mode; /* backup last TCX overlap mode */ + + if( st->igf ) + { + int proc = st->hIGFDec.flatteningTrigger; + if( proc && fUseTns != 0 ) + { + proc = 0; + } + + if( proc ) + { + short int startLine = st->hIGFDec.infoIGFStartLine; + short int endLine = st->hIGFDec.infoIGFStopLine; + float x_itf[N_MAX_TCX-IGF_START_MN]; + int j; + + const int* chk_sparse = st->hIGFDec.flag_sparse; + const float* virtualSpec = st->hIGFDec.virtualSpec; + + const int maxOrder = 8; + int curr_order = 0; + float A_itf[ITF_MAX_FILTER_ORDER+1]; + float predictionGain = 0; + + for (j = startLine; j < endLine; j++) + { + if( chk_sparse[j-IGF_START_MN] == 2 ) + { + x_itf[j-IGF_START_MN] = x[j]; + x[j] = virtualSpec[j-IGF_START_MN]; + } + } + + ITF_Detect( x+IGF_START_MN, startLine, endLine, maxOrder, A_itf, &predictionGain, &curr_order ); + + ITF_Apply(x, startLine, endLine, A_itf, curr_order); + + for (j = startLine; j < endLine; j++) + { + if( chk_sparse[j-IGF_START_MN] == 2 ) + { + x[j] = x_itf[j-IGF_START_MN]; + } + } + } + else + { + + } + } + + if( (L_frame == st->L_frame >> 1) && st->tcxonly ) + { + int L = L_frameTCX; + if( (tcx_cfg->fIsTNSAllowed && fUseTns != 0 && bfi!= 1) || (L_spec > L_frameTCX) ) + { + L = L_spec; + } + tcxInvertWindowGrouping( tcx_cfg, xn_buf, x, L, fUseTns, st->last_core, index, frame_cnt, bfi ); + } + + /*-----------------------------------------------------------* + * Temporal Noise Shaping Synthesis * + *-----------------------------------------------------------*/ + if( tcx_cfg->fIsTNSAllowed && fUseTns != 0 && bfi!= 1 ) + { + /* Apply TNS to get the reconstructed signal */ + + SetTnsConfig(tcx_cfg, L_frame_glob == st->L_frame, (st->last_core == ACELP_CORE) && (frame_cnt == 0)); + + ApplyTnsFilter(tcx_cfg->pCurrentTnsConfig, &tnsData, x, 0); + + if ((L_frame == st->L_frame >> 1) && (st->tcxonly)) + { + if ((tcx_cfg->tcx_last_overlap_mode != FULL_OVERLAP) || + ((tcx_cfg->tcx_curr_overlap_mode == FULL_OVERLAP) && (frame_cnt == 0) && (index == 0)) ) + { + const int L_win = tcx_cfg->tnsConfig[0][0].iFilterBorders[0] >> 1; + /* undo rearrangement of LF sub-window lines for TNS synthesis filtering */ + if (L_frameTCX > 2*L_win) + { + const int L_win2 = L_frameTCX >> 1; + mvr2r( x + L_win + 8, x + L_win2 + 8, L_win - 8 ); + mvr2r( x + 8, x + L_win2, 8 ); + mvr2r( x + 16, x + 8, L_win - 8 ); + set_zero( x + L_win, L_win2 - L_win ); + set_zero( x + L_win2 + L_win, L_win2 - L_win ); + } + else + { + mvr2r(x+8, xn_buf, L_win ); + mvr2r( xn_buf, x+L_win, 8 ); + mvr2r( xn_buf+8, x+8, L_win-8 ); + } + + } + } + } + + + /*-----------------------------------------------------------* + * Prepare OLA buffer after waveadjustment. * + * Compute inverse MDCT of x[]. * + *-----------------------------------------------------------*/ + + mvr2r( x, xn_bufFB, max(L_spec, max(L_frame, L_frameTCX)) ); + + if( st->igf ) + { + set_zero(xn_bufFB+st->hIGFDec.infoIGFStartLine, L_frameTCX-st->hIGFDec.infoIGFStartLine); + } + + IMDCT( xn_bufFB, + st->syn_Overl, + st->syn_Overl_TDAC, + xn_buf, + tcx_cfg->tcx_aldo_window_1_trunc, + tcx_cfg->tcx_aldo_window_2, + tcx_cfg->tcx_mdct_window_half, + tcx_cfg->tcx_mdct_window_minimum, + tcx_cfg->tcx_mdct_window_trans, + tcx_cfg->tcx_mdct_window_half_length, + tcx_cfg->tcx_mdct_window_min_length, + index, + left_rect, + tcx_offset, + overlap, + L_frame, + L_frameTCX, + max(L_frameTCX, L_spec) >> 1, + L_frame_glob, + frame_cnt, + bfi, + st->old_outLB, + 0, + st, + 0, + acelp_zir ); + + /* Generate additional comfort noise to mask potential coding artefacts */ + if( st->flag_cna) + { + generate_masking_noise_mdct(x, st->hFdCngDec->hFdCngCom); + } + + IMDCT( x, + st->syn_OverlFB, + st->syn_Overl_TDACFB, + xn_bufFB, + 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, + max(L_frameTCX, L_spec) >> 1, + L_frameTCX_glob, + frame_cnt, + bfi, + st->old_out, + 1, + st, + 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 = tcx_cfg->fIsTNSAllowed & fUseTns; + st->tcxltp_third_last_pitch = st->tcxltp_second_last_pitch; + st->tcxltp_second_last_pitch = st->old_fpitch; + st->old_fpitch = st->tcxltp_pitch_int + st->tcxltp_pitch_fr/(float)st->pit_res_max; + st->old_fpitchFB = st->old_fpitch * (float)L_frameTCX / (float)L_frame; + } + + /* Update old_syn_overl */ + if (!tcx_cfg->last_aldo) + { + mvr2r(xn_buf+L_frame, st->syn_Overl, overlap); + mvr2r(xn_bufFB+L_frameTCX, st->syn_OverlFB, overlapFB); + } + + /* Output */ + mvr2r( xn_buf+(overlap>>1)-tcx_offset, synth, L_frame_glob ); + mvr2r( xn_bufFB+(overlapFB>>1)-tcx_offsetFB, synthFB, L_frameTCX_glob ); + + return; +} + + +/*-------------------------------------------------------------------* + * decoder_tcx_post() + * + * + *-------------------------------------------------------------------*/ + +void decoder_tcx_post( + Decoder_State *st, + float *synth, + float *synthFB, + float *A, + int bfi +) +{ + int i; + float level_syn, gainCNG = 0.0f, step; + float xn_buf[L_FRAME_MAX]; + + /* TCX output */ + mvr2r( synth, xn_buf, st->L_frame ); + + /* first TCX frame after ACELP; overwrite ltp initialization done during acelp PLC */ + if( !bfi && st->prev_bfi && !st->last_core ) + { + st->tcxltp_last_gain_unmodified = 0.0f; + } + + if (bfi && !st->use_partial_copy) + { + /* run lpc gain compensation not for waveform adjustment */ + if (!st->enablePlcWaveadjust || st->plcInfo.concealment_method == TCX_TONAL ) + { + float gainHelperFB = st->gainHelper; + float stepCompensateFB = st->stepCompensate * st->L_frame / st->L_frameTCX; + + for( i=0; i < st->L_frameTCX; i++ ) + { + synthFB[i] *= gainHelperFB; + gainHelperFB -= stepCompensateFB; + } + } + + for( i=0; i < st->L_frame; i++ ) + { + xn_buf[i] *= st->gainHelper; + st->gainHelper -= st->stepCompensate; + } + } + + /* PLC: [TCX: Fade-out] + * PLC: estimate and update CNG energy */ + level_syn = (float)sqrt(( dotp(synthFB, synthFB, st->L_frameTCX)) / st->L_frameTCX); + + + /* PLC: [TCX: Fade-out] + * PLC: update or retrieve the background level */ + if( bfi == 0 && st->tcxonly && st->clas_dec == UNVOICED_CLAS ) + { + minimumStatistics( st->NoiseLevelMemory_bfi, &st->NoiseLevelIndex_bfi, &st->CurrLevelIndex_bfi, &st->CngLevelBackgroundTrace_bfi, + &st->LastFrameLevel_bfi, level_syn, PLC_MIN_CNG_LEV, PLC_MIN_STAT_BUFF_SIZE); + } + + /* PLC: [TCX: Fade-out] + * PLC: fade-out in time domain */ + if( bfi ) + { + float conceal_eof_gainFB; + + if( st->tcxonly ) + { + gainCNG = st->CngLevelBackgroundTrace_bfi/(level_syn+0.01f); + } + else + { + gainCNG = st->cngTDLevel/(level_syn+0.01f); + } + if( st->nbLostCmpt == 1 ) + { + st->conceal_eof_gain = 1.0f; + } + + step = (st->conceal_eof_gain - ( st->conceal_eof_gain * st->damping + gainCNG * (1 - st->damping) )) / st->L_frame; + { + float stepFB = step * st->L_frame / st->L_frameTCX; + conceal_eof_gainFB = st->conceal_eof_gain; + + for( i=0; i < st->L_frameTCX; i++ ) + { + synthFB[i] *= conceal_eof_gainFB; + conceal_eof_gainFB -= stepFB; + } + } + + for( i=0; i < st->L_frame; i++ ) + { + xn_buf[i] *= st->conceal_eof_gain; + st->conceal_eof_gain -= step; + } + + /* run lpc gain compensation not for waveform adjustment */ + if( (!st->enablePlcWaveadjust || st->plcInfo.concealment_method == TCX_TONAL ) && !st->use_partial_copy ) + { + st->plcInfo.recovery_gain = conceal_eof_gainFB * st->last_concealed_gain_syn_deemph; + } + else + { + st->plcInfo.recovery_gain = conceal_eof_gainFB; + } + st->plcInfo.step_concealgain = step * st->L_frame / st->L_frameTCX; + } + + + /*-----------------------------------------------------------* + * Memory update * + *-----------------------------------------------------------*/ + + /* Update synth, exc and old_Aq */ + tcx_decoder_memory_update( xn_buf, synth, st->L_frame, A, st, st->syn ); + + /* PLC: [TCX: Memory update] */ + st->old_pitch_buf[0] = st->old_pitch_buf[st->nb_subfr]; + st->old_pitch_buf[1] = st->old_pitch_buf[st->nb_subfr+1]; + mvr2r( &st->old_pitch_buf[st->nb_subfr+2], &st->old_pitch_buf[2], st->nb_subfr ); + set_f( &st->old_pitch_buf[st->nb_subfr+2], st->old_fpitch, st->nb_subfr ); + st->bfi_pitch = st->old_fpitch; + st->bfi_pitch_frame = st->L_frame; + + st->mem_pitch_gain[2*st->nb_subfr+1] = st->mem_pitch_gain[st->nb_subfr+1]; + st->mem_pitch_gain[2*st->nb_subfr] = st->mem_pitch_gain[st->nb_subfr]; + + for( i = 0; i < st->nb_subfr; i++ ) + { + st->mem_pitch_gain[2*st->nb_subfr-1 - i] = st->mem_pitch_gain[st->nb_subfr-1 - i]; + st->mem_pitch_gain[st->nb_subfr-1 - i] = st->tcxltp_last_gain_unmodified; + } + + return; +} + +/*-------------------------------------------------------------------* + * IMDCT() + * + * + *-------------------------------------------------------------------*/ + +static void IMDCT( + float *x, + float *old_syn_overl, + float *syn_Overl_TDAC, + float *xn_buf, + float *tcx_aldo_window_1_trunc, + float *tcx_aldo_window_2, + float *tcx_mdct_window_half, + float *tcx_mdct_window_minimum, + float *tcx_mdct_window_trans, + int tcx_mdct_window_half_length, + int tcx_mdct_window_min_length, + int index, + int left_rect, + int tcx_offset, + int overlap, + int L_frame, + int L_frameTCX, + int L_spec_TCX5, + int L_frame_glob, + int frame_cnt, + int bfi, + float *old_out, + short FB_flag, + Decoder_State *st, + int fullbandScale, + float *acelp_zir +) +{ + short i, nz, aldo; + TCX_config *tcx_cfg = &st->tcx_cfg; + + aldo = 0; + + /* number of zero for ALDO windows*/ + nz = NS2SA(st->output_Fs, N_ZERO_MDCT_NS)*L_frame/L_frameTCX; + + if( (L_frameTCX == st->L_frameTCX >> 1) && (st->tcxonly) ) + { + /* 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 + */ + + if( (!bfi && tcx_cfg->tcx_last_overlap_mode != FULL_OVERLAP) || (bfi && (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 */ + float win[(L_FRAME_PLUS+L_MDCT_OVLP_MAX)/2]; + const int L_win = L_frame >> 1; + const int L_ola = (tcx_cfg->tcx_last_overlap_mode == MIN_OVERLAP) ? tcx_mdct_window_min_length : tcx_mdct_window_half_length; + int w; + + set_f( win, 0, (L_FRAME_PLUS+L_MDCT_OVLP_MAX)/2 ); + set_zero(xn_buf, tcx_offset+(L_ola>>1)); /* zero left end of buffer */ + + for (w = 0; w < 2; w++) + { + TCX_MDCT_Inverse(x+w*L_spec_TCX5, win, L_ola, 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, + (w > 0) ? 0 : left_rect, (w > 0) || (w == 0 && index == 2) ? MIN_OVERLAP : tcx_cfg->tcx_last_overlap_mode, + acelp_zir, st->old_syn_Overl, syn_Overl_TDAC, st->old_Aq_12_8, tcx_mdct_window_trans, L_win, tcx_offset<0?-tcx_offset: 0, + (w > 0) || (frame_cnt > 0) ? 1 : st->last_core_bfi, (w > 0) || (frame_cnt > 0) ? 0 : st->last_is_cng, fullbandScale ); + + if( w > 0 ) + { + tcx_windowing_synthesis_past_frame( xn_buf+tcx_offset-(L_ola>>1)+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 */ + v_add( win, xn_buf+tcx_offset-(L_ola>>1)+w*L_win, xn_buf+tcx_offset-(L_ola>>1)+w*L_win, L_ola ); + + /* copy new sub-window region not overlapping with previous window */ + mvr2r( win+L_ola, xn_buf+tcx_offset+(L_ola>>1)+w*L_win, L_win ); + } + + /* To assure that no garbage values are passed to overlap */ + set_zero( xn_buf+L_frame+tcx_offset+(L_ola>>1), overlap-tcx_offset-(L_ola>>1) ); + } + else if (!bfi && (frame_cnt == 0) && (tcx_cfg->tcx_curr_overlap_mode == FULL_OVERLAP)) + { + /* special overlap attempt, two transforms, grouping into one window */ + float win[(L_FRAME_PLUS+L_MDCT_OVLP_MAX)/2]; + const int L_win = L_frame >> 1; + const int L_ola = tcx_mdct_window_min_length; + int w; + + set_f( 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, win+L_win, 0, L_win-(L_ola>>1), L_ola); + + set_zero(xn_buf, (overlap>>1)); + + /* copy new sub-window region not overlapping with previous window */ + mvr2r(win+L_win, xn_buf+(overlap>>1), L_win+(L_ola>>1)); + + /* 2nd TCX-5 window, regular MDCT with minimum overlap on both sides */ + TCX_MDCT_Inverse(x+L_spec_TCX5, win, L_ola, 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, tcx_mdct_window_trans, L_win, + tcx_offset<0?-tcx_offset: 0, + 1, /* st->last_mode_bfi */ 0, /* st->last_is_cng */ fullbandScale ); + + tcx_windowing_synthesis_past_frame( xn_buf+(overlap>>1)+L_win-(L_ola>>1), 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, 2 ); + + /* add part of current sub-window overlapping with previous window */ + v_add(win, xn_buf+(overlap>>1)+L_win-(L_ola>>1), xn_buf+(overlap>>1)+L_win-(L_ola>>1), L_ola); + + /* copy new sub-window region not overlapping with previous window */ + mvr2r(win+L_ola, xn_buf+(overlap>>1)+L_win+(L_ola>>1), L_win); + + /* extra folding-out on left side of win, for perfect reconstruction */ + for (w = (overlap>>1); w < overlap; w++) + { + xn_buf[overlap-1-w] = -1.0f * xn_buf[w]; + } + + 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, + tcx_mdct_window_trans, 2*L_win, tcx_offset<0?-tcx_offset: 0, + st->last_core_bfi, st->last_is_cng, fullbandScale ); + } + else + { + /* default, i.e. maximum overlap, single transform, no grouping */ + + TCX_MDCT_Inverse(x, xn_buf, overlap, L_frame-overlap, overlap); + + 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, !bfi && (frame_cnt > 0) && (index == 0) && ( st->last_core != ACELP_CORE) ? MIN_OVERLAP : index, + acelp_zir, st->old_syn_Overl, syn_Overl_TDAC, st->old_Aq_12_8, tcx_mdct_window_trans, L_frame_glob >> 1, + tcx_offset<0?-tcx_offset: 0, + (frame_cnt > 0 /*|| (st->last_con_tcx )*/) ? 1 : st->last_core_bfi, (frame_cnt > 0) ? 0 : st->last_is_cng, fullbandScale ); + + } /* tcx_last_overlap_mode != FULL_OVERLAP */ + } + else + { + /* frame is TCX-20 or not TCX-only */ + assert(frame_cnt == 0); + if (st->tcx_cfg.tcx_last_overlap_mode != TRANSITION_OVERLAP) + { + float tmp[L_FRAME_PLUS]; + + edct(x, xn_buf+overlap/2+nz, L_frame); + v_multc( xn_buf+overlap/2+nz, (float)sqrt((float)L_frame / NORM_MDCT_FACTOR), tmp, L_frame); + window_ola( tmp, xn_buf, old_out, L_frame, tcx_cfg->tcx_last_overlap_mode, tcx_cfg->tcx_curr_overlap_mode, 0, 0, NULL ); + aldo = 1; + + } + else + { + TCX_MDCT_Inverse(x, xn_buf, overlap, L_frame-overlap, overlap); + + /*-----------------------------------------------------------* + * Windowing, overlap and add * + *-----------------------------------------------------------*/ + + /* Window current frame */ + 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, tcx_mdct_window_trans, L_frame_glob >> 1, + tcx_offset<0?-tcx_offset: 0, + st->last_core_bfi, + st->last_is_cng, + fullbandScale ); + } + } /* TCX-20 and TCX-only */ + + /* Window and overlap-add past frame if past frame is TCX */ + if( (frame_cnt != 0) || (st->last_core_bfi > ACELP_CORE) ) + { + if (((L_frameTCX == st->L_frameTCX >> 1) && (st->tcxonly)) || (st->tcx_cfg.tcx_last_overlap_mode == TRANSITION_OVERLAP)) + { + if (!bfi && (frame_cnt > 0) && (index == 0) && (tcx_cfg->tcx_curr_overlap_mode == FULL_OVERLAP) && (st->last_core != ACELP_CORE)) + { + index = MIN_OVERLAP; /* use minimum overlap between the two TCX-10 windows */ + } + + if( tcx_cfg->last_aldo ) + { + for (i=0; i < overlap - tcx_mdct_window_min_length; i++) + { + xn_buf[i+overlap/2-tcx_offset] += old_out[i+nz]; + } + + /* fade truncated ALDO window */ + for ( ; i < overlap; i++) + { + xn_buf[i+overlap/2-tcx_offset] += old_out[i+nz] * tcx_mdct_window_minimum[overlap-1-i]; + } + } + else + { + 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, + (index == 0 || tcx_cfg->tcx_last_overlap_mode == MIN_OVERLAP) ? tcx_cfg->tcx_last_overlap_mode : index ); + if (bfi) + { + for (i=0; i>1)] += old_syn_overl[i]; + } + } + } + } + } + + if( !aldo && (((L_frameTCX == st->L_frameTCX >> 1)&& frame_cnt > 0) || L_frameTCX != (st->L_frameTCX >> 1)) ) + { + /*Compute windowed synthesis in case of switching to ALDO windows in next frame*/ + mvr2r( xn_buf+L_frame-nz, old_out, nz+overlap ); + set_zero( old_out+nz+overlap, 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( tcx_cfg->tcx_curr_overlap_mode == FULL_OVERLAP ) + { + for (i=0; ilast_aldo = aldo; + } + + /* Smoothing between the ACELP PLC and TCX Transition frame. Using the shape of the half overlap window for the crossfading. */ + if( left_rect && (frame_cnt == 0) && (st->last_core_bfi == ACELP_CORE) && st->prev_bfi ) + { + if( FB_flag ) + { + for (i=0; isyn_OverlFB[i] * tcx_mdct_window_half[tcx_mdct_window_half_length-1-i] * tcx_mdct_window_half[tcx_mdct_window_half_length-1-i]; + } + } + else + { + for (i=0; isyn_Overl[i] * tcx_mdct_window_half[tcx_mdct_window_half_length-1-i] * tcx_mdct_window_half[tcx_mdct_window_half_length-1-i]; + } + } + } + + return; +} diff --git a/lib_dec/dec_tran.c b/lib_dec/dec_tran.c new file mode 100644 index 000000000..0437ddf47 --- /dev/null +++ b/lib_dec/dec_tran.c @@ -0,0 +1,167 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * decod_tran() + * + * Decode transition (TC) frames + *-------------------------------------------------------------------*/ + +void decod_tran( + Decoder_State *st, /* i/o: decoder static memory */ + const short L_frame, /* i : length of the frame */ + const short tc_subfr, /* i : TC subframe index */ + const float *Aq, /* i : LP filter coefficient */ + const short coder_type, /* i : coding type */ + const float Es_pred, /* i : predicted scaled innov. energy */ + float *pitch_buf, /* o : floating pitch values for each subframe*/ + float *voice_factors, /* o : voicing factors */ + float *exc, /* i/o: adapt. excitation exc */ + float *exc2, /* i/o: adapt. excitation/total exc */ + float *bwe_exc, /* i/o: excitation for SWB TBE */ + short *unbits, /* i/o: number of unused bits */ + const short sharpFlag, /* i : formant sharpening flag */ + float *gain_buf +) +{ + short T0, T0_frac, T0_min, T0_max; /* integer pitch variables */ + float gain_code; /* Quantized algebraic codeebook gain */ + float norm_gain_code; /* normalized algebraic codeebook gain */ + float gain_pit = 0; /* Quantized pitch gain */ + float voice_fac; /* Voicing factor */ + float gain_inov; /* inovation gain */ + float code[L_SUBFR]; /* algebraic codevector */ + const float *p_Aq; /* pointer to lp filter coefficient */ + float *pt_pitch; /* pointer to floating pitch */ + short i_subfr, i; /* tmp variables */ + short position; /* TC related flag */ + float gain_preQ = 0; /* Gain of prequantizer excitation */ + float code_preQ[L_SUBFR]; /* Prequantizer excitation */ + short Jopt_flag; /* flag indicating zero adaptive contribtuion */ + float norm_gain_preQ; + + gain_preQ = 0; + set_f( code_preQ, 0, L_SUBFR ); + /*----------------------------------------------------------------* + * ACELP subframe loop + *----------------------------------------------------------------*/ + + p_Aq = Aq; + pt_pitch = pitch_buf; + Jopt_flag = 0; + norm_gain_preQ = 0.0f; + + for (i_subfr = 0; i_subfr < L_frame; i_subfr += L_SUBFR) + { + /*------------------------------------------------------------* + * TC : subframe determination & + * adaptive/glottal part of excitation construction + *------------------------------------------------------------*/ + + transition_dec( st, st->core_brate, 0, L_frame, i_subfr, coder_type, tc_subfr, &Jopt_flag, exc, + &T0, &T0_frac, &T0_min, &T0_max, &pt_pitch, &position, bwe_exc ); + + /*-----------------------------------------------------------------* + * Transform domain contribution decoding - active frames + *-----------------------------------------------------------------*/ + + if( st->core_brate > ACELP_24k40 ) + { + transf_cdbk_dec( st, st->core_brate, coder_type, 0, i_subfr, tc_subfr, Es_pred, 0, + &st->mem_preemp_preQ, &gain_preQ, &norm_gain_preQ, code_preQ, unbits ); + } + + /*-----------------------------------------------------------------* + * ACELP codebook search + pitch sharpening + *-----------------------------------------------------------------*/ + + inov_decode( st, st->core_brate, 0, L_frame, coder_type, sharpFlag, i_subfr, tc_subfr, p_Aq, st->tilt_code, *pt_pitch, code ); + + /*-----------------------------------------------------------------* + * 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( st, st->core_brate, L_frame, i_subfr, tc_subfr, Es_pred, code, &gain_pit, &gain_code, &gain_inov, &norm_gain_code ); + } + else + { + /* 5-bit decoding */ + if ( st->core_brate > ACELP_32k ) + { + gain_dec_SQ( st, st->core_brate, coder_type, i_subfr, tc_subfr, code, Es_pred, &gain_pit, &gain_code, &gain_inov, &norm_gain_code ); + } + else + { + gain_dec_mless( st, st->core_brate, L_frame, coder_type, i_subfr, tc_subfr, code, Es_pred, &gain_pit, &gain_code, &gain_inov, &norm_gain_code ); + } + } + + /* update LP filtered gains for the case of frame erasures */ + lp_gain_updt( i_subfr, gain_pit, norm_gain_code + norm_gain_preQ, &st->lp_gainp, &st->lp_gainc, L_frame ); + + st->tilt_code = est_tilt( exc+i_subfr, gain_pit, code, gain_code, &voice_fac,L_SUBFR,0 ); + + /*----------------------------------------------------------------------* + * Find the total excitation + *----------------------------------------------------------------------*/ + + for (i = 0; i < L_SUBFR; i++) + { + exc2[i+i_subfr] = gain_pit*exc[i+i_subfr]; + exc[i+i_subfr] = exc2[i+i_subfr] + gain_code*code[i]; + } + + /*-----------------------------------------------------------------* + * Add the ACELP pre-quantizer contribution + *-----------------------------------------------------------------*/ + + if( st->core_brate > ACELP_24k40 ) + { + for ( i = 0; i < L_SUBFR; i++ ) + { + exc2[i+i_subfr] += gain_preQ * code_preQ[i]; + exc[i+i_subfr] += gain_preQ * code_preQ[i]; + } + } + + /*-----------------------------------------------------------------* + * Prepare TBE excitation + *-----------------------------------------------------------------*/ + + prep_tbe_exc( L_frame, i_subfr, gain_pit, gain_code, code, voice_fac, &voice_factors[i_subfr/L_SUBFR], + bwe_exc, gain_preQ, code_preQ, T0, coder_type, st->core_brate ); + + /*----------------------------------------------------------------* + * Excitation enhancements (update of total excitation signal) + *----------------------------------------------------------------*/ + if( st->core_brate > ACELP_32k ) + { + mvr2r( exc+i_subfr, exc2+i_subfr, L_SUBFR ); + } + else + { + enhancer( MODE1, st->core_brate, -1, 0, coder_type, L_frame, voice_fac, st->stab_fac, + norm_gain_code, gain_inov, &st->gc_threshold, code, exc2 + i_subfr, gain_pit, st->dispMem ); + } + + p_Aq += (M+1); + pt_pitch++; + st->tilt_code_dec[i_subfr/L_SUBFR] = st->tilt_code; + gain_buf[i_subfr/L_SUBFR] = gain_pit; + } + + /* SC-VBR */ + st->prev_gain_pit_dec = gain_pit; + + return; +} diff --git a/lib_dec/dec_uv.c b/lib_dec/dec_uv.c new file mode 100644 index 000000000..fd8217cbb --- /dev/null +++ b/lib_dec/dec_uv.c @@ -0,0 +1,83 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include "prot.h" + +/*-------------------------------------------------------------------* + * decod_unvoiced() + * + * Decode unvoiced (UC) frames + *-------------------------------------------------------------------*/ + +void decod_unvoiced( + Decoder_State *st, /* i/o: decoder static memory */ + const float *Aq, /* i : LP filter coefficient */ + const short coder_type, /* i : coding type */ + float *tmp_noise, /* o : long term temporary noise energy */ + float *pitch_buf, /* o : floating pitch values for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *exc, /* o : adapt. excitation exc */ + float *exc2, /* o : adapt. excitation/total exc */ + float *bwe_exc /* i/o: excitation for SWB TBE */ + , float *gain_buf +) +{ + float gain_pit = 0; /* Quantized pitch gain */ + float gain_code; /* Quantized algebraic codeebook gain */ + float gain_inov; /* inovation gain */ + float norm_gain_code; /* normalized algebraic codeebook gain */ + float voice_fac; /* Voicing factor */ + float code[L_SUBFR]; /* algebraic codevector */ + short i_subfr; + float *pt_pitch; + const float *p_Aq; + + if( st->last_ppp_mode_dec == 1 || st->last_nelp_mode_dec == 1 ) + { + /* SC_VBR - reset the decoder, to avoid memory not updated issue for this unrealistic case */ + CNG_reset_dec( st, pitch_buf, voice_factors ); + } + + p_Aq = Aq; /* pointer to interpolated LPC parameters */ + pt_pitch = pitch_buf; /* pointer to the pitch buffer */ + + for( i_subfr=0; i_subfrcore_brate, i_subfr, code, &norm_gain_code, + &st->lp_gainp, &st->lp_gainc, &gain_inov, &st->tilt_code, + &voice_fac, &gain_pit, pt_pitch, exc, &gain_code, exc2 ); + + *tmp_noise = norm_gain_code; + + /*----------------------------------------------------------------* + * Excitation enhancements (update of total excitation signal) + *----------------------------------------------------------------*/ + + enhancer( MODE1, st->core_brate, -1, 0, coder_type, L_FRAME, voice_fac, st->stab_fac, + norm_gain_code, gain_inov, &st->gc_threshold, code, exc2 + i_subfr, gain_pit, st->dispMem ); + + voice_factors[i_subfr/L_SUBFR] = 0.0f; + + interp_code_5over2( &exc[i_subfr], &bwe_exc[i_subfr * HIBND_ACB_L_FAC], L_SUBFR ); + + p_Aq += (M+1); + pt_pitch++; + st->tilt_code_dec[i_subfr/L_SUBFR] = st->tilt_code; + } + + /* SC-VBR */ + st->prev_gain_pit_dec = gain_pit; + + set_f( gain_buf, 0, NB_SUBFR ); + + return; +} diff --git a/lib_dec/decision_matrix_dec.c b/lib_dec/decision_matrix_dec.c new file mode 100644 index 000000000..259f0f38c --- /dev/null +++ b/lib_dec/decision_matrix_dec.c @@ -0,0 +1,526 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "stat_dec.h" +#include "rom_com.h" +#include "prot.h" + +/*-----------------------------------------------------------------* + * decision_matrix_dec() + * + * ACELP/HQ core selection + * Read ACELP signalling bits from the bitstream + * Set extension layers + *-----------------------------------------------------------------*/ + +void decision_matrix_dec( + Decoder_State *st, /* i/o: decoder state structure */ + short *coder_type, /* o : coder type */ + short *sharpFlag, /* o : formant sharpening flag */ + short *hq_core_type, /* o : HQ core type */ + short *core_switching_flag/* o : ACELP->HQ switching frame flag */ +) +{ + short start_idx; + short ppp_nelp_mode; + long ind; + short nBits; + short tmp; + st->core = -1; + st->core_brate = 0; + st->extl = -1; + st->extl_brate = 0; + st->ppp_mode_dec = 0; + st->nelp_mode_dec = 0; + st->igf = 0; + + if( st->total_brate > ACELP_8k00 ) + { + st->vbr_hw_BWE_disable_dec = 0; + } + + if( st->mdct_sw == MODE2 ) + { + st->core = HQ_CORE; + } + else + { + if ( st->total_brate == FRAME_NO_DATA || st->total_brate == SID_2k40 ) + { + st->core = ACELP_CORE; + st->core_brate = st->total_brate; + + if( st->total_brate != FRAME_NO_DATA ) + { + st->cng_type = get_next_indice( st, 1 ); + + if( st->cng_type == LP_CNG ) + { + st->L_frame = L_FRAME; + + if( get_next_indice( st, 1 ) == 1 ) + { + st->L_frame = L_FRAME16k; + } + } + else + { + st->bwidth = get_next_indice(st, 2); + + if( get_next_indice(st, 1) == 0 ) + { + st->L_frame = L_FRAME; + } + else + { + st->L_frame = L_FRAME16k; + } + } + } + + if( st->output_Fs >= 32000 && st->bwidth >= SWB ) + { + st->extl = SWB_CNG; + } + if ( st->total_brate == FRAME_NO_DATA && st->prev_bfi && !st->bfi && st->L_frame > L_FRAME16k) + { + st->L_frame = st->last_CNG_L_frame; + } + + return; + } + + /* SC-VBR */ + else if ( st->total_brate == PPP_NELP_2k80 ) + { + st->core = ACELP_CORE; + st->core_brate = PPP_NELP_2k80; + st->L_frame = L_FRAME; + st->fscale = sr2fscale(INT_FS_12k8); + + if( st->ini_frame == 0 ) + { + /* avoid switching of internal ACELP Fs in the very first frame */ + st->last_L_frame = st->L_frame; + st->last_core = st->core; + st->last_core_brate = st->core_brate; + st->last_extl = st->extl; + } + + st->vbr_hw_BWE_disable_dec = 1; + + get_next_indice( st, 1 ); + + ppp_nelp_mode = (short) get_next_indice( st, 2 ); + + /* 0 - PPP_NB, 1 - PPP_WB, 2 - NELP_NB, 3 - NELP_WB */ + if ( ppp_nelp_mode == 0 ) + { + st->ppp_mode_dec = 1; + *coder_type = VOICED; + st->bwidth = NB; + } + else if ( ppp_nelp_mode == 1 ) + { + st->ppp_mode_dec = 1; + *coder_type = VOICED; + st->bwidth = WB; + } + else if ( ppp_nelp_mode == 2 ) + { + st->nelp_mode_dec = 1; + *coder_type = UNVOICED; + st->bwidth = NB; + } + else if ( ppp_nelp_mode == 3 ) + { + st->nelp_mode_dec = 1; + *coder_type = UNVOICED; + st->bwidth = WB; + } + + return; + } + + /*---------------------------------------------------------------------* + * ACELP/HQ core selection + *---------------------------------------------------------------------*/ + + if ( st->total_brate < ACELP_24k40 ) + { + st->core = ACELP_CORE; + } + else if ( st->total_brate >= ACELP_24k40 && st->total_brate <= ACELP_64k ) + { + /* read the ACELP/HQ core selection bit */ + tmp = (short) get_next_indice( st, 1 ); + + if( tmp == 0 ) + { + st->core = ACELP_CORE; + } + else + { + st->core = HQ_CORE; + } + } + } + + /*-----------------------------------------------------------------* + * Read ACELP signalling bits from the bitstream + *-----------------------------------------------------------------*/ + + if( st->core == ACELP_CORE ) + { + /* find the section in the ACELP signalling table corresponding to bitrate */ + start_idx = 0; + while ( acelp_sig_tbl[start_idx] != st->total_brate ) + { + start_idx++; + if( start_idx >= MAX_ACELP_SIG ) + { + st->BER_detect = 1; + start_idx = 0; + break; + } + } + + /* skip the bitrate */ + start_idx += 1; + + /* retrieve the number of bits */ + nBits = (short) acelp_sig_tbl[start_idx++]; + + start_idx += get_next_indice( st, nBits ); + if( start_idx >= MAX_ACELP_SIG ) + { + ind = 0; + st->BER_detect = 1; + } + else + { + /* retrieve the signalling indice */ + ind = acelp_sig_tbl[start_idx]; + + /* convert signalling indice into signalling information */ + *coder_type = ind & 0x7; + if ( *coder_type == LR_MDCT ) + { + st->core = HQ_CORE; + st->bwidth = (ind >> 3) & 0x7; + } + else + { + st->bwidth = (ind >> 3) & 0x7; + *sharpFlag = (ind >> 6) & 0x1; + } + } + + /* detect corrupted signalling (due to bit errors) */ + if( ( st->BER_detect ) || + ( ind >= 1<<7 ) || + ( st->total_brate <= ACELP_13k20 && st->bwidth == FB ) || + ( st->total_brate >= ACELP_32k && st->bwidth == NB ) || + ( st->total_brate >= ACELP_32k && !(*coder_type == GENERIC || *coder_type == TRANSITION || *coder_type == INACTIVE ) ) || + ( st->total_brate < ACELP_13k20 && st->bwidth != NB && *coder_type == LR_MDCT ) || + ( st->total_brate >= ACELP_13k20 && *coder_type == UNVOICED ) || + ( st->total_brate >= ACELP_13k20 && *coder_type == AUDIO && st->bwidth == NB ) + ) + { + st->BER_detect = 0; + st->bfi = 1; + if( st->ini_frame == 0 ) + { + st->core = ACELP_CORE; + st->L_frame = L_FRAME; + st->last_core = st->core; + st->last_core_brate = st->core_brate; + } + else if( st->last_total_brate == -1 ) /* can happen in case of BER when no good frame was received before */ + { + *coder_type = st->last_coder_type; + st->bwidth = st->last_bwidth; + st->total_brate = st->last_total_brate_ber; + if( st->last_core == AMR_WB_CORE ) + { + st->core = ACELP_CORE; + st->codec_mode = MODE1; + } + else if( st->last_core_bfi == TCX_20_CORE || st->last_core_bfi == TCX_10_CORE ) + { + st->core = st->last_core_bfi; + st->codec_mode = MODE2; + } + else + { + st->core = st->last_core; + st->codec_mode = MODE1; + } + st->core_brate = st->last_core_brate; + st->extl = st->last_extl; + st->extl_brate = st->total_brate - st->core_brate; + } + else + { + *coder_type = st->last_coder_type; + st->bwidth = st->last_bwidth; + st->total_brate = st->last_total_brate; + if( st->last_core == AMR_WB_CORE ) + { + st->core = ACELP_CORE; + st->codec_mode = MODE1; + } + else if( st->last_core == TCX_20_CORE || st->last_core == TCX_10_CORE ) + { + st->core = st->last_core; + st->codec_mode = MODE2; + } + else + { + st->core = st->last_core; + st->codec_mode = MODE1; + } + st->core_brate = st->last_core_brate; + st->extl = st->last_extl; + st->extl_brate = st->total_brate - st->core_brate; + } + return; + } + } + + /*-----------------------------------------------------------------* + * Set extension layers + *-----------------------------------------------------------------*/ + + if ( st->core == ACELP_CORE && st->bwidth == WB && st->total_brate < ACELP_9k60 ) + { + if ( st->vbr_hw_BWE_disable_dec == 0 ) + { + st->extl = WB_BWE; + } + } + else if ( st->core == ACELP_CORE && st->bwidth == WB && st->total_brate >= ACELP_9k60 && st->total_brate <= ACELP_16k40 ) + { + /* read the WB TBE/BWE selection bit */ + if ( get_next_indice( st, 1 ) ) + { + st->extl = WB_BWE; + st->extl_brate = WB_BWE_0k35; + } + else + { + st->extl = WB_TBE; + st->extl_brate = WB_TBE_1k05; + } + } + else if ( st->core == ACELP_CORE && (st->bwidth == SWB || st->bwidth == FB) && st->total_brate >= ACELP_13k20 ) + { + if (st->total_brate >= ACELP_48k) + { + st->extl = SWB_BWE_HIGHRATE; + if( st->bwidth == FB ) + { + st->extl = FB_BWE_HIGHRATE; + } + + st->extl_brate = SWB_BWE_16k; + } + + /* read the SWB TBE/BWE selection bit */ + else + { + tmp = get_next_indice( st, 1 ); + + if( tmp ) + { + st->extl = SWB_BWE; + st->extl_brate = SWB_BWE_1k6; + } + else + { + st->extl = SWB_TBE; + st->extl_brate = SWB_TBE_1k6; + if( st->total_brate >= ACELP_24k40 ) + { + st->extl_brate = SWB_TBE_2k8; + } + } + } + + /* set FB TBE and FB BWE extension layers */ + if ( st->bwidth == FB && st->total_brate >= ACELP_24k40 ) + { + if ( st->extl == SWB_BWE ) + { + st->extl = FB_BWE; + st->extl_brate = FB_BWE_1k8; + } + else if ( st->extl == SWB_TBE ) + { + st->extl = FB_TBE; + st->extl_brate = FB_TBE_3k0; + } + } + } + + /* set core bitrate */ + st->core_brate = st->total_brate - st->extl_brate; + + /*-----------------------------------------------------------------* + * Read HQ signalling bits from the bitstream + * Set HQ core type + *-----------------------------------------------------------------*/ + + + if ( st->core == HQ_CORE ) + { + if( st->mdct_sw != MODE2 ) + { + /* skip the HQ/TCX core switching flag */ + get_next_indice_tmp( st, 1 ); + } + + /* read ACELP->HQ core switching flag */ + *core_switching_flag = (short)get_next_indice( st, 1 ); + + if( *core_switching_flag == 1 ) + { + st->last_L_frame_ori = st->last_L_frame; + + /* read ACELP L_frame info */ + if( get_next_indice( st, 1 ) == 0 ) + { + st->last_L_frame = L_FRAME; + } + else + { + st->last_L_frame = L_FRAME16k; + } + } + + if( st->mdct_sw != MODE2 ) + { + /* read/set band-width (needed for different I/O sampling rate support) */ + if( st->total_brate > ACELP_16k40 ) + { + ind = get_next_indice( st, 2 ); + + if( ind == 0 ) + { + st->bwidth = NB; + } + else if( ind == 1 ) + { + st->bwidth = WB; + } + else if( ind == 2 ) + { + st->bwidth = SWB; + } + else + { + st->bwidth = FB; + } + } + } + + /* detect bit errors in signalling */ + if( ( st->total_brate >= ACELP_24k40 && st->bwidth == NB ) || + ( st->core == HQ_CORE && st->total_brate <= LRMDCT_CROSSOVER_POINT && st->bwidth == FB) + ) + { + st->bfi = 1; + + st->core_brate = st->total_brate; + st->extl = -1; + st->extl_brate = 0; + if( st->last_core == AMR_WB_CORE ) + { + st->core = ACELP_CORE; + st->L_frame = L_FRAME; + st->codec_mode = MODE1; + st->last_L_frame = L_FRAME; + + if( st->total_brate >= ACELP_16k40 ) + { + st->total_brate = ACELP_13k20; + st->core_brate = st->total_brate; + } + } + else + { + /* make sure, we are in a valid configuration wrt to bandwidth */ + st->bwidth = WB; + } + } + + /* set HQ core type */ + *hq_core_type = NORMAL_HQ_CORE; + if( (st->bwidth == SWB || st->bwidth == WB) && st->total_brate <= LRMDCT_CROSSOVER_POINT ) + { + *hq_core_type = LOW_RATE_HQ_CORE; + } + else if( st->bwidth == NB ) + { + *hq_core_type = LOW_RATE_HQ_CORE; + } + } + + /*-----------------------------------------------------------------* + * Set ACELP frame length + *-----------------------------------------------------------------*/ + + if( st->core_brate == FRAME_NO_DATA ) + { + /* prevent "L_frame" changes in CNG segments */ + st->L_frame = st->last_L_frame; + } + else if ( st->core_brate == SID_2k40 && st->bwidth == WB && st->first_CNG && st->act_cnt2 < MIN_ACT_CNG_UPD ) + { + /* prevent "L_frame" changes in SID frame after short segment of active frames */ + st->L_frame = st->last_CNG_L_frame; + } + else if ( ( st->core_brate == SID_2k40 && st->total_brate >= ACELP_9k60 && st->bwidth == WB ) || + ( st->total_brate > ACELP_24k40 && st->total_brate < HQ_96k ) || ( st->total_brate == ACELP_24k40 && st->bwidth >= WB ) ) + { + st->L_frame = L_FRAME16k; + } + else + { + st->L_frame = L_FRAME; + } + + if ( st->L_frame == L_FRAME16k ) + { + st->nb_subfr = NB_SUBFR16k; + } + else + { + st->nb_subfr = NB_SUBFR; + } + + if( st->output_Fs == 8000 ) + { + st->extl = -1; + } + else if( st->output_Fs == 16000 && st->L_frame == L_FRAME16k ) + { + st->extl = -1; + st->extl_brate = 0; + } + + if ( st->ini_frame == 0 ) + { + /* avoid switching of internal ACELP Fs in the very first frame */ + st->last_L_frame = st->L_frame; + st->last_core = st->core; + st->last_core_brate = st->core_brate; + st->last_extl = st->extl; + } + + return; +} diff --git a/lib_dec/decoder.c b/lib_dec/decoder.c new file mode 100644 index 000000000..9cee6dc83 --- /dev/null +++ b/lib_dec/decoder.c @@ -0,0 +1,244 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include +#include +#include "options.h" +#include "wmc_auto.h" +#include "prot.h" +#include "cnst.h" +#include "rom_com.h" +#include "g192.h" +#include "wmc_auto.h" + +#define WMC_TOOL_SKIP + +/*------------------------------------------------------------------------------------------* + * Global variables + *------------------------------------------------------------------------------------------*/ +long frame = 0; /* Counter of frames */ + +/*------------------------------------------------------------------------------------------* + * Main decoder function + *------------------------------------------------------------------------------------------*/ + +int main( int argc, char *argv[] ) +{ + FILE *f_stream; /* input bitstream file */ + FILE *f_synth; /* output synthesis file */ + Decoder_State *st; /* decoder state structure */ + short output_frame, dec_delay, zero_pad; + short quietMode = 0; + short noDelayCmp = 0; + float output[L_FRAME48k]; /* 'float' buffer for output synthesis */ + short data[L_FRAME48k]; /* 'short' buffer for output synthesis */ +#ifdef SUPPORT_JBM_TRACEFILE + char *jbmTraceFileName = NULL; /* VOIP tracefile name */ +#endif + char *jbmFECoffsetFileName = NULL; /* VOIP tracefile name */ + +#ifdef WMOPS + reset_wmops(); + reset_mem(USE_BYTES); +#endif + + /*------------------------------------------------------------------------------------------* + * Allocate memory for static variables + * Processing of command-line parameters + * Decoder initialization + *------------------------------------------------------------------------------------------*/ + +#undef WMC_TOOL_SKIP + if ( (st = (Decoder_State *) malloc( sizeof(Decoder_State) ) ) == NULL ) +#define WMC_TOOL_SKIP + { + fprintf(stderr, "Can not allocate memory for decoder state structure\n"); + exit(-1); + } + /* set to NULL, to avoid reading of uninitialized memory in case of early abort */ + st->cldfbAna = st->cldfbBPF = st->cldfbSyn = NULL; + st->hFdCngDec = NULL; + + io_ini_dec( argc, argv, &f_stream, &f_synth, + &quietMode, &noDelayCmp, st, +#ifdef SUPPORT_JBM_TRACEFILE + &jbmTraceFileName, +#endif + &jbmFECoffsetFileName + ); + + /*------------------------------------------------------------------------------------------* + * VOIP client + *------------------------------------------------------------------------------------------*/ + + if( st->Opt_VOIP ) + { + if( decodeVoip( st, f_stream, f_synth, +#ifdef SUPPORT_JBM_TRACEFILE + jbmTraceFileName, +#endif + jbmFECoffsetFileName, + quietMode + ) != 0 ) + { +#undef WMC_TOOL_SKIP + free( st ); +#define WMC_TOOL_SKIP + fclose( f_synth ); + fclose( f_stream ); + return -1; + } + } + + /*------------------------------------------------------------------------------------------* + * Regular EVS decoder with ITU-T G.192 bitstream + *------------------------------------------------------------------------------------------*/ + + else + { + /*------------------------------------------------------------------------------------------* + * Allocate memory for static variables + * Decoder initialization + *------------------------------------------------------------------------------------------*/ + + init_decoder( st ); + reset_indices_dec( st ); + + srand( (unsigned int) time(0) ); + + /* output frame length */ + output_frame = (short)(st->output_Fs / 50); + + if( noDelayCmp == 0 ) + { + /* 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(st->output_Fs, get_delay(DEC, st->output_Fs) + 0.5f); + } + 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" ); + } +#ifdef WMOPS + reset_wmops(); +#endif + + while( st->bitstreamformat==G192 ? read_indices( st, f_stream, 0 ) : read_indices_mime( st, f_stream, 0) ) + { + /* run the main decoding routine */ + if ( st->codec_mode == MODE1 ) + { + if ( st->Opt_AMR_WB ) + { + amr_wb_dec( st, output ); + } + else + { + evs_dec( st, output, FRAMEMODE_NORMAL ); + } + } + else + { + if( !st->bfi ) + { + evs_dec( st, output, FRAMEMODE_NORMAL ); + } + else + { + evs_dec( st, output, FRAMEMODE_MISSING ); + } + } + + /* convert 'float' output data to 'short' */ + syn_output( output, output_frame, data ); + /* increase the counter of initialization frames */ + if( st->ini_frame < MAX_FRAME_COUNTER ) + { + st->ini_frame++;} + + /* write the synthesized signal into output file */ + /* do final delay compensation */ + if ( dec_delay == 0 ) + { + fwrite( data, sizeof(short), output_frame, f_synth ); + } + else + { + if ( dec_delay <= output_frame ) + { + fwrite( &data[dec_delay], sizeof(short), output_frame - dec_delay, f_synth ); + dec_delay = 0; + } + else + { + dec_delay -= output_frame; + } + } + + frame++; + if( quietMode == 0 ) + { + fprintf( stdout, "%-8ld\b\b\b\b\b\b\b\b", frame ); + } + +#ifdef WMOPS + update_wmops(); + update_mem(); +#endif + } + + + fflush( stderr ); + if (quietMode == 0) + { + fprintf( stdout, "\n\n" ); + fprintf(stdout, "Decoding finished\n\n"); + } + else + { + fprintf(stdout, "Decoding of %ld frames finished\n\n", frame); + } + fprintf( stdout, "\n\n" ); + + /* add zeros at the end to have equal length of synthesized signals */ + set_s( data, 0, zero_pad ); + fwrite( data, sizeof(short), zero_pad, f_synth ); + destroy_decoder( st ); + } + +#undef WMC_TOOL_SKIP + free( st ); +#define WMC_TOOL_SKIP + +#ifdef WMOPS + print_wmops(); + print_mem(NULL); +#endif + + 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 000000000..6bb9f447b --- /dev/null +++ b/lib_dec/dlpc_avq.c @@ -0,0 +1,247 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "prot.h" +#include +#include + + +/*------------------------------------------------------------------* +* dlpc_avq() +* +* Variable bit-rate multiple LPC un-quantizer +*------------------------------------------------------------------*/ + +int dlpc_avq( + int *index, /* (i) Quantization indices */ + float *LSF_Q, /* (o) Quantized LSF vectors */ + int numlpc, /* (i) Number of sets of lpc */ + float sr_core +) +{ + int i, nbi, last; + int *p_index, q_type; + + /* Last LPC index */ + + if ( numlpc==1 ) + { + last = 0; + } + else + { + last = M; + } + + p_index = index; + + /* Decode last LPC */ + for (i=0; inext_bit_pos; + + /* Index bits */ + *ind = 0; + + while (get_next_indice_1(st) && !st->BER_detect) + { + *ind += 1; + } + + if (*ind != 0) + { + *ind += 1; + } + + return st->next_bit_pos - start_bit_pos; + +} + + +/*------------------------------------------------------------------* +* pack4bits() +* +* +*------------------------------------------------------------------*/ + +static int pack4bits( + int nbits, + Decoder_State *st, + int *prm +) +{ + int i; + + i=0; + + while (nbits > 4) + { + prm[i] = get_next_indice(st, 4); + nbits -= 4; + i++; + } + prm[i] = get_next_indice(st, nbits); + i++; + + return(i); +} + + +/*------------------------------------------------------------------* +* decode_lpc_avq() +* +* +*------------------------------------------------------------------*/ + +int decode_lpc_avq( + Decoder_State *st, + int numlpc, + int *param_lpc +) +{ + int k,j; + int nb, qn1, qn2, avqBits, q_type; + int start_bit_pos; + + + j = 0; + start_bit_pos = st->next_bit_pos; + + + for (k=0; k 4) + { + nb = unary_decode(st, &qn1); + + if (nb == 1) qn1 += 5; + else if (nb == 2) qn1 += 4; + else if (nb == 3) qn1 = 0; + else qn1 += 3; + } + + if (qn2 > 4) + { + nb = unary_decode(st, &qn2); + + if (nb == 1) qn2 += 5; + else if (nb == 2) qn2 += 4; + else if (nb == 3) qn2 = 0; + else qn2 += 3; + } + + /* check for potential bit errors */ + if( qn1 > NB_SPHERE || qn2 > NB_SPHERE ) + { + qn1 = 0; + qn2 = 0; + st->BER_detect = 1; + } + + param_lpc[j] = qn1; + j++; + param_lpc[j] = qn2; + j++; + + /* Decode Split-by-2 algebraic VQ */ + avqBits = 4*qn1; + pack4bits(avqBits, st, ¶m_lpc[j]); + j += qn1; + + avqBits = 4*qn2; + pack4bits(avqBits, st, ¶m_lpc[j]); + j += qn2; + } + + return st->next_bit_pos - start_bit_pos; +} diff --git a/lib_dec/dlpc_stoch.c b/lib_dec/dlpc_stoch.c new file mode 100644 index 000000000..3244f311a --- /dev/null +++ b/lib_dec/dlpc_stoch.c @@ -0,0 +1,106 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include "options.h" +#include "prot.h" +#include "rom_com.h" +#include "basop_proto_func.h" + +/*------------------------------------------------------------------* +* lpc_unquantize() +* +* +*------------------------------------------------------------------*/ + +void lpc_unquantize( + Decoder_State * st, + float *lsfold, + float *lspold, + float *lsf, + float *lsp, + int lpcQuantization, + int *param_lpc, + int numlpc, + int core, + float *mem_MA, + float *lspmid, + float *lsfmid, + short coder_type, + int acelp_midLpc, + int narrow_band, + short *seed_acelp, + int sr_core, + short *mid_lsf_int, + short prev_bfi, + short *LSF_Q_prediction, /* o : LSF prediction mode */ + short *safety_net +) +{ + int nb_indices=0, k; + + mvr2r(lsfold, &lsf[0], M); + mvr2r(lspold, &lsp[0], M); + + if( lpcQuantization == 0 ) + { + nb_indices = dlpc_avq(param_lpc, &lsf[M], numlpc, sr_core ); + for ( k=0; kbwidth */ , ENDLSF_NBITS, &lsf[M], st->mem_AR, mem_MA, sr_core, st->core_brate, + &st->offset_scale1[0][0], &st->offset_scale2[0][0], &st->offset_scale1_p[0][0], &st->offset_scale2_p[0][0], + &st->no_scales[0][0], &st->no_scales_p[0][0], &st->safety_net, param_lpc, LSF_Q_prediction, &nb_indices); + } + else + { + if (st->core == TCX_20_CORE) + { + lsf_end_dec( st, AUDIO, 1-narrow_band /* st->bwidth */ , ENDLSF_NBITS, &lsf[M], st->mem_AR, mem_MA, sr_core, st->core_brate, + &st->offset_scale1[0][0], &st->offset_scale2[0][0], &st->offset_scale1_p[0][0], &st->offset_scale2_p[0][0], + &st->no_scales[0][0], &st->no_scales_p[0][0], &st->safety_net, param_lpc, LSF_Q_prediction, &nb_indices); + } + else + { + lsf_end_dec( st, coder_type, 1-narrow_band /* st->bwidth */ , 31, &lsf[M], st->mem_AR, mem_MA, sr_core, st->core_brate, + &st->offset_scale1[0][0], &st->offset_scale2[0][0], &st->offset_scale1_p[0][0], &st->offset_scale2_p[0][0], + &st->no_scales[0][0], &st->no_scales_p[0][0], &st->safety_net, param_lpc, LSF_Q_prediction, &nb_indices); + } + } + + lsf2lsp(&lsf[M], &lsp[M], M, sr_core); + } + else + { + assert(0); + } + + *seed_acelp=0; + for(k=nb_indices-1; k>=0; k--) + { + /* rightshift before *seed_acelp+param_lpc[i] to avoid overflows*/ + *seed_acelp=(short)((((*seed_acelp)>>1)+param_lpc[k]) * 31821L + 13849L); + } + + /* Decoded mid-frame lsf */ + if( lpcQuantization && acelp_midLpc && core == ACELP_CORE && st->rate_switching_reset == 0 ) + { + midlsf_dec( &lsf[0], &lsf[M], (short)param_lpc[nb_indices], lsfmid, M, coder_type, mid_lsf_int, prev_bfi, *safety_net ); + + reorder_lsf( lsfmid, LSF_GAP_MID, M, sr_core ); + lsf2lsp( 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 000000000..1142d1743 --- /dev/null +++ b/lib_dec/er_dec_acelp.c @@ -0,0 +1,693 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "prot.h" +#include "options.h" + + +/*-------------------------------------------------------------------* +* con_acelp() +* +* Concealment function for ACELP and TD-TCX +*--------------------------------------------------------------------*/ + +void con_acelp( + float A[], /* input: coefficients NxAz[M+1] */ + int coder_type, /* input: ACELP coder type */ + float synth[], /* i/o: synthesis */ + int *pT, /* out: pitch for all subframe */ + float *pgainT, /* out: pitch gain for all subfr */ + float stab_fac, /* input: stability of isf */ + Decoder_State *st, /* i/o : coder memory state */ + float pitch_buffer[], /* i/o: floating pitch values for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *bwe_exc /* o : excitation for SWB TBE */ +) +{ + int i, i_subfr, L_frame, T0; + float tmp_deemph; + float mem_syn[M], mem_syn2[M], mem[M], *syn; + float *noise_buf; + float *exc, *harmonic_exc_buf, buf[L_EXC_MEM_DEC+M+L_FRAME16k+L_FRAME16k/2], *p_A; + float pitch_buf[NB_SUBFR16k]; + float alpha = 0.0f; + float step, gain, gainCNG, gain_inov, ftmp; + float *pt_exc,tmp_tc,predPitchLag; + float pc = 0.f; + short extrapolationFailed,tmpSeed,Tc; + float *pt1_exc; + float *w = st->tcx_cfg.tcx_mdct_window; + int W1, W2, j; + int l_fir_fer = L_FIR_FER; + float lpFiltAdapt[3]; + float hp_filt[3]; + int nSubframes; + float exc_unv[L_FRAME16k+L_FRAME16k/2]; + float syn_unv[L_FRAME16k+L_FRAME16k/2]; + float mem_syn_unv[M]; + float gain_lpc[NB_SUBFR16k]; + float h1[L_SUBFR+1]; + float gainSynthDeemph; + float tmp = 0.f; + int fUseExtrapolatedPitch; + + /* Framing parameters */ + + L_frame = st->L_frame; + + fUseExtrapolatedPitch = 0; + extrapolationFailed = 1; + + /*------------------------------------------------------------------------* + * Initialize buffers * + *------------------------------------------------------------------------*/ + + /* set ACELP synthesis memory */ + mvr2r( st->mem_syn2, mem_syn, M); + + /* set excitation memory*/ + harmonic_exc_buf = buf+M; + exc = harmonic_exc_buf+L_EXC_MEM_DEC; + mvr2r(st->old_exc, harmonic_exc_buf, L_EXC_MEM_DEC); + exc[L_frame] = 0.0f; + + /*------------------------------------------------------------------------* + * PLC: [ACELP:Extrapolate Pitch Lag] + *------------------------------------------------------------------------*/ + + if (st->flagGuidedAcelp == 1) + { + T0 = st->guidedT0; + } + + pitch_pred_linear_fit( st->nbLostCmpt, st->last_good, st->old_pitch_buf, &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 = (int)(predPitchLag+0.5f); + + if( extrapolationFailed ) + { + /*------------------------------------------------------------------------* + * - Construct adaptive codebook from side information * + *------------------------------------------------------------------------*/ + + if( st->flagGuidedAcelp == 0) + { + nSubframes = 0; + } + else + { + nSubframes = 2; + /* Construct adaptive codebook with T0, T0_frac, T0_res, gain_pit for 2 sub-frames */ + for( i=0; i<2*L_SUBFR; i++ ) + { + exc[i] = exc[i-st->guidedT0]; + } + } + } + else + { + nSubframes = 0; + } + + + if( nSubframes > 0 ) + { + tmp_tc = (float)st->guidedT0; /* take the transmit pitch*/ + } + else + { + tmp_tc = st->old_fpitch; /* take the previous frame last pitch*/ + } + + /* PLC: [ACELP: Fade-out] + * PLC: calculate damping factor */ + alpha = Damping_fact(coder_type, st->nbLostCmpt, st->last_good, stab_fac, &(st->lp_gainp), 0); + + if (st->nbLostCmpt==1) + { + st->cummulative_damping = 1.0f; + } + else + { + st->cummulative_damping *= alpha; + } + + /*-----------------------------------------------------------------* + * PLC: [ACELP: adaptive codebook] + * PLC: Construct the harmonic part of excitation + *-----------------------------------------------------------------*/ + + if( st->last_good >= UNVOICED_TRANSITION ) + { + + /*---------------------------------------------------------------* + * Last pitch cycle of the previous frame is repeatedly copied. * + *---------------------------------------------------------------*/ + + Tc = (short)(tmp_tc + 0.5f); + + if ((T0 > 0) && (T0 != Tc) && (abs(T0-Tc) < 0.15f*Tc) && extrapolationFailed == 0 ) + { + fUseExtrapolatedPitch = 1; + } + + if(st->enableGplc) + { + pt_exc = &exc[nSubframes*L_SUBFR]; + } + else + { + pt_exc = exc; + } + 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; + pt_exc = harmonic_exc_buf; + assert(pt_exc < pt1_exc-1); + } + + if( st->nbLostCmpt == 1 ) + { + /* pitch cycle is first low-pass filtered */ + /*get filter coefficients*/ + genPlcFiltBWAdap(st->sr_core, &lpFiltAdapt[0], 0, st->cummulative_damping); + for( i=0 ; i< Tc; i++ ) + { + *pt_exc++ = ( lpFiltAdapt[0] * pt1_exc[-1] + lpFiltAdapt[1] * pt1_exc[0] + lpFiltAdapt[2] * pt1_exc[1]); + pt1_exc++; + } + } + else + { + /* copy the first pitch cycle without low-pass filtering */ + for( i=0 ; i< Tc; i++ ) + { + *pt_exc++ = *pt1_exc++; + } + } + + if (fUseExtrapolatedPitch != 0) + { + pt1_exc = harmonic_exc_buf; + } + + for (i = 0; i < L_frame+(1-nSubframes)*L_SUBFR-Tc; i++) + { + *pt_exc++ = *pt1_exc++; + } + + /*-------------------------------------------------------* + * PLC: [ACELP: adaptive codebook] + * PLC: Resync pulse positions. + *-------------------------------------------------------*/ + + if( nSubframes > 0 ) + { + pitch_buf[0] = (float)st->guidedT0; + pitch_buf[1] = (float)st->guidedT0; + } + + if (nSubframes>0) + { + pitch_buf[3] = pitch_buf[2] = pitch_buf[1]; /* do not resync on second half of frame */ + if(st->nb_subfr == 5) + { + /* for guidedacelp cases and nSubframes=2, set pitch_buf[4] to avoid memory_access issues in post_decoder() */ + pitch_buf[4] = pitch_buf[3]; + } + } + else + { + if (fUseExtrapolatedPitch != 0) + { + get_subframe_pitch(st->nb_subfr, st->old_fpitch, predPitchLag, pitch_buf); + + PulseResynchronization(harmonic_exc_buf, exc, L_frame, st->nb_subfr, st->old_fpitch, predPitchLag); + } + else + { + set_f( 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+L_frame; + pt1_exc = pt_exc - ((T0 == 0) ? Tc : T0); + + for (i = 0; i < L_frame/2; i++) + { + *pt_exc++ = *pt1_exc++; + } + + /*-------------------------------------------------------* + * PLC: [ACELP: adaptive codebook] + * PLC: update the floating point pitch for consecutive loss + *-------------------------------------------------------*/ + + if (fUseExtrapolatedPitch != 0) + { + + if (st->flagGuidedAcelp == 1) + { + st->old_fpitch = (float) T0; + } + else + { + st->old_fpitch = predPitchLag; + } + } + + /*-------------------------------------------------------* + * PLC: [ACELP: adaptive BPF] + * PLC: Accommodate the BPF + *-------------------------------------------------------*/ + + st->bpf_gain_param = 3 ; /*full BPF*/ + + /*-------------------------------------------------------* + * PLC: [ACELP: adaptive codebook] + * PLC: Calculate the initial gain and fade out step. + *-------------------------------------------------------*/ + + pc = (float) fabs( pitch_buf[3] + pitch_buf[2] - pitch_buf[1] - pitch_buf[0] ) * 256.0f / (float)L_frame; + + if ((st->last_good <= UNVOICED_TRANSITION) && (coder_type == GENERIC) && (pc > 6)) + { + gain = 0.0f; + st->lp_gainp = 0.0f; + } + else + { + gain = 1.0f; /* start-of-the-frame gain */ + st->lp_gainp = alpha; + } + + step = (1.0f/L_frame) * (gain - st->lp_gainp); + + /*-------------------------------------------------------* + * PLC: [ACELP: Fade-out] + * Apply fade out + *-------------------------------------------------------*/ + + for (i_subfr = 0; i_subfr < st->nb_subfr; i_subfr++) + { + pgainT[i_subfr] = gain; + + for (i = i_subfr*L_SUBFR; i < (i_subfr+1)*L_SUBFR; i++) + { + exc[i] *= gain; + gain -= step; + } + } + + for ( ; i < L_frame+(L_frame/2); i++ ) + { + exc[i] *= gain; + gain -= step; + } + + for (i = 0; i < st->nb_subfr; i ++) + { + pT[i] = (int)( pitch_buf[i] + 0.5f); + pitch_buffer[i] = pitch_buf[i]; + } + + /* update old exc without random part*/ + mvr2r(harmonic_exc_buf+L_frame, st->old_exc, L_EXC_MEM_DEC); + + } + else + { + /* No harmonic part */ + set_zero(&exc[0], L_frame+L_frame/2); + + for (i = 0; i < st->nb_subfr; i ++) + { + pitch_buf[i] = st->pit_max; + pgainT[i] = 0.f; + pT[i] = L_SUBFR; + pitch_buffer[i] = L_SUBFR; + } + + st->bpf_gain_param = 0; /*no BPF*/ + } + + /*-----------------------------------------------------------------* + * Construct the random part of excitation + *-----------------------------------------------------------------*/ + noise_buf = buf; + tmpSeed = st->seed_acelp; + + for (i = 0; i < L_frame+l_fir_fer-1; i++) + { + noise_buf[i] = (float)own_random(&tmpSeed); + } + st->seed_acelp = tmpSeed; + + for ( ; i < L_frame+(L_frame/2)+l_fir_fer-1; i++) + { + noise_buf[i] = (float)own_random(&tmpSeed); + } + + /*get filter coefficients*/ + genPlcFiltBWAdap(st->sr_core, &hp_filt[0], 1, st->cummulative_damping); + + /* PLC: [ACELP: Fade-out] + * PLC: retrieve background level */ + tmp = 1.0f; + gainSynthDeemph=getLevelSynDeemph( &(tmp), A, L_SUBFR, st->preemph_fac, L_frame/L_SUBFR); + gainCNG = st->cngTDLevel/gainSynthDeemph; + + gain = st->lp_gainc; /* start-of-the-frame gain */ + + ftmp = 2.0f * gain; + + if (gainCNG > ftmp) + { + gainCNG = ftmp; + } + + st->lp_gainc = alpha * st->lp_gainc + (1.0f - alpha) * gainCNG; /* end-of-the-frame gain */ + + if( (st->last_good == UNVOICED_TRANSITION) && (coder_type == GENERIC)) + { + st->lp_gainc = gainCNG; + } + + highPassFiltering(st->last_good, L_frame+ l_fir_fer/2, noise_buf, hp_filt, l_fir_fer); + + /* Find energy normalization factor */ + pt_exc = noise_buf + l_fir_fer/2; + gain_inov = 1.0f / (float)sqrt( dotp( pt_exc, pt_exc, L_frame ) / L_frame + 0.01f ); + + /* PLC: [ACELP: Fade-out] + * PLC: Linearly attenuate the gain through the frame */ + step = (1.0f/L_frame) * (gain - st->lp_gainc); + + if ((st->last_good == UNVOICED_CLAS) && (coder_type!=UNVOICED)) /* Attenuate somewhat on unstable unvoiced */ + { + gain_inov *= 0.8f; + } + + if (st->last_good >= UNVOICED_TRANSITION) + { + float tilt_code; + + tilt_code = (float)(0.10f*(1.0f + st->voice_fac)); + gain_inov *= (1.f - tilt_code); + } + + pt_exc = noise_buf; + + /* non-causal ringing of the FIR filter */ + + for( i=0 ; i< l_fir_fer/2; i++ ) + { + *pt_exc++ *= (gain_inov * gain); + } + + /* Actual filtered random part of excitation */ + + for( i=0 ; i< L_frame; i++ ) + { + *pt_exc++ *= (gain_inov * gain); + gain -= step; + } + + for( i=0 ; i< (L_frame/2)+l_fir_fer/2; i++ ) + { + *pt_exc++ *= (gain_inov * gain); + } + + st->past_gcode = gain; + + if( st->last_good < UNVOICED_TRANSITION ) + { + mvr2r(noise_buf+l_fir_fer/2, exc, L_frame+L_frame/2); + mvr2r(harmonic_exc_buf+L_frame, st->old_exc, L_EXC_MEM_DEC); + mvr2r( exc, exc_unv, L_frame+ (L_frame/2)); /* Update exc_unv */ + } + else + { + mvr2r( noise_buf+l_fir_fer/2, exc_unv, L_frame+ (L_frame/2)); /* Update exc_unv */ + } + + /* Compute total excitation in noisebuffer to save memories */ + if(st->last_good >= UNVOICED_TRANSITION) + { + for( i=0 ; i< L_frame+1; i++ ) + { + noise_buf[i] = exc[i]+exc_unv[i]; + } + } + else + { + noise_buf = exc_unv; + } + + if(L_frame == L_FRAME) + { + interp_code_5over2(noise_buf, bwe_exc, L_frame); + set_f(voice_factors, st->last_voice_factor, NB_SUBFR); + } + else + { + interp_code_4over2(noise_buf, bwe_exc, L_frame); + set_f(voice_factors, st->last_voice_factor, NB_SUBFR16k); + } + + /*----------------------------------------------------------* + * - compute the synthesis speech * + *----------------------------------------------------------*/ + + /* Init syn buffer */ + syn = buf + M; + mvr2r(st->mem_syn2, buf, M ); + + if (st->nbLostCmpt == 1) + { + + if(st->last_good < UNVOICED_TRANSITION ) + { + mvr2r(st->mem_syn2, mem_syn_unv, M ); + } + else + { + set_zero( mem_syn_unv, M ); + } + } + else + { + mvr2r( st->mem_syn_unv_back, mem_syn_unv, M ); + } + + /* voiced synth */ + + if(st->last_good >= UNVOICED_TRANSITION) + { + p_A = A; + + for (i_subfr = 0; i_subfr < L_frame; i_subfr += L_SUBFR) + { + tmp = 0; + set_zero( h1, L_SUBFR+1 ); + set_zero( mem, M ); + h1[0] = 1.0f; + syn_filt(p_A, M,h1, h1, L_SUBFR, mem, 0); /* impulse response of LPC */ + deemph(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)); + p_A += (M+1); + } + + j=0; + for (i_subfr = 0; i_subfr < L_frame; i_subfr += L_SUBFR) + { + + for (i=0; ilast_gain_syn_deemph*gain_lpc[j]; + } + j++; + } + + for (i=L_frame; ilast_gain_syn_deemph*gain_lpc[3]; + } + p_A = A; + + for (i_subfr = 0; i_subfr < L_frame; i_subfr += L_SUBFR) + { + syn_filt(p_A, M,&exc[i_subfr], &syn[i_subfr], L_SUBFR, mem_syn, 1); + p_A += (M+1); + } + + mvr2r( mem_syn, mem_syn2, M ); + + /* synthesize ola*/ + syn_filt(p_A-(M+1), M, &exc[L_frame], &syn[L_frame], (L_frame/2), mem_syn2, 0); + } + + /* unvoiced synth */ + tmp = 0; + p_A = st->Aq_cng; + + for (i_subfr = 0; i_subfr < L_frame; i_subfr += L_SUBFR) + { + set_zero(h1, L_SUBFR+1); + set_zero(mem, M); + h1[0] = 1.0f; + syn_filt(p_A, M,h1, h1, L_SUBFR, mem, 0); /* impulse response of LPC */ + deemph(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)); + p_A += (M+1); + } + + j=0; + for (i_subfr = 0; i_subfr < L_frame; i_subfr += L_SUBFR) + { + + for (i=0; ilast_gain_syn_deemph*gain_lpc[j]; + } + j++; + } + + for (i=L_frame; ilast_gain_syn_deemph*gain_lpc[j-1]; + } + p_A = st->Aq_cng; + + for (i_subfr = 0; i_subfr < L_frame; i_subfr += L_SUBFR) + { + syn_filt(p_A, M,&exc_unv[i_subfr], &syn_unv[i_subfr], L_SUBFR, mem_syn_unv, 1); + p_A += (M+1); + } + + mvr2r(mem_syn_unv,st->mem_syn_unv_back,M); + + if(st->last_good < UNVOICED_TRANSITION) + { + mvr2r(mem_syn_unv,mem_syn,M); + } + + /* unvoiced for ola */ + syn_filt(p_A-(M+1), M,&exc_unv[i_subfr], &syn_unv[i_subfr], (L_frame/2), mem_syn_unv, 0); + + /* add separate synthesis buffers */ + if(st->last_good >= UNVOICED_TRANSITION) + { + for( i=0 ; i < L_frame; i++ ) + { + syn[i] += syn_unv[i]; + } + } + else + { + mvr2r(syn_unv,syn,L_frame+L_frame/2); + } + + + /* update buffer for the classification */ + FEC_clas_estim( syn, pitch_buf, st->L_frame, coder_type, st->codec_mode, st->mem_syn_clas_estim, &(st->clas_dec), + &st->lp_ener_bfi, st->core_brate, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1.0f, st->narrowBand, 0, + 1, st->preemph_fac, st->tcxonly, st->last_core_brate ); + + /* Update Pitch Lag memory */ + mvr2r( &st->old_pitch_buf[L_frame/L_SUBFR], st->old_pitch_buf, L_frame/L_SUBFR ); + mvr2r( pitch_buf, &st->old_pitch_buf[L_frame/L_SUBFR], L_frame/L_SUBFR ); + + /*updating enr_old parameters*/ + fer_energy(L_frame, st->last_good, syn, tmp_tc, &(st->enr_old), 1); + + /* update ACELP synthesis memory */ + mvr2r( mem_syn, st->mem_syn2, M ); + mvr2r( syn+L_frame-L_SYN_MEM, st->mem_syn_r, L_SYN_MEM ); + + /* Deemphasis and output synth */ + tmp_deemph = st->syn[M]; + deemph(syn, st->preemph_fac, L_frame+L_frame/2, &tmp_deemph); + + mvr2r(syn, synth, L_frame); + mvr2r(syn+L_frame-L_frame/2, st->old_syn_Overl, L_frame/2); + + + /* save last half frame if next frame is TCX */ + mvr2r(syn+L_frame, st->syn_Overl_TDAC, L_frame/2); + mvr2r(syn+L_frame-M-1, st->syn, 1+M); + + /* update old_Aq */ + mvr2r(p_A-(M+1), st->old_Aq_12_8, M+1); + + + mvr2r(syn+L_frame, st->syn_Overl, L_frame/2); + + W1 = st->tcx_cfg.tcx_mdct_window_length; + W2 = st->tcx_cfg.tcx_mdct_window_length/2; + + st->tcx_cfg.tcx_curr_overlap_mode = FULL_OVERLAP; + { + short n = (short)((float)L_frame*N_ZERO_MDCT_NS/FRAME_SIZE_NS); + + mvr2r(syn+L_frame-n, st->old_outLB, L_frame-n); + + for (i=0; iold_outLB[i+n] *= w[W1-1-i]*w[W1-1-i]; + } + set_zero(&st->old_outLB[W1+n], n); + } + + /* create aliasing and windowing */ + + for (i=0; isyn_Overl_TDAC[i]*w[W1-1-i]; + } + + for (i=0; isyn_Overl_TDAC[i] = buf[i]+buf[W1-1-i]; /* A-D */ + } + + for (i=0; isyn_Overl_TDAC[W2+i] = buf[W2+i]+buf[W1-1-W2-i]; /* B-C */ + } + + for (i=0; isyn_Overl_TDAC[i] *= w[W1-1-i]; + } + + /* update memory for full band */ + lerp(st->syn_Overl_TDAC, st->syn_Overl_TDACFB, st->L_frameTCX/2, L_frame/2); + lerp(st->syn_Overl, st->syn_OverlFB, st->L_frameTCX/2, L_frame/2); + lerp(st->old_outLB, st->old_out, st->L_frameTCX, L_frame); + + /* copy total excitation exc2 as 16kHz for acelp mode1 decoding */ + lerp(exc, st->old_exc2, L_EXC_MEM, L_frame); + lerp(syn, st->old_syn2, L_EXC_MEM, L_frame); + st->bfi_pitch = pitch_buf[st->nb_subfr-1]; + st->bfi_pitch_frame = L_frame; + + return; +} diff --git a/lib_dec/er_dec_tcx.c b/lib_dec/er_dec_tcx.c new file mode 100644 index 000000000..ee45858f5 --- /dev/null +++ b/lib_dec/er_dec_tcx.c @@ -0,0 +1,550 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "options.h" +#include "prot.h" +#include "rom_dec.h" + + +/*-----------------------------------------------------------------* + * con_tcx() + * + * + *-----------------------------------------------------------------*/ + +void con_tcx( + Decoder_State* st, /* i/o: coder memory state */ + float synth[] /* i/o: synth[] */ +) +{ + short i, n, L_frame, L_subfr, fLowPassFilter, T0; + int offset = 0; + int mem_syn_r_size_old, mem_syn_r_size_new; + float *noise; + float mem_syn[M], *syn; + float *exc, buf[OLD_EXC_SIZE_DEC+L_FRAME_MAX+L_FRAME_MAX/NB_SUBFR+1+L_FRAME_MAX/2]; + float pre_emph_buf; + float pitch_buf[NB_SUBFR16k], hp_filt[L_FIR_FER2]; + float predPitchLag, alpha = 0.0f; + float tmp_deemph, step, gain, gainCNG, gain_inov, ftmp; + float *pt_exc, *pt1_exc; + short Tc, tmpSeed; + short fUseExtrapolatedPitch=0; + float *ana_window; + float r[M+1], A_local[M+1], mem; + float *w; + short W1, W2; + short extrapolationFailed=1; + float gainSynthDeemph; + float tmp=0.f; + float old_pitch_buf[2*NB_SUBFR16k+2]; + + /* Framing parameters */ + L_frame = st->L_frameTCX; + L_subfr = st->L_frameTCX/st->nb_subfr; + w = st->tcx_cfg.tcx_mdct_windowFB; + W1 = st->tcx_cfg.tcx_mdct_window_lengthFB; + W2 = st->tcx_cfg.tcx_mdct_window_lengthFB/2; + + /* take the previous frame last pitch */ + Tc = (short)(st->old_fpitchFB + 0.5f); + + set_zero(buf,sizeof(buf)/sizeof(buf[0])); + + v_multc(st->old_pitch_buf, (float)L_frame / st->L_frame, old_pitch_buf, 2*NB_SUBFR16k+2); + + /* set excitation memory*/ + exc = buf+OLD_EXC_SIZE_DEC; + + tmp_deemph = synth[-1]; + pre_emph_buf = synth[-1]; + + if( st->nbLostCmpt == 1 || st->tcxConceal_recalc_exc ) + { + /* apply pre-emphasis to the signal */ + mem = synth[-(L_frame/2+st->pit_max_TCX+2*M)-1]; + + preemph(&synth[-(L_frame/2+st->pit_max_TCX+2*M)], st->preemph_fac, L_frame/2+st->pit_max_TCX+2*M, &mem); + st->lp_gainc = 0.0f; + + st->lp_gainp = get_gain( synth-2*L_subfr, synth-2*L_subfr-Tc, 2*L_subfr, NULL ); + + if(st->lp_gainp < 0.0f) + { + st->lp_gainp = 0.0f; + } + + if(st->lp_gainp > 1.0f) + { + st->lp_gainp = 1.0f; + } + ana_window = buf; + ham_cos_window(ana_window, 3*L_frame/4, L_frame/4); + + /* Autocorrelation */ + autocorr( &(synth[-L_frame-1]), r, M, L_frame, ana_window, 0, 0, 0 ); + + /* Lag windowing */ + lag_wind( r, M, st->output_Fs, LAGW_STRONG ); + + /* Levinson Durbin */ + lev_dur(A_local, r, M, NULL); + + /* copy for multiple frame loss */ + mvr2r( A_local, st->old_Aq_12_8, M+1 ); + + /* Residu */ + assert((2*L_subfr+Tc+1+M) <= st->old_synth_lenFB); + residu(A_local, M, &(synth[-(2*L_subfr+Tc+1+M)]), &(exc[-(2*L_subfr+Tc+1+M)]), 2*L_subfr+Tc+1+M); + } + else + { + /* apply pre-emphasis to the signal */ + mem = synth[-L_frame-1]; + + preemph(&synth[-L_frame], st->preemph_fac, L_frame, &mem); + mvr2r( st->old_Aq_12_8, A_local, M+1 ); + offset = L_frame/2; + + if(st->last_good >= UNVOICED_TRANSITION ) + { + i = max(Tc - L_frame/2, 0); + mvr2r(st->old_excFB, &(exc[-i]), offset+i); + } + else + { + mvr2r(st->old_excFB, &(exc[-2*L_subfr]), 2*L_subfr+offset); + } + } + + /*-----------------------------------------------------------------* + * PLC: Construct the harmonic part of excitation + *-----------------------------------------------------------------*/ + + if(st->last_good != UNVOICED_CLAS && !((st->last_good == UNVOICED_TRANSITION) && (st->core_ext_mode == GENERIC)) ) + { + if ( st->nbLostCmpt == 1 || st->tcxConceal_recalc_exc ) + { + st->lp_gainc = 0.0f; + + for ( i=0; i<2*L_subfr; i++ ) + { + st->lp_gainc += ( exc[i-2*L_subfr] - st->lp_gainp * exc[i-2*L_subfr-Tc] ) * ( exc[i-2*L_subfr] - st->lp_gainp * exc[i-2*L_subfr-Tc] ); + } + st->lp_gainc = (float)sqrt(st->lp_gainc / (2.0f*L_subfr) ); + } + if( ( st->nbLostCmpt == 1 ) && st->rf_frame_type >= RF_TCXFD && st->rf_frame_type <= RF_TCXTD2 && st->use_partial_copy ) + { + predPitchLag = (st->tcxltp_pitch_int + st->tcxltp_pitch_fr/(float)st->pit_res_max) * (float)st->L_frameTCX / (float)st->L_frame; + T0 = (int)(predPitchLag+0.5f); + + if ((T0 > 0) && (T0 != Tc) && ((float)abs(T0-Tc) < 0.15f*Tc) ) + { + fUseExtrapolatedPitch = 1; + } + } + else + { + pitch_pred_linear_fit( st->nbLostCmpt, st->last_good, old_pitch_buf, &(st->old_fpitchFB), + &predPitchLag, st->pit_min_TCX, st->pit_max_TCX, st->mem_pitch_gain, + st->output_Fs > 25600, st->plc_use_future_lag, &extrapolationFailed, st->nb_subfr); + + T0 = (int)(predPitchLag+0.5f); + + if ((T0 > 0) && (T0 != Tc) && ((float)abs(T0-Tc) < 0.15f*Tc) && extrapolationFailed == 0 ) + { + fUseExtrapolatedPitch = 1; + } + } + + fLowPassFilter = 0; + pt_exc = exc + offset; + + pt1_exc = pt_exc - Tc; + + if (fUseExtrapolatedPitch != 0) + { + pt_exc = buf; + } + + if(st->stab_fac < 1 && st->nbLostCmpt == 1 ) + { + /* pitch cycle is first low-pass filtered */ + for( i=0 ; i< Tc; i++ ) + { + if (st->output_Fs <= 16000) + { + *pt_exc++ = ( 0.0053f * pt1_exc[-5] + + 0.0000f * pt1_exc[-4] + + -0.0440f * pt1_exc[-3] + + 0.0000f * pt1_exc[-2] + + 0.2637f * pt1_exc[-1] + + 0.5500f * pt1_exc[0] + + 0.2637f * pt1_exc[1] + + 0.0000f * pt1_exc[2] + + -0.0440f * pt1_exc[3] + + 0.0000f * pt1_exc[4] + + 0.0053f * pt1_exc[5]); + } + else /*(st->output_Fs >= 32000)*/ + { + *pt_exc++ = (-0.0053f * pt1_exc[-5] + + -0.0037f * pt1_exc[-4] + + -0.0140f * pt1_exc[-3] + + 0.0180f * pt1_exc[-2] + + 0.2668f * pt1_exc[-1] + + 0.4991f * pt1_exc[0] + + 0.2668f * pt1_exc[1] + + 0.0180f * pt1_exc[2] + + -0.0140f * pt1_exc[3] + + -0.0037f * pt1_exc[4] + + -0.0053f * pt1_exc[5]); + } + pt1_exc++; + } + fLowPassFilter = 1; + } + else + { + /* copy the first pitch cycle without low-pass filtering */ + for( i=0 ; i< Tc; i++ ) + { + *pt_exc++ = *pt1_exc++; + } + fLowPassFilter = 1; + } + + if (fUseExtrapolatedPitch != 0) + { + pt1_exc = buf; + } + + for (i = 0; i < L_frame-fLowPassFilter*Tc+L_subfr; i++) + { + *pt_exc++ = *pt1_exc++; + } + + if (fUseExtrapolatedPitch != 0) + { + get_subframe_pitch(st->nb_subfr, st->old_fpitch, predPitchLag * st->L_frame/L_frame, pitch_buf); + + PulseResynchronization(buf, exc, L_frame, st->nb_subfr, st->old_fpitchFB, predPitchLag); + } + else + { + set_f(pitch_buf, st->old_fpitch, st->nb_subfr); + } + + if ( st->nbLostCmpt == 1 ) + { + pt_exc = exc+L_frame; + pt1_exc = pt_exc - ((T0 == 0) ? Tc : T0); + + for (i = 0; i < L_frame/2; i++) + { + *pt_exc++ = *pt1_exc++; + } + } + + if (fUseExtrapolatedPitch != 0) + { + st->old_fpitchFB = predPitchLag; + } + st->bpf_gain_param = 0; + + /* PLC: calculate damping factor */ + alpha = Damping_fact(st->core_ext_mode, st->nbLostCmpt, st->last_good, st->stab_fac, &(st->lp_gainp), 0 ); + + if( st->nbLostCmpt == 1 ) + { + st->cummulative_damping = 1; + } + else + { + st->cummulative_damping *= alpha; + } + + gain = 1.0f; + if( st->rf_frame_type == RF_TCXTD1 && st->use_partial_copy == 1 ) + { + gain = 0.5f; + } + + step = (1.0f/(L_frame+(L_frame/2))) * (gain - alpha); + + /* PLC: Apply fade out */ + for( i=offset; i < L_frame+(L_frame/2); i++ ) + { + exc[i] *= gain; + gain -= step; + } + + offset = max(((short)(st->old_fpitchFB + 0.5f)) - L_frame/2, 0); + mvr2r(exc+L_frame-offset, st->old_excFB, L_frame/2+offset); + + /* copy old_exc as 16kHz for acelp decoding */ + if(st->nbLostCmpt == 1) + { + lerp(exc-L_frame/2, st->old_exc, L_EXC_MEM_DEC, L_frame+L_frame/2); + } + else + { + mvr2r(st->old_exc+L_FRAME16k, st->old_exc, L_FRAME16k/2); + lerp(exc, st->old_exc+L_FRAME16k/2, L_FRAME16k, L_frame); + } + } + else + { + /* No harmonic part */ + set_zero(&exc[0], L_frame+L_frame/2); + + if ( st->nbLostCmpt == 1 ) + { + st->lp_gainc = 0.0f; + + for ( i=0; i<2*L_subfr; i++ ) + { + st->lp_gainc += ( exc[i-2*L_subfr] ) * ( exc[i-2*L_subfr]); + } + st->lp_gainc = (float)sqrt(st->lp_gainc / (2.0f*L_subfr) ); + } + + set_f( pitch_buf, (float)L_SUBFR, st->nb_subfr); + + /* PLC: calculate damping factor */ + alpha = Damping_fact(st->core_ext_mode, st->nbLostCmpt, st->last_good, st->stab_fac, &(st->lp_gainp), 0); + } + + /*-----------------------------------------------------------------* + * Construct the random part of excitation + *-----------------------------------------------------------------*/ + + tmpSeed = st->seed_acelp; + noise = buf; + + for (i = 0; i < L_frame+L_FIR_FER2-1; i++) + { + noise[i] = (float)own_random(&tmpSeed); + } + st->seed_acelp = tmpSeed; + + for ( ; i < L_frame+(L_frame/2)+2*L_FIR_FER2; i++) + { + noise[i] = (float)own_random(&tmpSeed); + } + + if (st->last_good == VOICED_CLAS || st->last_good == ONSET) + { + mem = noise[0]; + preemph(&noise[1], st->output_Fs<=16000 ? 0.2f : 0.6f, L_frame+(L_frame/2)+L_FIR_FER2, &mem); + } + + /* high rate filter tuning */ + if(st->output_Fs<=16000) + { + for( i=0; i< L_FIR_FER2; i++ ) + { + hp_filt[i] = h_high3_16[i]; + } + } + else /*(st->output_Fs==32000)*/ + { + for( i=0; i< L_FIR_FER2; i++ ) + { + hp_filt[i] = h_high3_32[i]; + } + } + + if ( st->nbLostCmpt == 1 ) + { + highPassFiltering(st->last_good, L_frame+L_frame/2+L_FIR_FER2, noise, hp_filt, L_FIR_FER2); + } + else + { + if(st->last_good > UNVOICED_TRANSITION ) + { + for( i=0 ; i< L_frame+L_frame/2+L_FIR_FER2; i++ ) + { + noise[i] = (1-st->cummulative_damping)*noise[i]+ st->cummulative_damping*dotp(&noise[i], hp_filt, L_FIR_FER2 ); + } + } + } + + /* PLC: [TCX: Fade-out] retrieve background level */ + tmp = 1.0f; + gainSynthDeemph = getLevelSynDeemph(&(tmp), A_local, L_frame/4, st->preemph_fac, 1); + if (st->tcxonly) + { + gainCNG = st->CngLevelBackgroundTrace_bfi/gainSynthDeemph; + } + else + { + gainCNG = st->cngTDLevel/gainSynthDeemph; + } + gain = st->lp_gainc; /* start-of-the-frame gain */ + + if( st->rf_frame_type == RF_TCXTD1 && st->use_partial_copy == 1 ) + { + gain *= 0.7f; + } + + ftmp = 2.0f * gain; + + if (gainCNG > ftmp) + { + gainCNG = ftmp; + } + + st->lp_gainc = alpha * st->lp_gainc + (1.0f - alpha) * gainCNG; /* end-of-the-frame gain */ + + /* PLC: [TCX: Fade-out] Linearly attenuate the gain through the frame */ + step = (1.0f/L_frame) * (gain - st->lp_gainc); + pt_exc = noise + L_FIR_FER2/2; + + gain_inov = 1.0f / (float)sqrt( dotp( pt_exc, pt_exc, L_frame ) / L_frame + 0.01f );/* normalize energy */ + + if ((st->last_good == UNVOICED_CLAS) && (st->core_ext_mode != UNVOICED)) + { + gain_inov *= 0.8f; + } + else if (!((st->last_good == UNVOICED_CLAS) || (st->last_good == UNVOICED_TRANSITION))) + { + gain_inov *= (1.1f - 0.75f * st->lp_gainp); + } + st->lp_gainp = alpha; + pt_exc = noise; /* non-causal ringing of the FIR filter */ + + for( i=0 ; i< L_FIR_FER2/2; i++ ) + { + *pt_exc++ *= (gain_inov * gain); + } + + for( i=0 ; i< L_frame+L_FIR_FER2/2; i++ ) /* Actual filtered random part of excitation */ + { + *pt_exc++ *= (gain_inov * gain); + gain -= step; + } + + for( i=0 ; i< (L_frame/2); i++ ) /* causal ringing of the FIR filter */ + { + *pt_exc++ *= (gain_inov * gain); + } + + /*-----------------------------------------------------------------* + * Construct the total excitation + *-----------------------------------------------------------------*/ + + if(st->last_good >= UNVOICED_TRANSITION ) + { + for( i=0 ; i< (L_frame+L_frame/2); i++ ) + { + exc[i] += noise[i+(L_FIR_FER2/2)]; + } + } + else + { + mvr2r(noise+L_FIR_FER2/2, exc, L_frame+L_frame/2); + mvr2r(exc+L_frame-2*L_subfr, st->old_excFB, 2*L_subfr+L_frame/2); + + /* copy old_exc as 16kHz for acelp decoding */ + if(st->nbLostCmpt == 1) + { + lerp(exc, st->old_exc, L_EXC_MEM_DEC, L_frame+L_frame/2); + } + else + { + mvr2r(st->old_exc+L_FRAME16k, st->old_exc, L_FRAME16k/2); + lerp(exc, st->old_exc+L_FRAME16k/2, L_FRAME16k, L_frame); + } + } + + /* Update Pitch Lag memory */ + mvr2r( &st->old_pitch_buf[st->nb_subfr], st->old_pitch_buf, st->nb_subfr ); + mvr2r( pitch_buf, &st->old_pitch_buf[st->nb_subfr], st->nb_subfr ); + + /*----------------------------------------------------------* + * - compute the synthesis speech * + *----------------------------------------------------------*/ + + syn = buf + M; + mvr2r(synth-M, buf, M); + mvr2r( buf, mem_syn, M); + + syn_filt(A_local, M, &exc[0], &syn[0], L_frame+ (L_frame/2), mem_syn, 1); + + n = (short)((float)L_frame*N_ZERO_MDCT_NS/FRAME_SIZE_NS); + + /* update ACELP synthesis memory */ + mem_syn_r_size_old=(int)(1.25*L_frame/20.f); + + /* copy mem_syn as 16kHz */ + mem_syn_r_size_new=(int)(1.25*L_FRAME16k/20.f); + mvr2r(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 ); + mvr2r( st->mem_syn_r+L_SYN_MEM-M, st->mem_syn2, M ); + + /* Deemphasis and output synth and ZIR */ + deemph(syn, st->preemph_fac, L_frame+L_frame/2, &tmp_deemph); + mvr2r(syn+L_frame-M-1, st->syn, 1+M); + + + lerp( syn+L_frame-L_frame/2, st->old_syn_Overl, st->L_frame/2, L_frame/2 ); + mvr2r(syn+L_frame-n, st->old_out, L_frame-n); + + for (i = 0; i < W1; i++) + { + st->old_out[i+n] *= w[W1-1-i]*w[W1-1-i]; + } + set_zero(&st->old_out[W1+n], n); + + mvr2r(syn, synth, L_frame); + + mvr2r(syn+L_frame, st->syn_OverlFB, L_frame/2); + + /* copy total excitation exc2 as 16kHz for ACELP MODE1 decoding */ + lerp( exc, st->old_exc2, L_EXC_MEM, L_frame ); + lerp( syn, st->old_syn2, L_EXC_MEM, L_frame ); + st->bfi_pitch = pitch_buf[st->nb_subfr-1]; + st->bfi_pitch_frame = st->L_frame; + + /* create aliasing and windowing need for transition to TCX10/5 */ + mvr2r(syn+L_frame, st->syn_Overl_TDACFB, L_frame/2); + + for (i=0; isyn_Overl_TDACFB[i]*w[W1-1-i]; + } + + for (i=0; isyn_Overl_TDACFB[i] = buf[i]+buf[W1-1-i]; /* A-D */ + } + + for (i=0; isyn_Overl_TDACFB[W2+i] = buf[W2+i]+buf[W1-1-W2-i];/* B-C */ + } + + for (i=0; isyn_Overl_TDACFB[i] *= w[W1-1-i]; + } + + st->tcx_cfg.tcx_curr_overlap_mode = FULL_OVERLAP; + synth[-1] = pre_emph_buf; + /* update memory for low band */ + lerp( st->syn_OverlFB, st->syn_Overl, st->L_frame/2, L_frame/2 ); + lerp( st->syn_Overl_TDACFB, st->syn_Overl_TDAC, st->L_frame/2, L_frame/2 ); + lerp( st->old_out, st->old_outLB, st->L_frame, L_frame ); + + + st->old_enr_LP = enr_1_Az( A_local, L_SUBFR ); + + return; +} diff --git a/lib_dec/er_scale_syn.c b/lib_dec/er_scale_syn.c new file mode 100644 index 000000000..5ef7b8156 --- /dev/null +++ b/lib_dec/er_scale_syn.c @@ -0,0 +1,104 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "prot.h" +#include "cnst.h" + + + +#define WMC_TOOL_SKIP + + +/*----------------------------------------------------------------------------------* +* Damping_fact() +* +* Estimate damping factor +*----------------------------------------------------------------------------------*/ + +float Damping_fact( const short coder_type, int nbLostCmpt, short last_good, float stab_fac, float *lp_gainp, int core) +{ + float alpha, gain; + + if(core == ACELP_CORE) + { + alpha = ALPHA_VT;/* rapid convergence to 0 */ + if( ( coder_type == UNVOICED) && (nbLostCmpt <= 3)) /* Clear unvoiced last good frame */ + { + alpha = ALPHA_UU; + } + else if( last_good == UNVOICED_CLAS ) + { + if( nbLostCmpt == 1 ) + { + /* If stable, do not decrease the energy, pitch gain = 0 */ + alpha = stab_fac * (1.0f - 2.0f*ALPHA_U) + 2.0f*ALPHA_U; /* [0.8, 1.0] */ + } + else if (nbLostCmpt == 2 ) + { + alpha = ALPHA_U*1.5f; /* 0.6 */ + } + else + { + alpha = ALPHA_U; /* 0.4 go rapidly to CNG gain, pitch gain = 0 */ + } + } + else if( last_good == UNVOICED_TRANSITION ) + { + alpha = ALPHA_UT; + } + else if( (last_good == ONSET) && (nbLostCmpt <= 3) && (coder_type == GENERIC)) + { + alpha = 0.8f; + } + else if( ( (last_good == VOICED_CLAS) || (last_good == ONSET) ) && (nbLostCmpt <= 3) ) + { + alpha = ALPHA_V; /* constant for the first 3 erased frames */ + } + if(last_good >= VOICED_CLAS) + { + if( nbLostCmpt == 1 ) /* if first erased frame in a block, reset harmonic gain */ + { + gain = (float)sqrt( *lp_gainp ); /* move pitch gain towards 1 for voiced to remove energy fluctuations */ + + if( gain > 0.98f ) + { + gain = 0.98f; + } + else if( gain < 0.85f ) + { + gain = 0.85f; + } + alpha *= gain; + } + else if( nbLostCmpt == 2 ) + { + alpha = (0.6f+0.35f*stab_fac)**lp_gainp; + } + else + { + *lp_gainp *= (0.7f+0.2f*stab_fac); + alpha = *lp_gainp; + } + } + } + else + { + if (nbLostCmpt < 2) + { + alpha = (0.7f+0.3f*stab_fac); + } + else if (nbLostCmpt == 2) + { + alpha = (0.45f+0.4f*stab_fac); + } + else + { + alpha = 0.35f+0.4f*stab_fac; + } + } + return alpha; +} diff --git a/lib_dec/er_sync_exc.c b/lib_dec/er_sync_exc.c new file mode 100644 index 000000000..3d5be2035 --- /dev/null +++ b/lib_dec/er_sync_exc.c @@ -0,0 +1,301 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + + +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" +#include "cnst.h" +#include +#include +#include +#include + + +#define NB_PULSES_MAX 15 + +/*------------------------------------------------------------------------- +* +* Perform resynchronisation of the last glottal pulse in voiced lost frame +* +*------------------------------------------------------------------------*/ + + +/** Get the location of the minimum energy in the given signal. + * @param x Input signal. + * @param length The length of the input signal. + * @param filterLength the length of the filter length used for the energy calculation. + * @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 int GetMinimumPosition(float const * x, int length, int filterLength) +{ + int iMinEnergyPos, center, i; + float energy, minEnergy; + + + + filterLength = min(filterLength, length); + center = filterLength/2; + iMinEnergyPos = center; + if (filterLength > 0) + { + minEnergy = sum2_f(x, filterLength); + energy = 0; + center += 1; /* To avoid adding 1 in the loop */ + for (i = 0; i < length-filterLength; i++) + { + energy -= x[i]*x[i]; + energy += x[i+filterLength]*x[i+filterLength]; + if (energy < 0) + { + minEnergy += energy; + energy = 0; + iMinEnergyPos = i+center; + } + } + } + + return iMinEnergyPos; +} + +/** Get the location of the maximum peak in the given signal. + * @param x Input signal. + * @param length The length of the input signal. + * @returns Index of the position of the maximum peak, that is the position i where abs(x[i]) has it's maximum. + */ +static int FindMaxPeak(float const * x, int length) +{ + int iMax, i; + float maxVal; + + + + iMax = 0; + maxVal = 0.0f; + for (i = 0; i < length; i++) + { + float const absVal = (float)fabs(x[i]); + if (absVal > maxVal) + { + maxVal = absVal; + iMax = i; + } + } + + return iMax; +} + +static void AddSamples(float const * old_exc, float * new_exc, int L_frame, int n_samples_to_add, int const min_pos[], int const points_by_pos[], int nb_min) +{ + float * pt_dest; + float const * pt_src; + int last_min_pos, i, j; + + + + pt_dest = new_exc; + pt_src = old_exc; + last_min_pos = 0; + for (i = 0; i < nb_min; i++) + { + float ftmp; + /* Copy section */ + for (j = min_pos[i] - last_min_pos; j > 0; j--) + { + *pt_dest++ = *pt_src++; + } + /* Add some samples */ + ftmp = -(*pt_src/20); + for (j = 0; j < points_by_pos[i]; j++) + { + *pt_dest++ = ftmp; + ftmp = -ftmp; + } + /* Prepare for the next loop iteration */ + last_min_pos = min_pos[i]; + } + /* Copy remaining length */ + for (j = L_frame-n_samples_to_add-last_min_pos; j > 0; j--) + { + *pt_dest++ = *pt_src++; + } + +} + +static void RemoveSamples(float const * old_exc, float * new_exc, int L_frame, int n_samples_to_add, int const min_pos[], int const points_by_pos[], int nb_min) +{ + float * pt_dest; + float const * pt_src; + int last_min_pos, i, j; + + + pt_dest = new_exc+L_frame; + last_min_pos = L_frame-n_samples_to_add; + for(i = nb_min-1; i >= 0; i--) + { + /* Compute len to copy */ + /* Copy section, removing some samples */ + pt_src = old_exc+last_min_pos; + for (j = last_min_pos - (min_pos[i]+points_by_pos[i]); j > 0; j--) + { + *--pt_dest = *--pt_src; + } + /* Prepare for the next loop iteration */ + last_min_pos = min_pos[i]; + } + /* Copy remaining length */ + pt_src = old_exc+last_min_pos; + for (j = last_min_pos; j > 0; j--) + { + *--pt_dest = *--pt_src; + } + +} + +/** Resynchronize glottal 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(float const * src_exc, float * dst_exc, int nFrameLength, int nSubframes, float pitchStart, float pitchEnd) +{ + int T0, i, k; + float pitchDelta, samplesDelta, perCycleDeltaDelta, cycleDelta, freqStart, fractionalLeft, absPitchDiff; + int roundedPitchStart, nSamplesDelta, nSamplesDeltaRemain, iMinPos1, iMinPos[NB_PULSES_MAX+1], iDeltaSamples[NB_PULSES_MAX+1], maxDeltaSamples, roundedCycleDelta; + + + + assert((nFrameLength > 0) && (nFrameLength > pitchStart) && (nSubframes > 1) && (nSubframes <= 5) && (nFrameLength%nSubframes == 0) && (pitchStart > 0) && (pitchEnd > 0) && (pitchEnd/pitchStart > 1-2.0f/(nSubframes+1)) && (src_exc != NULL) && (dst_exc != NULL) && (src_exc < dst_exc)); + + pitchDelta = (pitchEnd - pitchStart)/nSubframes; + roundedPitchStart = (int)(pitchStart+0.5f); + freqStart = 1.0f/roundedPitchStart; + + /* Calculate number of samples to be removed (if negative) or added (if positive) */ + samplesDelta = 0.5f*pitchDelta*nFrameLength*(nSubframes+1)*freqStart; + samplesDelta -= nFrameLength*(1.0f-pitchStart*freqStart); + /* 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 = (int)floor(samplesDelta+0.5f); + nSamplesDeltaRemain = abs(nSamplesDelta); + /* Find the location of the glottal pulse */ + T0 = FindMaxPeak(src_exc, roundedPitchStart); + /* Get the index of the last pulse in the resynchronized frame */ + k = (int)ceil((nFrameLength-nSamplesDelta-T0)*freqStart - 1); + if ((k >= 0) && (k+1 <= NB_PULSES_MAX)) + { + absPitchDiff = (float)fabs(roundedPitchStart-pitchEnd); + /* 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)); + /* Calculate the integer number of samples to be added/removed in each pitch cycle */ + cycleDelta = max(0, (absPitchDiff-(k+1)*perCycleDeltaDelta)*T0*freqStart); + roundedCycleDelta = (int)(cycleDelta); + iDeltaSamples[0] = roundedCycleDelta; + fractionalLeft = cycleDelta-roundedCycleDelta; + nSamplesDeltaRemain -= roundedCycleDelta; + for (i = 1; i <= k; i++) + { + cycleDelta = (absPitchDiff-(k+1-i)*perCycleDeltaDelta) + fractionalLeft; + cycleDelta = max(0, cycleDelta); + /* Make sure that the number of samples increases */ + if (roundedCycleDelta > cycleDelta) + { + iDeltaSamples[i] = roundedCycleDelta; + roundedCycleDelta = (int)(cycleDelta); + iDeltaSamples[i-1] = roundedCycleDelta; + + } + else + { + roundedCycleDelta = (int)(cycleDelta); + iDeltaSamples[i] = roundedCycleDelta; + } + fractionalLeft = cycleDelta-roundedCycleDelta; + nSamplesDeltaRemain -= roundedCycleDelta; + } + iDeltaSamples[k+1] = max(0, nSamplesDeltaRemain); + maxDeltaSamples = max(iDeltaSamples[k], iDeltaSamples[k+1]); + + /* 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); + if (nSamplesDelta < 0) + { + /* Find the location of the minimum energy before the first pulse */ + if (iMinPos1 > roundedPitchStart + iDeltaSamples[0]/2) + { + iMinPos[0] = iMinPos1 - roundedPitchStart - iDeltaSamples[0]/2; + } + else + { + iMinPos[0] = GetMinimumPosition(src_exc, T0, iDeltaSamples[0]) - iDeltaSamples[0]/2; + } + /* Find the location of the minimum energy between the pulses */ + for (i = 1; i <= k; i++) + { + iMinPos[i] = iMinPos1 + (i-1)*roundedPitchStart - iDeltaSamples[i]/2; + } + /* Find the location of the minimum energy after the last pulse */ + if (iMinPos1 + k*roundedPitchStart + iDeltaSamples[k+1] - iDeltaSamples[k+1]/2 < nFrameLength-nSamplesDelta) + { + iMinPos[k+1] = iMinPos1 + k*roundedPitchStart - iDeltaSamples[k+1]/2; + } + 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; + } + if (iMinPos[k+1]+iDeltaSamples[k+1] > nFrameLength-nSamplesDelta) + { + iDeltaSamples[k] += iMinPos[k+1]+iDeltaSamples[k+1] - (nFrameLength-nSamplesDelta); + iDeltaSamples[k+1] = nFrameLength-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 (iMinPos1 > roundedPitchStart) + { + iMinPos[0] = iMinPos1 - roundedPitchStart; + } + else + { + iMinPos[0] = GetMinimumPosition(src_exc, T0, iDeltaSamples[0]); + } + /* Find the location of the minimum energy between the pulses */ + for (i = 1; i <= k; i++) + { + iMinPos[i] = iMinPos1; + iMinPos1 += roundedPitchStart; + } + /* Find the location of the minimum energy after the last pulse */ + if (iMinPos1 < nFrameLength-nSamplesDelta) + { + iMinPos[k+1] = iMinPos1; + } + else + { + iMinPos[k+1] = T0+k*roundedPitchStart + + GetMinimumPosition(src_exc+T0+k*roundedPitchStart, nFrameLength-nSamplesDelta-(T0+k*roundedPitchStart), iDeltaSamples[k+1]); + } + if (iMinPos[k+1]+iDeltaSamples[k+1] > nFrameLength-nSamplesDelta) + { + iDeltaSamples[k] += iMinPos[k+1]+iDeltaSamples[k+1] - (nFrameLength-nSamplesDelta); + iDeltaSamples[k+1] = 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 000000000..d22b21522 --- /dev/null +++ b/lib_dec/er_util.c @@ -0,0 +1,288 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "prot.h" +#include "cnst.h" +#include "stat_com.h" + + +/* PLC: [Common: Fade-out] + * PLC: and for PLC fade out */ + +void minimumStatistics( + float* noiseLevelMemory, + int* noiseLevelIndex, + int* currLevelIndex, + float* noiseEstimate, + float* lastFrameLevel, + float currentFrameLevel, + float const minLev, + int const buffSize +) +{ + float aOpt; + float f; + int p; + int i; + + if (currentFrameLevel < minLev) + { + currentFrameLevel = minLev; + } + /* compute optimal factor aOpt for recursive smoothing of frame minima */ + if (*lastFrameLevel >= *noiseEstimate) + { + aOpt = *noiseEstimate / *lastFrameLevel; + } + else + { + aOpt = *lastFrameLevel / *noiseEstimate; + } + aOpt *= aOpt; + *lastFrameLevel = currentFrameLevel; + /* recursively compute smoothed frame minima using optimal factor aOpt */ + f = currentFrameLevel * (1.0f - aOpt); + f += aOpt * noiseLevelMemory[(*currLevelIndex ? *currLevelIndex : buffSize)-1]; + /* if current frame min is a new local min, set index to current index */ + p = *noiseLevelIndex; + if (noiseLevelMemory[p] >= f) + { + noiseLevelMemory[*currLevelIndex] = f; + p = *currLevelIndex; + } + else + { + noiseLevelMemory[*currLevelIndex] = f; + /* current min is not a new min, so check if min must be re-searched */ + if (p != *currLevelIndex) + { + f = noiseLevelMemory[p]; /* min is still in memory, so return it */ + } + else + { + /* p == currLevelIndex; min was removed from memory, re-search min */ + for (i = *currLevelIndex + 1; i < buffSize; i++) + { + if (f >= noiseLevelMemory[i]) + { + f = noiseLevelMemory[i]; + p = i; + } + } + for (i = 0; i <= *currLevelIndex; i++) + { + if (f >= noiseLevelMemory[i]) + { + f = noiseLevelMemory[i]; + p = i; + } + } + } + } + /* update local-minimum-value index and current circular-buffer index */ + *noiseLevelIndex = p; + p = *currLevelIndex + 1; + *currLevelIndex = (p == buffSize) ? 0 : p; + + *noiseEstimate = f; + + return; +} + + +/*----------------------------------------------------------------------* + * PLC: [ACELP: Fade-out] + * PLC: getLevelSynDeemph: derives on frame or subframe basis the level + * of LPC synthesis and deeemphasis based on the given input + *----------------------------------------------------------------------*/ +float getLevelSynDeemph(float const h1Init[], /* i: input value or vector to be processed */ + float const A[], /* i: LPC coefficients */ + int const lenLpcExc, /* i: length of the LPC excitation buffer */ + float const preemph_fac, /* i: preemphasis factor */ + int const numLoops) /* i: number of loops */ +{ + float levelSynDeemphSub; + float levelSynDeemph = 0; + float h1[L_FRAME_PLUS/4]; + float mem[M]; + float tmp = 0; + int loop; + + for (loop = 0; loop < numLoops; loop++) + { + set_zero(h1, lenLpcExc); + set_zero(mem, M); + + h1[0] = *h1Init; + + syn_filt(A, M, h1, h1, lenLpcExc, mem, 0); + deemph(h1, preemph_fac, lenLpcExc, &tmp); + A += (M+1); + + /* gain introduced by synthesis+deemphasis */ + levelSynDeemphSub = (float)sqrt(dotp( h1, h1, lenLpcExc)); + + /* mean of the above across all subframes */ + levelSynDeemph += (1.0f/(float)numLoops) * levelSynDeemphSub; + } + return levelSynDeemph; +} + +void genPlcFiltBWAdap(int const sr_core, /* i: core sampling rate */ + float* lpFiltAdapt, /* o: filter coefficients for filtering codebooks in case of flc */ + int const type, /* i: type of filter, either 0 : lowpass or 1 : highpass */ + float const alpha /* i: fade out factor [0 1) used decrease filter tilt */ + ) +{ + float a; + switch (sr_core) + { + case 16000 : + a = 0.4000f; + break; + default : + a = 0.2813f; /*sr_core = 12800*/ + break; + } + switch (type) + { + case 0 : + *lpFiltAdapt++ = a/(2.f*a+1.f); + *lpFiltAdapt++ = 1.f/(2.f*a+1.f); + *lpFiltAdapt = a/(2.f*a+1.f); + break; + case 1 : + a *= alpha; + *lpFiltAdapt++ = -a/(2.f*a+1.f); + *lpFiltAdapt++ = 1.f/(2.f*a+1.f); + *lpFiltAdapt = -a/(2.f*a+1.f); + break; + default : + fprintf(stderr,"PLC: Filter type neither lowpass nor highpass.\n"); + assert(0); + break; + } + +} + + +/*-----------------------------------------------------------------* + * PLC: [ACELP: general] + * PLC: high pass filtering + *-----------------------------------------------------------------*/ +void highPassFiltering(const short last_good, /* i: last classification type */ + const int L_buffer, /* i: buffer length */ + float exc2[], /* i/o: unvoiced excitation before the high pass filtering */ + const float hp_filt[], /* i: high pass filter coefficients */ + const int l_fir_fer) /* i: high pass filter length */ +{ + int i; + + if( last_good > UNVOICED_TRANSITION ) + { + for( i=0 ; i< L_buffer; i++ ) + { + exc2[i] = dotp(&exc2[i], hp_filt, l_fir_fer); + } + } +} + + +/*----------------------------------------------------------------------------------* + * PLC: [Common: mode decision] + * PLC: Decide which Concealment to use. Update pitch lags if needed + *----------------------------------------------------------------------------------*/ +int GetPLCModeDecision(Decoder_State *st /* i/o: decoder memory state pointer */ + ) +{ + int core; + int numIndices = 0; + if( st->flagGuidedAcelp == 1 ) + { + /* update mem_lag according to info available on future frame */ + st->old_pitch_buf[2*st->nb_subfr] = (float)st->guidedT0; + st->old_pitch_buf[2*st->nb_subfr+1] = (float)st->guidedT0; + st->mem_pitch_gain[0] = st->mem_pitch_gain[1] = 1.f; + } + if(( st->last_core > ACELP_CORE && st->tcxltp_last_gain_unmodified != 0 ) || ( st->flagGuidedAcelp == 1 )) + { + /* no updates needed here, because already updated in last good frame */ + st->plc_use_future_lag = 1; + } + else + { + st->plc_use_future_lag = 0; + } + if (st->last_core == -1) + { + if (st->Opt_AMR_WB) + { + core = 0; + } + else + { + core = 1; + } + st->last_core = ACELP_CORE; + st->tonal_mdct_plc_active = 0; + } + else + { + core = 0; + if (st->nbLostCmpt > 1) + { + core = st->last_core_bfi; + } + + /* no FD TCX PLC after a TCX transition frame: the appropriate framing is not implemented */ + if (st->nbLostCmpt == 1) + { + st->tonal_mdct_plc_active = 0; + if ( !(st->rf_flag && st->use_partial_copy && (st->rf_frame_type == RF_TCXTD1 || st->rf_frame_type == RF_TCXTD2))) + { + if ((st->last_core == TCX_20_CORE) + && (st->second_last_core == TCX_20_CORE) + && ((st->old_fpitch <= 0.5f*st->L_frame) || (st->tcxltp_last_gain_unmodified <= 0.4f)) + /* 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 */ + && (st->old_fpitch == st->tcxltp_second_last_pitch) + && !st->last_tns_active + && !st->second_last_tns_active) + { + + TonalMDCTConceal_Detect(&st->tonalMDCTconceal, + (st->tcxltp_last_gain_unmodified > 0) ? st->old_fpitch : 0, + &numIndices); + if ((numIndices > 10) + || ((numIndices > 5) + && (fabs(st->tcxltp_third_last_pitch-st->tcxltp_second_last_pitch) < 0.5f) + ) + || ((numIndices > 0) && ((st->last_good <= UNVOICED_TRANSITION) || (st->tcxltp_last_gain_unmodified <= 0.4f)) + && (fabs(st->tcxltp_third_last_pitch-st->tcxltp_second_last_pitch) < 0.5f) + )) + { + core = 1; + st->tonal_mdct_plc_active = 1; + } + else if (st->last_good <= UNVOICED_TRANSITION || st->tcxltp_last_gain_unmodified <= 0.4f) + { + core = 1; + } + } + else if (st->last_core != ACELP_CORE) + { + if (st->last_good <= UNVOICED_TRANSITION || st->tcxltp_last_gain_unmodified <= 0.4f) + { + core = st->last_core; + } + } + } + } + } + return core; +} diff --git a/lib_dec/evs_dec.c b/lib_dec/evs_dec.c new file mode 100644 index 000000000..be290b343 --- /dev/null +++ b/lib_dec/evs_dec.c @@ -0,0 +1,1041 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*--------------------------------------------------------------------------* + * evs_dec() + * + * Principal decoder routine + *--------------------------------------------------------------------------*/ + +void evs_dec( + Decoder_State *st, /* i/o: Decoder state structure */ + float *output, /* o : output synthesis signal */ + frameMode frameMode /* i : Decoder frame mode */ +) +{ + short i, output_frame, coder_type; + short sharpFlag; + float synth[L_FRAME48k + HQ_DELTA_MAX*HQ_DELAY_COMP]; + float hb_synth[L_FRAME48k]; + float tmp_buffer[L_FRAME48k]; + short tmps, incr; + float bwe_exc_extended[L_FRAME32k+NL_BUFF_OFFSET]; + float voice_factors[NB_SUBFR16k]; + float fb_exc[L_FRAME16k]; + short core_switching_flag; + float old_syn_12k8_16k[L_FRAME16k]; + float tmp; + float pitch_buf[NB_SUBFR16k]; + short unbits; + short hq_core_type; + short post_hq_delay; + short sid_bw; + short delay_comp, delta, delay_tdbwe; + float tmpF; + short concealWholeFrame; /* status after decoding */ + short concealWholeFrameTmp; + float pcmbufFB[L_FRAME_MAX]; + + push_wmops("evs_dec"); + + /*------------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + + delay_tdbwe=0; + sid_bw = -1; + concealWholeFrameTmp = -1; + if( !st->bfi ) + { + st->extl = -1; + } + + output_frame = (short)(st->output_Fs / 50); + + core_switching_flag = 0; + sharpFlag = 0; + unbits = 0; + + st->use_partial_copy = 0; + st->rf_flag = 0; + + if( st->bfi == 1 ) + { + hq_core_type = st->last_hq_core_type; + coder_type = st->last_coder_type; + } + else + { + hq_core_type = -1; + coder_type = INACTIVE; + } + + /* PLC: [TCX: Fade-out-recovery] + * PLC: overlapping part needs to be attenuated for first good frame */ + if (!st->bfi && st->prev_bfi && (st->last_codec_mode == MODE2) && (st->last_core_bfi == TCX_20_CORE || st->last_core_bfi == TCX_10_CORE)) + { + v_multc( st->old_out, st->plcInfo.recovery_gain, st->old_out, st->L_frameTCX ); + v_multc( st->old_outLB, st->plcInfo.recovery_gain, st->old_outLB, st->L_frame ); + + if( !st->tcx_cfg.last_aldo ) + { + v_multc( st->syn_OverlFB, st->plcInfo.recovery_gain, st->syn_OverlFB, st->tcx_cfg.tcx_mdct_window_lengthFB ); + v_multc( st->syn_Overl, st->plcInfo.recovery_gain, st->syn_Overl, st->tcx_cfg.tcx_mdct_window_length ); + } + } + + set_f( voice_factors, 0.f, NB_SUBFR16k ); + set_f( hb_synth, 0.0f, L_FRAME48k ); + + st->rate_switching_reset = 0; + + if(!st->bfi) + { + st->flagGuidedAcelp = 0; + } + + /*----------------------------------------------------------------* + * Updates in case of AMR-WB IO mode -> EVS primary mode switching + *----------------------------------------------------------------*/ + + if( st->last_core == AMR_WB_CORE ) + { + updt_IO_switch_dec( output_frame, st ); + } + + if( frameMode != FRAMEMODE_MISSING ) /* frame mode normal or future frame */ + { + getPartialCopyInfo(st, &coder_type, &sharpFlag); + + frameMode = st->bfi; + } + + if( st->rf_frame_type == RF_NO_DATA && st->use_partial_copy ) + { + /* the partial copy is a RF FRAME_NO_DATA frame and should follow the concealment path*/ + st->bfi = 1; + st->codec_mode = st->last_codec_mode; + frameMode = FRAMEMODE_MISSING; + st->use_partial_copy = 0; + } + + /* if previous frame was concealed via ACELP, drop TCX partial copy info and continue ACELP concealment */ + if( st->use_partial_copy && st->core == TCX_20_CORE && st->prev_bfi && st->last_core == ACELP_CORE ) + { + st->bfi = 1; + st->codec_mode = st->last_codec_mode; + frameMode = FRAMEMODE_MISSING; + st->use_partial_copy = 0; + st->core = ACELP_CORE; + } + + /* if previous frame was HQ Core/TCX10/TCX20 (high bitrate), drop partial copy info and continue HQ Core/TCX10/TCX20 concealment */ + if( st->use_partial_copy && (st->last_core == HQ_CORE || st->last_core == TCX_10_CORE || (st->last_core == TCX_20_CORE && getTcxonly(st->last_total_brate))) ) + { + st->bfi = 1; + st->codec_mode = st->last_codec_mode; + frameMode = FRAMEMODE_MISSING; + st->use_partial_copy = 0; + st->core = st->last_core; + } + + /*------------------------------------------------------------------* + * Decoding + *-----------------------------------------------------------------*/ + + if( st->codec_mode == MODE1 ) + { + /*------------------------------------------------------------------* + * Decision matrix (selection of technologies) + *-----------------------------------------------------------------*/ + + /* decision matrix (selection of technologies) */ + if( st->bfi != 1 ) + { + decision_matrix_dec( st, &coder_type, &sharpFlag, &hq_core_type, &core_switching_flag ); + + if( st->bfi != 1 ) + { + st->sr_core = 50*st->L_frame; + st->fscale_old = st->fscale; + st->fscale = sr2fscale(st->sr_core); + } + else + { + frameMode = FRAMEMODE_MISSING; + } + } + } + + + if( st->codec_mode == MODE1 ) + { + /*------------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + + if( st->bfi == 1 ) + { + st->nbLostCmpt++; + } + else + { + st->nbLostCmpt = 0; + } + st->enablePlcWaveadjust = 0; + + /*---------------------------------------------------------------------* + * Detect bandwidth switching + *---------------------------------------------------------------------*/ + + bandwidth_switching_detect( st ); + + /*---------------------------------------------------------------------* + * Preprocessing (preparing) for ACELP/HQ core switching + *---------------------------------------------------------------------*/ + + core_switching_pre_dec( st, output_frame ); + + /*---------------------------------------------------------------------* + * ACELP core decoding + * HQ core decoding + *---------------------------------------------------------------------*/ + + if ( st->core == ACELP_CORE ) + { + /* ACELP core decoder */ + acelp_core_dec( st, synth, bwe_exc_extended, voice_factors, old_syn_12k8_16k, coder_type, sharpFlag, pitch_buf, &unbits, &sid_bw ); + } + else + { + /* HQ core decoder */ + hq_core_dec( st, synth, output_frame, hq_core_type, core_switching_flag ); + } + + /*---------------------------------------------------------------------* + * Postprocessing for ACELP/HQ core switching + *---------------------------------------------------------------------*/ + + core_switching_post_dec( st, synth, output_frame, core_switching_flag, coder_type ); + + /*---------------------------------------------------------------------* + * Pre-processing for bandwidth switching + *---------------------------------------------------------------------*/ + + bw_switching_pre_proc( st, old_syn_12k8_16k ); + + /*---------------------------------------------------------------------* + * WB TBE decoding + * WB BWE decoding + *---------------------------------------------------------------------*/ + + + if( st->extl == WB_TBE ) + { + /* WB TBE decoder */ + wb_tbe_dec( st, coder_type, bwe_exc_extended, voice_factors, hb_synth ); + } + + if( st->extl == WB_BWE && st->bws_cnt == 0 ) + { + /* WB BWE decoder */ + wb_bwe_dec( synth, hb_synth, output_frame, st, coder_type, voice_factors, pitch_buf ); + } + + /*---------------------------------------------------------------------* + * SWB(FB) TBE decoding + * SWB(FB) BWE decoding + *---------------------------------------------------------------------*/ + + if( st->extl == SWB_TBE || st->extl == FB_TBE + ||( coder_type != AUDIO && coder_type != INACTIVE && st->core_brate >= SID_2k40 && st->core == ACELP_CORE + && st->output_Fs >= 32000 && st->bwidth > NB && st->bws_cnt > 0 && !st->ppp_mode_dec && !( st->nelp_mode_dec == 1 && st->bfi == 1 ) ) ) + + { + /* SWB TBE decoder */ + swb_tbe_dec( st, coder_type, bwe_exc_extended, voice_factors,old_syn_12k8_16k, fb_exc, hb_synth, pitch_buf ); + + /* FB TBE decoder */ + if( output_frame == L_FRAME48k && st->extl == FB_TBE ) + { + fb_tbe_dec( st, fb_exc, hb_synth ); + } + } + else if( st->extl == SWB_BWE || st->extl == FB_BWE || (st->output_Fs >= 32000 && st->core == ACELP_CORE && st->bwidth > NB + && st->bws_cnt > 0 && !st->ppp_mode_dec && !( st->nelp_mode_dec == 1 && st->bfi == 1 ) ) ) + + { + /* SWB BWE decoder */ + swb_bwe_dec( st, synth, hb_synth, output_frame, coder_type ); + } + else if( st->extl == SWB_BWE_HIGHRATE || st->extl == FB_BWE_HIGHRATE ) + { + swb_bwe_dec_hr( st, old_syn_12k8_16k, hb_synth, output_frame, unbits, pitch_buf ); + } + + /*---------------------------------------------------------------------* + * FEC - recovery after lost HQ core (smoothing of the BWE component) + *---------------------------------------------------------------------*/ + + if( st->prev_bfi && st->last_core == HQ_CORE && st->extl != -1 ) + { + tmp = FRAC_BWE_SMOOTH/output_frame; + + for (i = 0; i < output_frame/FRAC_BWE_SMOOTH; i++) + { + hb_synth[i] *= (i*tmp); + } + } + + /*---------------------------------------------------------------------* + * SWB CNG + *---------------------------------------------------------------------*/ + + if( output_frame >= L_FRAME32k ) + { + /* SHB CNG decoder */ + swb_CNG_dec( st, synth, hb_synth, sid_bw ); + } + + + /*----------------------------------------------------------------* + * Delay ACELP core synthesis to be synchronized with the components of bandwidth extension layers + *----------------------------------------------------------------*/ + + if ( output_frame >= L_FRAME16k ) + { + tmps = NS2SA(st->output_Fs, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS); + mvr2r( synth, tmp_buffer, output_frame ); + mvr2r( st->prev_synth_buffer, synth, tmps ); + mvr2r( tmp_buffer, synth + tmps, output_frame - tmps ); + mvr2r( tmp_buffer + output_frame - tmps, st->prev_synth_buffer, tmps ); + } + + if( st->core == ACELP_CORE + && !st->bfi && st->prev_bfi + && st->last_total_brate >= HQ_48k + && st->last_codec_mode == MODE2 + && (st->last_core_bfi == TCX_20_CORE || st->last_core_bfi == TCX_10_CORE) + && st->plcInfo.concealment_method == TCX_NONTONAL + && st->plcInfo.nbLostCmpt < 4 ) + { + tmps = 0; + if( output_frame >= L_FRAME16k ) + { + tmps = NS2SA(st->output_Fs, DELAY_BWE_TOTAL_NS); + } + + waveform_adj2( st->tonalMDCTconceal.secondLastPcmOut, + synth+tmps, + st->plcInfo.data_noise, + &st->plcInfo.outx_new_n1, + &st->plcInfo.nsapp_gain, + &st->plcInfo.nsapp_gain_n, + &st->plcInfo.recovery_gain, + st->plcInfo.step_concealgain, + st->plcInfo.Pitch, + st->plcInfo.FrameSize, + tmps, + st->plcInfo.nbLostCmpt + 1, + st->bfi ); + st->plcInfo.Pitch = 0; + } + + /*----------------------------------------------------------------* + * Addition of BWE components to the ACELP core synthesis + *----------------------------------------------------------------*/ + + if( st->extl != -1 || (st->bws_cnt > 0 && st->core == ACELP_CORE) ) + { + /* Calculate an additional delay of extension layer components to be synchronized with ACELP synthesis */ + if (st->L_frame == L_FRAME ) + { + /* TBE on top of ACELP@12.8kHz */ + tmps = NS2SA( st->output_Fs, MAX_DELAY_TBE_NS - DELAY_SWB_TBE_12k8_NS ); + } + else + { + if( st->extl == SWB_BWE_HIGHRATE || st->extl == FB_BWE_HIGHRATE ) + { + /* HR SWB BWE on top of ACELP@16kHz */ + tmps = NS2SA(st->output_Fs, DELAY_BWE_TOTAL_NS); + } + else + { + /* TBE on top of ACELP@16kHz */ + tmps = NS2SA( st->output_Fs, MAX_DELAY_TBE_NS - DELAY_SWB_TBE_16k_NS ); + } + } + + /* Smooth transitions when switching between different technologies */ + if( (st->extl != st->last_extl || (st->extl == st->last_extl && (st->core ^ st->last_core) == HQ_CORE)) && !(st->extl == SWB_CNG && st->last_extl == SWB_TBE) ) + { + /* switching between BWE and TBE technologies */ + incr = (short) ( L_FRAME / (tmps + 0.5f) ); + for (i=0; ihb_prev_synth_buffer, 0.0f, tmps ); + } + else if( tmps < st->old_bwe_delay ) + { + /* 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) ); + for (i=0; ihb_prev_synth_buffer[i] * sin_table256[255 - i * incr] + + st->hb_prev_synth_buffer[st->old_bwe_delay - 1 - i] * sin_table256[i * incr]; + } + + mvr2r( tmp_buffer, st->hb_prev_synth_buffer, tmps ); + } + else if( tmps > st->old_bwe_delay ) + { + /* 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) ); + for( i=0; iold_bwe_delay; i++ ) + { + tmp_buffer[i] = st->hb_prev_synth_buffer[i] * sin_table256[255 - i * incr]; + } + + for( ; iold_bwe_delay; i++ ) + { + tmp_buffer[tmps - 1 - i] += st->hb_prev_synth_buffer[st->old_bwe_delay - 1 - i] * sin_table256[i * incr]; + } + + mvr2r( tmp_buffer, st->hb_prev_synth_buffer, tmps ); + } + + /* Delay hb_synth */ + mvr2r( hb_synth, tmp_buffer, output_frame ); + mvr2r( st->hb_prev_synth_buffer, hb_synth, tmps ); + mvr2r( tmp_buffer, hb_synth + tmps, output_frame - tmps ); + mvr2r( tmp_buffer + output_frame - tmps, st->hb_prev_synth_buffer, tmps ); + + st->old_bwe_delay = tmps; + if( ( st->ppp_mode_dec || ( st->nelp_mode_dec == 1 && st->bfi == 1 ) ) && st->L_frame == st->last_L_frame && (st->bws_cnt > 1 || st->last_extl != -1) ) + + { + mvr2r( st->old_hb_synth, hb_synth, output_frame ); + } + else + { + mvr2r( hb_synth, st->old_hb_synth, output_frame ); + } + + /* Add the delayed hb_synth component to the delayed ACELP synthesis */ + v_add( synth, hb_synth, synth, output_frame ); + + /* SWB CNG/DTX - calculate SHB energy */ + if ( output_frame >= L_FRAME32k && st->extl > SWB_CNG ) + { + st->last_shb_ener = 0.001f; + for ( i=0; ilast_shb_ener += hb_synth[i] * hb_synth[i]; + } + st->last_shb_ener /= (float)output_frame; + st->last_shb_ener = 10 * (float)log10(st->last_shb_ener); + } + } + + /* TCX-LTP Postfilter: used in Mode 1 to update memories and to avoid discontinuities when the past frame was TCX */ + tcx_ltp_post( st->tcxltp, ACELP_CORE, output_frame, st->L_frame_past, 0, synth, NULL, NS2SA( st->output_Fs, TCXLTP_DELAY_NS ), + 0, 0, 0, 0.f, &st->tcxltp_pitch_int_post_prev, &st->tcxltp_pitch_fr_post_prev, &st->tcxltp_gain_post_prev, + &st->tcxltp_filt_idx_prev, st->pit_res_max, &st->pit_res_max_past, 0.f, 0, st->tcxltp_mem_in, st->tcxltp_mem_out, st->total_brate ); + + /* final output of synthesis signal */ + mvr2r( synth, output, output_frame ); + } + else /* Mode 2 */ + { + + /* -------------------------------------------------------------- * + * Mode 2 concealment + * -------------------------------------------------------------- */ + + concealWholeFrame = 0; + + if( frameMode == FRAMEMODE_NORMAL ) + { + st->m_decodeMode = DEC_NO_FRAM_LOSS; + } + + if( frameMode == FRAMEMODE_MISSING ) + { + if( st->use_partial_copy && st->rf_frame_type >= RF_TCXFD && st->rf_frame_type <= RF_TCXTD2 ) + { + st->m_decodeMode = DEC_NO_FRAM_LOSS; + } + else + { + st->m_decodeMode = DEC_CONCEALMENT_EXT; + } + } + + if( st->m_decodeMode == DEC_CONCEALMENT_EXT ) + { + concealWholeFrame = 1; + } + + /* -------------------------------------------------------------- * + * Decode core + * -------------------------------------------------------------- */ + + dec_acelp_tcx_frame( st, &coder_type, &concealWholeFrame, output, + st->p_bpf_noise_buf, pcmbufFB, bwe_exc_extended, voice_factors, pitch_buf ); + + concealWholeFrameTmp = concealWholeFrame; + if(st->bfi) + { + frameMode = FRAMEMODE_MISSING; + } + + if( st->igf ) + { + /* TBE for Mode 2 interface */ + if( (st->bfi == 0 || st->last_core == ACELP_CORE) && st->core == ACELP_CORE ) + { + switch( st->bwidth ) + { + case WB: + st->extl = WB_TBE; + st->extl_brate = WB_TBE_0k35; + break; + case SWB: + st->extl = SWB_TBE; + st->extl_brate = SWB_TBE_1k6; + break; + + case FB: + st->extl = FB_TBE; + st->extl_brate = FB_TBE_1k8; + break; + } + } + else + { + st->extl = IGF_BWE; + st->extl_brate = 0; + } + + if( st->output_Fs == 8000 || ( st->output_Fs == 16000 && st->L_frame == L_FRAME16k ) ) + { + st->extl = -1; + } + + st->core_brate = st->total_brate - st->extl_brate; + + st->bws_cnt = 0; + st->bws_cnt1 = 0; + st->tilt_wb = 0; + + if( st->m_frame_type == ACTIVE_FRAME ) + { + if( (st->bfi == 0 || st->last_core == ACELP_CORE) && st->core == ACELP_CORE ) + { + if( st->extl == WB_TBE ) + { + wb_tbe_dec( st, coder_type, bwe_exc_extended, voice_factors, hb_synth ); + } + else if( st->extl == SWB_TBE || st->extl == FB_TBE ) + { + /* SWB TBE decoder */ + swb_tbe_dec( st, coder_type, bwe_exc_extended, voice_factors, st->old_core_synth, fb_exc, hb_synth, pitch_buf ); + + if( st->extl == FB_TBE && output_frame == L_FRAME48k ) + { + fb_tbe_dec( st, fb_exc, hb_synth ); + } + } + mvr2r( hb_synth, st->old_hb_synth, output_frame ); + } + else + { + if( st->last_core == ACELP_CORE ) + { + if( ( st->bwidth == SWB || st->bwidth == FB ) && + (( st->last_extl == SWB_TBE || st->last_extl == FB_TBE) && st->last_codec_mode == MODE2 ) ) + { + GenTransition( st->syn_overlap, st->old_tbe_synth, 2*NS2SA(st->output_Fs, DELAY_BWE_TOTAL_NS), hb_synth, + st->genSHBsynth_Hilbert_Mem, st->genSHBsynth_state_lsyn_filt_shb_local, + st->mem_resamp_HB_32k, + + &(st->syn_dm_phase), + st->output_Fs, st->int_3_over_2_tbemem_dec, st->rf_flag, st->total_brate ); + } + else if ( st->bwidth == WB && st->last_extl == WB_TBE ) + { + GenTransition_WB( st->syn_overlap, st->old_tbe_synth, 2*NS2SA(st->output_Fs, DELAY_BWE_TOTAL_NS), hb_synth, + st->state_lsyn_filt_shb, st->state_lsyn_filt_dwn_shb, st->output_Fs, st->mem_resamp_HB ); + } + + TBEreset_dec( st, st->bwidth ); + } + else if( st->last_codec_mode == MODE1 ) + { + swb_tbe_reset( st->mem_csfilt, st->mem_genSHBexc_filt_down_shb, st->state_lpc_syn, + st->syn_overlap, st->state_syn_shbexc, &(st->tbe_demph), &(st->tbe_premph), st->mem_stp_swb, &(st->gain_prec_swb) ); + if( sub(st->extl, FB_TBE) == 0 ) + { + set_f( st->fb_state_lpc_syn, 0, LPC_SHB_ORDER ); + st->fb_tbe_demph = 0; + fb_tbe_reset_synth( st->fbbwe_hpf_mem, &st->prev_fbbwe_ratio ); + } + swb_tbe_reset_synth( st->genSHBsynth_Hilbert_Mem, st->genSHBsynth_state_lsyn_filt_shb_local ); + } + } + } + } + + + if( st->m_frame_type != ACTIVE_FRAME ) + { + st->extl = -1; + st->extl_brate = 0; + } + + /* -------------------------------------------------------------- * + * Postprocessing + * -------------------------------------------------------------- */ + + { + float *realBuffer[CLDFB_NO_COL_MAX], *imagBuffer[CLDFB_NO_COL_MAX]; + float realBufferTmp[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], imagBufferTmp[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + + for( i=0; icldfbSyn->nab = min( st->cldfbAna->no_channels, st->cldfbSyn->no_channels ); + st->cldfbAna->nab = 0; + + if( st->hFdCngDec != NULL && (st->sr_core == 8000 || st->sr_core == 12800 || st->sr_core == 16000) && st->total_brate <= ACELP_32k ) + { + /* -------------------------------------------------------------- * + * In CLDFB domain: + * - perform noise estimation during active frames + * - do CNG during inactive frames + * -------------------------------------------------------------- */ + + noisy_speech_detection( st->VAD && st->m_frame_type==ACTIVE_FRAME, output, st->hFdCngDec->hFdCngCom->frameSize, + st->hFdCngDec->msNoiseEst, st->hFdCngDec->psize_shaping, st->hFdCngDec->nFFTpart_shaping, + &(st->hFdCngDec->lp_noise), &(st->hFdCngDec->lp_speech), &(st->hFdCngDec->hFdCngCom->flag_noisy_speech) ); + + st->hFdCngDec->hFdCngCom->likelihood_noisy_speech = 0.99f*st->hFdCngDec->hFdCngCom->likelihood_noisy_speech + 0.01f*(float)st->hFdCngDec->hFdCngCom->flag_noisy_speech; + + st->lp_noise = st->hFdCngDec->lp_noise; + + ApplyFdCng( output, realBuffer, imagBuffer, st->hFdCngDec, st->m_frame_type, st, concealWholeFrame, 0 ); + + /* Generate additional comfort noise to mask potential coding artefacts */ + if( st->m_frame_type == ACTIVE_FRAME && st->flag_cna ) + { + generate_masking_noise( output, st->hFdCngDec->hFdCngCom, st->hFdCngDec->hFdCngCom->frameSize, 0 ); + } + } + + if( st->flag_cna == 0 && st->L_frame == L_FRAME16k && st->last_flag_cna == 1 && ( (st->last_core == ACELP_CORE && st->last_coder_type != AUDIO) || st->last_core == TCX_20_CORE || st->last_core == AMR_WB_CORE ) ) + { + v_multc( st->hFdCngDec->hFdCngCom->olapBufferSynth2+5*st->L_frame/4, 256.f, tmp_buffer, st->L_frame/2 ); + v_add( tmp_buffer, output, output, st->L_frame/2 ); + } + + if( st->m_frame_type == ACTIVE_FRAME ) + { + cldfbAnalysis( output, realBuffer, imagBuffer, -1, st->cldfbAna ); + } + else + { + float timeDomainBuffer[L_FRAME16k]; + float A[M+1]; + + mvr2r( st->hFdCngDec->hFdCngCom->timeDomainBuffer, timeDomainBuffer, st->L_frame ); + mvr2r( st->hFdCngDec->hFdCngCom->A_cng, A, M+1 ); + + update_decoder_LPD_cng( st, coder_type, timeDomainBuffer, A, st->p_bpf_noise_buf ); + + /* Generate additional comfort noise to mask potential coding artefacts */ + if( st->flag_cna ) + { + generate_masking_noise( timeDomainBuffer, st->hFdCngDec->hFdCngCom, st->hFdCngDec->hFdCngCom->frameSize, 0 ); + } + else if( st->L_frame == L_FRAME16k && st->last_flag_cna == 1 && ( (st->last_core == ACELP_CORE && st->last_coder_type != AUDIO) || st->last_core == TCX_20_CORE || st->last_core == AMR_WB_CORE ) ) + { + v_multc( st->hFdCngDec->hFdCngCom->olapBufferSynth2+5*st->L_frame/4, 256.f, tmp_buffer, st->L_frame/2 ); + v_add( tmp_buffer, timeDomainBuffer, timeDomainBuffer, st->L_frame/2 ); + } + + /* check if the CLDFB works on the right sample rate */ + if( (st->cldfbAna->no_channels * st->cldfbAna->no_col) != st->L_frame ) + { + resampleCldfb (st->cldfbAna, (st->L_frame * 50)); + resampleCldfb (st->cldfbBPF, (st->L_frame * 50)); + + } + + st->cldfbSyn->bandsToZero = 0; + if( st->bwidth == NB && st->cldfbSyn->no_channels > 10 ) + { + st->cldfbSyn->bandsToZero = st->cldfbSyn->no_channels - 10; + } + else if( st->hFdCngDec->hFdCngCom->regularStopBand < st->cldfbSyn->no_channels ) + { + st->cldfbSyn->bandsToZero = st->cldfbSyn->no_channels - st->hFdCngDec->hFdCngCom->regularStopBand; + } + cldfbAnalysis( timeDomainBuffer, realBuffer, imagBuffer, -1, st->cldfbAna ); + } + + if( st->flag_cna == 0 ) + { + set_f( st->hFdCngDec->hFdCngCom->olapBufferSynth2, 0.f, st->hFdCngDec->hFdCngCom->fftlen ); + } + + if( st->p_bpf_noise_buf ) + { + addBassPostFilter( st->p_bpf_noise_buf, -1, realBuffer, imagBuffer, st->cldfbBPF ); + } + + if (st->output_Fs > 8000) + { + calcGainTemp_TBE( realBuffer, imagBuffer, st->tecDec.loBuffer, 0, + st->cldfbAna->no_col, st->cldfbAna->no_channels, st->tecDec.pGainTemp, st->tec_flag ); + } + + /* set high band buffers to zero. Covering the current frame and the overlap area. */ + if( st->m_frame_type == ACTIVE_FRAME ) + { + for( i = 0; i < CLDFB_NO_COL_MAX; i++ ) + { + set_f( &realBuffer[i][st->cldfbSyn->nab], 0.f, st->cldfbSyn->no_channels - st->cldfbSyn->nab ); + set_f( &imagBuffer[i][st->cldfbSyn->nab], 0.f, st->cldfbSyn->no_channels - st->cldfbSyn->nab ); + } + } + + cldfbSynthesis( realBuffer, imagBuffer, output, -1, st->cldfbSyn ); + + /* set multiplication factor according to the sampling rate */ + delay_comp = NS2SA(st->output_Fs, DELAY_CLDFB_NS); + delay_tdbwe= NS2SA(st->output_Fs, DELAY_BWE_TOTAL_NS- DELAY_CLDFB_NS); + + /* MODE1 MDCT to ACELP 2 transition */ + if( st->last_codec_mode == MODE1 && st->last_core_bfi > ACELP_CORE ) + { + mvr2r( st->delay_buf_out, output, delay_comp ); /* copy the HQ/ACELP delay synchronization buffer at the beginning of ACELP frame */ + + if( st->core == ACELP_CORE ) + { + tmpF = 1.0f/(float)NS2SA(st->output_Fs, 3000000); + if(st->prev_bfi && st->HqVoicing ) + { + mvr2r( st->fer_samples, st->old_out+NS2SA(st->output_Fs, N_ZERO_MDCT_NS), NS2SA(st->output_Fs,3000000) ); + } + for( i=0; ioutput_Fs, 3000000); i++ ) + { + output[i+delay_comp] = (1-tmpF*(float)i)*st->old_out[i+NS2SA(st->output_Fs, N_ZERO_MDCT_NS)] + tmpF*(float)i*output[i+delay_comp]; + } + } + else + { + if( st->output_Fs == 8000 ) + { + mvr2r( st->delay_buf_out, st->FBTCXdelayBuf, delay_comp ); + } + else + { + mvr2r( st->prev_synth_buffer, st->FBTCXdelayBuf, delay_tdbwe ); + mvr2r( st->delay_buf_out, st->FBTCXdelayBuf + delay_tdbwe, delay_comp ); + } + } + } + + /* set delay compensation between HQ synthesis and ACELP synthesis */ + if( st->core == ACELP_CORE && !st->con_tcx ) + { + set_f( st->delay_buf_out, 0, delay_comp ); + mvr2r( output, st->previoussynth, output_frame ); + } + else + { + mvr2r( st->old_synthFB+st->old_synth_lenFB-delay_comp, st->delay_buf_out, delay_comp ); + + if( st->output_Fs == 8000 ) + { + mvr2r( st->FBTCXdelayBuf, st->previoussynth, delay_comp ); + } + else + { + mvr2r( st->FBTCXdelayBuf + delay_tdbwe, st->previoussynth, delay_comp ); + } + + mvr2r( pcmbufFB, st->previoussynth + delay_comp, output_frame - delay_comp ); + } + + /* Delay compensation for TBE */ + if( output_frame >= L_FRAME16k ) + { + mvr2r( output, tmp_buffer, output_frame ); + mvr2r( st->prev_synth_buffer, output, delay_tdbwe ); + mvr2r( tmp_buffer, output + delay_tdbwe, output_frame - delay_tdbwe ); + mvr2r( tmp_buffer + output_frame - delay_tdbwe, st->prev_synth_buffer, delay_tdbwe ); + } + + if( st->igf && st->m_frame_type == ACTIVE_FRAME ) + { + if( !st->bfi && st->core == ACELP_CORE && (st->tec_flag || st->tfa_flag) && (st->output_Fs > 8000) ) + { + procTecTfa_TBE( hb_synth, st->tecDec.pGainTemp, st->tfa_flag, st->last_core, (int)(output_frame / N_TEC_TFA_SUBFR), st->tec_flag == 2 ? 1 : 0 ); + } + + if( (((!st->bfi || st->last_core == ACELP_CORE) && st->core == ACELP_CORE) || + (st->last_core == ACELP_CORE && st->bwidth != NB && st->last_codec_mode == MODE2)) + && (st->output_Fs > 8000) ) + { + /* Add the delayed hb_synth component to the delayed core synthesis */ + v_add( output, hb_synth, output, output_frame ); + } + } + } + + /* set delay */ + if( st->output_Fs == 8000 ) + { + tmps = NS2SA( st->output_Fs, DELAY_CLDFB_NS ); + } + else + { + tmps = NS2SA( st->output_Fs, DELAY_BWE_TOTAL_NS ); + } + delta = NS2SA( st->output_Fs, TCXLTP_DELAY_NS ); + + /* TCX/ACELP/HQ-CORE->TCX */ + if( (st->bfi && st->last_core > ACELP_CORE) || st->core > ACELP_CORE ) + { + /* TCX / HQ-CORE / TD-TCX-PLC -> TCX / TD-TCX-PLC */ + if( st->last_core_bfi > ACELP_CORE || (st->bfi && st->last_core > ACELP_CORE) || (st->prev_bfi && st->last_con_tcx)) + { + mvr2r( st->FBTCXdelayBuf, output, tmps ); + mvr2r( pcmbufFB, output + tmps, st->L_frameTCX - tmps ); + } + /* ACELP -> TCX */ + else + { + /*cross-fading between LB-TCX and FB-TCX over 2.3125ms*/ + for( i = 0; i < tmps; i++ ) + { + output[i+tmps] = (output[i+tmps] * (tmps-i) + pcmbufFB[i] * i) / tmps; + } + mvr2r( pcmbufFB+tmps, output + 2*tmps, st->L_frameTCX - 2*tmps ); + } + + mvr2r( pcmbufFB + st->L_frameTCX - tmps, st->FBTCXdelayBuf, tmps ); + + if( st->bfi && st->last_core > ACELP_CORE ) + { + if( st->output_Fs == 8000 ) + { + mvr2r(st->FBTCXdelayBuf, st->delay_buf_out, NS2SA(st->output_Fs, DELAY_CLDFB_NS)); + } + else + { + mvr2r( st->FBTCXdelayBuf, st->prev_synth_buffer, NS2SA(st->output_Fs, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS) ); + mvr2r( st->FBTCXdelayBuf + NS2SA(st->output_Fs, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS), st->delay_buf_out, NS2SA(st->output_Fs, DELAY_CLDFB_NS) ); + } + } + } + /* TCX/TD TCX PLC->ACELP */ + else if( st->last_codec_mode == MODE2 && st->last_core > ACELP_CORE ) + { + mvr2r( st->FBTCXdelayBuf, output, delta ); + for( i = delta; i < tmps; i++ ) + { + output[i] = (output[i] * (i-delta) + st->FBTCXdelayBuf[i] * (tmps-i)) / (tmps-delta); + } + } + + tcx_ltp_post( st->tcxltp, st->core, output_frame, st->L_frame, NS2SA( st->output_Fs, ACELP_LOOK_NS ) + tmps, output, + st->FBTCXdelayBuf, delta, st->bfi, st->tcxltp_pitch_int, st->tcxltp_pitch_fr, st->tcxltp_gain, + &st->tcxltp_pitch_int_post_prev, &st->tcxltp_pitch_fr_post_prev, &st->tcxltp_gain_post_prev, &st->tcxltp_filt_idx_prev, + st->pit_res_max, &st->pit_res_max_past, st->damping, st->total_brate >= HQ_96k, st->tcxltp_mem_in, st->tcxltp_mem_out, st->total_brate ); + } /* end of Mode 2 */ + + /*----------------------------------------------------------------* + * Save synthesis for HQ FEC + *----------------------------------------------------------------*/ + + post_hq_delay = NS2SA( st->output_Fs, POST_HQ_DELAY_NS ); + if( st->codec_mode == MODE1 ) + { + mvr2r( st->synth_history+output_frame, st->synth_history, output_frame-post_hq_delay+NS2SA( st->output_Fs, PH_ECU_MEM_NS )); + mvr2r( output, st->old_synthFB+output_frame-post_hq_delay, output_frame ); + /* 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 */ + set_f( st->old_synthFB+2*output_frame-post_hq_delay, 0.f, post_hq_delay ); + + if ( output_frame >= L_FRAME16k ) + { + mvr2r( st->prev_synth_buffer, st->old_synthFB+2*output_frame-NS2SA(st->output_Fs, DELAY_BWE_TOTAL_NS), NS2SA(st->output_Fs, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS)); + } + + if (st->core != ACELP_CORE) + { + if ( output_frame >= L_FRAME16k ) + { + mvr2r( synth+output_frame, st->old_synthFB+2*output_frame-NS2SA(st->output_Fs, DELAY_CLDFB_NS), NS2SA(st->output_Fs, DELAY_CLDFB_NS)); + mvr2r( st->old_out+NS2SA(st->output_Fs, N_ZERO_MDCT_NS), st->old_synthFB+2*output_frame, NS2SA(st->output_Fs, PH_ECU_LOOKAHEAD_NS)); + } + else + { + mvr2r( synth+output_frame, st->old_synthFB+2*output_frame-NS2SA(st->output_Fs, DELAY_BWE_TOTAL_NS), NS2SA(st->output_Fs, DELAY_CLDFB_NS)); + mvr2r( st->old_out+NS2SA(st->output_Fs, N_ZERO_MDCT_NS), st->old_synthFB+2*output_frame-NS2SA(st->output_Fs, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS), NS2SA(st->output_Fs, PH_ECU_LOOKAHEAD_NS)); + } + } + } + + /*----------------------------------------------------------------* + * HP filtering + *----------------------------------------------------------------*/ + + hp20( output, output_frame, st->mem_hp20_out, st->output_Fs ); + + + /*--------------------------------------------------------* + * Updates + *--------------------------------------------------------*/ + + if( st->last_is_cng == 0 && st->codec_mode == MODE2 ) + { + st->bfi = 0; + if( st->use_partial_copy && st->rf_frame_type >= RF_TCXFD && st->rf_frame_type <= RF_TCXTD2 ) + { + if( frameMode == FRAMEMODE_MISSING ) + { + st->bfi = 1; + } + } + else if( st->m_decodeMode == DEC_CONCEALMENT_EXT ) + { + st->bfi = 1; + } + + updt_dec_common( st, -1, output ); + } + else + { + if( st->codec_mode == MODE2 ) + { + st->bfi = 0; + } + updt_dec_common( st, hq_core_type, output ); + } + + if( st->codec_mode == MODE2 ) + { + if( st->use_partial_copy && st->rf_frame_type == RF_NELP ) + { + st->last_nelp_mode_dec = 1; + } + else + { + st->last_nelp_mode_dec = 0; + } + } + + st->prev_use_partial_copy = st->use_partial_copy; + + st->prev_tilt_code_dec = 0.0f; + for( i=0; iprev_tilt_code_dec += st->tilt_code_dec[i]*0.25f; + } + + if( st->core == HQ_CORE ) + { + st->prev_coder_type = GENERIC; + } + else + { + st->prev_coder_type = coder_type; + } + + if( st->core_brate > SID_2k40 && st->first_CNG == 1 ) + { + if( st->act_cnt >= BUF_DEC_RATE ) + { + st->act_cnt = 0; + } + + st->act_cnt++; + + if( st->act_cnt == BUF_DEC_RATE && st->ho_hist_size > 0 ) + { + st->ho_hist_size--; + } + + if( ++(st->act_cnt2) >= MIN_ACT_CNG_UPD ) + { + st->act_cnt2 = MIN_ACT_CNG_UPD; + } + } + + if( st->core_brate <= SID_2k40 && st->first_CNG == 0 && st->cng_type == LP_CNG ) + { + st->first_CNG = 1; + } + + /* update bandwidth switching parameters */ + if( st->codec_mode == MODE1 ) + { + updt_bw_switching( st, output ); + } + else + { + st->last_bwidth = st->bwidth; + } + + /* synchronisation of CNG seeds */ + if( st->bfi || (st->core_brate != FRAME_NO_DATA && st->core_brate != SID_2k40) ) + { + own_random( &(st->cng_seed) ); + own_random( &(st->cng_ener_seed) ); + } + + if( st->enablePlcWaveadjust && !concealWholeFrameTmp ) + { + /* update the parameters used in waveform adjustment */ + concealment_update2( output, &st->plcInfo, st->L_frameTCX ); + } + + st->last_total_brate_ber = st->total_brate; + if( !st->bfi ) + { + st->last_total_brate = st->total_brate; + } + + st->last_flag_cna = st->flag_cna; + st->hFdCngDec->hFdCngCom->frame_type_previous = st->m_frame_type; + + st->prev_bws_cnt = st->bws_cnt; + + pop_wmops(); + + return; +} diff --git a/lib_dec/evs_rtp_payload.c b/lib_dec/evs_rtp_payload.c new file mode 100644 index 000000000..a283cd2af --- /dev/null +++ b/lib_dec/evs_rtp_payload.c @@ -0,0 +1,240 @@ + /*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + + #include + #include "wmc_auto.h" + #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 000000000..bf83ac9a3 --- /dev/null +++ b/lib_dec/evs_rtp_payload.h @@ -0,0 +1,173 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 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 000000000..b0105b6f3 --- /dev/null +++ b/lib_dec/fd_cng_dec.c @@ -0,0 +1,1136 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "typedef.h" +#include "options.h" +#include "prot.h" +#include "rom_com.h" + +#define DELTA_MASKING_NOISE 1e-20f + +/*------------------------------------------------------------------- + * createFdCngDec() + * + * 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; + + return; +} + + +/*------------------------------------------------------------------- + * initFdCngDec() + * + * Initialize an instance of type FD_CNG + *-------------------------------------------------------------------*/ + +void initFdCngDec( + HANDLE_FD_CNG_DEC hs, /* i/o: Contains the variables related to the FD-based CNG process */ + float scale +) +{ + /* Initialize common */ + initFdCngCom( hs->hFdCngCom, scale ); + + /* Set some counters and flags */ + hs->flag_dtx_mode = 0; + hs->lp_noise = -20.f; + hs->lp_speech = 25.f; + + /* Initialize noise estimation algorithm */ + set_f( hs->bandNoiseShape, 0.0f, FFTLEN2 ); + set_f( hs->partNoiseShape, 0.0f, NPART ); + set_f( hs->msPeriodog, 0.0f, NPART_SHAPING ); + set_f( hs->msAlpha, 0.0f, NPART_SHAPING ); + set_f( hs->msBminWin, 0.0f, NPART_SHAPING ); + set_f( hs->msBminSubWin, 0.0f, NPART_SHAPING ); + set_f( hs->msPsd, 0.0f, NPART_SHAPING ); + set_f( hs->msNoiseFloor, 0.0f, NPART_SHAPING ); + set_f( hs->msNoiseEst, 0.0f, NPART_SHAPING ); + set_f( hs->msMinBuf, FLT_MAX, MSNUMSUBFR*NPART_SHAPING ); + set_f( hs->msCurrentMin, FLT_MAX, NPART_SHAPING ); + set_f( hs->msCurrentMinOut, FLT_MAX, NPART_SHAPING ); + set_f( hs->msCurrentMinSubWindow, FLT_MAX, NPART_SHAPING ); + set_i( hs->msLocalMinFlag, 0, NPART_SHAPING ); + set_i( hs->msNewMinFlag, 0, NPART_SHAPING ); + set_f( hs->msPsdFirstMoment, 0.0f, NPART_SHAPING ); + set_f( hs->msPsdSecondMoment, 0.0f, NPART_SHAPING ); + hs->msPeriodogBufPtr = 0; + set_f( hs->msPeriodogBuf, 0.0f, MSBUFLEN*NPART_SHAPING ); + set_f( hs->msLogPeriodog, 0.0f, NPART_SHAPING ); + set_f( hs->msLogNoiseEst, 0.0f, NPART_SHAPING ); + set_f ( hs->psize_shaping, 0.0f, NPART_SHAPING ); + hs->nFFTpart_shaping = 0; + + return; +} + + +/*------------------------------------------------------------------- + * configureFdCngDec() + * + * Configure an instance of type FD_CNG + *-------------------------------------------------------------------*/ + +void configureFdCngDec( + HANDLE_FD_CNG_DEC hsDec, /* i/o: Contains the variables related to the FD-based CNG process */ + short bandwidth, + int bitrate, + short L_frame +) +{ + int j, stopBandFR; + HANDLE_FD_CNG_COM hsCom = hsDec->hFdCngCom; + + hsCom->CngBandwidth = bandwidth; + if ( hsCom->CngBandwidth == FB ) + { + hsCom->CngBandwidth = SWB; + } + if ( bitrate != FRAME_NO_DATA && bitrate != SID_2k40 ) + { + hsCom->CngBitrate = bitrate; + } + hsCom->numSlots = 16; + + /* NB configuration */ + if ( bandwidth == NB ) + { + hsCom->FdCngSetup = FdCngSetup_nb; + hsCom->numCoreBands = 16; + hsCom->regularStopBand = 16; + } + + /* WB configuration */ + else if ( bandwidth == WB ) + { + /* FFT 6.4kHz, no CLDFB */ + if ( hsCom->CngBitrate <= ACELP_8k00 && L_frame==L_FRAME ) + { + hsCom->FdCngSetup = FdCngSetup_wb1; + hsCom->numCoreBands = 16; + hsCom->regularStopBand = 16; + } + /* FFT 6.4kHz, CLDFB 8.0kHz */ + else if ( hsCom->CngBitrate <= ACELP_13k20 || L_frame==L_FRAME ) + { + hsCom->FdCngSetup = FdCngSetup_wb2; + hsCom->numCoreBands = 16; + hsCom->regularStopBand = 20; + if ( L_frame==L_FRAME16k ) + { + hsCom->FdCngSetup = FdCngSetup_wb2; + hsCom->numCoreBands = 20; + hsCom->regularStopBand = 20; + hsCom->FdCngSetup.fftlen = 640; + hsCom->FdCngSetup.stopFFTbin = 256; + } + } + /* FFT 8.0kHz, no CLDFB */ + else + { + hsCom->FdCngSetup = FdCngSetup_wb3; + hsCom->numCoreBands = 20; + hsCom->regularStopBand = 20; + } + } + + /* SWB/FB configuration */ + else + { + /* FFT 6.4kHz, CLDFB 14kHz */ + if ( L_frame==L_FRAME ) + { + hsCom->FdCngSetup = FdCngSetup_swb1; + hsCom->numCoreBands = 16; + hsCom->regularStopBand = 35; + } + /* FFT 8.0kHz, CLDFB 16kHz */ + else + { + hsCom->FdCngSetup = FdCngSetup_swb2; + hsCom->numCoreBands = 20; + hsCom->regularStopBand = 40; + } + } + hsCom->fftlen = hsCom->FdCngSetup.fftlen; + hsCom->stopFFTbin = hsCom->FdCngSetup.stopFFTbin; + + /* Configure the SID quantizer and the Comfort Noise Generator */ + + hsCom->startBand = 2; + hsCom->stopBand = 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_inv, 0); + if ( hsCom->stopFFTbin == 160 ) + { + hsCom->nFFTpart = 17; + } + else if ( hsCom->stopFFTbin == 256 ) + { + hsCom->nFFTpart = 20; + } + else + { + hsCom->nFFTpart = 21; + } + hsCom->nCLDFBpart = hsCom->npart - hsCom->nFFTpart; + for(j=0; jnCLDFBpart; j++) + { + hsCom->CLDFBpart[j] = hsCom->part[j+hsCom->nFFTpart] - (hsCom->stopFFTbin-hsCom->startBand); + hsCom->CLDFBpsize_inv[j] = hsCom->psize_inv[j+hsCom->nFFTpart]; + } + + stopBandFR = (int)floor( 1000.f/*Hz*/ / 25.f/*Hz/Bin*/ ); + if ( stopBandFR > hsCom->stopFFTbin ) + { + stopBandFR = hsCom->stopFFTbin; + } + 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_inv_shaping, stopBandFR ); + + hsDec->nFFTpart_shaping = hsDec->npart_shaping; + + switch (hsCom->fftlen) + { + case 512: + hsCom->fftSineTab = NULL; + hsCom->olapWinAna = olapWinAna512; + hsCom->olapWinSyn = olapWinSyn256; + break; + case 640: + hsCom->fftSineTab = fftSineTab640; + hsCom->olapWinAna = olapWinAna640; + hsCom->olapWinSyn = olapWinSyn320; + break; + default: + assert(!"Unsupported FFT length for FD-based CNG"); + break; + } + hsCom->frameSize = hsCom->fftlen >> 1; + + return; +} + + +/*------------------------------------------------------------------- + * deleteFdCngDec() + * + * Delete the instance of type FD_CNG + *-------------------------------------------------------------------*/ + +void deleteFdCngDec( + HANDLE_FD_CNG_DEC * hFdCngDec +) +{ + + HANDLE_FD_CNG_DEC hsDec = *hFdCngDec; + if (hsDec != NULL) + { + deleteFdCngCom(&(hsDec->hFdCngCom)); + free(hsDec); + *hFdCngDec = NULL; + } + + return; +} + + +/*------------------------------------------------------------------- + * ApplyFdCng() + * + * Apply the CLDFB-based CNG at the decoder + *-------------------------------------------------------------------*/ + +void ApplyFdCng( + float * timeDomainInput, + float ** realBuffer, /* i/o: Real part of the buffer */ + float ** imagBuffer, /* i/o: Imaginary part of the buffer */ + HANDLE_FD_CNG_DEC st, /* i/o: FD_CNG structure containing all buffers and variables */ + unsigned char m_frame_type, /* i : Type of frame at the decoder side */ + Decoder_State *stdec, + const int concealWholeFrame, + short is_music +) +{ + float* cngNoiseLevel = st->hFdCngCom->cngNoiseLevel; + float* sidNoiseEst = st->hFdCngCom->sidNoiseEst; + int j,k; + float factor; + float lsp_cng[M]; + + if( st->hFdCngCom->frame_type_previous == ACTIVE_FRAME ) + { + st->hFdCngCom->inactive_frame_counter = 0; + } + + switch (m_frame_type) + { + + case ACTIVE_FRAME: + /************************** + * ACTIVE_FRAME at DECODER * + **************************/ + + st->hFdCngCom->inactive_frame_counter = 0; + st->hFdCngCom->sid_frame_counter = 0; + /* set noise estimation inactive during concealment, as no update with noise generated by concealment should be performed. */ + /* set noise estimation inactive when we have bit errors, as no update with noise generated by corrupt frame (biterror) should be performed. */ + if ( concealWholeFrame==0 && + *timeDomainInput(-FLT_MAX) && + *(timeDomainInput+st->hFdCngCom->frameSize-1)hFdCngCom->frameSize-1)>(-FLT_MAX) + && + !(!st->flag_dtx_mode&& stdec->VAD) + && !(stdec->cng_type==LP_CNG && st->flag_dtx_mode) + && ( is_music == 0 ) + && (!stdec->BER_detect) + ) + { + /* Perform noise estimation at the decoder */ + perform_noise_estimation_dec(timeDomainInput, 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); + + /* Update CNG levels */ + if ( st->flag_dtx_mode && stdec->cng_type == FD_CNG ) + { + bandcombinepow(st->bandNoiseShape, st->hFdCngCom->stopFFTbin-st->hFdCngCom->startBand, st->hFdCngCom->part, st->hFdCngCom->nFFTpart, st->hFdCngCom->psize_inv, st->partNoiseShape); /* This needs to be done only once per inactive phase */ + + j = 0; + for(k=0 ; khFdCngCom->nFFTpart ; k++) + { + factor = (st->hFdCngCom->sidNoiseEst[k]+DELTA)/(st->partNoiseShape[k]+DELTA); + for(; j<=st->hFdCngCom->part[k] ; j++) + { + cngNoiseLevel[j] = st->bandNoiseShape[j] * factor; + } + } + } + else + { + /* This sets the new CNG levels until a SID update overwrites it */ + mvr2r(st->bandNoiseShape, cngNoiseLevel, st->hFdCngCom->stopFFTbin-st->hFdCngCom->startBand); /* This sets the new CNG levels until a SID update overwrites it */ + } + + stdec->cngTDLevel = (float)sqrt( (sum_f(cngNoiseLevel, st->hFdCngCom->stopFFTbin - st->hFdCngCom->startBand) / 2 * st->hFdCngCom->fftlen) / stdec->L_frame); + } + if ((concealWholeFrame==1) && (stdec->nbLostCmpt==1) + && sum_f(cngNoiseLevel+st->hFdCngCom->startBand, st->hFdCngCom->stopFFTbin - st->hFdCngCom->startBand)>0.01f) + { + /* update lsf cng estimate for concealment. Do that during concealment, in order to avoid addition clean channel complexity*/ + lpc_from_spectrum( cngNoiseLevel, st->hFdCngCom->startBand, st->hFdCngCom->stopFFTbin, st->hFdCngCom->fftlen, st->hFdCngCom->fftSineTab, st->hFdCngCom->A_cng, 0 ); + + a2lsp_stab( st->hFdCngCom->A_cng, lsp_cng, stdec->lspold_cng ); + mvr2r( lsp_cng, stdec->lspold_cng, M ); + + lsp2lsf( lsp_cng, stdec->lsf_cng, M, stdec->sr_core ); + stdec->plcBackgroundNoiseUpdated = 1; + } + break; + + case SID_FRAME: + st->flag_dtx_mode = 1; + + case ZERO_FRAME: + + if( stdec!=NULL && stdec->cng_type == LP_CNG ) + { + /* Perform noise estimation on inactive phase at the decoder */ + perform_noise_estimation_dec(timeDomainInput, 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); + + /* This sets the new CNG levels until a SID update overwrites it */ + mvr2r(st->bandNoiseShape, cngNoiseLevel, st->hFdCngCom->stopFFTbin-st->hFdCngCom->startBand); /* This sets the new CNG levels until a SID update overwrites it */ + + stdec->cngTDLevel = (float)sqrt( (sum_f(cngNoiseLevel, st->hFdCngCom->stopFFTbin - st->hFdCngCom->startBand) / 2 * st->hFdCngCom->fftlen) / stdec->L_frame); + break; + } + + st->hFdCngCom->inactive_frame_counter++; + + /************************************* + * SID_FRAME or ZERO_FRAME at DECODER * + *************************************/ + + /* Detect first non-active frame */ + if (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->hFdCngCom->stopFFTbin-st->hFdCngCom->startBand, st->hFdCngCom->part, st->hFdCngCom->nFFTpart, st->hFdCngCom->psize_inv, st->partNoiseShape); + } + if (m_frame_type == SID_FRAME) + { + if (st->hFdCngCom->msFrCnt_init_counter < st->hFdCngCom->msFrCnt_init_thresh) + { + /* At initialization, interpolate the bin/band-wise levels from the partition levels */ + scalebands(sidNoiseEst, st->hFdCngCom->part, st->hFdCngCom->npart, st->hFdCngCom->midband, st->hFdCngCom->nFFTpart, st->hFdCngCom->stopBand-st->hFdCngCom->startBand, cngNoiseLevel, 1); + } + else + { + /* Interpolate the CLDFB band levels from the SID (partition) levels */ + if (st->hFdCngCom->regularStopBand>st->hFdCngCom->numCoreBands) + { + scalebands(sidNoiseEst, st->hFdCngCom->part, st->hFdCngCom->npart, st->hFdCngCom->midband, st->hFdCngCom->nFFTpart, st->hFdCngCom->stopBand-st->hFdCngCom->startBand, cngNoiseLevel, 0); + } + /* Shape the SID noise levels in each FFT bin */ + j = 0; + for(k=0 ; khFdCngCom->nFFTpart ; k++) + { + factor = (sidNoiseEst[k]+DELTA)/(st->partNoiseShape[k]+DELTA); + for(; j<=st->hFdCngCom->part[k] ; j++) + { + cngNoiseLevel[j] = st->bandNoiseShape[j] * factor; + } + } + } + } + + if( stdec->codec_mode == MODE2 ) + { + /* Generate comfort noise during SID or zero frames */ + generate_comfort_noise_dec(realBuffer, imagBuffer, stdec); + } + + break; + + default: + break; + } + + return; +} + + +/*------------------------------------------------------------------- + * perform_noise_estimation_dec() + * + * Perform noise estimation at the decoder + *-------------------------------------------------------------------*/ + +void perform_noise_estimation_dec( + const float * timeDomainInput, + HANDLE_FD_CNG_DEC st /* i/o: FD_CNG structure containing all buffers and variables */ +) +{ + float * ptr_r; + float * ptr_i; + int startBand = st->hFdCngCom->startBand; + int stopFFTbin = st->hFdCngCom->stopFFTbin; + float * fftBuffer = st->hFdCngCom->fftBuffer; + float * periodog = st->hFdCngCom->periodog; + float * ptr_per = periodog; + float * msPeriodog = st->msPeriodog; + float * msNoiseEst = st->msNoiseEst; + + float * msLogPeriodog = st->msLogPeriodog; + float * msLogNoiseEst = st->msLogNoiseEst; + + int * part = st->part_shaping; + int npart = st->npart_shaping; + int nFFTpart = st->nFFTpart_shaping; + float * psize = st->psize_shaping; + float * psize_inv = st->psize_inv_shaping; + + /* Perform STFT analysis */ + AnalysisSTFT(timeDomainInput, fftBuffer, st->hFdCngCom); + + /* Compute the squared magnitude in each FFT bin */ + if( startBand == 0 ) + { + (*ptr_per) = fftBuffer[0]*fftBuffer[0]; /* DC component */ + ptr_per++; + ptr_r = fftBuffer + 2; + } + else + { + ptr_r = fftBuffer + 2*startBand; + } + + ptr_i = ptr_r+1; + + for( ; ptr_per < periodog+stopFFTbin-startBand ; ptr_per++) + { + (*ptr_per) = (*ptr_r)*(*ptr_r) + (*ptr_i)*(*ptr_i); + ptr_r += 2; + ptr_i += 2; + } + /* Nyquist frequency is discarded */ + + /* Rescale to get energy/sample: it should be 2*(1/N)*(2/N), parseval relation with 1/N,*2 for nrg computed till Nyquist only, 2/N as windowed samples correspond to half a frame*/ + v_multc( periodog, 4.f/(float)(st->hFdCngCom->fftlen*st->hFdCngCom->fftlen), periodog, stopFFTbin-startBand); + + /* Adjust to the desired frequency resolution by averaging over spectral partitions for SID transmission */ + bandcombinepow( periodog, stopFFTbin-startBand, part, npart, psize_inv, msPeriodog ); + + /* Compress MS inputs */ + compress_range( msPeriodog, msLogPeriodog, npart ); + + /* Call the minimum statistics routine for noise estimation */ + minimum_statistics( npart, nFFTpart, psize, msLogPeriodog, st->msNoiseFloor, 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(msLogNoiseEst, msNoiseEst, npart); + + return; +} + + +/*------------------------------------------------------------------- + * FdCng_decodeSID() + * + * Decode the FD-CNG bitstream + *-------------------------------------------------------------------*/ + +void FdCng_decodeSID( + Decoder_State *corest /* i/o: decoder state structure */ +) +{ + int N; + float* sidNoiseEst; + float gain; + float preemph_fac; + + int i, index; + float v[32]; + int indices[32]; + HANDLE_FD_CNG_COM st; + + st = (corest->hFdCngDec)->hFdCngCom; + + sidNoiseEst = st->sidNoiseEst; + preemph_fac = corest->preemph_fac; + + N = st->npart; + gain = 0.0f; + st->sid_frame_counter++; + + /* Read bitstream */ + for ( i=0; iCngBandwidth == NB) + { + sidNoiseEst[N-1] *= NB_LAST_BAND_SCALE; + } + + if ( st->CngBandwidth == SWB && st->CngBitrate <= ACELP_13k20 ) + { + 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); + + lpc_from_spectrum(st->cngNoiseLevel, st->startBand, st->stopFFTbin, st->fftlen, st->fftSineTab, st->A_cng, preemph_fac ); + + return; +} + + +/*------------------------------------------------------------------- + * noisy_speech_detection() + * + * + *-------------------------------------------------------------------*/ + +void noisy_speech_detection( + const short vad, + const float * ftimeInPtr, /* i : input time-domain frame */ + const int frameSize, /* i : frame size */ + const float * msNoiseEst, /* i : noise estimate over all critical bands */ + const float * psize, /* i : partition sizes */ + const int nFFTpart, /* i : Number of partitions taken into account */ + float *lp_noise, /* i/o: long term total Noise energy average */ + float *lp_speech, /* i/o: long term active speech energy average */ + short *flag_noisy_speech +) +{ + float tmp; + + if( vad == 0 ) + { + tmp = dotp(msNoiseEst, psize, nFFTpart); + *lp_noise = 0.995f * *lp_noise + 0.005f * 10.f*(float)log10( tmp + DELTA); + } + else + { + tmp = dotp(ftimeInPtr, ftimeInPtr, frameSize) * 2.f/frameSize; + *lp_speech = 0.995f * *lp_speech + 0.005f * 10.f*(float)log10( tmp + DELTA ); + } + + tmp = *lp_speech - 45.f; + if (*lp_noisehFdCngDec; + HANDLE_FD_CNG_COM st = std->hFdCngCom; + float * cngNoiseLevel = st->cngNoiseLevel; + float * ptr_level = cngNoiseLevel; + short * seed = &(st->seed); + float scale = 1.f; + float scaleCldfb = CLDFB_SCALING / st->scalingFactor; + float * fftBuffer = st->fftBuffer; + float * timeDomainOutput = st->timeDomainBuffer; + float preemph_fac = stdec->preemph_fac; + int tcx_transition = 0; + float enr, att; + short bwidth = stdec->bwidth; + short CNG_mode = stdec->CNG_mode; + + /* + 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) + { + rand_gauss(&fftBuffer[0], seed); + fftBuffer[0] *= (float)sqrt(scale **ptr_level); /* DC component in FFT */ + ptr_level++; + ptr_r = fftBuffer + 2; + } + else + { + fftBuffer[0] = 0.f; + set_f( fftBuffer+2, 0.0f, 2*(st->startBand-1) ); + ptr_r = fftBuffer + 2*st->startBand; + } + ptr_i = ptr_r + 1; + for( ; ptr_level < cngNoiseLevel+st->stopFFTbin-st->startBand ; ptr_level++) + { + /* Real part in FFT bins */ + rand_gauss(ptr_r, seed); + (*ptr_r) *= (float)sqrt((scale **ptr_level)*0.5f); + ptr_r += 2; + /* Imaginary part in FFT bins */ + rand_gauss(ptr_i, seed); + (*ptr_i) *= (float)sqrt((scale **ptr_level)*0.5f); + ptr_i += 2; + } + + /* Remaining FFT bins are set to zero */ + set_f( fftBuffer+2*st->stopFFTbin, 0.0f, st->fftlen-2*st->stopFFTbin); + + /* Nyquist frequency is discarded */ + fftBuffer[1] = 0.f; + + /* If previous frame is active, reset the overlap-add buffer */ + if( st->frame_type_previous==ACTIVE_FRAME ) + { + set_f( st->olapBufferSynth, 0.0f, st->fftlen); + if( (stdec->core > 0 && stdec->codec_mode == MODE2) || stdec->codec_mode == MODE1 ) + { + tcx_transition = 1; + } + } + + /* Perform STFT synthesis */ + SynthesisSTFT(fftBuffer, timeDomainOutput, st->olapBufferSynth, st->olapWinSyn, tcx_transition, st ); + + /* update CNG excitation energy for LP_CNG */ + + /* calculate the residual signal energy */ + enr = dotp( st->exc_cng, st->exc_cng, st->frameSize ) / st->frameSize; + + /* convert log2 of residual signal energy */ + enr = (float)log10( enr + 0.1f ) / (float)log10( 2.0f ); + + /* decrease the energy in case of WB input */ + if( bwidth != NB ) + { + if( bwidth == WB ) + { + if( CNG_mode >= 0 ) + { + /* Bitrate adapted attenuation */ + att = ENR_ATT[CNG_mode]; + } + else + { + /* Use least attenuation for higher bitrates */ + att = ENR_ATT[4]; + } + } + else + { + att = 1.5f; + } + + enr -= att; + } + + stdec->lp_ener = 0.8f * stdec->lp_ener + 0.2f * pow( 2.0f, enr ); + + /* + 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 + */ + if (bufferReal!=NULL && st->numCoreBands < st->regularStopBand) + { + for(j=st->numCoreBands ; jregularStopBand ; j++) + { + for(i=0 ; inumSlots ; i++) + { + /* Real part in CLDFB band */ + rand_gauss(&bufferReal[i][j], seed); + bufferReal[i][j] *= (float)sqrt((scaleCldfb **ptr_level)*0.5f); + /* Imaginary part in CLDFB band */ + rand_gauss(&bufferImag[i][j], seed); + bufferImag[i][j] *= (float)sqrt((scaleCldfb **ptr_level)*0.5f); + } + ptr_level++; + } + } + + /* Overlap-add when previous frame is active */ + if( st->frame_type_previous == ACTIVE_FRAME && stdec->codec_mode == MODE2 ) + { + float noise[2048], old_exc_ener = 0.f, gain = 0.f, tmp; + int N = st->frameSize; + short seed_loc = st->seed; + float *old_exc, old_Aq[M+1], *old_syn_pe, old_syn; + + if( stdec->core > ACELP_CORE ) + { + 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, + stdec->tcx_cfg.tcx_last_overlap_mode==ALDO_WINDOW? FULL_OVERLAP: stdec->tcx_cfg.tcx_last_overlap_mode, + NULL, NULL, NULL, NULL, NULL, N/2, stdec->tcx_cfg.tcx_offset<0?-stdec->tcx_cfg.tcx_offset: 0, + 1, 0, 0 ); + + if( stdec->tcx_cfg.last_aldo ) + { + for (i=0; i<(st->frameSize-NS2SA(stdec->sr_core, N_ZERO_MDCT_NS)); i++) + { + timeDomainOutput[i] += stdec->old_outLB[i+NS2SA(stdec->sr_core, N_ZERO_MDCT_NS)]; + } + } + 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] += stdec->syn_Overl[i]; + } + } + } + else + { + + mvr2r(stdec->old_Aq_12_8, old_Aq,M+1); + old_exc = stdec->old_exc+L_EXC_MEM_DEC-(N/2); + old_syn_pe = stdec->mem_syn2; + old_syn = stdec->syn[M]; + + for ( i=0; iolapWinSyn[N/2+i]; + } + } + } + + return; +} + + +/*------------------------------------------------------------------- + * generate_comfort_noise_dec_hf() + * + * Generate the comfort noise based on the target noise level for the CLDFB part + *-------------------------------------------------------------------*/ + +void generate_comfort_noise_dec_hf( + float ** bufferReal, /* o : Real part of input bands */ + float ** bufferImag, /* o : Imaginary part of input bands */ + Decoder_State *stdec +) +{ + short i,j; + float * ptr_level; + HANDLE_FD_CNG_COM st = stdec->hFdCngDec->hFdCngCom; + short * seed = &(st->seed); + float scale = CLDFB_SCALING / st->scalingFactor; + + ptr_level=st->cngNoiseLevel+st->stopFFTbin-st->startBand; + /* + 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 + */ + if (st->numCoreBands < st->regularStopBand) + { + for(j=st->numCoreBands ; jregularStopBand ; j++) + { + for(i=0 ; inumSlots ; i++) + { + /* Real part in CLDFB band */ + rand_gauss(&bufferReal[i][j], seed); + bufferReal[i][j] *= (float)sqrt((scale **ptr_level)*0.5f); + /* Imaginary part in CLDFB band */ + rand_gauss(&bufferImag[i][j], seed); + bufferImag[i][j] *= (float)sqrt((scale **ptr_level)*0.5f); + } + ptr_level++; + } + } + + return; +} + + +/*------------------------------------------------------------------- + * generate_masking_noise() + * + * Generate additional comfort noise (kind of noise filling) + *-------------------------------------------------------------------*/ + +void generate_masking_noise( + float * timeDomainBuffer, /* i/o: time-domain signal */ + HANDLE_FD_CNG_COM st, /* i/o: FD_CNG structure containing all buffers and variables */ + short length, + short core +) +{ + float * cngNoiseLevel = st->cngNoiseLevel; + float * fftBuffer = st->fftBuffer; + short i; + float maskingNoise[L_FRAME16k]; + float * ptr_r; + float * ptr_i; + float * ptr_level = cngNoiseLevel; + int startBand = st->startBand; + short * seed = &(st->seed); + float scale = 1.f; + int scaleTableSize; + + /* skip noise generating if level is very low, to avoid problems with possibly running into denormals */ + if( st->likelihood_noisy_speech > DELTA_MASKING_NOISE ) + { + + if( core != AMR_WB_CORE ) + { + /* Compute additional CN level */ + scaleTableSize = sizeof (scaleTable_cn_only) / sizeof (scaleTable_cn_only[0]); + + for (i = 0 ; i < scaleTableSize ; i++) + { + if ( (st->CngBandwidth == scaleTable_cn_only[i].bwmode) && + (st->CngBitrate >= scaleTable_cn_only[i].bitrateFrom) && + (st->CngBitrate < scaleTable_cn_only[i].bitrateTo) ) + { + break; + } + } + + scale *= (float)pow( 10.f,-scaleTable_cn_only[i].scale/10.f ) - 1.f; + } + else + { + /* Compute additional CN level */ + scaleTableSize = sizeof (scaleTable_cn_only_amrwbio) / sizeof (scaleTable_cn_only_amrwbio[0]); + + for (i = 0 ; i < scaleTableSize ; i++) + { + if (st->CngBitrate >= scaleTable_cn_only_amrwbio[i][0]) + { + break; + } + } + + if(ilikelihood_noisy_speech; + + /* + 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 (startBand==0) + { + rand_gauss(&fftBuffer[0], seed); + ptr_r = fftBuffer + 2; + fftBuffer[0] *= (float)sqrt(scale **ptr_level ); /* DC component in FFT */ + ptr_level++; + } + else + { + fftBuffer[0] = 0.f; + set_f( fftBuffer+2, 0.0f, 2*(startBand-1) ); + ptr_r = fftBuffer + 2*startBand; + } + ptr_i = ptr_r + 1; + + for( ; ptr_level < cngNoiseLevel+st->stopFFTbin-startBand ; ptr_level++) + { + /* Real part in FFT bins */ + rand_gauss(ptr_r, seed); + (*ptr_r) *= (float)sqrt((scale **ptr_level )*0.5f); + ptr_r += 2; + /* Imaginary part in FFT bins */ + rand_gauss(ptr_i, seed); + (*ptr_i) *= (float)sqrt((scale **ptr_level )*0.5f); + ptr_i += 2; + } + + /* Remaining FFT bins are set to zero */ + set_f( fftBuffer+2*st->stopFFTbin, 0.0f, st->fftlen-2*st->stopFFTbin); + /* Nyquist frequency is discarded */ + fftBuffer[1] = 0.f; + + } + else + { + /* very low level case - update random seeds and reset FFT buffer; don't fully skip SynthesisSTFT(), because of the buffer updates done there... */ + generate_masking_noise_update_seed( st ); + + set_f( fftBuffer, 0.f, st->fftlen ); + } + + /* Perform STFT synthesis */ + SynthesisSTFT( fftBuffer, maskingNoise, st->olapBufferSynth2, st->olapWinSyn, 0, st ); + + /* Add some comfort noise on top of decoded signal */ + v_add(maskingNoise, timeDomainBuffer, timeDomainBuffer, min(st->frameSize,length)); + + return; +} + + +/*------------------------------------------------------------------- + * 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: FD_CNG structure containing all buffers and variables */ +) +{ + float * cngNoiseLevel = st->cngNoiseLevel; + float * ptr_level = cngNoiseLevel; + int startBand = st->startBand; + short * seed = &(st->seed); + float tmp = 0; + + /* + 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 (startBand==0) + { + rand_gauss(&tmp, seed); + ptr_level++; + } + + for( ; ptr_level < cngNoiseLevel+st->stopFFTbin-startBand ; ptr_level++) + { + /* Real part in FFT bins */ + rand_gauss(&tmp, seed); + rand_gauss(&tmp, seed); + } + + return; +} + + +/*------------------------------------------------------------------- + * generate_masking_noise_mdct() + * + * Generate additional comfort noise (kind of noise filling) + *-------------------------------------------------------------------*/ + +void generate_masking_noise_mdct( + float * mdctBuffer, /* i/o: time-domain signal */ + HANDLE_FD_CNG_COM st /* i/o: FD_CNG structure containing all buffers and variables */ +) +{ + + float * cngNoiseLevel = st->cngNoiseLevel; + short i; + float maskingNoise[2*L_FRAME16k]; + float * ptr_r; + + float * ptr_level = cngNoiseLevel; + int startBand = st->startBand; + short * seed = &(st->seed); + float scale = 1.f; + int scaleTableSize; + + /* skip noise generating if level is very low, to avoid problems with possibly running into denormals */ + if( st->likelihood_noisy_speech > DELTA_MASKING_NOISE ) + { + + /* Compute additional CN level */ + scaleTableSize = sizeof (scaleTable_cn_only) / sizeof (scaleTable_cn_only[0]); + + for (i = 0 ; i < scaleTableSize ; i++) + { + if ( (st->CngBandwidth == scaleTable_cn_only[i].bwmode) && + (st->CngBitrate >= scaleTable_cn_only[i].bitrateFrom) && + (st->CngBitrate < scaleTable_cn_only[i].bitrateTo) ) + { + break; + } + } + + scale *= (float)pow( 10.f,-scaleTable_cn_only[i].scale/10.f ) - 1.f; + + /* Exclude clean speech */ + scale *= st->likelihood_noisy_speech; + + /* + 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 (startBand==0) + { + rand_gauss(&maskingNoise[0], seed); + maskingNoise[0] *= (float)sqrt(scale **ptr_level * 0.5f ); /* DC component in FFT */ + ptr_level++; + ptr_r = maskingNoise + 1; + } + else + { + maskingNoise[0] = 0.f; + set_f( maskingNoise+1, 0.0f, (startBand-1) ); + ptr_r = maskingNoise + startBand; + } + + for( ; ptr_level < cngNoiseLevel+st->stopFFTbin-startBand ; ptr_level++) + { + /* MDCT bins */ + rand_gauss(ptr_r, seed); + (*ptr_r) *= (float)sqrt(scale **ptr_level * 0.5f ); + ptr_r += 1; + } + + /*re-normalization of energy level: M/sqrt(2)*/ + v_multc(maskingNoise, (float)sqrt(NORM_MDCT_FACTOR), maskingNoise, st->stopFFTbin); + + /* Add some comfort noise on top of decoded signal */ + v_add(maskingNoise, mdctBuffer, mdctBuffer, st->stopFFTbin); + + } + else + { + /* very low level case - just update random seeds */ + if ( startBand == 0 ) + { + rand_gauss(&maskingNoise[0], seed); + ptr_level++; + } + + for( ; ptr_level < cngNoiseLevel+st->stopFFTbin-startBand ; ptr_level++ ) + { + rand_gauss(&maskingNoise[0], seed); + } + } + + return; +} diff --git a/lib_dec/gain_dec.c b/lib_dec/gain_dec.c new file mode 100644 index 000000000..9bc161147 --- /dev/null +++ b/lib_dec/gain_dec.c @@ -0,0 +1,653 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + + +/*---------------------------------------------------------------------* + * Es_pred_dec() + * + * Decoding of scaled predicted innovation energy to be used in all subframes + *---------------------------------------------------------------------*/ + +void Es_pred_dec( + float *Es_pred, /* o : predicited scaled innovation energy */ + const int enr_idx, /* i : indice */ + const short nb_bits, /* i : number of bits */ + const short no_ltp /* i : no LTP flag */ +) +{ + if( !no_ltp ) + { + switch ( nb_bits ) + { + case 5: + *Es_pred = Es_pred_qua_5b[enr_idx]; + break; + case 4: + *Es_pred = Es_pred_qua_4b[enr_idx]; + break; + case 3: + *Es_pred = Es_pred_qua_3b[enr_idx]; + break; + default: + *Es_pred = Es_pred_qua_5b[enr_idx]; + break; + } + } + else + { + *Es_pred = Es_pred_qua_4b_no_ltp[enr_idx]; + } + + return; +} + + +/*--------------------------------------------------------------------------* + * lp_gain_updt() + * + * Update of LP pitch and code gains (FEC) + *-------------------------------------------------------------------------*/ + +void lp_gain_updt( + const short i_subfr, /* i : subframe number */ + const float gain_pit, /* i : Decoded gain pitch */ + const float norm_gain_code, /* i : Normalised gain code */ + float *lp_gainp, /* i/o: LP-filtered pitch gain(FEC) */ + float *lp_gainc, /* i/o: LP-filtered code gain (FEC) */ + const short L_frame /* i : length of the frame */ +) +{ + if( L_frame == L_FRAME ) + { + if( i_subfr == 0 ) + { + *lp_gainp = 0.1f * gain_pit; + *lp_gainc = 0.1f * norm_gain_code; + } + else if( i_subfr == L_SUBFR ) + { + *lp_gainp += 0.2f * gain_pit; + *lp_gainc += 0.2f * norm_gain_code; + } + else if( i_subfr == 2*L_SUBFR ) + { + *lp_gainp += 0.3f * gain_pit; + *lp_gainc += 0.3f * norm_gain_code; + } + else /* i_subfr == 3*L_SUBFR */ + { + *lp_gainp += 0.4f * gain_pit; + *lp_gainc += 0.4f * norm_gain_code; + } + } + else + { + if( i_subfr == 0 ) + { + *lp_gainp = (1.0f/15.0f) * gain_pit; + *lp_gainc = (1.0f/15.0f) * norm_gain_code; + } + else if( i_subfr == L_SUBFR ) + { + *lp_gainp += (2.0f/15.0f) * gain_pit; + *lp_gainc += (2.0f/15.0f) * norm_gain_code; + } + else if( i_subfr == 2*L_SUBFR ) + { + *lp_gainp += (3.0f/15.0f) * gain_pit; + *lp_gainc += (3.0f/15.0f) * norm_gain_code; + } + else if( i_subfr == 3*L_SUBFR ) + { + *lp_gainp += (4.0f/15.0f) * gain_pit; + *lp_gainc += (4.0f/15.0f) * norm_gain_code; + } + else /* i_subfr == 4*L_SUBFR */ + { + *lp_gainp += (5.0f/15.0f) * gain_pit; + *lp_gainc += (5.0f/15.0f) * norm_gain_code; + } + } + + return; +} + + +/*---------------------------------------------------------------------* + * gain_dec_tc() + * + * Decoding of pitch and codebook gains and updating long term energies + *---------------------------------------------------------------------*/ + +void gain_dec_tc( + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : core bitrate */ + const short L_frame, /* i : length of the frame */ + const short i_subfr, /* i : subframe number */ + const short tc_subfr, /* i : TC subframe index */ + const float Es_pred, /* i : predicted scaled innov. energy */ + const float *code, /* i : algebraic code excitation */ + float *gain_pit, /* o : pitch gain */ + float *gain_code, /* o : Quantized codeebook gain */ + float *gain_inov, /* o : unscaled innovation gain */ + float *norm_gain_code /* o : norm. gain of the codebook excit. */ +) +{ + short index, nBits; + float Ecode, gcode0; + float Ei; + + *gain_pit = 0; + + /*----------------------------------------------------------------* + * find number of bits for gain dequantization + *----------------------------------------------------------------*/ + + if( L_frame == L_FRAME ) + { + nBits = gain_bits_tbl[BIT_ALLOC_IDX(core_brate, TRANSITION, i_subfr, TC_SUBFR2IDX(tc_subfr))]; + } + else /* L_frame == L_FRAME16k */ + { + nBits = gain_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ(core_brate, TRANSITION, i_subfr, TC_SUBFR2IDX_16KHZ(tc_subfr))]; + } + + /*-----------------------------------------------------------------* + * calculate the predicted gain code + *-----------------------------------------------------------------*/ + + Ecode = (dotp( code, code, L_SUBFR) + 0.01f) / L_SUBFR; + *gain_inov = 1.0f / (float)sqrt( Ecode ); + Ei = 10 * (float)log10( Ecode ); + gcode0 = (float) pow(10, 0.05 * (Es_pred - Ei)); + + /*------------------------------------------------------------------------------------------* + * Select the gain quantization table and dequantize the gain + *------------------------------------------------------------------------------------------*/ + + index = (short)get_next_indice( st, nBits ); + + if( nBits > 3 ) + { + *gain_code = gain_dequant( index, G_CODE_MIN, G_CODE_MAX, nBits ); + } + else /* nBits == 3 */ + { + *gain_code = tbl_gain_code_tc[index]; + } + + /*-----------------------------------------------------------------* + * decode normalized codebook gain + *-----------------------------------------------------------------*/ + + *gain_code *= gcode0; + *norm_gain_code = *gain_code / *gain_inov; + + return; +} + +/*---------------------------------------------------------------------* + * gain_dec_amr_wb() + * + * Decoding of pitch and fixed codebook gains (used also in AMR-WB IO mode) + *---------------------------------------------------------------------*/ + +void gain_dec_amr_wb( + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : core bitrate */ + float *gain_pit, /* o : Quantized pitch gain */ + float *gain_code, /* o : Quantized codeebook gain */ + float *past_qua_en, /* i/o: gain quantization memory (4 words) */ + float *gain_inov, /* o : unscaled innovation gain */ + const float *code, /* i : algebraic code excitation */ + float *norm_gain_code /* o : norm. gain of the codebook excitation */ +) +{ + short i, index; + short nbits; + float gcode0, qua_en; + const float *t_qua_gain; + + *gain_inov = 1.0f/ (float)sqrt( ( dotp( code, code, L_SUBFR ) + 0.01f ) / L_SUBFR ); + + /*-----------------------------------------------------------------* + * Select the gain quantization table + *-----------------------------------------------------------------*/ + + if( core_brate < ACELP_12k65) + { + nbits = 6; + t_qua_gain = t_qua_gain6b; + } + else + { + nbits = 7; + t_qua_gain = t_qua_gain7b; + } + + /*-----------------------------------------------------------------* + * predicted code gain + *-----------------------------------------------------------------*/ + + /* start with predicting code energy in dB */ + gcode0 = MEAN_ENER; + for (i=0; i0; i--) + { + past_qua_en[i] = past_qua_en[i-1]; + } + past_qua_en[0] = (float)(20.0*log10(qua_en)); + + /*-----------------------------------------------------------------* + * Normalized code gain + *-----------------------------------------------------------------*/ + + *norm_gain_code = *gain_code / *gain_inov; + + return; +} + +/*--------------------------------------------------------------------------* + * gain_dec_mless() + * + * Decoding of pitch and codebook gains without updating long term energies + *-------------------------------------------------------------------------*/ + +void gain_dec_mless( + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : core bitrate */ + const short L_frame, /* i : length of the frame */ + const short coder_type, /* i : coding type */ + const short i_subfr, /* i : subframe number */ + const short tc_subfr, /* i : TC subframe index */ + const float *code, /* i : algebraic code excitation */ + const float Es_pred, /* i : predicted scaled innov. energy */ + float *gain_pit, /* o : Quantized pitch gain */ + float *gain_code, /* o : Quantized codeebook gain */ + float *gain_inov, /* o : unscaled innovation gain */ + float *norm_gain_code /* o : norm. gain of the codebook excitation */ +) +{ + short index, nBits; + float gcode0, Ei, Ecode; + const float *qua_table; + + /*-----------------------------------------------------------------* + * decode pitch gain + *-----------------------------------------------------------------*/ + + if( L_frame == L_FRAME ) + { + nBits = gain_bits_tbl[BIT_ALLOC_IDX(core_brate, coder_type, i_subfr, TC_SUBFR2IDX(tc_subfr))]; + } + else /* L_frame == L_FRAME16k */ + { + nBits = gain_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ(core_brate, coder_type, i_subfr, TC_SUBFR2IDX_16KHZ(tc_subfr))]; + } + + if( (tc_subfr == 3*L_SUBFR && i_subfr == 3*L_SUBFR && L_frame == L_FRAME) || + (tc_subfr == 4*L_SUBFR && i_subfr == 4*L_SUBFR && L_frame == L_FRAME16k) ) + { + /* decode pitch gain */ + index = (short)get_next_indice( st, nBits >> 1 ); + Ei = (G_PITCH_MAX_TC192 - G_PITCH_MIN_TC192) / ((1 << (nBits >> 1)) - 1); /* set quantization step */ + *gain_pit = usdequant( index, G_PITCH_MIN_TC192, Ei ); + + /* calculate the predicted gain code */ + Ecode = (dotp( code, code, L_SUBFR) + 0.01f) / L_SUBFR; + *gain_inov = 1.0f / (float)sqrt( Ecode ); + Ei = 10 * (float)log10( Ecode ); + gcode0 = (float) pow(10, 0.05 * (Es_pred - Ei)); + + /* decode normalized codebook gain */ + index = (short)get_next_indice( st, (nBits+1)>>1 ); + *gain_code = gain_dequant( index, G_CODE_MIN_TC192, G_CODE_MAX_TC192, (nBits+1)>>1 ); + *gain_code *= gcode0; + } + else + { + switch ( nBits ) + { + case 7: + { + qua_table = gain_qua_mless_7b; + break; + } + case 6: + { + qua_table = gain_qua_mless_6b; + break; + } + case 5: + { + qua_table = gain_qua_mless_5b; + break; + } + default: + { + qua_table = gain_qua_mless_6b; + break; + } + } + + if( coder_type == INACTIVE && nBits == 6 ) + { + nBits--; + } + + index = (short)get_next_indice( st, nBits ); + + *gain_pit = qua_table[index * 2]; + Ecode = (dotp( code, code, L_SUBFR) + 0.01f) / L_SUBFR; + *gain_inov = 1.0f / (float)sqrt( Ecode ); + Ei = 10 * (float)log10( Ecode ); + + /*-----------------------------------------------------------------* + * calculate the predicted gain code + *-----------------------------------------------------------------*/ + + gcode0 = (float) pow(10, 0.05 * (Es_pred - Ei)); + + /*-----------------------------------------------------------------* + * decode normalized codebook gain + *-----------------------------------------------------------------*/ + + *gain_code = qua_table[index * 2 + 1] * gcode0; + } + + *norm_gain_code = *gain_code / *gain_inov; + + return; +} + +/*--------------------------------------------------------------------------* + * gain_dec_lbr() + * + * Decoding of pitch and codebook gains in ACELP at 6.6 and 7.5 kbps + *-------------------------------------------------------------------------*/ + +void gain_dec_lbr( + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : core bitrate */ + const short coder_type, /* i : coding type */ + const short i_subfr, /* i : subframe index */ + const float *code, /* i : algebraic excitation */ + float *gain_pit, /* o : quantized pitch gain */ + float *gain_code, /* o : quantized codebook gain */ + float *gain_inov, /* o : gain of the innovation (used for normalization) */ + float *norm_gain_code, /* o : norm. gain of the codebook excitation */ + float gains_mem[] /* i/o: pitch gain and code gain from previous subframes */ +) +{ + short index, nBits, n_pred, ctype; + float gcode0, aux[10], Ecode; + const float *b, *cdbk = 0; + + Ecode = ( dotp( code, code, L_SUBFR ) + 0.01f ) / L_SUBFR; + *gain_inov = 1.0f / (float)sqrt(Ecode); + + /*-----------------------------------------------------------------* + * select the codebook, size and number of bits + * set the gains searching range + *-----------------------------------------------------------------*/ + + nBits = gain_bits_tbl[BIT_ALLOC_IDX(core_brate, coder_type, i_subfr, 0)]; + ctype = 2*(coder_type - 1); + + /*-----------------------------------------------------------------* + * calculate prediction of gcode + * search for the best codeword + *-----------------------------------------------------------------*/ + + if (i_subfr == 0) + { + b = b_1sfr; + n_pred = 2; + + switch ( nBits ) + { + case 8: + { + cdbk = gp_gamma_1sfr_8b; + break; + } + case 7: + { + cdbk = gp_gamma_1sfr_7b; + break; + } + case 6: + { + cdbk = gp_gamma_1sfr_6b; + break; + } + } + + /* calculate predicted gain */ + aux[0] = 1.0f; + aux[1] = ctype; + gcode0 = (float)pow(10, dotp(b, aux, n_pred) - 0.5f * (float)log10(Ecode)); + + /* retrieve the codebook index and calculate both gains */ + index = (short)get_next_indice( st, nBits ); + *gain_pit = cdbk[index * 2]; + *gain_code = cdbk[index * 2 + 1] * gcode0; + gains_mem[0] = *gain_code; + gains_mem[3] = *gain_pit; + } + else if (i_subfr == L_SUBFR) + { + b = b_2sfr; + n_pred = 4; + + switch ( nBits ) + { + case 7: + { + cdbk = gp_gamma_2sfr_7b; + break; + } + case 6: + { + cdbk = gp_gamma_2sfr_6b; + break; + } + } + + /* calculate predicted gain */ + aux[0] = 1.0f; + aux[1] = ctype; + aux[2] = (float)log10(gains_mem[0]); + aux[3] = gains_mem[3]; + gcode0 = (float)pow(10, dotp(b, aux, n_pred)); + + /* retrieve the codebook index and calculate both gains */ + index = (short)get_next_indice( st, nBits ); + *gain_pit = cdbk[index * 2]; + *gain_code = cdbk[index * 2 + 1] * gcode0; + gains_mem[1] = *gain_code; + gains_mem[4] = *gain_pit; + } + else if (i_subfr == 2*L_SUBFR) + { + b = b_3sfr; + n_pred = 6; + + cdbk = gp_gamma_3sfr_6b; + + /* calculate predicted gain */ + aux[0] = 1.0f; + aux[1] = ctype; + aux[2] = (float)log10(gains_mem[0]); + aux[3] = (float)log10(gains_mem[1]); + aux[4] = gains_mem[3]; + aux[5] = gains_mem[4]; + gcode0 = (float)pow(10, dotp(b, aux, n_pred)); + + /* retrieve the codebook index and calculate both gains */ + index = (short)get_next_indice( st, nBits ); + *gain_pit = cdbk[index * 2]; + *gain_code = cdbk[index * 2 + 1] * gcode0; + + gains_mem[2] = *gain_code; + gains_mem[5] = *gain_pit; + } + else if (i_subfr == 3*L_SUBFR) + { + b = b_4sfr; + n_pred = 8; + + cdbk = gp_gamma_4sfr_6b; + + /* calculate predicted gain */ + aux[0] = 1.0f; + aux[1] = ctype; + aux[2] = (float)log10(gains_mem[0]); + aux[3] = (float)log10(gains_mem[1]); + aux[4] = (float)log10(gains_mem[2]); + aux[5] = gains_mem[3]; + aux[6] = gains_mem[4]; + aux[7] = gains_mem[5]; + gcode0 = (float)pow(10, dotp(b, aux, n_pred)); + + /* retrieve the codebook index and calculate both gains */ + index = (short)get_next_indice( st, nBits ); + *gain_pit = cdbk[index * 2]; + *gain_code = cdbk[index * 2 + 1] * gcode0; + } + + *norm_gain_code = *gain_code / *gain_inov; + + return; +} + +/*--------------------------------------------------------------------------* + * gain_dec_SQ() + * + * Decoding of pitch and codebook gains using scalar quantizers + *-------------------------------------------------------------------------*/ + +void gain_dec_SQ( + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : core bitrate */ + const short coder_type, /* i : coding type */ + const short i_subfr, /* i : subframe number */ + const short tc_subfr, /* i : TC subframe index */ + const float *code, /* i : algebraic code excitation */ + const float Es_pred, /* i : predicted scaled innov. energy */ + float *gain_pit, /* o : Quantized pitch gain */ + float *gain_code, /* o : Quantized codeebook gain */ + float *gain_inov, /* o : unscaled innovation gain */ + float *norm_gain_code /* o : norm. gain of the codebook excitation */ +) +{ + short index, nBits; + float gcode0, Ei, Ecode; + short tmp16; + /*-----------------------------------------------------------------* + * get number of bits + *-----------------------------------------------------------------*/ + + nBits = gain_bits_16kHz_tbl[ BIT_ALLOC_IDX_16KHZ(core_brate, coder_type, i_subfr, TC_SUBFR2IDX_16KHZ(tc_subfr)) ]; + + /*-----------------------------------------------------------------* + * decode pitch gain + *-----------------------------------------------------------------*/ + + index = (short)get_next_indice( st, nBits>>1 ); + /*Ei = (G_PITCH_MAX - G_PITCH_MIN) / ((1 << (nBits>>1)) - 1);*/ /* set quantization step */ + tmp16 = div_s(1,((1 << (nBits>>1)) - 1) ); /* Q15*/ + Ei = (float)mult_r((short)(G_PITCH_MAX*8192.0f+0.5f),tmp16)/8192.0f; + + *gain_pit = usdequant( index, G_PITCH_MIN, Ei ); + + /*-----------------------------------------------------------------* + * calculate the predicted gain code + *-----------------------------------------------------------------*/ + + Ecode = (dotp( code, code, L_SUBFR) + 0.01f) / L_SUBFR; + *gain_inov = 1.0f / (float)sqrt( Ecode ); + Ei = 10 * (float)log10( Ecode ); + gcode0 = (float) pow(10, 0.05 * (Es_pred - Ei)); + + /*-----------------------------------------------------------------* + * decode normalized codebook gain + *-----------------------------------------------------------------*/ + + index = (short)get_next_indice( st, (nBits+1)>>1 ); + *gain_code = gain_dequant( index, G_CODE_MIN, G_CODE_MAX, (nBits+1)>>1 ); + *gain_code *= gcode0; + *norm_gain_code = *gain_code / *gain_inov; + + return; +} + + +/*-------------------------------------------------* + * gain_dec_gaus() + * + * Decoding of gains for Gaussian codebook + *-------------------------------------------------*/ + +float gain_dec_gaus( /* o : quantized codebook gain */ + const short index, /* i : quantization index */ + const short bits, /* i : number of bits to quantize */ + const float lowBound, /* i : lower bound of quantizer (dB) */ + const float topBound, /* i : upper bound of quantizer (dB) */ + const float gain_inov, /* i : unscaled innovation gain */ + float *norm_gain_code /* o : gain of normalized gaus. excit. */ +) +{ + float gain, enr, stepSize; + + /*-----------------------------------------------------------------* + * quantize linearly the log E + *-----------------------------------------------------------------*/ + + stepSize = (topBound - lowBound)/((float)(1< +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ + +static void gaus_dec2v( Decoder_State *st, float *code, const short lg, const short nb_bits ); +static void dec_2pos( short index, short *ind1, short *ind2, float *sign1, float *sign2, const short n ); + +/*---------------------------------------------------------------------* + * gaus_dec() + * + * no adaptive excitation constructed + * - decode the codebook indices, + * - find the excitation + *---------------------------------------------------------------------*/ + +void gaus_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : core bitrate */ + const short i_subfr, /* i: subframe index */ + float *code, /* o: unvoiced excitation */ + float *norm_gain_code, /* o: gain of the normalized gaussian excitation */ + float *lp_gainp, /* i/o: LP-filtered pitch gain (FEC) */ + float *lp_gainc, /* i/o: LP-filtered code gain (FEC) */ + float *gain_inov, /* o: unscaled innovation gain */ + float *tilt_code, /* o: synthesis excitation spectrum tilt */ + float *voice_fac, /* o: estimated voicing factor */ + float *gain_pit, /* o: pitch gain */ + float *pt_pitch, /* o: floating pitch buffer */ + float *exc, /* o: excitation signal frame */ + float *gain_code, /* o: gain of the gaussian excitation */ + float *exc2 /* o : Scaled excitation signal frame */ +) +{ + short i, idx, nb_bits; + + /*----------------------------------------------------------------* + * Decode Gaussian excitation + *----------------------------------------------------------------*/ + + nb_bits = FCB_bits_tbl[BIT_ALLOC_IDX(core_brate, UNVOICED, i_subfr, TC_SUBFR2IDX(-1))]; + + gaus_dec2v( st, code, L_SUBFR, nb_bits>>1 ); + + /*-----------------------------------------------------------------* + * Decode gain of Gaussian excitation and normalized Gaussian excitation + *-----------------------------------------------------------------*/ + + *gain_inov = 1.0f / (float)sqrt( ( dotp( code, code, L_SUBFR ) + 0.01f ) / L_SUBFR ); + + nb_bits = gain_bits_tbl[BIT_ALLOC_IDX(core_brate, UNVOICED, i_subfr, TC_SUBFR2IDX(-1))]; + idx = (short)get_next_indice( st, nb_bits ); + + /* safety check in case of bit errors */ + if( idx > 78 ) + { + idx = 78; + st->BER_detect = 1; + } + + *gain_code = gain_dec_gaus( idx, nb_bits, -30.0f, 190.0f, *gain_inov, norm_gain_code ); + + /* update LP filtered gains for the case of frame erasures */ + lp_gain_updt( i_subfr, 0.0f, *norm_gain_code, lp_gainp, lp_gainc, L_FRAME ); /* supposes that gain_dec_gaus() is used for ACELP@12k8 only */ + + /*-----------------------------------------------------------------* + * Updates + *-----------------------------------------------------------------*/ + + *tilt_code = 0.0f; + *voice_fac = -1.0f; /* only unvoiced */ + *gain_pit = 0.0f; /* needed for BASS postfitler */ + *pt_pitch = (float)L_SUBFR; /* floating pitch buffer */ + + /*-----------------------------------------------------------------* + * Construct scaled excitation + *-----------------------------------------------------------------*/ + + set_f(&exc2[i_subfr], 0, L_SUBFR); + for (i = 0; i < L_SUBFR; i++) + { + exc[i+i_subfr] = *gain_code * code[i]; + } + + return; +} + +/*-----------------------------------------------------* + * gaus_dec2v() + * + * decoder of Gaussian Codebook for unvoiced + * consisting of addition of 2 Gaussian vectors + * + * One Gaussian vector of 190 values + *-----------------------------------------------------*/ + +static void gaus_dec2v( + Decoder_State *st, /* i/o: decoder state structure */ + float *code, /* o: decoded gaussian codevector */ + const short lg, /* i: codevector length */ + const short nb_bits /* i: nb ob bits per track (max 6)*/ +) +{ + short i, ind1, ind2, idx, index_delta; + short nvec, step; + float sign1, sign2; + float *pt1, *pt2; + float gaus_dico2[190]; + float delta; + + nvec = 1 << nb_bits; + step = 0x80 >> nb_bits; + + idx = (short)get_next_indice( st, 2*nb_bits+1 ); + index_delta = (short)get_next_indice( st, 3 ); + + dec_2pos( idx, &ind1, &ind2, &sign1, &sign2, nvec ); + + delta = STEP_DELTA * (float)(index_delta); + if( delta > 0.0f ) + { + gaus_dico2[0] = gaus_dico[0]; + for (i=1; i<190; i++) + { + gaus_dico2[i] = (gaus_dico[i] - delta*gaus_dico[i-1])/(1 + delta*delta); + } + } + else + { + for (i=0; i<190; i++) + { + gaus_dico2[i] = gaus_dico[i]; + } + } + + pt1 = &gaus_dico2[ind1 * step]; + pt2 = &gaus_dico2[ind2 * step]; + + for(i=0; i>1; + + *ind1 = index/n; + *ind2 = index -(*ind1*n); + if( *ind1 > *ind2) + { + *sign2 = -*sign1; + } + else + { + *sign2 = *sign1; + } + + return; +} + + +#define WMC_TOOL_SKIP + + +/*-----------------------------------------------------* + * gaus_L2_dec : + * + * decoder of Gaussian Codebook for unvoiced as Layer 2 + * + * One Gaussian vector + *-----------------------------------------------------*/ + +void gaus_L2_dec( + float *code, /* o: decoded gaussian codevector */ + float tilt_code, + const float *Aq, + float formant_enh_num, + short *seed_acelp /*i/o: random seed */ +) +{ + short i; + + /*Generate white gaussian noise using central limit theorem method (N only 4 as E_util_random is not purely uniform)*/ + for( i=0; i +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * decod_audio() + * + * Decode audio (AC) frames + *-------------------------------------------------------------------*/ + +void decod_audio( + Decoder_State *st, /* i/o: decoder static memory */ + float dct_epit[], /* o : GSC excitation in DCT domain */ + const float *Aq, /* i : LP filter coefficient */ + const short coder_type, /* i : coding type */ + float *tmp_noise, /* o : long term temporary noise energy */ + float *pitch_buf, /* o : floating pitch values for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *exc, /* i/o: adapt. excitation exc */ + float *exc2, /* i/o: adapt. excitation/total exc */ + float *bwe_exc, /* o : excitation for SWB TBE */ + float *lsf_new, /* i : ISFs at the end of the frame */ + float *gain_buf +) +{ + short tmp_nb_bits_tot, pit_band_idx; + float code[L_SUBFR]; + short Diff_len, nb_subfr, i; + short nb_frame_flg; + float Es_pred = 0.0f; + short Len, max_len; + short attack_flag; + float low_pit; + short last_bin; + short nbits; + float exc_wo_nf[L_FRAME]; + + short nb_bits; /* number of bits */ + int indice; /* parameter indices to read */ + + /*---------------------------------------------------------------* + * Initialization + *---------------------------------------------------------------*/ + + Diff_len = 0; + + /* decode GSC attack flag (used to reduce possible pre-echo) */ + attack_flag = (short) get_next_indice( st, 1 ); + + /* decode GSC SWB speech flag */ + if( coder_type != INACTIVE && st->total_brate >= ACELP_13k20 ) + { + st->GSC_noisy_speech = (short) get_next_indice( st, 1 ); + } + + /* safety check in case of bit errors */ + if( st->GSC_noisy_speech && st->bwidth != SWB ) + { + st->BER_detect = 1; + st->GSC_noisy_speech = 0; + } + + /*---------------------------------------------------------------* + * Decode energy dynamics + *---------------------------------------------------------------*/ + + if( st->GSC_noisy_speech ) + { + nb_subfr = NB_SUBFR; + st->cor_strong_limit = 0; + st->noise_lev = NOISE_LEVEL_SP3; + } + else + { + if( st->core_brate <= ACELP_8k00 ) + { + st->noise_lev = (short)get_next_indice( st, 2 ) + NOISE_LEVEL_SP2; + } + else + { + st->noise_lev = (short)get_next_indice( st, 3 ) + NOISE_LEVEL_SP0; + } + + /*---------------------------------------------------------------* + * Decode number of subframes + *---------------------------------------------------------------*/ + + st->cor_strong_limit = 1; + nb_subfr = SWNB_SUBFR; + if( st->core_brate >= ACELP_9k60 ) + { + nbits = 1; + + nb_frame_flg = (short)get_next_indice( st, nbits ); + + if( (nb_frame_flg & 0x1) == 0) + { + nb_subfr = 2*SWNB_SUBFR; + st->cor_strong_limit = 0; + } + } + } + + /*---------------------------------------------------------------* + * Decode the last band where the adaptive (pitch) contribution is significant + *---------------------------------------------------------------*/ + + if( st->core_brate < CFREQ_BITRATE ) + { + if( st->core_brate < ACELP_9k60 && coder_type == INACTIVE ) + { + nbits = 1; + } + else + { + nbits = 3; + } + } + else + { + nbits = 4; + } + + if( st->core_brate < ACELP_9k60 && coder_type != INACTIVE ) + { + pit_band_idx = 1; + } + else + { + pit_band_idx = (short)get_next_indice( st, nbits ); + } + + if( pit_band_idx != 0 ) + { + if( st->core_brate < ACELP_9k60 ) + { + pit_band_idx = 7+BAND1k2; /* At low rate, if pitch model is chosen, then for to be use on extented and constant frequency range */ + } + else + { + pit_band_idx += BAND1k2; + } + + /* detect bit errors in the bitstream */ + if( pit_band_idx > 13 ) /* The maximum decodable index is 10 + BAND1k2 (3) = 13 */ + { + pit_band_idx = 13; + st->BER_detect = 1; + } + + Diff_len = (short)(mfreq_loc[pit_band_idx]/BIN_SIZE); + } + + st->Last_GSC_pit_band_idx = pit_band_idx; + + /*--------------------------------------------------------------------------------------* + * Decode adaptive (pitch) excitation contribution + * Reset unvaluable part of the adaptive (pitch) excitation contribution + *--------------------------------------------------------------------------------------*/ + + if( pit_band_idx > BAND1k2 ) + { + /*---------------------------------------------------------------* + * Decode adaptive (pitch) excitation contribution + *---------------------------------------------------------------*/ + + if( st->GSC_noisy_speech && nb_subfr == NB_SUBFR ) + { + nb_bits = Es_pred_bits_tbl[BIT_ALLOC_IDX(st->core_brate, GENERIC, -1, -1)]; + indice = (short)get_next_indice( st, nb_bits ); + Es_pred_dec(&Es_pred, indice, nb_bits, 0); + } + + dec_pit_exc( st, L_FRAME, Aq, Es_pred, pitch_buf, code, exc, nb_subfr, gain_buf ); + + if( st->core_brate < ACELP_9k60 ) + { + minimum( pitch_buf, L_FRAME>>6, &low_pit); + + if( low_pit < 64 ) + { + pit_band_idx = 9+BAND1k2; + if(st->bwidth == NB) + { + pit_band_idx = 7+BAND1k2; + } + } + else if( low_pit < 128 ) + { + pit_band_idx = 5+BAND1k2; + } + else + { + pit_band_idx = 3+BAND1k2; + } + + Diff_len = (short)(mfreq_loc[pit_band_idx]/BIN_SIZE); + st->Last_GSC_pit_band_idx = pit_band_idx; + } + + /*---------------------------------------------------------------* + * DCT transform + *---------------------------------------------------------------*/ + + edct( exc, dct_epit, L_FRAME ); + + /*---------------------------------------------------------------* + * Reset unvaluable part of the adaptive (pitch) excitation contribution + *---------------------------------------------------------------*/ + + max_len = L_FRAME - Diff_len; + if(st->bwidth == NB) + { + max_len = 160-Diff_len; + } + + Len = 80; + if( max_len < 80 ) + { + Len = max_len; + } + + if(st->core_brate == ACELP_8k00 && st->bwidth != NB ) + { + for (i=0; i < max_len; i++) + { + dct_epit[i+Diff_len] = 0.0f; + } + } + else + { + for (i = 0; i < Len; i++) + { + dct_epit[i+Diff_len] *= sm_table[i]; + } + for (; i < max_len; i++) + { + dct_epit[i+Diff_len] = 0.0f; + } + } + + st->bfi_pitch = (short)(mean(pitch_buf, nb_subfr)+0.5f); + st->bfi_pitch_frame = L_FRAME; + + Diff_len++; + st->bpf_off = 0; + } + else + { + /* No adaptive (pitch) excitation contribution */ + st->bpf_off = 1; + set_f( dct_epit, 0.0f, L_FRAME ); + set_f( pitch_buf, (float)L_SUBFR, NB_SUBFR ); + + set_f( gain_buf, 0.f, NB_SUBFR16k); + + st->bfi_pitch = L_SUBFR; + st->bfi_pitch_frame = L_FRAME; + st->lp_gainp = 0.0f; + st->lp_gainc = 0.0f; + st->tilt_code = 0; + pit_band_idx = 0; + Diff_len = 0; + } + + /*--------------------------------------------------------------------------------------* + * GSC decoder + *--------------------------------------------------------------------------------------*/ + + /* find the current total number of bits used */ + tmp_nb_bits_tot = st->next_bit_pos; + + if( st->extl_brate > 0 ) + { + /* subtract 1 bit for TBE/BWE BWE flag (bit counted in extl_brate) */ + tmp_nb_bits_tot--; + } + + if( coder_type == INACTIVE && st->core_brate <= ACELP_9k60 ) + { + tmp_nb_bits_tot += 5; /* for noisiness */ + } + + gsc_dec( st, dct_epit, pit_band_idx, Diff_len, tmp_nb_bits_tot, nb_subfr, coder_type, &last_bin, lsf_new, exc_wo_nf, tmp_noise ); + + /*--------------------------------------------------------------------------------------* + * iDCT transform + *--------------------------------------------------------------------------------------*/ + + edct( dct_epit, exc, L_FRAME ); + edct( exc_wo_nf, exc_wo_nf, L_FRAME ); + + /*----------------------------------------------------------------------* + * Remove potential pre-echo in case an onset has been detected + *----------------------------------------------------------------------*/ + + pre_echo_att( &st->Last_frame_ener, exc, attack_flag, st->last_coder_type ); + + /*--------------------------------------------------------------------------------------* + * Update BWE excitation + *--------------------------------------------------------------------------------------*/ + + set_f( voice_factors, 0.0f, NB_SUBFR16k ); + interp_code_5over2( exc, bwe_exc, L_FRAME ); + + /*--------------------------------------------------------------------------------------* + * Updates + *--------------------------------------------------------------------------------------*/ + + mvr2r( exc, exc2, L_FRAME ); + mvr2r( exc_wo_nf, exc, L_FRAME ); + + /*--------------------------------------------------------------------------------------* + * Channel aware mode parameters + *--------------------------------------------------------------------------------------*/ + + set_f( st->tilt_code_dec, 0, NB_SUBFR16k ); + + return; +} + + + +/*-------------------------------------------------------------------* + * gsc_dec() + * + * Generic audio signal decoder + *-------------------------------------------------------------------*/ + +void gsc_dec( + Decoder_State *st, /* i/o: State structure */ + float exc_dct_in[], /* i/o: dct of pitch-only excitation / total excitation */ + const short pit_band_idx, /* i : bin position of the cut-off frequency */ + const short Diff_len, /* i : Lenght of the difference signal (before pure spectral)*/ + const short bits_used, /* i : Number of bit used before frequency Q */ + const short nb_subfr, /* i : Number of subframe considered */ + const short coder_type, /* i : coding type */ + short *last_bin, /* i : last bin of bit allocation */ + float *lsf_new, /* i : ISFs at the end of the frame */ + float *exc_wo_nf, /* o : excitation (in f domain) without noisefill */ + float *tmp_noise /* o : long-term noise energy */ +) +{ + short i, j, bit, nb_subbands, pvq_len; + short bitallocation_band[MBANDS_GN]; + short bitallocation_exc[2]; + float Ener_per_bd_iQ[MBANDS_GN]; + short max_ener_band[MBANDS_GN]; + float exc_diffQ[L_FRAME]; + short bits_per_bands[MBANDS_GN]; /*Q3*/ + float concat_out[L_FRAME]; + short npulses[NB_SFM]; + short maxpulse[NB_SFM]; + float mean_gain; + short Mbands_gn = 16; + short seed_init; + + /*--------------------------------------------------------------------------------------* + * Initialization + *--------------------------------------------------------------------------------------*/ + + bit = bits_used; + set_f( exc_diffQ, 0.0f, L_FRAME ); + + /*--------------------------------------------------------------------------------------* + * Gain decoding + *--------------------------------------------------------------------------------------*/ + + if( st->bfi || st->BER_detect ) + { + /* copy old gain */ + mvr2r( st->old_y_gain, Ener_per_bd_iQ, Mbands_gn ); + mean_gain = st->lp_gainc/10.0f; + for( i=0; ilp_gainc *= 0.98f; + } + else + { + mean_gain = gsc_gaindec( st, Ener_per_bd_iQ, st->core_brate, st->old_y_gain, coder_type, st->bwidth ); + + st->lp_gainc = 10.0f * mean_gain; + } + + *tmp_noise = st->lp_gainc; + + *last_bin = 0; + if( st->core_brate == ACELP_8k00 && st->bwidth != NB ) + { + bitallocation_exc[0] = 0; + bitallocation_exc[1] = 0; + } + + set_s( bitallocation_band, 0, MBANDS_GN ); + + if( st->bfi || st->BER_detect ) + { + /*--------------------------------------------------------------------------------------* + * Copy old spectrum + * reduce spectral dynamic + * save spectrum + *--------------------------------------------------------------------------------------*/ + + if(st->last_good == INACTIVE_CLAS || st->Last_GSC_noisy_speech_flag == 1) + { + for( i=0; iLast_GSC_spectrum[i] = 0.8f * own_random(&st->seed_tcx)/32768.0f+0.2f*st->Last_GSC_spectrum[i]; + } + mvr2r( st->Last_GSC_spectrum, exc_diffQ, L_FRAME ); + } + + mvr2r( st->Last_GSC_spectrum, exc_diffQ, L_FRAME ); + + for( i=0; iLast_GSC_spectrum[i] *= 0.75f; + } + } + else + { + /*--------------------------------------------------------------------------------------* + * PVQ decoder + *--------------------------------------------------------------------------------------*/ + + bands_and_bit_alloc( st->cor_strong_limit, st->noise_lev, st->core_brate, Diff_len, bit, &bit, Ener_per_bd_iQ, + max_ener_band, bits_per_bands, &nb_subbands, NULL, NULL, &pvq_len, coder_type, + st->bwidth, st->GSC_noisy_speech ); + + set_s( npulses, 0, NB_SFM ); + + pvq_core_dec( st, gsc_sfm_start, gsc_sfm_end, gsc_sfm_size, concat_out, bit, nb_subbands, bits_per_bands, NULL, npulses, maxpulse, ACELP_CORE ); + + seed_init = 0; + for( j = 0; j < nb_subbands; j++ ) + { + mvr2r( concat_out+j*16, exc_diffQ + max_ener_band[j]*16, 16); + + if( max_ener_band[j] > *last_bin ) + { + *last_bin = max_ener_band[j]; + } + + bitallocation_band[max_ener_band[j]] = 1; + + seed_init += npulses[j]; + } + if( st->last_coder_type != AUDIO /* First audio frame */ + && st->last_coder_type != UNVOICED ) /* last_coder_type == INACTIVE is overwritten in update_dec to UNVOICED */ + { + for(j = 0; j < nb_subbands*16; j++) + { + if( concat_out[j] > 0 ) + { + seed_init = (short)((int)seed_init<<3); + } + if( concat_out[j] < 0 ) + { + seed_init += 3; + } + } + + st->seed_tcx = seed_init; + } + + if( st->core_brate == ACELP_8k00 && st->bwidth != NB ) + { + if( exc_diffQ[L_FRAME8k - 2] != 0 ) + { + bitallocation_exc[0] = 1; + } + + if( exc_diffQ[L_FRAME8k - 1] != 0 ) + { + bitallocation_exc[1] = 1; + } + } + + mvr2r( exc_diffQ, st->Last_GSC_spectrum, 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( st->cor_strong_limit, coder_type, st->noise_lev, st->core_brate, exc_diffQ ); + } + + /*--------------------------------------------------------------------------------------* + * Estimate noise level + *--------------------------------------------------------------------------------------*/ + + highband_exc_dct_in( st->core_brate, mfreq_bindiv_loc, *last_bin, Diff_len, st->noise_lev, pit_band_idx, exc_diffQ, + &st->seed_tcx, Ener_per_bd_iQ, nb_subfr, exc_dct_in, st->last_coder_type, bitallocation_band, lsf_new, + st->last_exc_dct_in, &st->last_ener, st->last_bitallocation_band, bitallocation_exc, st->bfi, coder_type, + st->bwidth, exc_wo_nf, st->GSC_noisy_speech + ,st->lt_ener_per_band + ); + + exc_dct_in[0] = 0; + + return; +} diff --git a/lib_dec/gs_dec_amr_wb.c b/lib_dec/gs_dec_amr_wb.c new file mode 100644 index 000000000..072ae13ad --- /dev/null +++ b/lib_dec/gs_dec_amr_wb.c @@ -0,0 +1,394 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define BAND3k 15 +#define BIN_1k2 48 +#define BAND_2k 12 +#define BAND_0k4 4 +#define ALP 0.7f +#define MALP (1.0f-ALP) +#define ALPMY (0.86f) +#define ALPY 1.5f + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static void NoiseFill( float *exc_diffQ, short *seed_tcx, const short Mbands_gn ); +static void Ener_per_band( const float exc_diff[], float y_gain4[] ); +static void Apply_gain( float exc_diffQ[], float Ener_per_bd_iQ[], float Ener_per_bd_yQ[]); +static void normalize_spec( float fac_up, float fy_norm[], const short L_frame ); +static void gs_dec_amr_wb( const long core_brate, short *seed_tcx, const float dct_in[], + float dct_out[], const float pitch[], const float voice_fac + ,const short clas, const short coder_type + ); + + +/*-------------------------------------------------------------------* + * NoiseFill() + * + * noise fill function for unvoiced/inactive frames (used only in AMR-WB IO mode) + *-------------------------------------------------------------------*/ + +static void NoiseFill( + float *exc_diffQ, /* i/o: Noise per band */ + short *seed_tcx, /* i : Seed for noise */ + const short Mbands_gn /* i : number of bands */ +) +{ + short StartBin, NB_Qbins, i_band, k; + StartBin = 0; + NB_Qbins = 0; + + for( i_band = 0; i_band < Mbands_gn; i_band++ ) + { + StartBin += NB_Qbins; + NB_Qbins = crit_bins[i_band]; + for( k=StartBin; k= ACELP_12k65 ) + { + etmp14 *=2; + } + + mDiff_len = (short)(etmp14+0.5f); + etmp14 = 32768.0f; + j = 0; + for(i = 0; i < CRIT_NOIS_BAND; i++) + { + if( fabs(crit_bands_loc[i] - mDiff_len) < etmp14 ) + { + etmp14 = (float)fabs(crit_bands_loc[i] - mDiff_len); + j += crit_bins[i]; + } + } + + mDiff_len = j; + if( mDiff_len < BIN_1k2 ) + { + mDiff_len = BIN_1k2; + } + mvr2r(dct_in, exc_diffQ, mDiff_len); + set_f(exc_diffQ+mDiff_len, 0, L_FRAME-mDiff_len); + + /*--------------------------------------------------------------------------------------* + * normalization of the spectrum and noise fill + *--------------------------------------------------------------------------------------*/ + + normalize_spec(4, exc_diffQ , mDiff_len); + NoiseFill( exc_diffQ, seed_tcx, CRIT_NOIS_BAND); + + + /*--------------------------------------------------------------------------------------* + * Recompute energy per band of the modified excitation vector (in frequency domain) + *--------------------------------------------------------------------------------------*/ + + Ener_per_band( exc_diffQ, Ener_per_bd_yQ ); + + /*--------------------------------------------------------------------------------------* + * Compute tilt factor and amplify HF accordingly + *--------------------------------------------------------------------------------------*/ + + ftmp = (0.5f * (1.0f - voice_fac)); /* 1=unvoiced, 0=voiced */ + + for(i = 240; i < L_FRAME; i++) + { + ftmp1 = ftmp*(0.067f * i - 15.0f); + ftmp1 = max(1.0f, ftmp1); + exc_diffQ[i] *= ftmp1; + } + + /*--------------------------------------------------------------------------------------* + * Match the energy of the modified excitation vector to the decoded excitation + *--------------------------------------------------------------------------------------*/ + + Apply_gain( exc_diffQ, Ener_per_bd_iQ, Ener_per_bd_yQ); + + /*--------------------------------------------------------------------------------------* + * Copy to the output vector + *--------------------------------------------------------------------------------------*/ + + mvr2r( exc_diffQ, dct_out, L_FRAME ); + + return; +} + +/*-------------------------------------------------------------------* + * improv_amr_wb_gs() + * + * Modify the decoded excitation to increase quality of + * unvoiced and audio signals (used only in AMR-WB IO mode) + *-------------------------------------------------------------------*/ + +void improv_amr_wb_gs( + const short clas, /* i : signal frame class */ + const short coder_type, /* i : coder type */ + const long core_brate, /* i : bitrate allocated to the core */ + short *seed_tcx, /* i/o: Seed used for noise generation */ + float *old_Aq, /* i/o: old LPC filter coefficient */ + float *mem_syn2, /* i/o: synthesis memory */ + const float lt_voice_fac, /* i/o: long term voice factor */ + const short locattack, /* i : Flag for a detected attack */ + float *Aq, /* i/o: Decoded LP filter coefficient */ + float *exc2, /* i/o: Decoded complete excitation */ + float *mem_tmp, /* i/o: synthesis temporary memory */ + float *syn, /* i/o: Decoded synthesis to be updated */ + const float *pitch_buf, /* i : Decoded pitch buffer */ + const float Last_ener /* i : Last energy */ + ,const short rate_switching_reset /* i : rate switching reset flag */ + ,const short last_coder_type /* i : Last coder_type */ +) +{ + short i; + float dct_exc_in[L_FRAME], dct_exc_out[L_FRAME]; + float 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 */ + if( ( locattack == 0 && core_brate <= ACELP_12k65) && + ( (core_brate < ACELP_8k85 && clas != AUDIO_CLAS && (clas == UNVOICED_CLAS || clas == VOICED_TRANSITION)) || coder_type == INACTIVE ) ) + { + /*------------------------------------------------------------* + * two differents paths: + * unvoiced or inactive + * generic audio sound + * LP filter smoothing for inactive parts + *------------------------------------------------------------*/ + *seed_tcx = (short)((short)(pitch_buf[0]*64.0f)*(short)(pitch_buf[3]*64.0f)); + + if( coder_type == INACTIVE && Last_ener > -3.0f && last_coder_type == UNVOICED && rate_switching_reset == 0 ) + { + mvr2r( Aq, Aq_orig, NB_SUBFR*(M+1) ); + + for(i =0; i < NB_SUBFR * (M+1); i++) + { + Aq[i] = ALP*old_Aq[i] + MALP*Aq[i]; + } + + /* check the smoothed LP filter stability */ + enr_LP_old = enr_1_Az( old_Aq, L_SUBFR ); + for(i =0; i < NB_SUBFR; i++) + { + enr_LP_new = enr_1_Az( Aq+i*(M+1), L_SUBFR ); + + if( enr_LP_new > 128 * enr_LP_old ) + { + /* filter is unstable, do not modify the excitation */ + mvr2r( Aq_orig, Aq, NB_SUBFR*(M+1) ); + return; + } + + enr_LP_old = enr_LP_new; + } + } + + /*------------------------------------------------------------* + * Find frequency representation of the excitation + * Do the excitation modification according to the content + * Go back to time domain -> Overwrite excitation + *------------------------------------------------------------*/ + + edct( exc2, dct_exc_in, L_FRAME ); + set_f( exc2, 0, L_FRAME ); + set_f( dct_exc_out, 0, L_FRAME ); + + gs_dec_amr_wb( core_brate, seed_tcx, dct_exc_in, dct_exc_out, pitch_buf, lt_voice_fac, clas, coder_type ); + + edct( dct_exc_out, exc2, L_FRAME ); + + /*------------------------------------------------------------* + * Redo core synthesis at 12k8 Hz with the modified excitation + *------------------------------------------------------------*/ + + mvr2r( mem_tmp, mem_syn2, M ); + syn_12k8( L_FRAME, Aq, exc2, syn, mem_syn2, 1 ); + } + + return; +} diff --git a/lib_dec/hdecnrm.c b/lib_dec/hdecnrm.c new file mode 100644 index 000000000..c646243ca --- /dev/null +++ b/lib_dec/hdecnrm.c @@ -0,0 +1,367 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include "rom_dec.h" + +/*--------------------------------------------------------------------------*/ +/* Function decode_huff_context */ +/* ~~~~~~~~~~~~~~~~~ */ +/* */ +/* Context based Huffman decoding for indices of quantized norms */ +/*--------------------------------------------------------------------------*/ +/* const short *hufftab, (i) Huffman table */ +/* short *rbits (i/o) the number of read bits */ +/*--------------------------------------------------------------------------*/ +static +short decode_huff_context( + Decoder_State *st, /* i/o: decoder state structure */ + const short *hufftab, + short *rbits +) +{ + while( *hufftab > 0) + { + *rbits+=(*hufftab & 0xf); + hufftab += (*hufftab >> 4) + get_next_indice( st, *hufftab & 0xf ); + } + + return (-*hufftab); +} + + +/*--------------------------------------------------------------------------*/ +/* Function hdecnrm */ +/* ~~~~~~~~~~~~~~~~~ */ +/* */ +/* Huffman decoding for indices of quantized norms */ +/*--------------------------------------------------------------------------*/ +/* short N (i) number of norms */ +/* short *index (o) indices of quantized norms */ +/*--------------------------------------------------------------------------*/ + +void hdecnrm( + Decoder_State *st, /* i/o: decoder state structure */ + const short N, + short *index +) +{ + short i, j, k, n, m; + short temp; + short *pidx; + + pidx = index; + + m = N - 1; + for (i=0; i> j; + *index++ = huff_tab[offset[j] + k]; + } + + /* Put back unused bits */ + st->next_bit_pos -= j; + + return; +} + + +/*-------------------------------------------------------------------------- + * hdecnrm_context() + * + * Huffman decoding for indices of quantized norms + *--------------------------------------------------------------------------*/ + +void hdecnrm_context( + Decoder_State *st, /* i/o: decoder state structure */ + const short N, /* i : number of norms */ + short *index, /* o : indices of quantized norms */ + short *n_length /* o : decoded stream length */ +) +{ + short i, prevj; + + prevj = index[0] + OFFSET_NORM; + for( i=1; i < N; i++) + { + if( prevj > HTH_NORM ) + { + /* above */ + index[i] = decode_huff_context( st, hntable, n_length); + index[i] = 31 - index[i]; + } + else + { + if( prevj < LTH_NORM ) + { + /* less */ + index[i] = decode_huff_context( st, hntable, n_length ); + } + else + { + /* equal */ + index[i] = decode_huff_context( st, hetable, n_length ); + } + } + prevj = index[i]; + } + + return; +} + +void hdecnrm_resize( + Decoder_State *st, /* i/o: decoder state structure */ + const short N, + short *index +) +{ + short i, j, k, m; + short temp; + short *pidx; + + pidx = index; + + m = N - 1; + for (i=0; i +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ + +static void hp400_12k8(float signal[], const short lg, float mem[]); + +static void filt_6k_7k(float signal[], const short lg, float mem[]); + +static void hf_synthesis( const long core_brate, const short output_frame, const float Aq[], const float exc[], + float synth[], float synth16k[], short *seed2, float *mem_hp400, float *mem_syn_hf, + float *mem_hf, float *delay_syn_hf, float *mem_hp_interp ); + +static void hf_synthesis_amr_wb( const long core_brate, const short output_subfr, const float Ap[], float exc16k[], + float synth_out[], float *mem_syn_hf, float *delay_syn_hf, float *mem_hp_interp, float p_r, + float hf_gain_i, float til, float voice_factors, const float exc[] ); + +static void envelope( const long core_brate, const float Aq[], float Ap[], float *r, float tilt0, float tilt, + float voice_factor, float *prev_r, float *voice_fac, float *unvoicing, float *unvoicing_sm, short *unvoicing_flag); + +static void AdaptiveStartBand( short *start_band, const long rate, const float *lsf, const float voicing_fac, const short clas, short *voicing_flag, + short *start_band_old, float *OptCrit_old ); + + +/*-------------------------------------------------------------------* + * hf_synth_init() + * + * hf synthesis filters initialization + * - initialization of 400 Hz high pass filter + * - initialization of band pass 6kHz to 7kHz FIR filter + *-------------------------------------------------------------------*/ + +void hf_synth_init( + float mem_hp400[], /* o : 400 Hz high pass filter memory initialization */ + float mem_hf[] /* o : band pass 6kHz to 7kHz FIR filter initialization */ +) +{ + set_f( mem_hp400, 0, 4 ); + + set_f( mem_hf, 0, (L_FIR-1) ); + + return; +} + +/*-------------------------------------------------------------------* + * 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( + float *prev_r, /* o : previous sub-frame gain */ + float *fmerit_w_sm, /* o : 1 sample memory fmerit_w param */ + float mem_syn_hf[], /* o : HF LPC synthesis filter initialization */ + short *frame_count, /* o : frame counter initialization */ + float *ne_min, /* o : minimum Noise gate - short-term energy initialization*/ + float *fmerit_m_sm, /* o : 1 sample memory fmerit_m param */ + float *voice_fac, /* o : voice factor initialization */ + float *unvoicing, /* o : unvoiced parameter */ + float *unvoicing_sm, /* o : smoothed unvoiced parameter */ + short *unvoicing_flag, /* o : unvoiced flag */ + short *voicing_flag, /* o : voiced flag */ + short *start_band_old, /* o : previous start point for copying frequency band */ + float *OptCrit_old /* o : previous criterion value for deciding the start point */ +) +{ + *prev_r = 0.0f; + set_f( mem_syn_hf, 0.0f, M ); + *fmerit_w_sm = 0.0f; + *frame_count = 0; + *ne_min = -30.0f; + *fmerit_m_sm = 0.0f; + *voice_fac = 0.0f; + *unvoicing = 0.0f; + *unvoicing_sm = 1.0f; + *unvoicing_flag = 0; + *voicing_flag = 0; + *start_band_old = 160; + *OptCrit_old = 1.0f; + + return; +} + +/*-------------------------------------------------------------------* + * hf_synth_amr_wb_reset() + * + * reset of HF synthesis filters + * - needed in switching scenarios + *-------------------------------------------------------------------*/ + +void hf_synth_amr_wb_reset( + short *seed2, /* i/o: random seed for HF noise gen */ + float mem_syn_hf[], /* o : HF synthesis memory */ + float mem_hp_interp[], /* o : interpol. memory */ + float *prev_r, /* o : previous sub-frame gain */ + float *fmerit_w_sm, /* o : 1 sample memory fmerit_w param */ + float delay_syn_hf[], /* o : HF synthesis memory */ + short *frame_count, /* o : frame counter memory */ + float *ne_min, /* o : minimum Noise gate - short-term energy memory */ + float *fmerit_m_sm, /* o : 1 sample memory fmerit_m param */ + float *voice_fac, /* o : voice factor memory */ + float *unvoicing, /* o : unvoiced parameter */ + float *unvoicing_sm, /* o : smoothed unvoiced parameter */ + short *unvoicing_flag, /* o : unvoiced flag */ + short *voicing_flag, /* o : voiced flag */ + short *start_band_old, /* o : previous start point for copying frequency band */ + float *OptCrit_old /* o : previous criterion value for deciding the start point */ +) +{ + short i; + + for( i=0; i FRAME_COUNT_HF_SYNTH && *amr_io_class == UNVOICED_CLAS ) + { + *frame_count = 0; + *ne_min = -30.0f; + } + else + { + if ( *frame_count > 2*FRAME_COUNT_HF_SYNTH ) + { + *frame_count = 2*FRAME_COUNT_HF_SYNTH; + } + else + { + (*frame_count)++; + } + + if ( ng_ener_ST < *ne_min ) + { + *ne_min = ng_ener_ST; + } + } + + voice_fac = 0.0f; + for( i=0; i 0.35f ? 0.35f : (fmerit < 0.15f ? 0.15f : fmerit); + if ( core_type == 1 ) + { + fmerit_w *= 0.5f; + } + + fmerit_w *= (1.0f + voice_fac); + *fmerit_w_sm = 0.9f*(*fmerit_w_sm) + 0.1f*fmerit_w; + fmerit_w = *fmerit_w_sm; + + fmerit_m = (2.0f - (fmerit < 0.5f ? 1.0f : fmerit)); + *fmerit_m_sm = 0.5f*(*fmerit_m_sm) + 0.5f*fmerit_m; + fmerit_m = *fmerit_m_sm; + + for (i=0; i 0 ) + { + tonal_ener += hb_tonal[i]*hb_tonal[i]; + } + } + for (; i 0 ) + { + tonal_ener += hb_tonal[i]*hb_tonal[i]; + } + } + for (; i 0 ) + { + tonal_ener += hb_tonal[i]*hb_tonal[i]; + } + } + g = beta * (hb_ener-tonal_ener)/(hb_ener - beta*tonal_ener); + if (g<0.01f && g>-0.01f) + { + inv_g = sign(g)*100; + } + else + { + inv_g = 1/g; + } + ener = 0.01f; + for (i=0; i0) + { + hb_tonal[i] *= g; + } + hb_amb[i] *= inv_g; + dct_hb[i+240] = hb_tonal[i] + hb_amb[i]; + dct_hb[i+240] *= signum[i]; + ener += dct_hb[i+240]*dct_hb[i+240]; + } + scale = (float)(gamma*sqrt(hb_ener/ener)); + + if( core_brate == ACELP_6k60 ) + { + filt_weight_coeff=60; + } + else if( core_brate == ACELP_8k85 ) + { + filt_weight_coeff=40; + } + else + { + filt_weight_coeff=20; + } + + for (i=0; i255 ) + { + dct_hb[i] *= 0.59525f; + } + + if (i >= 320-filt_weight_coeff) + { + dct_hb[i] *= filt_weight[i-320+filt_weight_coeff]; + } + } + + for( i=200; i<256; i++ ) + { + dct_hb[i] *= filt_hp[i-200]; + + if( core_brate < ACELP_23k85 ) + { + dct_hb[i] *= deem_tab[i-200]; + } + } + + if ( core_brate == ACELP_23k85 ) + { + for (i=0; i 1.0f || til0 < 0.0f ) + { + mvr2r( exc2385, exc16k, L_SUBFR16k ); + } + else + { + for ( i=0; ipp */ + *voice_fac = 0.75f*(*voice_fac) + 0.25f*voice_factor; + unvoicing_tmp = ((1.0f-tilt0)/2.0f) * (1-*voice_fac) * min(tilt/1.5f, 1.0f); + *unvoicing = 0.5f*(*unvoicing) + 0.5f*unvoicing_tmp; + + if( *unvoicing_sm > *unvoicing ) + { + *unvoicing_sm = 0.9f*(*unvoicing_sm) + 0.1f*(*unvoicing); + } + else + { + *unvoicing_sm = 0.99f*(*unvoicing_sm) + 0.01f*(*unvoicing); + } + + if (*unvoicing - *unvoicing_sm > 0.1f) + { + *unvoicing_flag = 1; + } + + if (*unvoicing - *unvoicing_sm < 0.05f) + { + *unvoicing_flag = 0; + } + + return (*unvoicing_flag && qq>pp); +} + +/*-----------------------------------------------------------------------------------* + * envelope() + * + * + *-----------------------------------------------------------------------------------*/ + +static void envelope( + const long core_brate, /* i : core bitrate */ + const float Aq[], /* i : de-quant. LPC coefficents */ + float Ap[], /* o : extended LPC coefficents */ + float *sub_gain, /* o : sub-frame gain */ + float tilt0, /* i : spectrum tilt */ + float tilt, /* i : spectrum tilt */ + float voice_factor, /* i : voice factor */ + float *prev_r, /* i/o: previous sub-frame gain */ + float *voice_fac, /* i/o: smoothed voiced parameter */ + float *unvoicing, /* i/o: unvoiced parameter */ + float *unvoicing_sm, /* i/o: smoothed unvoiced parameter */ + short *unvoicing_flag /* i/o: unvoiced flag */ +) +{ + float px, py, rx, ry, pp, rr; + short i, Unvoicing_flag; + float alpha; + float est_level1, est_level2, qx, qy, qq, env_level[3]; + float As[3], k1, k2; + + /* LPC envelope weighting */ + if( core_brate == ACELP_6k60 ) + { + weight_a( Aq, Ap, 0.9f, M ); + } + else + { + weight_a( Aq, Ap, 0.6f, M ); + } + + /* LPC envelope level estimate */ + pp = 0.0f; + px = 0.0f; + py = 0.0f; + rr = 0.0f; + rx = 0.0f; + ry = 0.0f; + for ( i=0; i<17; i++ ) + { + px += Ap[i]*exp_tab_p[i]; + py += Ap[i]*exp_tab_p[33-i]; + rx += Aq[i]*exp_tab_q[i]; + ry += Aq[i]*exp_tab_q[33-i]; + } + + pp = 1.0f/((float)sqrt(px*px+py*py)); + rr = 1.0f/((float)sqrt(rx*rx+ry*ry)); + + for ( i=0; i<3; i++ ) + { + As[i] = Aq[i]; + } + + if (As[2]==-1) + { + k2 = -0.6f; + k1 = 0.99f; + if (As[1]<0) + { + k1 = -k1; + } + } + else + { + k1 = As[1]/(1+As[2]); + k2 = As[2]; + if (k2>0.6f) + { + k2=0.6f; + } + if (k2<-0.6f) + { + k2=-0.6f; + } + if (k1>0.99f) + { + k1=0.99f; + } + if (k1<-0.99f) + { + k1=-0.99f; + } + } + + As[1]=(1+k2)*k1; + As[2]=k2; + + qq = 0.0f; + qx = 0.0f; + qy = 0.0f; + for ( i=0; i<3; i++ ) + { + qx += As[i]*exp_tab_q[i]; + qy += As[i]*exp_tab_q[33-i]; + } + + qq = 1.0f/((float)sqrt(qx*qx+qy*qy)); + + Unvoicing_flag = EnhanceClass( rr, pp, tilt0, tilt, voice_factor, voice_fac, unvoicing, unvoicing_sm, unvoicing_flag ); + + alpha = 0.0f; + if ( Unvoicing_flag ) + { + if (rr > (*prev_r)) + { + rr = 0.5f*rr + 0.5f*(*prev_r); + } + + *prev_r = rr; + rr *= min(1.0f, tilt*(1.6f - voice_factor)); + qq *= max(1.0f, tilt*(1.6f - voice_factor)); + rr = min(rr,qq); + rr= max(rr,pp); + } + else + { + if (rr < 1.0f && (*prev_r) < 1.0f) + { + alpha = (1-rr*rr); + } + + rr = alpha*(*prev_r) + (1-alpha)*rr; + *prev_r = rr; + + est_level1 = qq * min(1.0f, tilt*(1.6f - voice_factor)); + env_level[0] = pp; + env_level[1] = qq; + env_level[2] = rr; + v_sort( env_level, 0, 2 ); + rr = env_level[0]; + est_level2 = rr * (1.0f + (float)fabs(tilt-1) * (1.6f - voice_factor)); + rr = min(est_level1, est_level2); + } + + *sub_gain = min(5.0f, rr/pp); + + return; +} + +/*---------------------------------------------------------------------* + * AdaptiveStartBand() + * + * adaptively select the start band of bandwidth extension + *---------------------------------------------------------------------*/ + +static void AdaptiveStartBand( + short *start_band, /* o : start point of copied band */ + const long rate, /* i : core bitrate */ + const float *lsf, /* i : lsf frequency */ + const float voicing_fac, /* i : voicing factors */ + const short clas, /* i : signal class (determined by FEC algorithm)*/ + short *voicing_flag, + short *start_band_old, + float *OptCrit_old +) +{ + float lsf_diff[M], Crit, OptCrit = 1.0f, W; + short i, pos, M2, voicing_flag_old; + short tmp1, tmp2; + + /*voicing switching flag : to avoid switching start band frequently in VOICED or AUDIO area*/ + voicing_flag_old = *voicing_flag; + if( voicing_fac > 0.4f || (voicing_fac > 0.3f && clas >= VOICED_CLAS) || clas == AUDIO_CLAS ) + { + *voicing_flag = 1; + } + + if( voicing_fac < 0.2f && clas < VOICED_CLAS ) + { + *voicing_flag = 0; + } + + /* rate adaptive start band */ + *start_band = 160; + if( rate < ACELP_23k05 ) + { + for(i=1; i<(M-1); i++) + { + lsf_diff[i] = lsf[i] - lsf[i-1]; + } + + W = SQR(1.0f*rate/ACELP_19k85) / 6000.0f; + + if (clas == AUDIO_CLAS) + { + W *= 0.75f; + } + + pos = 2; + M2 = M-2; + if( *voicing_flag == 1 ) + { + if( rate <= ACELP_8k85 ) + { + M2 = M-8; + } + else if( rate <= ACELP_12k65 ) + { + M2 = M-6; + } + else if( rate <= ACELP_15k85 ) + { + M2 = M-4; + } + } + + for(i=2; i 64 ) ) + { + *OptCrit_old = OptCrit; + if ( abs((*start_band)-(*start_band_old))<20 && *voicing_flag==1 && voicing_flag_old==1 ) + { + *start_band = *start_band_old; + } + } + else + { + if (OptCrit<(*OptCrit_old) && (*voicing_flag)==1) + { + *OptCrit_old = OptCrit; + } + + *start_band = *start_band_old; + } + + if (clas == AUDIO_CLAS) + { + *start_band = min(*start_band, 120); + } + + if( *start_band % 2 != 0 ) + { + *start_band -= 1; + } + } + + *start_band_old = *start_band; + + return; +} + + +/*-------------------------------------------------------------------* + * hf_synth_reset() + * + * Reset of HF synthesis filters (needed in switching scenarios) + *-------------------------------------------------------------------*/ + +void hf_synth_reset( + short *seed2, /* i/o: random seed for HF noise gen */ + float mem_hf[], /* o : HF band-pass filter memory */ + float mem_syn_hf[], /* o : HF synthesis memory */ + float mem_hp400[], /* o : memory of hp 400 Hz filter */ + float mem_hp_interp[], /* o : interpol. memory */ + float delay_syn_hf[] /* o : HF synthesis memory */ +) +{ + short i; + + 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( + const long core_brate, /* i : core bitrate */ + const short output_subfr, /* i : output sub-frame length */ + const float Aq[], /* i : quantized Aq */ + const float exc[], /* i : excitation at 12.8 kHz */ + float synth[], /* i/o: 12.8kHz synthesis signal */ + float synth16k[], /* i/o: 16kHz synthesis signal */ + short *seed2, /* i/o: random seed for HF noise gen */ + float *mem_hp400, /* i/o: memory of hp 400 Hz filter */ + float *mem_syn_hf, /* i/o: HF synthesis memory */ + float *mem_hf, /* i/o: HF band-pass filter memory */ + float *delay_syn_hf, /* i/o: HF synthesis memory */ + float *mem_hp_interp /* i/o: interpol. memory */ +) +{ + short i, delay; + float tmp, ener, fac, scale; + float HF_exc[L_SUBFR16k], HF_syn[L_SUBFR16k], upsampled_HF_syn[L_FRAME48k/NB_SUBFR]; + float temp_buffer[NS2SA(16000,DELAY_CLDFB_NS) - L_FILT16k]; + float Ap[M16k+1]; + + /*-----------------------------------------------------------------* + * generate white noise vector + *-----------------------------------------------------------------*/ + + for( i=0; i 1.0f ) + { + fac = 1.0f; + } + + scale *= fac; + /*-----------------------------------------------------------------* + * modify HF excitation according to both calculated scaling factors + *-----------------------------------------------------------------*/ + + for( i=0; i 6kHz..7kHz + *-----------------------------------------------------------------*/ + + weight_a( Aq, Ap, 0.6f, M ); + syn_filt( Ap, M, HF_exc, HF_syn, L_SUBFR16k, mem_syn_hf, 1 ); + + /*-----------------------------------------------------------------* + * 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; + mvr2r( HF_syn+L_SUBFR16k-delay, temp_buffer, delay ); + mvr2r( HF_syn, HF_syn+delay, L_SUBFR16k-delay ); + mvr2r( delay_syn_hf, HF_syn, delay ); + mvr2r( temp_buffer, delay_syn_hf, delay ); + + /* interpolate the HF synthesis */ + if( output_subfr == L_FRAME48k/NB_SUBFR ) /* 48kHz sampled output */ + { + interpolate_3_over_1_allpass( HF_syn, L_SUBFR16k, upsampled_HF_syn, mem_hp_interp, allpass_poles_3_ov_2 ); + } + else if( output_subfr == L_FRAME32k/NB_SUBFR ) /* 32kHz sampled output */ + { + Interpolate_allpass_steep( HF_syn, mem_hp_interp, L_SUBFR16k, upsampled_HF_syn ); + } + else /* 16kHz sampled output */ + { + mvr2r( HF_syn, upsampled_HF_syn, L_SUBFR16k ); + } + + v_add( synth16k, upsampled_HF_syn, synth16k, output_subfr ); + + return; +} + + +/*-----------------------------------------------------------------------* + * hp400_12k8() + * + * 2nd order Cheb2 high pass filter with cut off frequency at 400 Hz. + * Optimized for fixed-point to get the following frequency response: + * + * frequency : 0Hz 100Hz 200Hz 300Hz 400Hz 630Hz 1.5kHz 3kHz + * dB loss : -infdB -30dB -20dB -10dB -3dB +6dB +1dB 0dB + * + * Algorithm : + * + * y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] + * + a[1]*y[i-1] + a[2]*y[i-2]; + * + * short b[3] = {3660, -7320, 3660}; in Q12 + * short a[3] = {4096, 7320, -3540}; in Q12 + * + * float b[3] = {0.893554687, -1.787109375, 0.893554687}; + * float a[3] = {1.000000000, 1.787109375, -0.864257812}; + *-----------------------------------------------------------------------*/ + +static void hp400_12k8( + float signal[], /* i/o: signal */ + const short lg, /* i : lenght of signal */ + float mem[] /* i/o: filter memory [4] */ +) +{ + short i; + float x0, x1, x2; + float yy0, yy1, y2; + + + yy1 = mem[0]; + y2 = mem[1]; + x0 = mem[2]; + x1 = mem[3]; + + for( i=0; i +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*--------------------------------------------------------------------------* + * hq_classifier_dec() + * + * HQ mode selector (decision_matrix) + *--------------------------------------------------------------------------*/ + +short hq_classifier_dec( /* o : Consumed bits */ + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : Core bit rate */ + const short length, /* i : Frame length */ + short *is_transient, /* o : Transient flag */ + short *hqswb_clas /* o : HQ class */ +) +{ + short bits; + + if( length >= L_FRAME32k && core_brate <= HQ_32k ) + { + *hqswb_clas = (short)get_next_indice( st, 2 ); + if ( length == L_FRAME48k ) + { + if ( *hqswb_clas == 0 ) + { + *hqswb_clas = HQ_GEN_FB; + } + } + } + else + { + *hqswb_clas = (short)get_next_indice( st, 1 ); + } + + *is_transient = 0; + if( *hqswb_clas == HQ_TRANSIENT ) + { + *is_transient = 1; + } + + if ( *hqswb_clas == HQ_NORMAL && length == L_FRAME32k && core_brate <= HQ_32k) + { + *hqswb_clas = HQ_GEN_SWB; + } + + if( length >= L_FRAME32k && core_brate <= HQ_32k ) + { + bits = 2; + } + else + { + bits = 1; + } + + return bits; +} diff --git a/lib_dec/hq_conf_fec.c b/lib_dec/hq_conf_fec.c new file mode 100644 index 000000000..9345aedec --- /dev/null +++ b/lib_dec/hq_conf_fec.c @@ -0,0 +1,37 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + + +/*--------------------------------------------------------------------------* + * hq_configure_bfi() + * + * Initialization of HQ bands and subframes + *--------------------------------------------------------------------------*/ + +void hq_configure_bfi( + short *nb_sfm, /* o : Number of sub bands */ + short *num_Sb, /* o : Number of FEC sub bands ? */ + short *num_bands_p, /* o : FEC sub bands */ + short const **sfmsize, /* o : Subband bandwidths */ + short const **sfm_start, /* o : Subband start coefficients */ + short const **sfm_end /* o : Subband end coefficients */ +) +{ + *num_Sb = MAX_SB_NB; + *nb_sfm = SFM_N_NB; + mvs2s( 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.c b/lib_dec/hq_core_dec.c new file mode 100644 index 000000000..26f0d5051 --- /dev/null +++ b/lib_dec/hq_core_dec.c @@ -0,0 +1,365 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*-------------------------------------------------------------------------- + * hq_core_dec() + * + * HQ core decoder + *--------------------------------------------------------------------------*/ + +void hq_core_dec( + Decoder_State *st, /* i/o: decoder state structure */ + float synth[], /* o : output synthesis */ + const short output_frame, /* i : output frame length */ + const short hq_core_type, /* i : HQ core type */ + const short core_switching_flag /* i : ACELP->HQ switching frame flag */ +) +{ + short num_bits, is_transient, hqswb_clas, inner_frame; + short i, j, flag_uv, num_Sb, nb_sfm; + short ynrm[NB_SFM], num_bands_p[MAX_SB_NB]; + float ener_match, mean_en_high; + float t_audio_q[L_FRAME48k], wtda_audio[2*L_FRAME48k]; + short delay_comp; + float normq[NB_SFM], SWB_fenv[SWB_FENV+DIM_FB]; + const short *sfmsize, *sfm_start, *sfm_end; + float gapsynth[L_FRAME48k]; + + + /*-------------------------------------------------------------------------- + * Initializations + *--------------------------------------------------------------------------*/ + + set_f( t_audio_q, 0.0f, L_FRAME48k ); + set_f( gapsynth, 0.0f, L_FRAME48k ); + set_s( num_bands_p, 0, MAX_SB_NB ); + set_s( ynrm, 39, NB_SFM ); /* Initialize to the smallest value */ + mean_en_high = 0.0f; + sfm_start = sfm_end = NULL; + num_Sb = nb_sfm = 0; + + if (st->tcx_cfg.tcx_curr_overlap_mode == FULL_OVERLAP) + { + st->tcx_cfg.tcx_last_overlap_mode = ALDO_WINDOW; + } + else + { + st->tcx_cfg.tcx_last_overlap_mode = st->tcx_cfg.tcx_curr_overlap_mode; + } + st->tcx_cfg.tcx_curr_overlap_mode = ALDO_WINDOW; + + /*-------------------------------------------------------------------------- + * Find the number of bits for transform-domain coding + *--------------------------------------------------------------------------*/ + + /* set the total bit-budget */ + num_bits = (short)(st->total_brate / 50); + + if( !st->bfi ) + { + if( core_switching_flag ) + { + /* Preprocessing in the first HQ frame after ACELP frame */ + core_switching_hq_prepare_dec( st, &num_bits, output_frame ); + + /* During ACELP->HQ core switching, limit the HQ core bitrate to 48kbps */ + if( num_bits > HQ_48k / 50 ) + { + num_bits = (short)(HQ_48k / 50); + } + } + + /* subtract signalling bits */ + num_bits -= st->next_bit_pos; + + /* set FEC parameters */ + flag_uv = 1 - st->HqVoicing; + + /* subtract the number of bits for pitch & gain at higher bitrates */ + if ( !(core_switching_flag) && st->core_brate > MINIMUM_RATE_TO_ENCODE_VOICING_FLAG ) + { + st->HqVoicing = (short) get_next_indice( st, 1 ); + num_bits -= 1; + } + else + { + st->HqVoicing = 0; + if ( st->core_brate > MINIMUM_RATE_TO_ENCODE_VOICING_FLAG ) + { + st->HqVoicing = 1; + } + } + } + else + { + flag_uv = 0; + } + + /* set inner frame (== coded bandwidth) length */ + inner_frame = inner_frame_tbl[st->bwidth]; + + if( st->bfi == 0) + { + if( output_frame >= L_FRAME16k ) + { + st->ph_ecu_HqVoicing = st->HqVoicing; + } + else + { + st->ph_ecu_HqVoicing = 0; + } + } + + if( output_frame == L_FRAME8k ) + { + hq_configure_bfi( &nb_sfm, &num_Sb, num_bands_p, &sfmsize, &sfm_start, &sfm_end ); + } + + /*-------------------------------------------------------------------------- + * transform-domain decoding + *--------------------------------------------------------------------------*/ + + if( st->bfi ) + { + is_transient = st->old_is_transient[0]; + if( output_frame >= L_FRAME16k ) + { + hq_ecu( st->prev_good_synth, t_audio_q, &st->time_offs, st->X_sav, &st->num_p, st->plocs, st->plocsi, st->env_stab, + &st->last_fec, st->ph_ecu_HqVoicing, &st->ph_ecu_active, gapsynth, st->prev_bfi, st->old_is_transient, + st->mag_chg_1st, st->Xavg, &st->beta_mute, output_frame, st ); + } + else + { + HQ_FEC_processing( st, t_audio_q, is_transient, st->ynrm_values, st->r_p_values, num_Sb, nb_sfm, num_bands_p, + output_frame, sfm_start, sfm_end ); + } + + st->old_is_transient[2] = st->old_is_transient[1]; + st->old_is_transient[1] = st->old_is_transient[0]; + + if( output_frame >= L_FRAME16k ) + { + /* keep st->previoussynth updated as in FEC_HQ_pitch_analysis but no LP analysis */ + delay_comp = NS2SA(st->output_Fs, DELAY_CLDFB_NS); + mvr2r( st->previoussynth + delay_comp, st->previoussynth, output_frame - delay_comp ); + mvr2r( st->delay_buf_out, st->previoussynth + output_frame - delay_comp, delay_comp ); + + flag_uv = 1; /* disable costly pitch out synthesis in bfi frame */ + st->HqVoicing = 1-flag_uv; /* safety setting for HQ->ACELP switch logic */ + set_f( st->fer_samples, 0.0f, L_FRAME48k ); /* safety, create a known signal state for HQ->ACELP switch logic */ + } + } + else + { + if( hq_core_type == LOW_RATE_HQ_CORE ) + { + if(st->prev_bfi == 1 ) + { + set_f( st->last_ni_gain, 0, BANDS_MAX ); + set_f( st->last_env, 0, BANDS_MAX ); + st->last_max_pos_pulse = 0; + } + + /* HQ low rate decoder */ + hq_lr_dec( st, t_audio_q, inner_frame, num_bits, &is_transient ); + + hqswb_clas = is_transient; + } + else + { + /* HQ high rate decoder */ + hq_hr_dec( st, t_audio_q, inner_frame, num_bits, ynrm, &is_transient, &hqswb_clas, SWB_fenv ); + } + + /* scaling (coefficients are in nominal level) */ + if( output_frame != NORM_MDCT_FACTOR ) + { + ener_match = (float)sqrt((float)output_frame/(float)NORM_MDCT_FACTOR); + + for( i=0; ibws_cnt1 > 0 ) + { + ener_match = (float)st->bws_cnt1 / (float)N_NS2W_FRAMES; + + if( is_transient ) + { + for( i = 0; i < NUM_TIME_SWITCHING_BLOCKS; i++ ) + { + for( j=inner_frame_tbl[st->bwidth-1]/NUM_TIME_SWITCHING_BLOCKS; jbwidth-1]; it_audio_q, 80 ); + } + else + { + mvr2r( t_audio_q, st->t_audio_q, L_FRAME ); + } + + /*-------------------------------------------------------------------------- + * Inverse transform + * Overlap-add + * Pre-echo reduction + *--------------------------------------------------------------------------*/ + + if( output_frame == L_FRAME8k || st->bfi == 0) + { + if((output_frame != inner_frame) && (st->bfi == 1)) + { + inverse_transform( t_audio_q, wtda_audio, is_transient, output_frame, output_frame ); + } + else + { + inverse_transform( t_audio_q, wtda_audio, is_transient, output_frame, inner_frame ); + } + } + if( output_frame == L_FRAME8k ) + { + if( st->bfi == 0 && st->prev_bfi == 0 ) + { + mvr2r( st->old_out + (short)(N_ZERO_MDCT_NS*output_frame/FRAME_SIZE_NS), st->prev_oldauOut, output_frame - (short)(N_ZERO_MDCT_NS*output_frame/FRAME_SIZE_NS) ); + } + else if( st->prev_bfi == 1 ) + { + set_f( st->prev_oldauOut, 0.0f, output_frame ); + } + if( (st->prev_bfi == 1 || st->bfi == 1) && !st->old_is_transient[2] && st->last_core == HQ_CORE && st->last_codec_mode == MODE1) + { + time_domain_FEC_HQ( st, wtda_audio, synth, mean_en_high, output_frame ); + } + else + { + window_ola( wtda_audio, synth, st->old_out, output_frame, st->tcx_cfg.tcx_last_overlap_mode, st->tcx_cfg.tcx_curr_overlap_mode, st->prev_bfi, st->oldHqVoicing, st->oldgapsynth ); + st->phase_mat_next = 0; + } + + if( (!st->bfi && !st->prev_bfi) || (!(output_frame >= L_FRAME16k)) ) + { + preecho_sb( st->core_brate, wtda_audio, synth, output_frame, &st->memfilt_lb, &st->mean_prev_hb, &st->smoothmem, + &st->mean_prev, &st->mean_prev_nc, &st->wmold_hb, &st->prevflag, &st->pastpre, st->bwidth ); + } + + } + else + { + if( st->bfi && output_frame >= L_FRAME16k) + { + window_ola( t_audio_q, synth, st->old_out, output_frame, ALDO_WINDOW, ALDO_WINDOW, st->prev_bfi && !st->ph_ecu_active, st->oldHqVoicing, st->oldgapsynth ); + } + else + { + window_ola( wtda_audio, synth, st->old_out, output_frame, st->tcx_cfg.tcx_last_overlap_mode, st->tcx_cfg.tcx_curr_overlap_mode, st->prev_bfi && !st->ph_ecu_active, st->oldHqVoicing, st->oldgapsynth ); + } + + if( (!st->bfi && !st->prev_bfi) || (!(output_frame >= L_FRAME16k)) ) + { + preecho_sb( st->core_brate, wtda_audio, synth, output_frame, &st->memfilt_lb, &st->mean_prev_hb, &st->smoothmem, + &st->mean_prev, &st->mean_prev_nc, &st->wmold_hb, &st->prevflag, &st->pastpre, st->bwidth ); + } + + } + + if (!st->bfi + && st->prev_bfi + && st->last_total_brate >= HQ_48k + && st->last_codec_mode == MODE2 + && (st->last_core_bfi == TCX_20_CORE || st->last_core_bfi == TCX_10_CORE) + && st->plcInfo.concealment_method == TCX_NONTONAL + && st->plcInfo.nbLostCmpt < 4 ) + { + waveform_adj2( + st->tonalMDCTconceal.secondLastPcmOut, + synth, + st->plcInfo.data_noise, + &st->plcInfo.outx_new_n1, + &st->plcInfo.nsapp_gain, + &st->plcInfo.nsapp_gain_n, + &st->plcInfo.recovery_gain, + st->plcInfo.step_concealgain, + st->plcInfo.Pitch, + st->plcInfo.FrameSize, + 0, + st->plcInfo.nbLostCmpt + 1, + st->bfi); + } + + if ( output_frame >= L_FRAME16k ) + { + if( st->ph_ecu_HqVoicing ) + { + st->oldHqVoicing = 1; + mvr2r( gapsynth, st->oldgapsynth, L_FRAME48k ); + } + else + { + st->oldHqVoicing = 0; + } + } + else + { + st->oldHqVoicing = 0; + } + + if( st->nbLostCmpt == FRAMECTTOSTART_MDCT ) + { + st->HqVoicing = 0; + } + + if( output_frame == L_FRAME8k ) + { + mvr2r( wtda_audio, st->oldIMDCTout, L_FRAME8k/2 ); + mvr2r( st->old_auOut_2fr + output_frame, st->old_auOut_2fr, output_frame ); + mvr2r( synth, st->old_auOut_2fr + output_frame, output_frame ); + } + + + /* update buffer of old subframe pitch values */ + if( st->last_core == HQ_CORE && st->L_frame != st->last_L_frame ) + { + set_f( &st->old_pitch_buf[st->L_frame/L_SUBFR], (float)L_SUBFR, st->L_frame/L_SUBFR ); + } + mvr2r( &st->old_pitch_buf[st->L_frame/L_SUBFR], st->old_pitch_buf, st->L_frame/L_SUBFR ); + set_f( &st->old_pitch_buf[st->L_frame/L_SUBFR], (float)L_SUBFR, st->L_frame/L_SUBFR ); + mvr2r( &st->mem_pitch_gain[2], &st->mem_pitch_gain[st->L_frame/L_SUBFR+2], st->L_frame/L_SUBFR ); + set_zero( &st->mem_pitch_gain[2], st->L_frame/L_SUBFR ); + + + return; +} diff --git a/lib_dec/hq_env_dec.c b/lib_dec/hq_env_dec.c new file mode 100644 index 000000000..435765c39 --- /dev/null +++ b/lib_dec/hq_env_dec.c @@ -0,0 +1,167 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "prot.h" +#include "rom_com.h" + +/*------------------------------------------------------------------------* + * decode_envelope_indices() + * + * Decode envelope indices + *------------------------------------------------------------------------*/ + +short decode_envelope_indices( /* o : Number of bits */ + Decoder_State *st, /* i/o: decoder state structure */ + const short start_norm, /* i : starting band index */ + const short num_sfm, /* i : Number of subbands */ + const short numnrmibits, /* i : Bitrate of fall-back coding mode */ + short *difidx, /* o : Diff indices/encoded diff indices */ + const short flag_HQ2, /* i : indicator of HQ2 core */ + const short is_transient /* i : transient flag */ +) +{ + short hcode_l; + short i; + short LCmode; + + if( flag_HQ2 == LOW_RATE_HQ_CORE || flag_HQ2 == LOW_RATE_HQ_CORE_TRAN) + { + LCmode = (short)get_next_indice( st, BITS_DE_HMODE); + difidx[start_norm] = (short)get_next_indice( st, BITS_DE_FCOMP); + } + else + { + LCmode = (short)get_next_indice( st, 2 ); + difidx[start_norm] = (short)get_next_indice( st, NORM0_BITS ); + } + + if(is_transient && flag_HQ2 == LOW_RATE_HQ_CORE_TRAN) + { + hcode_l = 0; + if(LCmode == 1 ) + { + hdecnrm_tran(st, num_sfm, &difidx[start_norm + 1] ); + for( i = start_norm + 1; i < start_norm + num_sfm; i++ ) + { + hcode_l += huffsizn_tran[difidx[i]]; + } + } + else + { + hdecnrm_context(st,num_sfm, &difidx[start_norm], &hcode_l); + } + } + else + { + hcode_l = 0; + if ( LCmode == 0 ) + { + hdecnrm_context( st, num_sfm, &difidx[start_norm], &hcode_l ); + } + else if( LCmode == 1 ) + { + hdecnrm_resize( st, num_sfm, &difidx[start_norm + 1] ); + + for( i = start_norm + 1; i < start_norm + num_sfm; i++ ) + { + hcode_l += resize_huffsizn[difidx[i]]; + } + + for( i = start_norm + 2; i< start_norm + num_sfm; i++ ) + { + if( difidx[i-1]>17 ) + { + difidx[i] = difidx[i] - min(difidx[i-1]-17,3); + } + + if( difidx[i-1]<13 ) + { + difidx[i] = difidx[i] - max(difidx[i-1]-13,-3); + } + } + } + else if ( LCmode == 2 ) + { + hdecnrm( st, num_sfm, &difidx[start_norm + 1] ); + for( i = start_norm + 1; i < start_norm + num_sfm; i++ ) + { + hcode_l += huffsizn[difidx[i]]; + } + } + else + { + for( i = start_norm + 1; i < start_norm + num_sfm; i++ ) + { + difidx[i] = (short)get_next_indice( st, NORMI_BITS ); + + } + hcode_l = numnrmibits; + } + } + + return hcode_l; +} + +/*------------------------------------------------------------------------* + * dequantize_norms() + * + * De-quantization of norms + *------------------------------------------------------------------------*/ + +void dequantize_norms( /* o : Number of bits */ + Decoder_State *st, /* i/o: decoder state structure */ + const short start_norm, /* i : First SDE encoded norm */ + const short num_sfm, /* i : Number of norms */ + const short is_transient, /* i : Transient flag */ + short *ynrm, /* o : Decoded norm indices */ + short *normqlg2 /* o : Log2 of decoded norms */ +) +{ + short i,j,k; + short idxbuf[NB_SFM]; + + /* First sub-frame */ + normqlg2[start_norm] = dicnlg2[ynrm[start_norm]]; + + /* Other sub-frames */ + if( is_transient ) + { + /* Recover quantization indices and quantized norms */ + idxbuf[0] = ynrm[0]; + for( i = 1; i < num_sfm; i++ ) + { + idxbuf[i] = ynrm[i] + idxbuf[i-1] - 15; + /* safety check in case of bit errors */ + if ( idxbuf[i] < 0 || idxbuf[i] > 39 ) + { + idxbuf[i] = 39; + st->BER_detect = 1; + } + } + + recovernorm( idxbuf, ynrm, normqlg2, num_sfm ); + } + else + { + for (i = start_norm + 1; i < start_norm + num_sfm; i++) + { + j = i - 1; + k = ynrm[j] - 15; + ynrm[i] = ynrm[i] + k; + /* safety check in case of bit errors */ + if ( ynrm[i] < 0 || ynrm[i] > 39 ) + { + ynrm[i] = 39; + st->BER_detect = 1; + } + normqlg2[i] = dicnlg2[ynrm[i]]; + } + } + + return; +} diff --git a/lib_dec/hq_hr_dec.c b/lib_dec/hq_hr_dec.c new file mode 100644 index 000000000..27ed8b79a --- /dev/null +++ b/lib_dec/hq_hr_dec.c @@ -0,0 +1,272 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*--------------------------------------------------------------------------* + * hq_pred_hb_bws() + * + * HQ core HB band-width switching handling + *--------------------------------------------------------------------------*/ + +static void hq_pred_hb_bws( + Decoder_State *st, /* i/o: decoder state structure */ + const short *ynrm, /* i : norm quantization index vector */ + const short length, /* i : frame length */ + const short hqswb_clas, /* i : HQ SWB class */ + const float *SWB_fenv /* i : SWB frequency envelopes */ +) +{ + short i; + + /* SWB switching to WB */ + if ( length >= L_FRAME32k ) /* wb switch to swb */ + { + /* calculate the switching parameters */ + if( (hqswb_clas != HQ_GEN_SWB && st->core_brate <= HQ_32k) || st->core_brate > HQ_32k ) + { + st->prev_ener_shb = 0.0f; + for( i=25; iprev_ener_shb += dicn[ynrm[i]]; + } + st->prev_ener_shb /= 6; + } + else + { + st->prev_ener_shb = 0.0f; + for( i=0; iprev_ener_shb += SWB_fenv[i]; + } + st->prev_ener_shb /= (SWB_FENV-3); + } + } + + if( st->last_inner_frame >= L_FRAME32k ) + { + set_f( st->prev_SWB_fenv, st->prev_ener_shb, SWB_FENV ); + } + + return; +} + + +/*--------------------------------------------------------------------------* + * hq_hr_dec() + * + * HQ high rate decoding routine + *--------------------------------------------------------------------------*/ + +void hq_hr_dec( + Decoder_State *st, /* i/o: decoder state structure */ + float *t_audio_q, /* o : transform-domain coefficients */ + const short length, /* i : frame length */ + short num_bits, /* i : number of available bits */ + short *ynrm, /* o : norm quantization index vector */ + short *is_transient, /* o : transient flag */ + short *hqswb_clas, /* o : HQ SWB class */ + float *SWB_fenv /* o : SWB frequency envelopes */ +) +{ + short nb_sfm; + short sum, hcode_l; + const short *sfmsize, *sfm_start, *sfm_end; + short num_sfm, numnrmibits; + short nf_idx; + short normqlg2[NB_SFM], R[NB_SFM]; + short pulses[NB_SFM], maxpulse[NB_SFM]; + float env_stab; + short Rsubband[NB_SFM]; /*Q3*/ + short start_norm, Npeaks = 0; + float noise_level[HVQ_BWE_NOISE_BANDS]; + short peak_idx[HVQ_MAX_PEAKS_32k]; + short hq_generic_offset; + short num_env_bands; + short hq_generic_exc_clas = 0; + short core_sfm; + short har_freq_est1, har_freq_est2; + short flag_dis; + const short *subband_search_offset; + short wBands[2]; + short b_delta_env; + short n_band; + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + set_s( pulses, 0, NB_SFM ); + set_s( maxpulse, 0, NB_SFM ); + flag_dis = 1; + har_freq_est1 = 0; + har_freq_est2 = 0; + set_s( peak_idx, 0, HVQ_MAX_PEAKS_32k); + + /*------------------------------------------------------------------* + * Decode classification + *------------------------------------------------------------------*/ + + num_bits -= hq_classifier_dec( st, st->core_brate, length, is_transient, hqswb_clas ); + + + /*------------------------------------------------------------------* + * set quantization parameters + *------------------------------------------------------------------*/ + + hq_configure( length, *hqswb_clas, st->core_brate, &num_sfm, &nb_sfm, &start_norm, + &num_env_bands, &numnrmibits, &hq_generic_offset, &sfmsize, &sfm_start, &sfm_end ); + + /*------------------------------------------------------------------* + * Unpacking bit-stream + *------------------------------------------------------------------*/ + + nf_idx = 0; + if( !*is_transient && *hqswb_clas != HQ_HVQ && !(length == L_FRAME16k && st->core_brate == HQ_32k)) + { + nf_idx = (short)get_next_indice( st, 2 ); + } + + + /*------------------------------------------------------------------* + * Decode envelope + *------------------------------------------------------------------*/ + + hcode_l = decode_envelope_indices( st, start_norm, num_env_bands, numnrmibits, ynrm, NORMAL_HQ_CORE, *is_transient ); + num_bits -= hcode_l + NORM0_BITS + FLAGS_BITS; + + dequantize_norms( st, start_norm, num_env_bands, *is_transient, ynrm, normqlg2 ); + + if ( *hqswb_clas == HQ_GEN_SWB || *hqswb_clas == HQ_GEN_FB ) + { + hq_generic_exc_clas = swb_bwe_gain_deq( st, HQ_CORE, NULL, SWB_fenv, st->core_brate == HQ_32k, *hqswb_clas ); + if (hq_generic_exc_clas == HQ_GENERIC_SP_EXC) + { + num_bits++; /* conditional 1 bit saving for representing FD3 BWE excitation class */ + } + map_hq_generic_fenv_norm(*hqswb_clas, SWB_fenv, ynrm, normqlg2, num_env_bands, nb_sfm, hq_generic_offset); + } + + env_stab = 0; + if( *hqswb_clas == HQ_HVQ ) + { + st->mem_env_delta = 0; + } + else if( length == L_FRAME32k ) + { + env_stab = env_stability( ynrm, SFM_N_ENV_STAB, st->mem_norm, &st->mem_env_delta ); + } + else + { + st->mem_norm[0] = 31; + st->mem_env_delta = 0; + } + + if( *hqswb_clas == HQ_HVQ ) + { + st->env_stab = 1.0f; /* stable by definition */ + } + else + { + if( length == L_FRAME32k ) + { + st->env_stab = env_stab; /* calculated stability */ + } + else + { + st->env_stab = env_stability( ynrm, SFM_N_ENV_STAB_WB, st->mem_norm_hqfec, &st->mem_env_delta_hqfec ); + } + } + st->env_stab_plc=env_stab_smo(min(st->env_stab,1.0f-stab_trans[L_STAB_TBL-1]),st->env_stab_state_p,&st->envstabplc_hocnt); + + /*------------------------------------------------------------------* + * Bit allocation + *------------------------------------------------------------------*/ + + hq_bit_allocation( st->core_brate, length, *hqswb_clas, &num_bits, normqlg2, nb_sfm, sfmsize, noise_level, + R, Rsubband, &sum, &core_sfm, num_env_bands ); + + if( st->bws_cnt1 > 0 && *hqswb_clas == HQ_GEN_SWB && st->core_brate == HQ_24k40 ) + { + if(st->L_frame == L_FRAME16k ) + { + for (n_band = 0; n_band < 4; n_band++) + { + SWB_fenv[n_band] *= (float)st->bws_cnt1 / (float)N_NS2W_FRAMES; + } + } + + for (n_band = 4; n_band < SWB_FENV; n_band++) + { + SWB_fenv[n_band] *= (float)st->bws_cnt1 / (float)N_NS2W_FRAMES; + } + } + + if ( *hqswb_clas == HQ_GEN_SWB || *hqswb_clas == HQ_GEN_FB ) + { + b_delta_env = get_nor_delta_hf(st, ynrm, Rsubband, num_env_bands, nb_sfm, core_sfm ); + sum -= b_delta_env; + } + + /*------------------------------------------------------------------* + * Decode spectral fine structure using HVQ/PVQ + *------------------------------------------------------------------*/ + + if( *hqswb_clas == HQ_HVQ ) + { + hvq_dec( st, num_bits, st->core_brate, ynrm, R, noise_level, peak_idx, &Npeaks, t_audio_q, st->core ); + } + else + { + pvq_core_dec(st, sfm_start, sfm_end, sfmsize, t_audio_q, sum, nb_sfm, Rsubband, R, pulses, maxpulse, HQ_CORE ); + } + + if( *hqswb_clas == HQ_HVQ || *hqswb_clas == HQ_HARMONIC ) + { + subband_search_offset = subband_search_offsets_13p2kbps_Har; + wBands[0] = SWB_SB_BW_LEN0_16KBPS_HAR; + wBands[1] = SWB_SB_BW_LEN1_16KBPS_HAR; + + har_est( t_audio_q, 300, &har_freq_est1, &har_freq_est2, &flag_dis, &st->prev_frm_hfe2, subband_search_offset, wBands, &st->prev_stab_hfe2 ); + + st->prev_frm_hfe2 = har_freq_est2; + } + + if( *hqswb_clas != HQ_HARMONIC || *hqswb_clas != HQ_HVQ || flag_dis == 0 ) + { + st->prev_frm_hfe2 = 0; /*reset*/ + st->prev_stab_hfe2 = 0;/*reset*/ + } + + /*------------------------------------------------------------------* + * Spectral filling + *------------------------------------------------------------------*/ + fill_spectrum( t_audio_q, R, *is_transient, ynrm, SWB_fenv, hq_generic_offset, nf_idx, length, env_stab, + &st->no_att_hangover, &st->energy_lt, &st->hq_generic_seed, hq_generic_exc_clas, + core_sfm, *hqswb_clas, noise_level, st->core_brate, st->prev_noise_level, &(st->prev_R), st->prev_coeff_out, + peak_idx, Npeaks, pulses, st->old_is_transient[0], st->prev_normq, st->prev_env, st->prev_bfi, + sfmsize, sfm_start, sfm_end, &st->prev_L_swb_norm, st->prev_hqswb_clas, num_sfm, num_env_bands ); + + enforce_zero_for_min_envelope( *hqswb_clas, ynrm, t_audio_q, nb_sfm, sfm_start, sfm_end ); + + if( *is_transient ) + { + de_interleave_spectrum( t_audio_q, length ); + } + + /*------------------------------------------------------------------* + * WB/SWB bandwidth switching + *------------------------------------------------------------------*/ + + hq_pred_hb_bws( st, ynrm, length, *hqswb_clas, SWB_fenv ); + + /* update */ + st->prev_hqswb_clas = *hqswb_clas; + + return; +} diff --git a/lib_dec/hq_lr_dec.c b/lib_dec/hq_lr_dec.c new file mode 100644 index 000000000..189da80e8 --- /dev/null +++ b/lib_dec/hq_lr_dec.c @@ -0,0 +1,1302 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_com.h" +#include "rom_dec.h" +#include "prot.h" +#include "stl.h" +#include "basop_util.h" + +/*--------------------------------------------------------------------------* + * Local functions + *--------------------------------------------------------------------------*/ + +static short p2a_threshold_dequant( Decoder_State *st, short *p2a_flags, const short bands, const short p2a_bands ); + +static void mdct_spectrum_fine_gain_dec( Decoder_State *st, float y2[], const short band_start[], const short band_end[], + const short k_sort[], const short bands, const Word32 L_qint, + const short Ngq, const short gqlevs, const short gqbits ); + +static float band_energy_dequant( Decoder_State *st, float band_energy[], const short bands, const Word32 L_qint, const Word16 eref_fx, const short is_transient ); + +static void spt_shorten_domain_set_dec( Decoder_State *st, const short p2a_flags[], const short new_band_start[], + const short new_band_end[], const short new_band_width[], const short bands, + short band_start[], short band_end[], short band_width[], short *bit_budget ); + +/*-------------------------------------------------------------------* + * hq_lr_dec() + * + * HQ low rate decoding routine + *-------------------------------------------------------------------*/ + +void hq_lr_dec( + Decoder_State *st, /* i/o: decoder state structure */ + float yout[], /* o : transform-domain output coefs. */ + const short inner_frame, /* i : inner frame length */ + short num_bits, /* i : number of available bits */ + short *is_transient /* o : transient flag */ +) +{ + short i, k1, pbits, p2a_flags[BANDS_MAX], bit_budget, bands, length, gqlevs, gqbits, Ngq, p2a_bands, ni_seed; + short band_start[BANDS_MAX], band_end[BANDS_MAX], band_width[BANDS_MAX]; + short k_sort[BANDS_MAX]; + int npulses[BANDS_MAX], inp_vector[L_FRAME48k]; + float ni_coef, ni_pd_th, pd_thresh, ld_slope; + float ebits, Rk[BANDS_MAX], band_energy[BANDS_MAX], y2[L_FRAME48k], p2a_th; + Word32 Rk_fx[BANDS_MAX]; + Word32 L_qint; /* Q29 */ + Word16 eref_fx; /* Q10 */ + Word16 bit_alloc_weight_fx; /* Q13 */ + float y2_ni[L_FRAME48k],y2_org[L_FRAME48k]; + short hqswb_clas = 0; + short lowlength, highlength, har_bands = 0; + float m[L_FRAME32k]; + float Ep[BANDS_MAX], enerH = 0.0f, enerL = 0.0f; + short lowband, highband, bw_low = 0, bw_high = 20; + float Ep_tmp[BANDS_MAX]; + float band_energy_tmp[BANDS_MAX]; + short last_bitalloc_max_band[2]; + long bwe_br; + short trans_bit, p2a_flags_tmp[BANDS_MAX]; + short adjustFlag = 0; + short prev_SWB_peak_pos_tmp[SPT_SHORTEN_SBNUM]; + int j, k; + short flag_spt; + short org_band_start[SPT_SHORTEN_SBNUM]; + short org_band_end[SPT_SHORTEN_SBNUM]; + short org_band_width[SPT_SHORTEN_SBNUM]; + short new_band_start[SPT_SHORTEN_SBNUM]; + short new_band_end[SPT_SHORTEN_SBNUM]; + short new_band_width[SPT_SHORTEN_SBNUM]; + Word32 L_tmp,L_tmp2,L_tmp3; + Word16 exp,tmp,exp2,tmp1,tmp2,tmp3,alpha_fx,frac1; + 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; */ + Word32 L_band_energy[BANDS_MAX],L_band_energy_tmp[BANDS_MAX]; + UWord16 lo; + Word16 Q_band_energy; + + set_s(last_bitalloc_max_band, 0, 2); + set_f( y2, 0.0f, L_FRAME48k ); + set_i( inp_vector, 0, inner_frame ); + flag_spt = 0; + set_s(prev_SWB_peak_pos_tmp, 0, SPT_SHORTEN_SBNUM); + bwe_br = st->core_brate; + + if( st->bwidth == SWB && ( bwe_br == HQ_16k40 || bwe_br == HQ_13k20 ) ) + { + hqswb_clas = (short)get_next_indice( st,2); + num_bits -= 2; + + *is_transient = 0; + if ( hqswb_clas == HQ_TRANSIENT ) + { + *is_transient = 1; + } + } + else + { + /* decode transient flag */ + *is_transient = (short)get_next_indice( st, 1 ); + num_bits--; + } + + + /* Configure decoder for different bandwidths, bit rates, etc. */ + hq2_core_configure( inner_frame, num_bits, *is_transient, &bands, &length, band_width, band_start, band_end, &L_qint, &eref_fx, + &bit_alloc_weight_fx, &gqlevs, &Ngq, &p2a_bands, &p2a_th, &pd_thresh, &ld_slope, &ni_coef, &ni_pd_th, bwe_br ); + + highlength = band_end[bands-1]; + har_bands = bands; + + if( st->bwidth == SWB && *is_transient == 0 && (bwe_br == HQ_16k40 || bwe_br == HQ_13k20) ) + { + /* reserve bits for HQ_NORMAL and HQ_HARMONIC */ + if( hqswb_clas == HQ_NORMAL || hqswb_clas==HQ_HARMONIC) + { + num_bits -= (short)get_usebit_npswb( hqswb_clas ); + } + + if( hqswb_clas == HQ_NORMAL ) + { + flag_spt = 1; + } + } + + if( (bwe_br == HQ_16k40 || bwe_br == HQ_13k20) && st->bwidth == SWB ) + { + if( st->prev_hqswb_clas != HQ_NORMAL ) + { + j = 0; + for(k=bands-SPT_SHORTEN_SBNUM; kprev_SWB_peak_pos[j] = 0; + j++; + } + } + } + + /* Spectral energy calculation/quantization */ + ebits = band_energy_dequant( st, band_energy, bands, L_qint, eref_fx, *is_transient ); + + /* simple check: band_energy is too large, Abnormal Situation of bit errors */ + for( k=0; k 45.0f || band_energy[k] < -6.7f ) + { + st->BER_detect = 1; + set_f( yout, 0, inner_frame ); + return; + } + } + + for (i = 0; i < bands; i++) + { + L_band_energy[i] = (Word32)(band_energy[i] * pow(2.0f, SWB_BWE_LR_Qbe)); + } + + /* First pass bit budget for TCQ of spectral band information */ + gqbits = (short int) log2_f ((float) gqlevs); + bit_budget = num_bits - (short) ceil (ebits) - Ngq * gqbits; + + pbits = 0; + if( st->bwidth == SWB && (bwe_br == HQ_16k40 || bwe_br == HQ_13k20) ) + { + if ( hqswb_clas == HQ_HARMONIC) + { + set_s( p2a_flags, 1, har_bands ); + } + else + { + /* High band tonality detector based on per band peak-to-average ratio */ + pbits = p2a_threshold_dequant( st, p2a_flags, bands, p2a_bands ); + bit_budget -= pbits; + + if( hqswb_clas == HQ_NORMAL ) + { + return_bits_normal2( &bit_budget, p2a_flags, bands, bits_lagIndices_modeNormal ); + } + } + } + else + { + /* High band tonality detector based on per band peak-to-average ratio */ + pbits = p2a_threshold_dequant( st, p2a_flags, bands, p2a_bands ); + bit_budget -= pbits; + } + + if( flag_spt == 1 ) + { + /* initalize the desired parameters for SPT */ + spt_shorten_domain_band_save( bands, band_start, band_end, band_width, org_band_start, org_band_end, org_band_width ); + spt_shorten_domain_pre( band_start, band_end, st->prev_SWB_peak_pos, bands, bwe_br, new_band_start, new_band_end, new_band_width ); + spt_shorten_domain_set_dec( st, p2a_flags, new_band_start, new_band_end, new_band_width, bands, band_start, band_end, band_width, &bit_budget ); + } + + /* safety check in case of bit errors */ + if( bit_budget < 2 ) + { + st->BER_detect = 1; + set_f( yout, 0, inner_frame ); + return; + } + + /* Estimate number of bits per sub-band */ +#define WMC_TOOL_SKIP + Q_band_energy = SWB_BWE_LR_Qbe; + FOR(i = 0; i < bands; 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 , sub(exp,6)); /* Q -6 */ + Ep[i] = (float)(Ep_fx[i]/pow(2.0,-6)); + } + + FOR( i = 0; i < bands; 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_lc1(L_tmp, &exp2); + move32();/*Q(31-exp2) */ + Ep_tmp_fx[i] = L_shr(L_tmp,sub(15,exp2));/*Q13 */ + Ep_tmp[i] = (float)(Ep_tmp_fx[i]/pow(2.0,13)); + } +#undef WMC_TOOL_SKIP + + if ( *is_transient == 0 && inner_frame == L_FRAME8k && st->core_brate <= 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] = (short)get_next_indice( st, 1 ); + } + +#define WMC_TOOL_SKIP + lowband = 6; move16(); + trans_bit = 2; move16(); + bit_budget =sub(bit_budget,trans_bit); + gama_fx = 27852; /*Q15 0.85f;*/ + beta_fx = 17203; + move16();/*Q14 1.05f; */ + set_s( &p2a_flags_tmp[bands-trans_bit], 0, 2 ); + + IF( st->core_brate == ACELP_13k20 ) + { + beta_fx = 13107; + move16();/*14 1.25f; */ + gama_fx = 31130; + move16();/*0.95f; */ + mvs2s(&p2a_flags[sub(bands,trans_bit)], &p2a_flags_tmp[sub(bands,trans_bit)], trans_bit); + } + + /* calculate the the low band/high band energy and the variance/avrage of the envelopes */ + Ep_vari_fx = 0; + move32(); + Ep_avrg_fx = 0; + move32(); + Ep_avrgL_fx = 0; + move32(); + Ep_peak_fx = 0; + move32(); + FOR( i = 0; i < bands; i++ ) + { + IF( sub(i,lowband) >= 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 */ + + } + ELSE + { + Ep_avrgL_fx = L_add(Ep_avrgL_fx,Ep_tmp_fx[i]);/*Q15 */ + IF(L_sub(Ep_tmp_fx[i],Ep_peak_fx) > 0) + { + Ep_peak_fx = Ep_tmp_fx[i]; + move32();/*Q15 */ + } + } + } + /* modify the last p2a_bands subbands band_energies */ + k = (int)bands; + mvi2i( L_band_energy,L_band_energy_tmp,k); /*Q_band_energy */ + Mpy_32_16_ss(Ep_peak_fx,24576,&L_tmp,&lo); + Mpy_32_16_ss(Ep_peak_fx,shl(sub(bands,lowband),9),&L_tmp2,&lo); + Mpy_32_16_ss(Ep_avrg_fx,1126,&L_tmp3,&lo); + + IF(( (L_sub(L_tmp, L_shr(Ep_avrgL_fx,1)) < 0 && st->core_brate == ACELP_13k20 ) || st->core_brate < ACELP_13k20 )&& + L_sub(L_tmp2, L_tmp3) < 0 && L_sub(L_tmp2, L_shr(Ep_avrg_fx,7)) > 0) + { + FOR(i = lowband; i < bands; i++) + { + Mpy_32_16_ss(Ep_avrg_fx,24576,&L_tmp,&lo); + IF(L_sub(L_shr(Ep_tmp_fx[i],1), L_tmp) < 0) + { + Mpy_32_16_ss(Ep_peak_fx,sub(bands,lowband),&L_tmp,&lo); + 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 + { + tmp = 0x7fff; + move16(); + exp = 0; + move16(); + } + Mpy_32_16_ss(Ep_avrg_fx,tmp,&L_tmp,&lo); + L_tmp = L_shl(L_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 */ + Mpy_32_16_ss(L_band_energy_tmp[i],tmp2,&L_band_energy_tmp[i],&lo); + } + } + } + ELSE + { + FOR(i = sub(bands,trans_bit); i < bands; i++) + { + alpha_fx = 16384; + move16();/*Q14 */ + IF( sub(p2a_flags_tmp[i],1) == 0) + { + Mpy_32_16_ss(Ep_tmp_fx[i],sub(bands,lowband),&L_tmp,&lo); + 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 + { + tmp = 0x7fff; + move16(); + exp = 0; + move16(); + } + Mpy_32_16_ss(Ep_vari_fx,3277,&L_tmp,&lo); + Mpy_32_16_ss(L_tmp,tmp,&L_tmp,&lo); + L_tmp = L_shl(L_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(); + } + Mpy_32_16_ss(Ep_vari_fx,6554,&L_tmp2,&lo); + Mpy_32_16_ss(L_tmp2,tmp2,&L_tmp2,&lo); + L_tmp2 = L_shl(L_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(sub(last_bitalloc_max_band[j++], 1) == 0) + { + Mpy_32_16_ss(Ep_tmp_fx[i],sub(bands,lowband),&L_tmp,&lo); + 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(); + } + Mpy_32_16_ss(Ep_avrg_fx,tmp,&L_tmp,&lo); + L_tmp = L_shl(L_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(); + } + Mpy_32_16_ss(Ep_tmp_fx[i],tmp2,&L_tmp,&lo); + L_tmp = L_shl(L_tmp,sub(19,exp));/*Q(13+exp-15 +19-exp +3 = 20) */ + Mpy_32_16_ss(L_tmp,shl(sub(bands,lowband),9),&L_tmp,&lo); + 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 */ + } + Mpy_32_16_ss(L_band_energy_tmp[i],alpha_fx,&L_tmp,&lo); + L_band_energy_tmp[i] = L_shl(L_tmp,1);/*Q(Q_band_energy+14-15 +1= Q_band_energy) */ + } + } + lowband = 3; + move16(); + Ep_avrg_fx = 0; + move32(); + Ep_avrgL_fx = 0; + move32(); + Ep_peak_fx = 0; + move32(); + FOR(i = 0; i < bands; i++) + { + IF(sub(i,lowband) >=0 ) + { + 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(L_sub(Ep_tmp_fx[i],Ep_peak_fx) > 0) + { + Ep_peak_fx = Ep_tmp_fx[i]; + move32();/*Q13 */ + } + } + } + Mpy_32_16_ss(Ep_peak_fx,28262,&L_tmp,&lo); + Mpy_32_16_ss(Ep_avrgL_fx,24576,&L_tmp2,&lo); + IF( L_sub(L_shr(Ep_avrg_fx,2), L_tmp2) > 0 && L_sub(L_shr(Ep_avrg_fx,4), L_tmp2) < 0 && L_sub(L_tmp, Ep_avrgL_fx)>0) + { + 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 + { + tmp = 0x7fff; + move16(); + exp = 0; + move16(); + } + Mpy_32_16_ss(Ep_peak_fx,tmp,&L_tmp,&lo); + Mpy_32_16_ss(L_tmp,lowband,&L_tmp,&lo); + Mpy_32_16_ss(L_tmp,18842,&L_tmp,&lo); + L_tmp = L_shl(L_tmp,sub(27,exp));/*Q14 0.5 */ + tmp2=extract_l(L_min(L_tmp,19661));/*14 */ + Mpy_32_16_ss(L_band_energy_tmp[i],tmp2,&L_tmp,&lo); + L_band_energy_tmp[i] = L_shl(L_tmp,1); /*Q_band_energy */ + } + } + for (i = 0; i < bands; i++) + { + band_energy_tmp[i] = (float)(L_band_energy_tmp[i]/pow(2.0f, SWB_BWE_LR_Qbe)); + } +#undef WMC_TOOL_SKIP + + hq2_bit_alloc( band_energy_tmp, bands, Rk_fx, &bit_budget, p2a_flags, bit_alloc_weight_fx, + band_width, num_bits, hqswb_clas, st->bwidth, *is_transient ); + } + else if( *is_transient == 0 && inner_frame == L_FRAME16k ) + { +#define WMC_TOOL_SKIP + bit_budget = sub(bit_budget,2);/* bits in high bands to indicate the last 2 subbands is allocated bits or not */ + /* decode the last p2a_bands-1 subbands bit-allocation index of the previous frame */ + for(i = 0; i < 2; i++) + { + last_bitalloc_max_band[i] = (short)get_next_indice( st, 1 ); + } + FOR( i = 0; i < bands; i++ ) + { + Ep_tmp_fx[i] = L_shl(Ep_tmp_fx[i],2); + } + IF( st->core_brate == 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,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,1)],1),band_start[highband]); + } + /* calculate the the low band/high band energy and the variance/avrage of the envelopes */ + enerL_fx = 0; + move32(); + enerH_fx = 0; + move32(); + Ep_vari_fx = 0; + move32(); + Ep_avrg_fx = 0; + move32(); + FOR( i = 0; i < bands; i++ ) + { + IF( sub(i,lowband) >= 0 && add(sub(i,bands),p2a_bands) < 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(sub(i,highband) >= 0) + { + enerH_fx = L_add(enerH_fx,L_shl(Ep_fx[i],2));/*Q0 */ + } + ELSE IF(sub(i,lowband) >= 0) + { + enerL_fx = L_add(enerL_fx,L_shl(Ep_fx[i],2));/*Q0 */ + } + } + + enerL = (float)(enerL_fx/pow(2.0,-4)); + enerH = (float)(enerH_fx/pow(2.0,-4)); + /* modify the last p2a_bands subbands band_energies */ + k = (int)bands; + mvi2i( L_band_energy,L_band_energy_tmp,k); /*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); + Mpy_32_16_ss(L_shl(enerH_fx,i),shl(bw_low,j),&L_tmp,&lo); + Mpy_32_16_ss(L_shl(enerL_fx,i),shl(bw_high,j),&L_tmp2,&lo); + L_tmp2 = L_sub(L_tmp,L_tmp2); + + FOR( i = sub(bands,p2a_bands); i < bands; i++ ) + { + IF( sub(p2a_flags[i],1) == 0 || L_tmp2 > 0 ) + { + tmp = sub(bands,p2a_bands); + 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(); + } + Mpy_32_16_ss(Ep_tmp_fx[i],tmp1,&L_tmp,&lo); + Mpy_32_16_ss(L_tmp,tmp,&L_tmp,&lo); + Mpy_32_16_ss(L_tmp,16384,&L_tmp,&lo); + L_tmp = L_shl(L_tmp,sub(32,exp));/*Q15 */ + tmp = extract_l(L_min(L_tmp,6554));/*Q15 */ + Mpy_32_16_ss(Ep_vari_fx,tmp1,&L_tmp,&lo); + Mpy_32_16_ss(L_tmp,tmp,&L_tmp,&lo); + 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),p2a_bands) > 0) + { + tmp = sub(bands, p2a_bands); + IF(sub(last_bitalloc_max_band[sub(i, add(tmp, 1))], 1) == 0) + { + tmp = sub(tmp,lowband); + Mpy_32_16_ss(Ep_tmp_fx[i],tmp,&L_tmp,&lo); + 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(); + } + Mpy_32_16_ss(Ep_avrg_fx,tmp,&L_tmp,&lo); + 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(); + } + Mpy_32_16_ss(Ep_tmp_fx[i],tmp1,&L_tmp,&lo); + Mpy_32_16_ss(L_tmp,tmp,&L_tmp,&lo); + 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 */ + } + } + Mpy_32_16_ss(L_band_energy_tmp[i],alpha_fx,&L_tmp,&lo); + L_band_energy_tmp[i] = L_shl(L_tmp,1);/*Q Q_band_energy */ + } + lowband = 6; + move16(); + Ep_avrg_fx = 0; + move32(); + Ep_avrgL_fx = 0; + move32(); + Ep_peak_fx = 0; + move32(); + FOR(i = 0; i < bands; i++) + { + IF(sub(i,lowband) >= 0) + { + 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(L_sub(Ep_tmp_fx[i],Ep_peak_fx) > 0) + { + Ep_peak_fx = Ep_tmp_fx[i]; + move32();/*Q15 */ + } + } + } + + Mpy_32_16_ss(Ep_peak_fx,24576,&L_tmp,&lo); + Mpy_32_16_ss(Ep_peak_fx,19661,&L_tmp2,&lo); + Mpy_32_16_ss(Ep_avrgL_fx,24576,&L_tmp3,&lo); + + IF( (L_sub(L_shr(Ep_avrgL_fx,1), Ep_avrg_fx)>0 && L_sub(L_tmp,L_shr(Ep_avrgL_fx,2)) > 0 && L_sub(L_shr(Ep_avrgL_fx,1),L_tmp2) < 0 ) || + (L_sub(L_shr(Ep_avrg_fx,1), Ep_avrgL_fx)>0 && L_sub(L_shr(Ep_avrg_fx,3),L_tmp3) < 0 && L_sub(L_tmp,L_shr(Ep_avrgL_fx,2)) > 0 ) ) + { + 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(); + } + Mpy_32_16_ss(Ep_peak_fx,tmp,&L_tmp,&lo); + Mpy_32_16_ss(L_tmp,lowband,&L_tmp,&lo); + L_tmp = L_shl(L_tmp,sub(28,exp));/*Q14 0.5 */ + tmp = extract_l(L_min(L_tmp,19661));/* Q14 */ + Mpy_32_16_ss(L_band_energy_tmp[i],tmp,&L_tmp,&lo); + L_band_energy_tmp[i] = L_shl(L_tmp,1); /*Q_band_energy */ + } + } + for (i = 0; i < bands; i++) + { + band_energy_tmp[i] = (float)(L_band_energy_tmp[i]/pow(2.0f, SWB_BWE_LR_Qbe)); + } +#undef WMC_TOOL_SKIP + + hq2_bit_alloc( band_energy_tmp, bands, Rk_fx, &bit_budget, p2a_flags, bit_alloc_weight_fx, + band_width, num_bits, hqswb_clas, st->bwidth,*is_transient ); + } + else if( st->bwidth == SWB && hqswb_clas == HQ_HARMONIC && (bwe_br == HQ_16k40 || bwe_br == HQ_13k20) ) + { + hq2_bit_alloc_har( band_energy, bit_budget, bands, Rk_fx, p2a_bands,bwe_br,p2a_flags,band_width); + } + else + { + hq2_bit_alloc( band_energy, bands, Rk_fx, &bit_budget, p2a_flags, bit_alloc_weight_fx, + band_width, num_bits, hqswb_clas, st->bwidth, *is_transient ); + } + + if( bit_budget < 0 ) + { + st->BER_detect = 1; + bit_budget = 0; + } + + tcq_core_LR_dec( st, inp_vector, bit_budget, bands, band_start, band_width, Rk_fx, npulses, k_sort, + p2a_flags, p2a_bands, last_bitalloc_max_band, inner_frame, adjustFlag, is_transient ); + + /* Prepare floating Rk for next modules */ + for( k = 0; k < bands; k++) + { + Rk[k] = WORD322FL_SCALE( Rk_fx[k], SWB_BWE_LR_QRk - 1); + } + + /* Denormalize the coded MDCT spectrum */ + mdct_spectrum_denorm( inp_vector, y2, band_start, band_end, band_width, band_energy, npulses, bands, ld_slope, pd_thresh ); + + /* Apply fine gain to denormalized coded spectrum */ + mdct_spectrum_fine_gain_dec( st, y2, band_start, band_end, k_sort, bands, L_qint, Ngq, gqlevs, gqbits ); + + /*restore the band information */ + if( flag_spt == 1 ) + { + spt_shorten_domain_band_restore( bands, band_start, band_end, band_width, org_band_start, org_band_end, org_band_width ); + } + + mvr2r( y2, y2_org, L_FRAME32k ); + + /* Inject noise into components having relatively low pulse energy per band */ + ni_seed = npulses[0] + npulses[1] + npulses[2] + npulses[3]; + + for(i=0; ilast_ni_gain, st->last_env, &st->last_max_pos_pulse, p2a_flags, p2a_bands, hqswb_clas, st->bwidth, bwe_br ); + + if( st->bwidth == SWB && (bwe_br == HQ_16k40 || bwe_br == HQ_13k20) ) + { + if( hqswb_clas == HQ_NORMAL || hqswb_clas == HQ_HARMONIC ) + { + preset_hq2_swb( hqswb_clas, band_end, &har_bands, p2a_bands,length, bands, &lowlength, &highlength, m ); + + /*Gap filling for the core coder*/ + swb_bwe_dec_lr( st, y2, m, bwe_br , bands, band_start, band_end, band_energy, p2a_flags, hqswb_clas, lowlength, + highlength, har_bands, &st->prev_frm_hfe2, &st->prev_stab_hfe2, band_width,y2_ni, &ni_seed ); + + post_hq2_swb( m, lowlength, highlength, hqswb_clas, har_bands, bands, p2a_flags, band_start, band_end, y2, npulses ); + + if( hqswb_clas == HQ_NORMAL ) + { + spt_swb_peakpos_tmp_save( y2, bands, band_start, band_end, prev_SWB_peak_pos_tmp ); + for( k=0; klast_inner_frame >= L_FRAME16k && st->bws_cnt > 0) ) + { + k1 = *is_transient ? bands - 2 : bands - 6; + st->prev_ener_shb = 0.0f; + + for( i = k1; i < bands; i++ ) + { + st->prev_ener_shb += Ep_tmp[i]/(bands-k1); + } + } + + if( st->last_inner_frame >= L_FRAME32k ) + { + set_f(st->prev_SWB_fenv, st->prev_ener_shb, SWB_FENV); + } + + updat_prev_frm( y2, yout, bwe_br, length, inner_frame, bands, st->bwidth, *is_transient, hqswb_clas, &st->prev_hqswb_clas, + st->prev_SWB_peak_pos, prev_SWB_peak_pos_tmp, &st->prev_frm_hfe2, &st->prev_stab_hfe2, st->bws_cnt ); + + return; +} + + +/*------------------------------------------------------------------------------------ + * small_symbol_dec_tran() + * + * Huffman decoding of differential energies + *--------------------------------------------------------------------------------------*/ +static short small_symbol_dec_tran( + Decoder_State *st, /* i/o: decoder state structure */ + int *qbidx, /* o : output of dequantized differential energy */ + const short bands, /* i : number of bands */ + const short is_transient /* i : transient flag */ +) +{ + short i, bits; + short difidx[BANDS_MAX]; + + /* Decoding differential energies*/ + bits = decode_envelope_indices(st, 0, bands, 0, difidx, LOW_RATE_HQ_CORE_TRAN ,is_transient); + bits += BITS_DE_FCOMP; + + /* counting 1 bit for band_energy_huff_coding_mode */ + bits += BITS_DE_HMODE; + + /* converting to original values */ + for( i=0; i 0) + { + *rbits+=(*hufftab & 0xf); + bit = (short)get_next_indice( st, *hufftab & 0xf ); + hufftab += (*hufftab >> 4) + bit; + } + + return (-*hufftab); +} + +static short large_symbol_dec( /* o : bits */ + Decoder_State *st, /* i/o: decoder state structure */ + int *qbidx, /* o : output of dequantized differential energy */ + const short bands /* i : number of bands */ +) +{ + short i, bits; + short LSB[BANDS_MAX]; + short basic_shift,cntbits,ns2mode; + short pos_outlyer; + short ns2mode0,ns2mode1; + + cntbits = BITS_DE_8SMODE; + ns2mode = (short)get_next_indice (st, BITS_DE_8SMODE); + + if (ns2mode == 0 ) + { + ns2mode0 = (short)get_next_indice (st, BITS_DE_8SMODE_N0); + ns2mode1 = (short)get_next_indice (st, BITS_DE_8SMODE_N1); + cntbits += BITS_DE_8SMODE_N0+BITS_DE_8SMODE_N1; + + if (ns2mode0 == 0) + { + if (ns2mode1 == 1) + { + pos_outlyer = (short)get_next_indice (st, BITS_DE_8SPOS); + cntbits+=BITS_DE_8SPOS; + qbidx[pos_outlyer] = ((short)get_next_indice (st, BITS_ABS_ENG) - ABS_ENG_OFFSET); + cntbits+=BITS_ABS_ENG; + } + else + { + pos_outlyer = -1; + } + + for( i=0; i Qbe(Q14) */ + band_energy[k] = (float)(L_band_energy[k]/pow(2.0f, SWB_BWE_LR_Qbe)); +#undef WMC_TOOL_SKIP + } + + if( is_transient ) + { + reverse_transient_frame_energies( band_energy, bands ); + } + + return( deng_bits ); +} + + +/*--------------------------------------------------------------------------* + * p2a_threshold_dequant() + * + * + *--------------------------------------------------------------------------*/ + +static short p2a_threshold_dequant( + Decoder_State *st, /* i/o: decoder state structure */ + short *p2a_flags, + const short bands, + const short p2a_bands +) +{ + short j, k; + + for( k = 0; k < bands - p2a_bands; k++ ) + { + p2a_flags[k] = 1; + } + + j = 0; + for( k = bands - p2a_bands; k < bands; k++ ) + { + p2a_flags[k] = (short) get_next_indice( st, 1 ); + j++; + } + + return( j ); +} + + +/*--------------------------------------------------------------------------* + * mdct_spectrum_fine_gain_dec() + * + * + *--------------------------------------------------------------------------*/ + +static void mdct_spectrum_fine_gain_dec( + Decoder_State *st, /* i/o: decoder state structure */ + float y2[], + const short band_start[], + const short band_end[], + const short k_sort[], + const short bands, + const Word32 L_qint, + const short Ngq, + const short gqlevs, + const short gqbits +) +{ + short i, k, imin; + float gamma; + float gain_table[MAX_GQLEVS]; + Word16 exp_normn, exp_normd; + Word16 delta_fx, Qdelta; + Word32 L_delta, L_q; + Word32 L_temp; + Word16 gain_table_fx[MAX_GQLEVS]; + Word16 Qgt; + Word16 temp_lo_fx, temp_hi_fx; + + /* Fine gain quantization on only the most significant energy bands */ +#define WMC_TOOL_SKIP + /*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 */ + gain_table[i] = (float)(gain_table_fx[i]/pow(2.0f, 14)); + } +#undef WMC_TOOL_SKIP + + for( k = bands - Ngq; k < bands; k++ ) + { + imin = (short)get_next_indice( st, gqbits ); + gamma = gain_table[imin]; + + for( i = band_start[k_sort[k]]; i <= band_end[k_sort[k]]; i++ ) + { + y2[i] *= gamma; + } + } + + return; +} + +/*--------------------------------------------------------------------------* + * spt_shorten_domain_set_dec() + * + * update the shorten band information based on p2a analysis + *--------------------------------------------------------------------------*/ + +static void spt_shorten_domain_set_dec( + Decoder_State *st, /* i: encoder state structure */ + const short p2a_flags[], /* i: p2a anlysis information */ + const short new_band_start[], /* i: new band start position */ + const short new_band_end[], /* i: new band end position */ + const short new_band_width[], /* i: new subband band width */ + const short bands, /* i: total number of subbands */ + short band_start[], /* o: band start position */ + short band_end[], /* o: band end position */ + short band_width[], /* o: sub band band width */ + short *bit_budget /* i/o: bit budget */ +) +{ + int j,k; + short kpos; + short spt_shorten_flag[SPT_SHORTEN_SBNUM]; + + kpos = 0; + j = 0; + for( k = bands - SPT_SHORTEN_SBNUM; k < bands; k++ ) + { + spt_shorten_flag[j] = 0; + if(p2a_flags[k] == 1) + { + spt_shorten_flag[j] = (short)get_next_indice (st, 1 ); + *bit_budget -= 1; + if(spt_shorten_flag[j] == 1) + { + band_start[k] = new_band_start[j]; + band_end[k] = new_band_end[j]; + band_width[k] = new_band_width[j]; + } + } + + kpos++; + j++; + } + + return; +} diff --git a/lib_dec/igf_dec.c b/lib_dec/igf_dec.c new file mode 100644 index 000000000..73eddfb13 --- /dev/null +++ b/lib_dec/igf_dec.c @@ -0,0 +1,945 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include +#include +#include "options.h" +#include "prot.h" +#include "cnst.h" +#include "stat_dec.h" + +/**********************************************************************/ /* +measures TCX noise +**************************************************************************/ +static int IGF_replaceTCXNoise_1( /**< out: | number of noise bands */ + const float *in, /**< in: | MDCT spectrum */ + const unsigned char *TCXNoise, /**< in: | tcx noise indicator vector */ + const int start, /**< in: | start MDCT subband index */ + const int stop, /**< in: | stop MDCT subband index */ + float *totalNoiseNrg /**< out: | measured noise energy */ +) +{ + int sb; + int noise; + float nE; + float val; + + noise = 0; + nE = FLT_MIN; + + for (sb = start; sb < stop; sb++) + { + if (TCXNoise[sb]) + { + val = in[sb]; + nE += val * val; + noise++; + } + } + + *totalNoiseNrg = nE; + + return noise; +} + +/**********************************************************************/ /* +replaces TCX noise +**************************************************************************/ +static void IGF_replaceTCXNoise_2(float *in, /**< in/out: | MDCT spectrum */ + const unsigned char *TCXNoise, /**< in: | tcx noise indicator vector */ + const int start, /**< in: | start MDCT subband index */ + const int stop, /**< in: | stop MDCT subband index */ + float totalNoiseNrg, /**< in: | measured noise energy */ + short *nfSeed /**< in: | random generator noise seed */ + ) +{ + int sb; + float rE; + float g; + float val; + + rE = FLT_MIN; + for (sb = start; sb < stop; sb ++) + { + if (TCXNoise[sb]) + { + val = (float)own_random(nfSeed); + in[sb] = val; + rE += val * val; + } + } + + g = (float)sqrt(totalNoiseNrg/rE); + + for (sb = start; sb < stop; sb ++) + { + if (TCXNoise[sb]) + { + in[sb] *= g; + } + } +} + +/**********************************************************************/ /* +reads whitening levels +**************************************************************************/ +static void IGF_decode_whitening_level(Decoder_State *st, /**< in: | decoder state */ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData, /**< in: | instance handle of IGF Deccoder */ + const int p /**< in: | tile index, p = [0, 3] */ + ) +{ + int tmp; + + tmp = get_next_indice(st, 1); + + if (tmp == 1) + { + tmp = get_next_indice(st, 1); + if (tmp == 1) + { + hPrivateData->currWhiteningLevel[p] = IGF_WHITENING_STRONG; + } + else + { + hPrivateData->currWhiteningLevel[p] = IGF_WHITENING_OFF; + } + } + else + { + hPrivateData->currWhiteningLevel[p] = IGF_WHITENING_MID; + } +} + +/**********************************************************************/ /* +reads flattening trigger +**************************************************************************/ +static void IGF_decode_temp_flattening_trigger(Decoder_State *st, /**< in: | decoder state */ + IGF_DEC_INSTANCE_HANDLE hInstance /**< in: | instance handle of IGF Deccoder */ + ) +{ + hInstance->flatteningTrigger = get_next_indice(st, 1); +} + +/**********************************************************************/ /* +square the MDCT spectrum +**************************************************************************/ +static void IGF_getMDCTSquare(const int startLine, /**< in: | start MDCT subband index */ + const int stopLine, /**< in: | stop MDCT subband index */ + const float *pSpectralData, /**< in: | MDCT spectrum */ + float *pSpecDataSqaure /**< out: | Squared MDCT spectrum */ + ) +{ + int i; + + for (i = startLine; i < stopLine; i++) + { + pSpecDataSqaure[i] = pSpectralData[i] * pSpectralData[i]; + } +} + +/**********************************************************************/ /* +calculate energy per SFB +**************************************************************************/ +static void IGF_calcSfbEnergy(const int startSfb, /**< in: | start sfb index */ + const int stopSfb, /**< in: | stop sfb index */ + const int *swb_offset, /**< in: | IGF swb offset table */ + const float *pPowerSpectrum, /**< in: | power spectrum */ + float *sfbEnergy /**< out: | SFB energies, will be initialized inside this function */ + ) +{ + int sfb; + int line; + + for (sfb = startSfb; sfb < stopSfb; sfb++) + { + sfbEnergy[sfb] = 0.f; + + for (line = swb_offset[sfb]; line < swb_offset[sfb + 1]; line++) + { + sfbEnergy[sfb] += pPowerSpectrum[line]; + } + } +} + +/**********************************************************************/ /* +set power spectrum values to zero, needed for energy calculation +**************************************************************************/ +static void IGF_setLinesToZero(const int startLine, /**< in: | start MDCT subband index */ + const int stopLine, /**< in: | stop MDCT subband index */ + const float *pSpectralData, /**< in: | original MDCT spectrum */ + float *squareSpecIGF /**< in/out: | prepared IGF energy spectrum */ + ) +{ + int i; + + for (i = startLine; i < stopLine; i++) + { + if (pSpectralData[i] != 0.f) + { + squareSpecIGF[i] = 0.f; + } + } +} + +/**********************************************************************/ /* +prepare IGF spectrum +**************************************************************************/ +static void IGF_prep(IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData, /**< in: | IGF private data handle */ + const int igfGridIdx, /**< in: | in case of CELP->TCX switching, use 1.25 framelength */ + const unsigned char *TCXNoise, /**< in: | TCX noise vector */ + float *igf_spec, /**< in: | prepared IGF spectrum */ + float *src_spec /**< in: | source spectrum */ + ) +{ + H_IGF_GRID hGrid; + H_IGF_INFO hInfo; + int i; + int tb; + int sfb; + int strt_cpy; + int tile_idx; + int *swb_offset; + float *sel_spec; + + hInfo = &hPrivateData->igfInfo; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + swb_offset = hGrid->swb_offset; + + for (tile_idx = 0; tile_idx < hGrid->nTiles; tile_idx ++) + { + strt_cpy = hGrid->sbWrap[tile_idx]; + + if (IGF_WHITENING_STRONG == hPrivateData->currWhiteningLevel[tile_idx]) + { + float abs_sum; + abs_sum = 0.f; + for(i = strt_cpy; i < hGrid->startLine; i++) + { + abs_sum += (float) fabs(src_spec[i]); + } + + tb = swb_offset[hGrid->sfbWrap[tile_idx]]; + + if( abs_sum > 0.f ) + { + for (i = strt_cpy; i < hGrid->startLine; i++) + { + igf_spec[tb++] = own_random(&hInfo->nfSeed); + } + } + else + { + for (i = strt_cpy; i < hGrid->startLine; i++) + { + igf_spec[tb++] = 0.f; + } + } + } + else + { + if (IGF_WHITENING_MID == hPrivateData->currWhiteningLevel[tile_idx]) + { + if (hPrivateData->n_noise_bands) + { + IGF_replaceTCXNoise_2(igf_spec, + TCXNoise, + hGrid->minSrcSubband, + hGrid->startLine, + hPrivateData->totalNoiseNrg, + &hInfo->nfSeed); + } + sel_spec = igf_spec; + } + else + { + if (hPrivateData->n_noise_bands_off) + { + IGF_replaceTCXNoise_2(src_spec, + TCXNoise, + hGrid->minSrcSubband, + hGrid->startLine, + hPrivateData->totalNoiseNrg_off, + &hInfo->nfSeed); + } + sel_spec = src_spec; + } + for (sfb = hGrid->sfbWrap[tile_idx]; sfb < hGrid->sfbWrap[tile_idx + 1]; sfb++) + { + for (tb = swb_offset[sfb]; tb < swb_offset[sfb + 1]; tb++) + { + igf_spec[tb] = sel_spec[strt_cpy]; + strt_cpy++; + } + } + } + } +} + +/**********************************************************************/ /* +calculates IGF energies +**************************************************************************/ +static void IGF_calc(const IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData, /**< in: | IGF private data handle */ + const int igfGridIdx, /**< in: | in case of CELP->TCX switching, use 1.25 framelength */ + const float *spectrum, /**< in: | MDCT spectrum */ + float *igf_spec /**< in: | prepared IGF spectrum */ + ) +{ + H_IGF_GRID hGrid; + float *igf_pN; + float *igf_sN; + float tmp[N_MAX_TCX] = {0.f}; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + igf_pN = hPrivateData->igf_pN; + igf_sN = hPrivateData->igf_sN; + + IGF_getMDCTSquare(hGrid->startLine, hGrid->stopLine, spectrum, tmp); + IGF_calcSfbEnergy(hGrid->startSfb, hGrid->stopSfb, hGrid->swb_offset, tmp, igf_sN); + IGF_getMDCTSquare(hGrid->startLine, hGrid->stopLine, igf_spec, tmp); + IGF_setLinesToZero(hGrid->startLine, hGrid->stopLine, spectrum, tmp); + IGF_calcSfbEnergy(hGrid->startSfb, hGrid->stopSfb, hGrid->swb_offset, tmp, igf_pN); +} + +/**********************************************************************/ /* +apply IGF +**************************************************************************/ +static void IGF_appl(IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData, /**< in: | IGF private data handle */ + const int igfGridIdx, /**< in: | in case of CELP->TCX switching, use 1.25 framelength */ + float *pSpectralData, /**< in: Q31 | MDCT spectrum */ + const float *igf_spec, /**< in: Q31 | prepared IGF spectrum */ + float *virtualSpec, /**< out:Q31 | virtual IGF spectrum, used for temp flattening */ + int *flag_sparse /**< out: Q0 | temp flattening indicator */ + ) +{ + H_IGF_GRID hGrid; + int tb; /* target subband */ + int sfb; + int s_sfb; + int start_sfb; + int stop_sfb; + int *swb_offset; + int hopsize; + float tmp; + float dE; + float dN[IGF_MAX_SFB+1]; + float gain[IGF_MAX_SFB]; + float dS[IGF_MAX_SFB]; + float width; + float sNlocal; + float E; + float sum; + float val; + float w0; + float w1; + float w2; + float *sN; + float *pN; + float gFactor; /* general SCF adaption */ + float fFactor; /* first SCF adaption */ + float lFactor; /* last SCF adaption */ + + /* initialize variables */ + w0 = 0.201f; + w1 = 0.389f; + w2 = 0.410f; + dE = 0.f; + + set_i(flag_sparse, 0.f, N_MAX_TCX-IGF_START_MN); + set_f(virtualSpec, 0.f, N_MAX_TCX-IGF_START_MN); + + + /* more inits */ + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + sN = hPrivateData->igf_sN; + pN = hPrivateData->igf_pN; + start_sfb = hGrid->startSfb; + stop_sfb = hGrid->stopSfb; + gFactor = hGrid->gFactor; + fFactor = hGrid->fFactor; + lFactor = hGrid->lFactor; + swb_offset = hGrid->swb_offset; + + /* collect energy below hGrid->startLine: */ + for (tb = hGrid->startLine-24; tb < hGrid->startLine; tb++) + { + dE += pSpectralData[tb] * pSpectralData[tb]; + } + dE = (float)sqrt(dE/24.); + + hopsize = 2; + hopsize = (hPrivateData->currWhiteningLevel[0] == IGF_WHITENING_OFF) ? 4 : hopsize; + hopsize = (hPrivateData->currWhiteningLevel[0] == IGF_WHITENING_MID) ? 2 : hopsize; + hopsize = (hPrivateData->currWhiteningLevel[0] == IGF_WHITENING_STRONG) ? 1 : hopsize; + hopsize = min(hopsize, hPrivateData->igfInfo.maxHopsize); + + if(hopsize > 1) + { + for (sfb = start_sfb; sfb < stop_sfb; sfb += hopsize) + { + for (tb = sfb+1; tb < min((sfb+hopsize),stop_sfb); tb++) + { + sN[sfb] += sN[tb]; + pN[sfb] += pN[tb]; + sN[tb] = 0.f; + pN[tb] = 0.f; + } + } + } + + /* IGF_rescale_SCF */ + if (hGrid->infoIsRefined) + { + for (sfb = start_sfb; sfb < stop_sfb; sfb+=2) + { + width = (float)(swb_offset[sfb + 2] - swb_offset[sfb]); + + tmp = (float)hPrivateData->igf_curr[sfb >> 1]; + tmp = (float)pow(2.0, 0.25 * tmp - 4.0); + tmp = tmp * tmp; + + sNlocal = sN[sfb] + sN[sfb + 1]; + sNlocal /= width; + + tmp = max(0.001 * sNlocal, tmp - sNlocal); + dN[sfb] = (float)sqrt(tmp); + dN[sfb+1] = dN[sfb]; + } + } + else + { + for (sfb = start_sfb; sfb < stop_sfb; sfb++) + { + width = (float)(swb_offset[sfb + 1] - swb_offset[sfb]); + + tmp = (float)hPrivateData->igf_curr[sfb]; + tmp = (float)pow(2.0, 0.25 * tmp - 4.0); + tmp = tmp * tmp; + + sNlocal = sN[sfb]; + sNlocal /= width; + + tmp = max(0.001 * sNlocal, tmp - sNlocal); + dN[sfb] = (float)sqrt(tmp); + } + } + + dS[start_sfb] = dN[start_sfb]; + /* first value with adaption to core energy: */ + if (dE < dN[start_sfb]) + { + dS[start_sfb] = dN[start_sfb] + fFactor * (dE - dN[start_sfb]); + } + /* last value with less energy: */ + dS[stop_sfb - 1] = lFactor * dN[stop_sfb - 1]; + + if (hGrid->infoIsRefined && hopsize == 1) + { + /* apply filter to absolute energy values: */ + for (sfb = start_sfb+1; sfb < stop_sfb-1; sfb++) + { + dS[sfb] = w0 * dN[sfb - 1] + w1 * dN[sfb] + w2 * dN[sfb + 1]; + } + } + else + { + for (sfb = start_sfb + 1; sfb < stop_sfb - 1; sfb++) + { + dS[sfb] = dN[sfb]; + } + } + + for (sfb = start_sfb; sfb < stop_sfb; sfb+=hopsize) + { + E = 0.f; + sum = 0; + for (tb = 0; tb < hopsize; tb++) + { + width = (float)(swb_offset[min(sfb + tb + 1, stop_sfb)] - swb_offset[min(sfb + tb, stop_sfb)]); + val = dS[min(sfb + tb,stop_sfb - 1)]; + E += val * val * width; + sum += width; + } + + dS[sfb] = (float)sqrt((E * hopsize) / sum); + dN[sfb] = gFactor * dS[sfb]; + + width = (float)(swb_offset[sfb + 1] - swb_offset[sfb]); + dN[sfb] = dN[sfb] * dN[sfb] * width; + gain[sfb] = 0.f; + + if (pN[sfb] > 1.e-20f) + { + gain[sfb] = (float)sqrt(dN[sfb] / pN[sfb]); + } + + for (s_sfb = sfb + 1; s_sfb < min(sfb + hopsize, stop_sfb); s_sfb++) + { + gain[s_sfb] = gain[sfb]; + } + } + + /* tiling */ + for(sfb = start_sfb; sfb < stop_sfb; sfb++) + { + + if (hPrivateData->frameLossCounter > 0) + { + gain[sfb] = min(gain[sfb], 12.f); + + if (hPrivateData->frameLossCounter < 5) + { + gain[sfb] -= gain[sfb] / 8 * hPrivateData->frameLossCounter; + } + else + { + gain[sfb] /= 2; + } + } + + for (tb = swb_offset[ sfb ]; tb < swb_offset[ sfb+1 ]; tb++) + { + if(pSpectralData[tb] == 0.f) + { + pSpectralData[tb] = igf_spec[tb] * gain[sfb]; + flag_sparse[tb-IGF_START_MN] = 1; + } + else + { + virtualSpec[tb-IGF_START_MN] = igf_spec[tb] * gain[sfb]; + flag_sparse[tb-IGF_START_MN] = 2; + + } + } + } +} + +/**********************************************************************/ /* +spectral whitening +**************************************************************************/ +static void IGF_getWhiteSpectralData(const float *in, /**< in: | MDCT spectrum */ + float *out, /**< out: | whitened spectrum */ + const int start, /**< in: | start MDCT subband index */ + const int stop, /**< in: | stop MDCT subband index */ + const int level /**< in: | whitening strength */ + ) +{ + int i; + int n; + int j; + float div; + float ak; + + /* inits */ + div = 0; + + for (i = start; i < stop - level; i++) + { + ak = 1e-3f; + for (j = i - level; j < i + level + 1; j++) + { + ak += in[j] * in[j]; + } + ak /= (float)(level * 2 + 1); + + + n = max(0.f, (int)(log(ak) * INV_LOG_2)); /* INV_LOG_2 = 1 / (float)log(2.0f)) */ + n >>= 1; /* sqrt() */ + div = (float)(pow(2.0f, (float)(21 - n))); + + + out[i] = in[i] * div; /* same as shift */ + } + + for (; i < stop; i++) + { + ak = 1e-3f; + + for (j = i - level; j < stop; j++) + { + ak += in[j]*in[j]; + } + ak /= (float)(stop - (i - level)); + + + n = max(0.f,(int)(log(ak) * INV_LOG_2)); /* INV_LOG_2 = 1 / (float)log(2.0f)) */ + n >>= 1; /* sqrt() */ + div = (float)(pow(2.0f, (float)(21 - n))); + + + out[i] = in[i] * div; /* same as shift */ + } +} + +/**********************************************************************/ /* +refines the IGF grid +**************************************************************************/ +static void IGF_RefineGrid(H_IGF_GRID hGrid /**< in/out: | IGF grid handle */ + ) +{ + int a[IGF_MAX_SFB+1]; /* +1: because in for-loop one value too much will be extrapolated */ + int sfb; + + set_i(a, 0, IGF_MAX_SFB+1); + + + hGrid->infoIsRefined = 1; + for (sfb = 0; sfb < hGrid->swb_offset_len; sfb++) + { + a[sfb*2 + 0] = hGrid->swb_offset[sfb]; + a[sfb*2 + 1] = round_f(hGrid->swb_offset[sfb] + 0.45f * (hGrid->swb_offset[sfb + 1] - hGrid->swb_offset[sfb])); + if (a[sfb*2 + 1] & 1) + { + a[sfb*2 + 1]--; + } + } + hGrid->stopSfb = hGrid->stopSfb * 2; + for (sfb = 0; sfb <= hGrid->stopSfb; sfb++) + { + hGrid->swb_offset[sfb] = a[sfb]; + } + + for (sfb = 0; sfb <= hGrid->nTiles; sfb++) + { + hGrid->sfbWrap[sfb] *= 2; + } +} + +/**********************************************************************/ /* +reads whitening information from the bitstream +**************************************************************************/ +void IGFDecReadData(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Deccoder */ + Decoder_State *st, /**< in: | decoder state */ + const int igfGridIdx, /**< in: | in case of CELP->TCX switching, use 1.25 framelength */ + const int isIndepFrame /**< in: | if 1: arith dec force reset, if 0: no reset */ + ) +{ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + int p; + int nT; + int tmp; + + if (hInstance != NULL) + { + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + nT = hGrid->nTiles; + tmp = -1; + + for (p = 0; p < IGF_MAX_TILES; p++) + { + hPrivateData->currWhiteningLevel[p] = IGF_WHITENING_OFF; + } + + if (isIndepFrame) + { + tmp = 0; + } + else + { + tmp = get_next_indice(st, 1); + } + if (tmp == 1) + { + for (p = 0; p < nT; p++) + { + hPrivateData->currWhiteningLevel[p] = hPrivateData->prevWhiteningLevel[p]; + } + } + else + { + IGF_decode_whitening_level(st, hPrivateData, 0); + tmp = (int)get_next_indice(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]; + } + } + } + for (p = 0; p < IGF_MAX_TILES; p++) + { + hPrivateData->prevWhiteningLevel[p] = hPrivateData->currWhiteningLevel[p]; + } + IGF_decode_temp_flattening_trigger(st, hInstance); + } +} + +/**********************************************************************/ /* +read the IGF level information from the bitsream +**************************************************************************/ +int IGFDecReadLevel( /**< out: | return igfAllZero flag indicating if no envelope is transmitted */ + const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Deccoder */ + Decoder_State *st, /**< in: | decoder state */ + const int igfGridIdx, /**< in: | in case of CELP->TCX switching, use 1.25 framelength */ + const int isIndepFrame /**< in: | if 1: arith dec force reset, if 0: no reset */ +) +{ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + int m_igfSfbStart; + int IGFAllZero; + + IGFAllZero = 1; + + if (hInstance != NULL) + { + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + m_igfSfbStart = hGrid->startSfb; + IGFAllZero = get_next_indice(st, 1); + + if (IGFAllZero == 0) + { + mvi2i(hPrivateData->igf_curr, hPrivateData->igf_prev, hGrid->stopSfb); + IGFSCFDecoderDecode(&hPrivateData->hArithSCFdec, + st, + &hPrivateData->igf_curr[m_igfSfbStart], /**< out: ptr to an array which will contain the decoded quantized coefficients */ + isIndepFrame); /**< in: if 1 on input reset will be forced, if 0 on input continue without reset */ + } + else + { + IGFSCFDecoderReset(&hPrivateData->hArithSCFdec); + set_i(&hPrivateData->igf_curr[m_igfSfbStart], 0, hGrid->stopSfb - m_igfSfbStart); + } + } + + hInstance->infoIGFAllZero = IGFAllZero; + return IGFAllZero; +} + +/**********************************************************************/ /* +apply the IGF decoder +**************************************************************************/ +void IGFDecApplyMono(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + float *spectrum, /**< in/out: | MDCT spectrum */ + const int igfGridIdx, /**< in: | in case of CELP->TCX switching, use 1.25 framelength */ + int bfi /**< in: | frame loss == 1, frame good == 0 */ + ) +{ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + int i; + int whiteningLevel; + float igf_spec[IGF_MAX_GRANULE_LEN] = {0.f}; + + /* initialize variables */ + whiteningLevel = 7; + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + hPrivateData->totalNoiseNrg = 0.f; + hPrivateData->n_noise_bands = 0; + hPrivateData->totalNoiseNrg_off = 0.f; + hPrivateData->n_noise_bands_off = 0; + + /* concealment counter */ + if (bfi) + { + hPrivateData->frameLossCounter++; + } + else + { + hPrivateData->frameLossCounter = 0; + } + + /* skip IGF processing if all IGF levels are zero */ + if (!hInstance->infoIGFAllZero) + { + + for (i = 0; i < hGrid->nTiles; i++) + { + if (hPrivateData->currWhiteningLevel[i] == IGF_WHITENING_MID) + { + IGF_getWhiteSpectralData(hPrivateData->pSpecFlat, + igf_spec, + hGrid->minSrcSubband, + hGrid->startLine, + whiteningLevel); + + hPrivateData->n_noise_bands = IGF_replaceTCXNoise_1(igf_spec, + hInstance->infoTCXNoise, + hGrid->minSrcSubband, + hGrid->startLine, + &hPrivateData->totalNoiseNrg); + break; + } + } + + for (i = 0; i < hGrid->nTiles; i++) + { + if (hPrivateData->currWhiteningLevel[i] == IGF_WHITENING_OFF) + { + hPrivateData->n_noise_bands_off = IGF_replaceTCXNoise_1(hPrivateData->pSpecFlat, + hInstance->infoTCXNoise, + hGrid->minSrcSubband, + hGrid->startLine, + &hPrivateData->totalNoiseNrg_off); + break; + } + } + + /* apply IGF in three steps: */ + IGF_prep(hPrivateData, igfGridIdx, hInstance->infoTCXNoise, igf_spec, hPrivateData->pSpecFlat); + IGF_calc(hPrivateData, igfGridIdx, spectrum, igf_spec); + IGF_appl(hPrivateData, igfGridIdx, spectrum, igf_spec, hInstance->virtualSpec, hInstance->flag_sparse); + + } + + /* reset TCX noise indicator vector */ + set_c((char*)(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 int bitRate, /**< in: | bitrate */ + const int mode, /**< in: | bandwidth mode */ + const int defaultStartLine, /**< in: | default start subband index */ + const int defaultStopLine /**< in: | default stop subband index */ + , const int rf_mode /**< in: | flag to signal the RF mode */ + ) +{ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData; + + hPrivateData = &hInstance->igfData; + hInstance->isIGFActive = 0; + + if (IGFCommonFuncsIGFConfiguration(bitRate, mode, &hPrivateData->igfInfo + , rf_mode + )) + { + IGFSCFDecoderOpen(&hPrivateData->hArithSCFdec, + hPrivateData->igfInfo.grid[0].stopSfb - hPrivateData->igfInfo.grid[0].startSfb, + bitRate, + mode + , rf_mode + ); + + hInstance->infoIGFStopLine = hPrivateData->igfInfo.grid[0].stopLine; + hInstance->infoIGFStartLine = hPrivateData->igfInfo.grid[0].startLine; + hInstance->infoIGFStopFreq = hPrivateData->igfInfo.grid[0].stopFrequency; + hInstance->infoIGFStartFreq = hPrivateData->igfInfo.grid[0].startFrequency; + hInstance->infoIGFAllZero = 0; + hInstance->isIGFActive = 1; + + if (hPrivateData->igfInfo.bitRateIndex <= IGF_BITRATE_SWB_48000 || 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]); + } + /* IGFDecOutInformation(hInstance); */ + } + else + { + hInstance->infoIGFStopLine = defaultStopLine; + hInstance->infoIGFStartLine = defaultStartLine; + hInstance->infoIGFStopFreq = -1; + hInstance->infoIGFStartFreq = -1; + 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 int igfGridIdx /**< in: | IGF grid index */ + ) +{ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + + hPrivateData = &hInstance->igfData; + if (hInstance->isIGFActive) + { + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + hInstance->infoIGFStartFreq = hGrid->startFrequency; + hInstance->infoIGFStopFreq = hGrid->stopFrequency; + hInstance->infoIGFStartLine = hGrid->startLine; + hInstance->infoIGFStopLine = hGrid->stopLine; + } +} + +/**********************************************************************/ /* +copy the LPC flat spectrum to IGF buffer +**************************************************************************/ +void IGFDecCopyLPCFlatSpectrum(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + const float *pSpectrumFlat, /**< in: | LPC flattend spectrum from TCX dec */ + const int igfGridIdx /**< in: | IGF grid index */ + ) +{ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + int i; + + if (hInstance) + { + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + + + for (i = hGrid->minSrcSubband - 7; i < hGrid->startLine; i++) + { + hPrivateData->pSpecFlat[i] = pSpectrumFlat[i] * 1024.f; + } + } +} + +/**********************************************************************/ /* +store the IGF bitstream information for TCX10 subframes +**************************************************************************/ +void IGFDecStoreTCX10SubFrameData(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + const int subFrameIdx /**< in: | index of subframe */ + ) +{ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData; + + hPrivateData = &hInstance->igfData; + + /* store igf energies for subframe*/ + mvi2i(hPrivateData->igf_curr, hPrivateData->igf_curr_subframe[subFrameIdx][0], IGF_MAX_SFB); + mvi2i(hPrivateData->igf_prev, hPrivateData->igf_prev_subframe[subFrameIdx], IGF_MAX_SFB); + + /* store spectral whitening information for current subframe */ + mvi2i(hPrivateData->currWhiteningLevel, hPrivateData->currWhiteningLevel_subframe[subFrameIdx], IGF_MAX_TILES); + mvi2i(hPrivateData->prevWhiteningLevel, hPrivateData->prevWhiteningLevel_subframe[subFrameIdx], IGF_MAX_TILES); + /* store flattening trigger for current subframe */ + hPrivateData->igf_flatteningTrigger_subframe[subFrameIdx] = hInstance->flatteningTrigger; +} + +/**********************************************************************/ /* +restore the IGF bitstream information for TCX10 subframes +**************************************************************************/ +void IGFDecRestoreTCX10SubFrameData(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + const int subFrameIdx /**< in: | index of subframe */ + ) +{ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData; + + hPrivateData = &hInstance->igfData; + + /* store igf energies for subframe*/ + mvi2i(hPrivateData->igf_curr_subframe[subFrameIdx][0], hPrivateData->igf_curr, IGF_MAX_SFB); + mvi2i(hPrivateData->igf_prev_subframe[subFrameIdx], hPrivateData->igf_prev, IGF_MAX_SFB); + + /* store spectral whitening information for current subframe */ + mvi2i(hPrivateData->currWhiteningLevel_subframe[subFrameIdx], hPrivateData->currWhiteningLevel, IGF_MAX_TILES); + mvi2i(hPrivateData->prevWhiteningLevel_subframe[subFrameIdx], hPrivateData->prevWhiteningLevel, IGF_MAX_TILES); + /* restore flattening trigger for current subframe */ + hInstance->flatteningTrigger = hPrivateData->igf_flatteningTrigger_subframe[subFrameIdx]; +} diff --git a/lib_dec/igf_scf_dec.c b/lib_dec/igf_scf_dec.c new file mode 100644 index 000000000..9d977dffe --- /dev/null +++ b/lib_dec/igf_scf_dec.c @@ -0,0 +1,327 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include +#include "prot.h" +#include "options.h" +#include "stat_dec.h" + + +/*---------------------------------------------------------------------* + * IGFSCFDecoderOpen() + * + * initialization of an instance of this module, pass a ptr to a hPublicData + *---------------------------------------------------------------------*/ + +void IGFSCFDecoderOpen( + IGFSCFDEC_INSTANCE_HANDLE hPublicData, /**< inout: handle to public data */ + int scfCountLongBlock, + int bitRate, + int mode, + int rf_mode /**< in: flag to signal the RF mode */ +) +{ + + hPublicData->scfCountLongBlock = scfCountLongBlock; + hPublicData->t = 0; /* 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 ); + + return; +} + +/*---------------------------------------------------------------------* + * quant_ctx() + * + * + *---------------------------------------------------------------------*/ + +static int quant_ctx(int ctx + ) +{ + /* + 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 ... + */ + if (abs(ctx) <= 3) + { + return ctx; + } + else if (ctx > 3) + { + return 3; + } + else + { + /* ctx < -3 */ + return -3; + } + +} + +/*---------------------------------------------------------------------* + * arith_decode_bits() + * + * + *---------------------------------------------------------------------*/ + +static int arith_decode_bits( + IGFSCFDEC_INSTANCE_HANDLE hPrivateData, /**< instance handle */ + Decoder_State *st, /**< in: pointer to decoder state */ + int nBits /**< number of bits to decode */ +) +{ + int i; + int x; + int bit; + + x = 0; + for (i = 0; i < nBits; ++i) + { + /* decode one bit using the new raw AC function */ + ari_decode_14bits_bit_ext(st, &bit, &hPrivateData->acState); + x = (x << 1) | bit; + } + + return x; +} + + +/*---------------------------------------------------------------------* + * arith_decode_residual() + * + * + *---------------------------------------------------------------------*/ + +static int arith_decode_residual( + IGFSCFDEC_INSTANCE_HANDLE hPrivateData, /**< instance handle */ + Decoder_State *st, /**< in: pointer to decoder state */ + const unsigned short* cumulativeFrequencyTable, /**< cumulative frequency table to be used */ + int tableOffset /**< offset used to align the table */ +) +{ + int val; + int x; + int extra; + int extra_tmp; + + /* decode one of the IGF_SYMBOLS_IN_TABLE == 27 alphabet symbols using the new raw AC function */ + ari_decode_14bits_s27_ext(st, &val, &hPrivateData->acState, cumulativeFrequencyTable); + + /* meaning of the values of val: */ + /* esc_{0} IGF_MIN_ENC_SEPARATE ... IGF_MAX_ENC_SEPARATE esc_{IGF_SYMBOLS_IN_TABLE - 1} */ + if ((val != 0) && (val != IGF_SYMBOLS_IN_TABLE - 1)) + { + x = (val - 1) + IGF_MIN_ENC_SEPARATE; + + + x -= tableOffset; + return x; + } + + /* decode one of the tails of the distribution */ + /* decode extra with 4 bits */ + extra = arith_decode_bits(hPrivateData, st, 4); + if (extra == 15) + { + /* escape code 15 to indicate extra >= 15 */ + /* decode addtional extra with 6 bits */ + extra_tmp = arith_decode_bits(hPrivateData, st, 6); + if (extra_tmp == 63) + { + /* escape code 63 to indicate extra_tmp >= 63 */ + /* decode safety extra with 7 bits */ + extra_tmp = 63 + arith_decode_bits(hPrivateData, st, 7); + } + extra = 15 + extra_tmp; + } + + if (val == 0) + { + /* escape code 0 to indicate x <= IGF_MIN_ENC_SEPARATE - 1 */ + x = (IGF_MIN_ENC_SEPARATE - 1) - extra; + } + else + { + /* escape code (IGF_SYMBOLS_IN_TABLE - 1) to indicate x >= IGF_MAX_ENC_SEPARATE + 1 */ + x = (IGF_MAX_ENC_SEPARATE + 1) + extra; + } + + x -= tableOffset; + + return x; +} + + +/*---------------------------------------------------------------------* + * arith_decode_flush() + * + * + *---------------------------------------------------------------------*/ + +static void arith_decode_flush( + Decoder_State *st /**< in: pointer to decoder state */ +) +{ + get_next_indice_tmp(st, -14); /* return back the least significant 14 bits to the bitstream */ + + return; +} + + +/*---------------------------------------------------------------------* + * decode_sfe_vector() + * + * + *---------------------------------------------------------------------*/ + +static void decode_sfe_vector( + IGFSCFDEC_INSTANCE_HANDLE hPrivateData, /**< instance handle */ + Decoder_State *st, /**< in: pointer to decoder state */ + int t, /**< frame counter reset to 0 at each independent frame */ + int *prev_x, /**< previous vector */ + int *x, /**< current vector to decode */ + int length /**< number of elements to decode */ +) +{ + /* + f + ^ + | d a x + | c b + | e --> t + */ + int f; + int pred; + int ctx; + int ctx_f; + int ctx_t; + + + for (f = 0; f < length; f++) + { + if (t == 0) + { + if (f == 0) + { + /* decode one of the IGF_SYMBOLS_IN_TABLE == 27 alphabet symbols using the new raw AC function */ + ari_decode_14bits_s27_ext(st, &pred, &hPrivateData->acState, hPrivateData->cf_se00); + x[f] = pred << 2; + x[f] += arith_decode_bits(hPrivateData, st, 2); /* LSBs as 2 bit raw */ + } + else if (f == 1) + { + pred = x[f - 1]; /* pred = b */ + x[f] = pred + arith_decode_residual( hPrivateData, st, hPrivateData->cf_se01, hPrivateData->cf_off_se01 ); + } + else + { + /* f >= 2 */ + pred = x[f - 1]; /* pred = b */ + ctx = quant_ctx(x[f - 1] - x[f - 2]); /* Q(b - e) */ + x[f] = pred + arith_decode_residual( hPrivateData, st, &hPrivateData->cf_se02[(IGF_SYMBOLS_IN_TABLE + 1) * (IGF_CTX_OFFSET + ctx)], + hPrivateData->cf_off_se02[IGF_CTX_OFFSET + ctx] ); + } + } + else + { + /* t == 1 */ + if (f == 0) + { + pred = prev_x[f]; /* pred = a */ + x[f] = pred + arith_decode_residual( hPrivateData, st, hPrivateData->cf_se10, hPrivateData->cf_off_se10 ); + } + else + { + /* (t == 1) && (f >= 1) */ + pred = prev_x[f] + x[f - 1] - prev_x[f - 1]; /* pred = a + b - c */ + ctx_f = quant_ctx(prev_x[f] - prev_x[f - 1]); /* Q(a - c) */ + ctx_t = quant_ctx(x[f - 1] - prev_x[f - 1]); /* Q(b - c) */ + x[f] = pred + arith_decode_residual(hPrivateData, st, + &hPrivateData->cf_se11[(IGF_SYMBOLS_IN_TABLE + 1) * IGF_CTX_COUNT * (IGF_CTX_OFFSET + ctx_t) + (IGF_SYMBOLS_IN_TABLE + 1) * (IGF_CTX_OFFSET + ctx_f)], + hPrivateData->cf_off_se11[IGF_CTX_COUNT * (IGF_CTX_OFFSET + ctx_t) + (IGF_CTX_OFFSET + ctx_f)]); + } + } + if (x[f] < 0) + { + x[f] = 0; + st->BER_detect = 1; + } + if (x[f] > 91) + { + x[f] = 91; + st->BER_detect = 1; + } + } + + return; +} + + +/*---------------------------------------------------------------------* + * IGFSCFDecoderReset() + * + * resets the internal decoder memory (context memory) + *---------------------------------------------------------------------*/ + +void IGFSCFDecoderReset( + IGFSCFDEC_INSTANCE_HANDLE hPublicData /**< inout: handle to public data or NULL in case there was no instance created */ +) +{ + + /* reset of coder */ + hPublicData->t = 0; + /* we do not need to fill hPublicData->prev with zeros, because when t = 0 no previous information is used */ + + return; +} + + +/*---------------------------------------------------------------------* + * IGFSCFDecoderDecode() + * + * main IGF decoder function + *---------------------------------------------------------------------*/ + +void IGFSCFDecoderDecode( + IGFSCFDEC_INSTANCE_HANDLE hPublicData, /**< inout: handle to public data or NULL in case there was no instance created */ + Decoder_State *st, /**< inout: pointer to decoder state */ + int *sfe, /**< out: ptr to an array which will contain the decoded quantized coefficients */ + int indepFlag /**< in: if 1 on input the encoder will be forced to reset, + if 0 on input the encodder will be forced to encode without a reset */ +) +{ + + + /* insert data */ + hPublicData->bitsRead = st->next_bit_pos; + ari_start_decoding_14bits(st, &hPublicData->acState); /* start AC decoding */ + + /* check if coder needs a reset and do it if neccessary */ + if (indepFlag) + { + /* reset of coder */ + IGFSCFDecoderReset(hPublicData); + } + + decode_sfe_vector( hPublicData, st, hPublicData->t, hPublicData->prev, sfe, hPublicData->scfCountLongBlock ); + + arith_decode_flush(st); /* finish decoding */ + + + /* advance history */ + mvi2i(sfe, hPublicData->prev, hPublicData->scfCountLongBlock); + hPublicData->t++; + + hPublicData->bitsRead = st->next_bit_pos - hPublicData->bitsRead; + + return; +} diff --git a/lib_dec/init_dec.c b/lib_dec/init_dec.c new file mode 100644 index 000000000..03a7f4ce9 --- /dev/null +++ b/lib_dec/init_dec.c @@ -0,0 +1,656 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" +#include + + +/*----------------------------------------------------------------------* + * init_decoder() + * + * Initialization of static variables for the decoder + *----------------------------------------------------------------------*/ + +void init_decoder( + Decoder_State *st /* o: Decoder static variables structure */ +) +{ + short i, j; + + /*-----------------------------------------------------------------* + * ACELP core parameters + *-----------------------------------------------------------------*/ + + st->codec_mode = MODE1; + st->last_codec_mode = MODE1; + st->core = ACELP_CORE; + st->L_frame = L_FRAME; + st->extl = -1; + st->total_brate = ACELP_8k00; + st->last_total_brate = -1; + st->last_total_brate_ber = -1; + st->core_brate = ACELP_8k00; + st->ini_frame = 0; + st->bwidth = NB; + st->extl_brate = 0; + + st->last_coder_type = GENERIC; + st->last_L_frame = st->L_frame; + st->last_core_brate = st->core_brate; + st->last_core = -1; + st->prev_last_core = -1; + st->last_hq_core_type = -1; + st->last_extl = st->extl; + + /* LSF initilaizations */ + mvr2r( GEWB_Ave, st->mem_AR, M ); + init_lvq( st->offset_scale1, st->offset_scale2, st->offset_scale1_p, st->offset_scale2_p, st->no_scales, st->no_scales_p ); + + set_f( st->mem_MA, 0, M ); + + set_f( st->dispMem, 0, 8 ); + + /* AMR-WB IO HF synth init */ + hf_synth_amr_wb_init( &st->prev_r, &st->fmerit_w_sm, st->mem_syn_hf, &st->frame_count, &st->ne_min, &st->fmerit_m_sm, &st->voice_fac_amr_wb_hf, + &st->unvoicing, &st->unvoicing_sm, &st->unvoicing_flag, &st->voicing_flag, &st->start_band_old, &st->OptCrit_old ); + + hf_synth_init( st->mem_hp400, st->mem_hf ); + set_f( st->mem_hp_interp, 0, INTERP_3_1_MEM_LEN ); + set_f( st->delay_syn_hf, 0, NS2SA(16000,DELAY_CLDFB_NS) ); + + st->tilt_code = 0.0f; + st->gc_threshold = 0.0f; + st->last_good = UNVOICED_CLAS; + st->clas_dec = UNVOICED_CLAS; + + st->lp_gainp = 0.0f; + st->lp_gainc = 0.0f; + + set_f( st->old_exc, 0, L_EXC_MEM_DEC ); + + /* AVQ pre-quantizer memory */ + st->mem_preemp_preQ = 0.0f; + st->last_nq_preQ = 0; + st->use_acelp_preq = 0; + + st->mem_deemph = 0.0f; + + set_f( st->mem_syn1, 0, M ); + st->mem_deemph_old_syn = 0.0f; + set_f( st->mem_syn2, 0, M ); + st->stab_fac = 0.0f; + st->stab_fac_smooth = 0.0f; + set_f( st->agc_mem2, 0, 2 ); + set_f( st->mem_hp20_out, 0.0f, 4 ); + set_f( st->mem_syn3, 0, M ); + + for (i=0; ipast_qua_en[i] = -14.0f; /* gain quantization memory (used in AMR-WB IO mode) */ + } + + mvr2r( GEWB_Ave, st->lsf_old, M ); + lsf2lsp( st->lsf_old, st->lsp_old, M, INT_FS_12k8 ); + + st->mid_lsf_int = 0; + st->safety_net = 0; + + /* parameters for AC mode (GSC) */ + st->seed_tcx = 15687; + st->GSC_noisy_speech = 0; + st->Last_GSC_noisy_speech_flag = 0; + st->cor_strong_limit = 1; + set_f( st->old_y_gain, 0, MBANDS_GN ); + st->noise_lev = NOISE_LEVEL_SP0; + set_f( st->Last_GSC_spectrum, 0.0f, L_FRAME ); + st->Last_GSC_pit_band_idx = 0; + + set_f( st->lt_ener_per_band, 1.0f, MBANDS_GN ); + set_f( st->last_exc_dct_in, 0, L_FRAME ); + st->last_ener = 0.0f; + set_s( st->last_bitallocation_band, 0, 6 ); + + /* NB post-filter */ + Init_post_filter( &(st->pfstat) ); + st->psf_lp_noise = 0.0f; + + /* FEC */ + st->scaling_flag = 0; + st->lp_ener_FEC_av = 5.0e5f; + st->lp_ener_FEC_max = 5.0e5f; + st->prev_bfi = 0; + st->lp_ener_bfi = 60.0f; + st->old_enr_LP = 0.0f; + st->lp_ener = 0.0f; + st->enr_old = 0.0f; + st->bfi_pitch = (float)L_SUBFR; + st->bfi_pitch_frame = L_FRAME; + set_f( st->mem_syn_clas_estim, 0.0f, L_SYN_MEM_CLAS_ESTIM ); + st->last_con_tcx = 0; + + for (i=0; i<2*NB_SUBFR16k; i++) + { + st->old_pitch_buf[i] = (float)L_SUBFR; + } + + st->upd_cnt = MAX_UPD_CNT; + + mvr2r( GEWB_Ave, st->lsfoldbfi0, M ); + mvr2r( GEWB_Ave, st->lsfoldbfi1, M ); + mvr2r( GEWB_Ave, st->lsf_adaptive_mean, M ); + + st->seed_acelp = RANDOM_INITSEED; + st->seed = RANDOM_INITSEED; + st->nbLostCmpt = 0; + st->decision_hyst = 0; + + /* fast recovery */ + set_f( st->old_exc2, 0, L_EXC_MEM ); + set_f( st->old_syn2, 0, L_EXC_MEM ); + + /* Stationary noise UV modification */ + st->unv_cnt = 0; + st->ge_sm = 10; + st->uv_count = 0; + st->act_count = 3; + mvr2r( st->lsp_old, st->lspold_s, M ); + st->noimix_seed = RANDOM_INITSEED; + st->min_alpha = 1; + st->exc_pe = 0; + + /*-----------------------------------------------------------------* + * LD music post-filter + *-----------------------------------------------------------------*/ + + set_f( st->dct_post_old_exc, 0, DCT_L_POST-OFFSET2 ); + st->LDm_enh_min_ns_gain = (float)pow(10.0f, -12/20.0f); + st->LDm_last_music_flag = 0; + set_f(st->LDm_lt_diff_etot, 0, MAX_LT); + st->LDm_thres[0] = TH_0_MIN; + st->LDm_thres[1] = TH_1_MIN; + st->LDm_thres[2] = TH_2_MIN; + st->LDm_thres[3] = TH_3_MIN; + st->LDm_nb_thr_1 = 0; + st->LDm_nb_thr_3 = 0; + st->LDm_mem_etot = 0.0f; + + for (i = 0; i < VOIC_BINS_HR; i++) + { + st->LDm_enh_lp_gbin[i] = 1.0f; + st->LDm_enh_lf_EO [i] = 0.01f; + } + + for (i = 0; i < MBANDS_GN_LD; i++) + { + st->LDm_bckr_noise[i] = E_MIN; + } + + set_f(st->filt_lfE, 1.0f, DCT_L_POST); + st->last_nonfull_music = 0; + + /*-----------------------------------------------------------------* + * CNG and DTX + *-----------------------------------------------------------------*/ + st->CNG = 0; /* RTXDTX handler CNG=1 nonCNG= 0,*/ + st->prev_ft_speech = 1; /* RXDTX handeler previous frametype flag for G.192 format AMRWB SID_FIRST detection */ + st->cng_seed = RANDOM_INITSEED; + st->cng_ener_seed = RANDOM_INITSEED; + st->cng_ener_seed1 = RANDOM_INITSEED; + st->old_enr_index = -1; + st->Enew = 0.0f; + st->first_CNG = 0; + mvr2r( st->lsp_old, st->lspCNG, M ); + st->last_allow_cn_step = 0; + st->shb_cng_ener = -6.02f; + st->wb_cng_ener = -6.02f; + st->last_wb_cng_ener = -6.02f; + st->last_shb_cng_ener = -6.02f; + st->swb_cng_seed = RANDOM_INITSEED; + st->ho_hist_ptr = -1; + st->ho_sid_bw = 0; + set_f( st->ho_lsp_hist, 0, HO_HIST_SIZE*M ); + set_f( st->ho_ener_hist, 0, HO_HIST_SIZE ); + set_f( st->ho_env_hist, 0, HO_HIST_SIZE*NUM_ENV_CNG ); + st->ho_hist_size = 0; + st->act_cnt = 0; + st->ho_circ_ptr = -1; + set_f( st->ho_lsp_circ, 0, HO_HIST_SIZE*M ); + set_f( st->ho_ener_circ, 0, HO_HIST_SIZE ); + set_f( st->ho_env_circ, 0, HO_HIST_SIZE*NUM_ENV_CNG ); + st->ho_circ_size = 0; + + set_s( st->ho_16k_lsp, 0, HO_HIST_SIZE ); + st->CNG_mode = -1; + st->last_active_brate = ACELP_7k20; + st->last_CNG_L_frame = L_FRAME; + st->act_cnt2 = 0; + st->num_ho = 0; + st->cng_type = -1; + st->last_cng_type = -1; + set_f( st->lp_env, 0.0f, NUM_ENV_CNG ); + set_f( st->exc_mem, 0.0f, 24 ); + set_f( st->exc_mem1, 0.0f, 30 ); + set_f( st->old_env, 0.0f, NUM_ENV_CNG ); + + for ( i=0; ilsp_shb_prev[i] = 0.5f * ((float) i)/((float) LPC_SHB_ORDER); + st->lsp_shb_prev_prev[i] = st->lsp_shb_prev[i]; + } + + st->shb_dtx_count = 0; + st->last_vad = 0; + st->trans_cnt = 0; + st->burst_cnt = 0; + st->last_shb_ener = 0.001f; + + /* HF (6-7kHz) BWE */ + st->seed2 = RANDOM_INITSEED; + + /*-----------------------------------------------------------------* + * HR SWB BWE parameters + *-----------------------------------------------------------------*/ + + set_f( st->t_audio_prev, 0, 2*END_FREQ_BWE_FULL_FB/50 - NUM_NONTRANS_START_FREQ_COEF ); + st->old_is_transient_hr_bwe = 0; + st->bwe_highrate_seed = 12345; + st->mem_EnergyLT = 0.0f; + + /*-----------------------------------------------------------------* + * HQ core parameters + *-----------------------------------------------------------------*/ + + set_f( st->old_out, 0, L_FRAME48k ); + set_f( st->old_outLB, 0, L_FRAME32k ); + set_f( st->old_coeffs, 0, L_FRAME8k ); + set_s(st->old_is_transient, 0, 3); + st->old_bfi_cnt = 0; + set_f( st->old_auOut_2fr, 0, L_FRAME8k*2 ); + set_f( st->old_out_pha[0], 0, N_LEAD_NB ); + set_f( st->old_out_pha[1], 0, N_LEAD_NB ); + st->prev_old_bfi = 0; + st->phase_mat_flag = 0; + st->phase_mat_next = 0; + st->old_Min_ind = 0; + st->diff_energy = 0.f; + set_f( st->oldIMDCTout, 0.f, L_FRAME8k/2 ); + set_f( st->prev_oldauOut, 0.f, L_FRAME8k); + st->stat_mode_out = 0; + st->stat_mode_old = 0; + st->oldHqVoicing=0; + + for( i=0; iynrm_values[i][j] = 0.f; + } + for( j=0; jr_p_values[i][j] = 0.f; + } + } + set_f( st->Norm_gain, 1.f, SFM_N_NB ); + set_f( st->energy_MA_Curr, 100.f, 2 ); + st->HQ_FEC_seed = RANDOM_INITSEED; + set_f( st->delay_buf_out, 0, HQ_DELTA_MAX*HQ_DELAY_COMP ); + set_f( st->previoussynth, 0, L_FRAME48k); + set_f( st->old_synth_sw, 0.0f, NS2SA(48000,FRAME_SIZE_NS-ACELP_LOOK_NS-DELAY_BWE_TOTAL_NS) ); + set_f( st->prev_noise_level, 0.0f, 2 ); + st->prev_R = 0; + set_f( st->prev_coeff_out, 0, L_HQ_WB_BWE ); + set_s( st->prev_SWB_peak_pos, 0, SPT_SHORTEN_SBNUM ); + + /* HQ GENERIC */ + st->hq_generic_seed = RANDOM_INITSEED; + + st->mem_norm[0] = 31; + set_s( st->mem_norm+1, 39, SFM_N_ENV_STAB-1 ); + st->mem_env_delta = 0; + st->no_att_hangover = 0; + st->energy_lt = 300.0f; + + st->HqVoicing = 0; + set_f( st->fer_samples, 0, L_FRAME48k ); + set_f( st->prev_env, 0, SFM_N_WB ); + set_f( st->prev_normq, 0, SFM_N_WB ); + st->prev_hqswb_clas = HQ_NORMAL; + + set_f( st->last_ni_gain, 0, BANDS_MAX ); + set_f( st->last_env, 0, BANDS_MAX ); + st->last_max_pos_pulse = 0; + st->prev_frm_hfe2 = 0; + st->prev_stab_hfe2 = 0; + st->prev_ni_ratio = 0.5f; + set_f(st->prev_En_sb, 0.0f, NB_SWB_SUBBANDS ); + + /* pre-echo reduction */ + reset_preecho_dec( st ); + + /*----------------------------------------------------------------------------------* + * HQ FEC + *----------------------------------------------------------------------------------*/ + + st->old_synthFB = st->synth_history + NS2SA(st->output_Fs, PH_ECU_MEM_NS); + st->prev_good_synth = st->old_synthFB + NS2SA(st->output_Fs, PH_ECU_LOOKAHEAD_NS); + + set_f( st->X_sav, 0.0f, PH_ECU_SPEC_SIZE ); + st->num_p = 0; + st->ph_ecu_active = 0; + st->ni_seed_forfec = 0; + st->last_fec = 0; + st->ph_ecu_HqVoicing = 0; + set_f( st->oldgapsynth, 0.0f, L_FRAME48k ); + st->env_stab = 0.75f; + st->mem_norm_hqfec[0] = 31; + set_s( st->mem_norm_hqfec+1, 39, SFM_N_ENV_STAB-1 ); + st->mem_env_delta_hqfec = 0; + st->env_stab_plc = 0.0f; + set_f( st->env_stab_state_p, 1.0f/NUM_ENV_STAB_PLC_STATES, NUM_ENV_STAB_PLC_STATES ); + st->envstabplc_hocnt = 0; + + set_f( st->mag_chg_1st, 1.0f, LGW_MAX ); + set_f( st->Xavg, 0.0f, LGW_MAX ); + st->beta_mute = BETA_MUTE_FAC_INI; + + set_s( st->prev_sign_switch, 0, HQ_FEC_SIGN_SFM ); + set_s( st->prev_sign_switch_2, 0, HQ_FEC_SIGN_SFM ); + + st->time_offs = 0; + st->ber_occured_in_pvq = 0; + + /*-----------------------------------------------------------------* + * SWB BWE parameters + *-----------------------------------------------------------------*/ + + set_f( st->old_wtda_swb, 0, L_FRAME48k); + set_f( st->old_syn_12k8_16k, 0, NS2SA(16000, DELAY_FD_BWE_ENC_NS) ); + st->prev_mode = NORMAL; + set_f( st->prev_SWB_fenv, 0, SWB_FENV ); + st->prev_Energy = 0.0f; + st->prev_L_swb_norm = 8; + st->Seed = 21211; + st->prev_frica_flag = 0; + set_f( st->mem_imdct, 0, L_FRAME48k ); + st->prev_td_energy = 0.0f; + st->prev_weight = 0.2f; + st->prev_flag = 0; + st->prev_coder_type = GENERIC; + st->last_wb_bwe_ener = 0.0f; + st->tilt_wb = 0.0f; + st->prev_Energy_wb = 0.0f; + + /*-----------------------------------------------------------------* + * TBE parameters + *-----------------------------------------------------------------*/ + + InitSWBdecBuffer( st ); + ResetSHBbuffer_Dec( st ); + + if( st->output_Fs == 48000 ) + { + set_f( st->fbbwe_hpf_mem[0], 0, 4 ); + set_f( st->fbbwe_hpf_mem[1], 0, 4 ); + set_f( st->fbbwe_hpf_mem[2], 0, 4 ); + set_f( st->fbbwe_hpf_mem[3], 0, 4 ); + } + + set_f( st->mem_resamp_HB, 0, INTERP_3_1_MEM_LEN ); + set_f( st->mem_resamp_HB_32k, 0, 2*ALLPASSSECTIONS_STEEP+1 ); + set_f( st->prev_synth_buffer, 0, NS2SA(48000, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS) ); + set_f( st->hb_prev_synth_buffer, 0, NS2SA(48000, DELAY_BWE_TOTAL_NS) ); + st->old_bwe_delay = -1; + + st->tilt_mem = 0.0f; + set_f( st->prev_lsf_diff, 0.5f, LPC_SHB_ORDER-2 ); + st->prev_tilt_para = 0.0f; + set_f( st->cur_sub_Aq, 0.0f, M+1 ); + set_f( st->int_3_over_2_tbemem_dec, 0.0f, INTERP_3_2_MEM_LEN ); + set_f( st->interpol_3_2_cng_dec, 0.0f, INTERP_3_2_MEM_LEN ); + + /* TD BWE post-processing */ + st->ptr_mem_stp_swb = st->mem_stp_swb + LPC_SHB_ORDER - 1; + set_f( st->mem_zero_swb, 0, LPC_SHB_ORDER ); + + for( i=0; iswb_lsp_prev_interp[i] = (float)cos( (float)i * EVS_PI / (float)10.0f ); + } + + st->prev1_shb_ener_sf = 1.0f; + st->prev2_shb_ener_sf = 1.0f; + st->prev3_shb_ener_sf = 1.0f; + st->prev_res_shb_gshape = 0.125f; + st->prev_mixFactors = 0.5f; + st->prev_GainShape = 0.0f; + set_f(st->fb_state_lpc_syn, 0, LPC_SHB_ORDER); + st->fb_tbe_demph = 0.0f; + + /*-----------------------------------------------------------------* + * WB/SWB bandwidth switching parameters + *-----------------------------------------------------------------*/ + + st->tilt_swb = 0.0f; + st->prev_ener = 0.0f; + st->prev_ener_shb = 0.0f; + st->prev_enerLH = 0.0f; + st->enerLH = 0.0f; + st->enerLL = 0.0f; + st->prev_enerLL = 0.0f; + st->prev_fractive = 0; + st->prev_bws_cnt = 0; + st->bws_cnt = N_WS2N_FRAMES; + st->bws_cnt1 = N_NS2W_FRAMES; + st->attenu1 = 0.1f; + st->last_inner_frame = L_FRAME8k; + st->last_bwidth = 0; + + st->prev_weight1 = 0.5f; + st->GainFrame_prevfrm = 0.0f; + + /*-----------------------------------------------------------------* + * channel-aware mode parameters + *-----------------------------------------------------------------*/ + + set_f( st->tilt_code_dec, 0.0f, NB_SUBFR16k ); + + st->use_partial_copy = 0; + st->prev_use_partial_copy = 0; + st->rf_flag = 0; + st->rf_flag_last = 0; + st->prev_rf_frame_type = 0; + st->next_coder_type = 0; + + st->rf_target_bits = 0; + + st->rf_indx_nelp_fid = 0; + st->rf_indx_nelp_iG1 = 0; + st->rf_indx_nelp_iG2[0] = 0; + st->rf_indx_nelp_iG2[1] = 0; + st->rf_indx_tbeGainFr = 0; + + /*-----------------------------------------------------------------* + * Improvement of unvoiced and audio signals in AMR-WB IO mode parameters + *-----------------------------------------------------------------*/ + + st->UV_cnt = 30; + st->LT_UV_cnt = 60.0f; + set_f(st->lt_diff_etot, 0, MAX_LT); + st->Last_ener = 0.0f; + set_f(st->old_Aq, 0, NB_SUBFR * (M+1) ); + st->old_Aq[0] = 1.0f; + st->old_Aq[M+1] = 1.0f; + st->old_Aq[2*(M+1)] = 1.0f; + st->old_Aq[3*(M+1)] = 1.0f; + st->lt_voice_fac = 0.0f; + + /*-----------------------------------------------------------------* + * Bass post-filter parameters + *-----------------------------------------------------------------*/ + + bass_psfilter_init( st->pst_old_syn, &(st->pst_mem_deemp_err), &(st->pst_lp_ener) ); + st->bpf_off = 0; + set_s( st->Track_on_hist, 0, L_TRACK_HIST ); + set_s( st->vibrato_hist, 0, L_TRACK_HIST ); + set_f( st->mem_mean_pit, 80, L_TRACK_HIST ); + st->psf_att = 1.0f; + + /*-----------------------------------------------------------------* + * FD BPF & resampling tools parameters + *-----------------------------------------------------------------*/ + + /* open analysis for max. SR 48kHz */ + openCldfb ( &st->cldfbAna, CLDFB_ANALYSIS, 48000); + + /* open analysis BPF for max. SR 16kHz */ + openCldfb ( &st->cldfbBPF, CLDFB_ANALYSIS, 16000); + + /* open synthesis for output SR */ + openCldfb ( &st->cldfbSyn, CLDFB_SYNTHESIS, st->output_Fs); + + st->last_active_bandsToZero_bwdec = 0; + st->flag_NB_bwddec = 0; + st->perc_bwddec = 0.0f; + st->last_flag_filter_NB = 0; + st->active_frame_cnt_bwddec = 0; + st->total_frame_cnt_bwddec = 0; + set_s(st->flag_buffer, 0, 20); + st->avg_nrg_LT = 0.0f; + + /*-----------------------------------------------------------------* + * Noise gate parameters + *-----------------------------------------------------------------*/ + + st->ng_ener_ST = -51.0f; + + st->Last_frame_ener = (float)MAX_32; + st->old_Es_pred = 0; + set_f(st->old_Aq_12_8 + 1, 0, M ); + st->old_Aq_12_8[0] = 1; + + /*-----------------------------------------------------------------* + * SC-VBR parameters + *-----------------------------------------------------------------*/ + + st->FadeScale = 1.0f; + st->last_ppp_mode_dec = 0; + st->old_ppp_mode = 0; + st->ppp_mode_dec = 0; + st->last_nelp_mode_dec = 0; + st->nelp_mode_dec = 0; + st->nelp_dec_seed = 0; + st->firstTime_voiceddec = 1; + st->prev_gain_pit_dec = 0.0f; + st->prev_tilt_code_dec = 0.0f; + st->vbr_hw_BWE_disable_dec = 0; + st->last_vbr_hw_BWE_disable_dec = 0; + set_f( st->old_hb_synth, 0, L_FRAME48k ); + + /* DTFS variables */ + set_f( st->dtfs_dec_a, 0, MAXLAG_WI ); + set_f( st->dtfs_dec_b, 0, MAXLAG_WI ); + st->dtfs_dec_lag = 0; + st->dtfs_dec_nH = 0; + st->dtfs_dec_nH_4kHz = 0; + st->dtfs_dec_upper_cut_off_freq_of_interest = 0; + st->dtfs_dec_upper_cut_off_freq = 0; + st->ph_offset_D = 0; + st->lastLgainD = 0; + st->lastHgainD = 0; + set_f( st->lasterbD, 0, NUM_ERB_WB ); + + /* NELP decoder variables */ + set_f( st->bp1_filt_mem_nb_dec, 0, 14 ); + set_f( st->bp1_filt_mem_wb_dec, 0, 8 ); + set_f( st->shape1_filt_mem_dec, 0, 20 ); + set_f( st->shape2_filt_mem_dec, 0, 20 ); + set_f( st->shape3_filt_mem_dec, 0, 20 ); + + /*-----------------------------------------------------------------* + * Mode 2 initialization + *-----------------------------------------------------------------*/ + + /* IGF */ + st->igf = 0; + memset( &st->hIGFDec, 0, sizeof(st->hIGFDec) ); + st->hIGFDec.igfData.igfInfo.nfSeed = 9733; + + st->enablePlcWaveadjust = 0; + + /* Init Core Decoder */ + open_decoder_LPD( st, st->total_brate, st->bwidth ); + + /* PLC mode initialization */ + st->m_decodeMode = DEC_NO_FRAM_LOSS; + + /* Init bandwidth / frame_type */ + st->m_frame_type = ACTIVE_FRAME; + st->m_old_frame_type = ACTIVE_FRAME; + + resampleCldfb( st->cldfbAna, st->L_frame*50 ); + resampleCldfb( st->cldfbBPF, st->L_frame*50 ); + + /* Create FD_CNG instance */ + createFdCngDec( &st->hFdCngDec ); + + /* Init FD-CNG */ + initFdCngDec( st->hFdCngDec, st->cldfbSyn->scale ); + + st->cngTDLevel = 0.f; + + st->lp_noise = -20.0f; + + st->force_lpd_reset = 0; + + + return; +} + + +/*----------------------------------------------------------------------* + * reset_preecho_dec() + * + * Initialization of static variables for pre-echo + *----------------------------------------------------------------------*/ + +void reset_preecho_dec( + Decoder_State *st /* i/o: Decoder static variables structure */ +) +{ + st->memfilt_lb = 0; + st->mean_prev_hb = 0; + st->smoothmem = 1; + st->mean_prev = 0; + st->mean_prev_nc = 0; + st->wmold_hb = 1; + st->prevflag = 0; + st->pastpre = 0; + + return; +} + + +/*----------------------------------------------------------------------* + * destroy_decoder() + * + * Free memory which was allocated in init_decoder() + *----------------------------------------------------------------------*/ + +void destroy_decoder( + Decoder_State *st /* o: Decoder static variables structure */ +) +{ + /* CLDFB BPF & resampling tools */ + deleteCldfb( &st->cldfbAna ); /* delete analysis for max. SR 16kHz */ + deleteCldfb( &st->cldfbBPF ); /* delete analysis BPF for max. SR 16kHz */ + deleteCldfb( &st->cldfbSyn ); /* delete synthesis for output SR */ + + deleteFdCngDec( &st->hFdCngDec ); + + return; +} diff --git a/lib_dec/inov_dec.c b/lib_dec/inov_dec.c new file mode 100644 index 000000000..75a2c3219 --- /dev/null +++ b/lib_dec/inov_dec.c @@ -0,0 +1,110 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + + +/*----------------------------------------------------------------------* + * inov_decode() + * + * Decode the algebraic innovation and do pitch sharpening + *----------------------------------------------------------------------*/ + +void inov_decode( + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : core bitrate */ + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short L_frame, /* i : length of the frame */ + const short coder_type, /* i : coding type */ + const short sharpFlag, /* i : formant sharpening flag */ + const short i_subfr, /* i : subframe index */ + const short tc_subfr, /* i : TC subframe index */ + const float *p_Aq, /* i : LP filter coefficients */ + const float tilt_code, /* i : tilt of the excitation of previous subframe */ + const float pt_pitch, /* i : pointer to current subframe fractional pitch*/ + float *code /* o : algebraic excitation */ +) +{ + short nBits; + float g1, g2; + + if ( 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( L_frame == L_FRAME ) + { + nBits = FCB_bits_tbl[BIT_ALLOC_IDX(core_brate, coder_type, i_subfr, TC_SUBFR2IDX(tc_subfr))]; + } + else /* L_frame == L_FRAME16k */ + { + nBits = FCB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ(core_brate, coder_type, i_subfr, TC_SUBFR2IDX_16KHZ(tc_subfr))]; + } + + if( nBits == 7 ) + { + dec_acelp_1t64( st, code ); + } + else if( nBits == 12 ) + { + dec_acelp_2t32( st, code ); + } + else + { + dec_acelp_4t64( st, nBits, code, Opt_AMR_WB ); + } + } + else + { + if ( core_brate == ACELP_6k60 ) + { + dec_acelp_2t32( st, code ); + } + else if ( core_brate == ACELP_8k85 ) + { + dec_acelp_4t64( st, 20, code, Opt_AMR_WB ); + } + else if ( core_brate == ACELP_12k65) + { + dec_acelp_4t64( st, 36, code, Opt_AMR_WB ); + } + else if ( core_brate == ACELP_14k25) + { + dec_acelp_4t64( st, 44, code, Opt_AMR_WB ); + } + else if ( core_brate == ACELP_15k85) + { + dec_acelp_4t64( st, 52, code, Opt_AMR_WB ); + } + else if ( core_brate == ACELP_18k25) + { + dec_acelp_4t64( st, 64, code, Opt_AMR_WB ); + } + else if ( core_brate == ACELP_19k85) + { + dec_acelp_4t64( st, 72, code, Opt_AMR_WB ); + } + else + { + dec_acelp_4t64( st, 88, code, Opt_AMR_WB ); + } + } + + cb_shape( 1, 1, 0, sharpFlag, 0, g1, g2, p_Aq, code, tilt_code, pt_pitch ); + + return; +} diff --git a/lib_dec/io_dec.c b/lib_dec/io_dec.c new file mode 100644 index 000000000..54742c570 --- /dev/null +++ b/lib_dec/io_dec.c @@ -0,0 +1,435 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "mime.h" + +#define WMC_TOOL_SKIP + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ + +static void usage_dec(void); +static char *to_upper( char *str ); + + +/*---------------------------------------------------------------------* + * io_ini_dec() + * + * Processing of command line parameters + *---------------------------------------------------------------------*/ + +void io_ini_dec( + 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 */ + short *quietMode, /* o : limited printouts */ + short *noDelayCmp, /* o : turn off delay compensation */ + Decoder_State *st, /* 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; + Word16 evs_magic, amrwb_magic; + + print_disclaimer( stderr ); + + st->writeFECoffset = 0; + + /*-----------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + + i = 1; + *f_synth = NULL; + *f_stream = NULL; + *quietMode = 0; + *noDelayCmp = 0; + + st->codec_mode = 0; /* unknown before first frame */ + st->Opt_AMR_WB = 0; + st->Opt_VOIP = 0; + + st->bitstreamformat = G192; + st->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->Opt_VOIP = 1; + st->bitstreamformat = VOIP_G192_RTP; + i += 1; + } + else if ( strcmp( to_upper(argv[i]), "-VOIP_HF_ONLY=0") == 0) + { + st->Opt_VOIP = 1; + st->bitstreamformat = VOIP_RTPDUMP; + st->sdp_hf_only = 0; + i += 1; + } + else if ( strcmp( to_upper(argv[i]), "-VOIP_HF_ONLY=1") == 0) + { + st->Opt_VOIP = 1; + st->bitstreamformat = VOIP_RTPDUMP; + st->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->writeFECoffset = 1; + *jbmFECoffsetFileName = argv[i+1]; + i = i + 2; + } + + /*-----------------------------------------------------------------* + * Quiet mode + *-----------------------------------------------------------------*/ + + else if ( strcmp( to_upper(argv[i]), "-Q" ) == 0 ) + { + *quietMode = 1; + 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->bitstreamformat = MIME; + st->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->output_Fs = (int)atoi( argv[i] ) * 1000; + + if( st->output_Fs != 8000 && st->output_Fs != 16000 && st->output_Fs != 32000 && st->output_Fs != 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->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))) + { + 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->amrwb_rfc4867_flag = 0; + } + else + { + fprintf( stderr, "Found MIME Magic number %s\n",AMRWB_MAGIC_NUMBER ); + st->amrwb_rfc4867_flag = 1; + st->Opt_AMR_WB = 1; /* needed in case first initial RFC4867 frames/ToCs are lost */ + } + } + + else if( st->Opt_VOIP == 0 ) + { + /* G.192 format .... preread the G.192 sync header */ + unsigned short 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( utmp != SYNC_GOOD_FRAME && 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( stdout, "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->Opt_VOIP ) + { + /*-----------------------------------------------------------------* + * Read information from bitstream + *-----------------------------------------------------------------*/ + st->ini_frame = 0; /* initialize, since this is needed within read_indices, to correctly set st->last_codec_mode */ + if( st->bitstreamformat == G192 ) + { + read_indices( st, *f_stream, 1 ); + } + else + { + st->total_brate=0; /* make sure total_brate is deterministic even if there are no MIME ToCs */ + read_indices_mime( st, *f_stream, 1 ); /* rew_flag == 1 , checks only very first frame */ + if( st->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 + *-----------------------------------------------------------------*/ + + /*-----------------------------------------------------------------* + * Print output sampling frequency + *-----------------------------------------------------------------*/ + + fprintf( stdout, "Output sampling rate: %d Hz\n", st->output_Fs ); + + /*-----------------------------------------------------------------* + * Print bitrate + *-----------------------------------------------------------------*/ + + fprintf( stdout, "Bitrate: %.2f kbps\n", (float)st->total_brate/1000 ); + + if( st->total_brate <= 0 ) + { + if( st->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 + 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 000000000..bacd24da9 --- /dev/null +++ b/lib_dec/jbm_jb4_circularbuffer.c @@ -0,0 +1,425 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +/** \file jbm_jb4_circularbuffer.c circular buffer (FIFO) with fixed capacity */ + + +/* system includes */ +#include +#include +#include +#include "options.h" +#define WMC_TOOL_SKIP +/* local includes */ +#include "jbm_jb4_circularbuffer.h" +/* instrumentation */ +#include "wmc_auto.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, + unsigned int *size, unsigned int 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) */ + unsigned int capacity; + /** position of next enque operation */ + unsigned int writePos; + /** position of next deque operation */ + unsigned int readPos; +}; + + +/* Creates a circular buffer (FIFO) */ +int JB4_CIRCULARBUFFER_Create( JB4_CIRCULARBUFFER_HANDLE *ph ) +{ + JB4_CIRCULARBUFFER_HANDLE h = malloc( sizeof( struct JB4_CIRCULARBUFFER ) ); + + + h->data = NULL; + h->capacity = 0; + h->writePos = 0; + h->readPos = 0; + + + *ph = h; + + + return 0; +} + +/* Destroys the circular buffer (FIFO) */ +void JB4_CIRCULARBUFFER_Destroy( JB4_CIRCULARBUFFER_HANDLE *ph ) +{ + JB4_CIRCULARBUFFER_HANDLE h; + + + if( !ph ) + return; + h = *ph; + if( !h ) + return; + + if( h->data ) + free( h->data ); + free( h ); + *ph = NULL; + +} + +/* Initializes a circular buffer (FIFO) with a fixed maximum allowed number of elements */ +int JB4_CIRCULARBUFFER_Init( JB4_CIRCULARBUFFER_HANDLE h, unsigned int capacity ) +{ + + + /* keep one element free to be able to decide between full/empty buffer */ + ++capacity; + h->data = malloc( capacity * sizeof( JB4_CIRCULARBUFFER_ELEMENT ) ); + + h->capacity = capacity; + h->writePos = 0; + h->readPos = 0; + + + + return 0; +} + +int JB4_CIRCULARBUFFER_Enque( JB4_CIRCULARBUFFER_HANDLE h, JB4_CIRCULARBUFFER_ELEMENT element ) +{ + + if( JB4_CIRCULARBUFFER_IsFull( h ) ) + { + return -1; + } + + h->data[h->writePos] = element; + ++h->writePos; + if( h->writePos == h->capacity ) + { + h->writePos = 0; + } + + + + return 0; +} + +int JB4_CIRCULARBUFFER_Deque( JB4_CIRCULARBUFFER_HANDLE h, JB4_CIRCULARBUFFER_ELEMENT *pElement ) +{ + + if( JB4_CIRCULARBUFFER_IsEmpty( h ) ) + { + return -1; + } + + *pElement = h->data[h->readPos]; + ++h->readPos; + if( h->readPos == h->capacity ) + { + h->readPos = 0; + } + + + + return 0; +} + +/* Returns the first element. */ +JB4_CIRCULARBUFFER_ELEMENT JB4_CIRCULARBUFFER_Front( const JB4_CIRCULARBUFFER_HANDLE h ) +{ + JB4_CIRCULARBUFFER_ELEMENT ret; + + + ret = h->data[h->readPos]; + + return ret; +} + +/* Returns the last element. */ +JB4_CIRCULARBUFFER_ELEMENT JB4_CIRCULARBUFFER_Back( const JB4_CIRCULARBUFFER_HANDLE h ) +{ + JB4_CIRCULARBUFFER_ELEMENT ret; + + + if(h->writePos != 0U) + { + ret = h->data[h->writePos - 1]; + } + else + { + ret = h->data[h->capacity - 1]; + } + + + return ret; +} + +int JB4_CIRCULARBUFFER_IsEmpty( const JB4_CIRCULARBUFFER_HANDLE h ) +{ + int ret; + + + if(h->readPos == h->writePos) + { + ret = 1; + } + else + { + ret = 0; + } + + + + return ret; +} + +int JB4_CIRCULARBUFFER_IsFull( const JB4_CIRCULARBUFFER_HANDLE h ) +{ + int ret; + + + + if(((h->writePos + 1) % h->capacity) == h->readPos) + { + ret = 1; + } + else + { + ret = 0; + } + + return ret; +} + +unsigned int JB4_CIRCULARBUFFER_Size( const JB4_CIRCULARBUFFER_HANDLE h ) +{ + unsigned int ret; + + + if( h->readPos <= h->writePos ) + { + ret = h->writePos - h->readPos; + } + else + { + /* wrap around */ + ret = h->writePos + h->capacity - h->readPos; + } + + + return ret; +} + +/* Calculates statistics over all elements: min element */ +void JB4_CIRCULARBUFFER_Min( const JB4_CIRCULARBUFFER_HANDLE h, JB4_CIRCULARBUFFER_ELEMENT *pMin ) +{ + unsigned int i; + JB4_CIRCULARBUFFER_ELEMENT minEle; + + + /* init output variable */ + minEle = h->data[h->readPos]; + + if( h->readPos <= h->writePos ) + { + /* no wrap around */ + /* calc statistics for [readPos;writePos[ */ + for( i = h->readPos; i != h->writePos; ++i ) + { + if( h->data[i] < minEle ) + { + minEle = h->data[i]; + } + } + } + else + { + /* wrap around */ + /* calc statistics for [readPos;capacity[ */ + for( i = h->readPos; i != h->capacity; ++i ) + { + if( h->data[i] < minEle ) + { + minEle = h->data[i]; + } + } + /* calc statistics for [0;writePos[ */ + for( i = 0; i != h->writePos; ++i ) + { + if( h->data[i] < minEle ) + { + minEle = h->data[i]; + } + } + } + + *pMin = minEle; + +} + +/* Calculates statistics over all elements: max element */ +void JB4_CIRCULARBUFFER_Max( const JB4_CIRCULARBUFFER_HANDLE h, JB4_CIRCULARBUFFER_ELEMENT *pMax ) +{ + unsigned int i; + JB4_CIRCULARBUFFER_ELEMENT maxEle; + + + /* init output variable */ + maxEle = h->data[h->readPos]; + if( h->readPos <= h->writePos ) + { + /* no wrap around */ + /* calc statistics for [readPos;writePos[ */ + for( i = h->readPos; i != h->writePos; ++i ) + { + if( h->data[i] > maxEle ) + { + maxEle = h->data[i]; + } + } + } + else + { + /* wrap around */ + /* calc statistics for [readPos;capacity[ */ + for( i = h->readPos; i != h->capacity; ++i ) + { + if( h->data[i] > maxEle ) + { + maxEle = h->data[i]; + } + } + /* calc statistics for [0;writePos[ */ + for( i = 0; i != h->writePos; ++i ) + { + if( h->data[i] > maxEle ) + { + maxEle = h->data[i]; + } + } + } + + *pMax = maxEle; + +} + +/* Calculates statistics over a considered fraction of all elements: min element and percentile */ +void JB4_CIRCULARBUFFER_MinAndPercentile( const JB4_CIRCULARBUFFER_HANDLE h, unsigned int nElementsToIgnore, + JB4_CIRCULARBUFFER_ELEMENT *pMin, JB4_CIRCULARBUFFER_ELEMENT *pPercentile ) +{ + unsigned int i; + JB4_CIRCULARBUFFER_ELEMENT maxElements[100]; + unsigned int maxElementsSize; + unsigned int maxElementsCapacity; + JB4_CIRCULARBUFFER_ELEMENT minEle; + + + /* init output variables */ + minEle = h->data[h->readPos]; + + /* 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 = 0; + maxElementsCapacity = nElementsToIgnore + 1; + assert( maxElementsCapacity <= sizeof(maxElements) / sizeof(maxElements[0]) ); + if( h->readPos <= h->writePos ) + { + /* no wrap around */ + /* calc statistics for [readPos;writePos[ */ + for( i = h->readPos; i != h->writePos; ++i ) + { + if( h->data[i] < minEle ) + { + minEle = h->data[i]; + } + 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( h->data[i] < minEle ) + { + minEle = h->data[i]; + } + JB4_CIRCULARBUFFER_calcPercentile( maxElements, &maxElementsSize, maxElementsCapacity, h->data[i] ); + } + /* calc statistics for [0;writePos[ */ + for( i = 0; i != h->writePos; ++i ) + { + if( h->data[i] < minEle ) + { + minEle = h->data[i]; + } + JB4_CIRCULARBUFFER_calcPercentile( maxElements, &maxElementsSize, maxElementsCapacity, h->data[i] ); + } + } + + *pPercentile = maxElements[0]; + *pMin = minEle; + +} + +/* Calculates percentile by selecting greatest elements. */ +static void JB4_CIRCULARBUFFER_calcPercentile( JB4_CIRCULARBUFFER_ELEMENT *elements, + unsigned int *size, unsigned int capacity, JB4_CIRCULARBUFFER_ELEMENT newElement ) +{ + unsigned int i; + + + /* insert newElement if elements buffer is not yet full */ + if( *size < capacity ) + { + for( i = 0; i != *size; ++i ) + { + if( newElement <= elements[i] ) + { + /* insert newElement at index i */ + memmove( elements + i + 1, elements + i, ( *size - i ) * sizeof( JB4_CIRCULARBUFFER_ELEMENT ) ); + elements[i] = newElement; + ++*size; + return; + } + } + /* newElement is maximum, just append it */ + elements[*size] = newElement; + ++*size; + return; + } + + /* check if newElement is too small to be inserted in elements buffer */ + if( newElement <= elements[0] ) + { + return; + } + + /* select position to insert newElement to elements */ + for( i = *size - 1; i != 0; --i ) + { + if( newElement >= elements[i] ) + { + /* insert newElement at index i */ + memmove( elements, elements + 1, i * sizeof( JB4_CIRCULARBUFFER_ELEMENT ) ); + elements[i] = newElement; + return; + } + } + /* newElement is just greater than first on in elements buffer */ + elements[0] = newElement; + +} diff --git a/lib_dec/jbm_jb4_circularbuffer.h b/lib_dec/jbm_jb4_circularbuffer.h new file mode 100644 index 000000000..db875af08 --- /dev/null +++ b/lib_dec/jbm_jb4_circularbuffer.h @@ -0,0 +1,51 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 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 + +/** handle for circular buffer (FIFO) with fixed capacity */ +typedef struct JB4_CIRCULARBUFFER *JB4_CIRCULARBUFFER_HANDLE; +/** type of circular buffer elements */ +typedef int JB4_CIRCULARBUFFER_ELEMENT; + +/** Creates a circular buffer (FIFO) + * @param[out] ph pointer to created handle + * @return 0 if succeeded */ +int 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 */ +int JB4_CIRCULARBUFFER_Init( JB4_CIRCULARBUFFER_HANDLE h, unsigned int capacity ); + +int JB4_CIRCULARBUFFER_Enque( JB4_CIRCULARBUFFER_HANDLE h, JB4_CIRCULARBUFFER_ELEMENT element ); +int 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 ); + +int JB4_CIRCULARBUFFER_IsEmpty( const JB4_CIRCULARBUFFER_HANDLE h ); +int JB4_CIRCULARBUFFER_IsFull( const JB4_CIRCULARBUFFER_HANDLE h ); +unsigned int 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, unsigned int 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 000000000..23af8fb7b --- /dev/null +++ b/lib_dec/jbm_jb4_inputbuffer.c @@ -0,0 +1,307 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + + +#include "wmc_auto.h" +/** \file jbm_jb4_inputbuffer.c RTP input buffer with fixed capacity. */ + +/* system includes */ +#include +#include +#include +#include "options.h" +#define WMC_TOOL_SKIP +/* instrumentation */ +/* local includes */ +#include "jbm_jb4_inputbuffer.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) */ + unsigned int capacity; + /** position of next enque operation */ + unsigned int writePos; + /** position of next deque operation */ + unsigned int readPos; + /** function to compare two elements */ + int (*compareFunction)( const JB4_INPUTBUFFER_ELEMENT first, const JB4_INPUTBUFFER_ELEMENT second, + bool_t *replaceWithNewElementIfEqual ); +}; + + +/* Creates a input buffer */ +int JB4_INPUTBUFFER_Create( JB4_INPUTBUFFER_HANDLE *ph ) +{ + JB4_INPUTBUFFER_HANDLE h = malloc( sizeof( struct JB4_INPUTBUFFER ) ); + + + h->data = NULL; + h->capacity = 0; + h->writePos = 0; + h->readPos = 0; + h->compareFunction = NULL; + + *ph = h; + + return 0; +} + +/* Destroys the input buffer */ +void JB4_INPUTBUFFER_Destroy( JB4_INPUTBUFFER_HANDLE *ph ) +{ + JB4_INPUTBUFFER_HANDLE h; + + if( !ph ) + { + return; + } + h = *ph; + if( !h ) + { + return; + } + if( h->data ) + free( h->data ); + free( h ); + *ph = NULL; + +} + +/* Initializes a input buffer with a fixed maximum allowed number of elements */ +int JB4_INPUTBUFFER_Init( JB4_INPUTBUFFER_HANDLE h, unsigned int capacity, + int (*compareFunction)( const JB4_INPUTBUFFER_ELEMENT first, const JB4_INPUTBUFFER_ELEMENT second, + bool_t *replaceWithNewElementIfEqual ) ) +{ + + /* keep one element free to be able to decide between full/empty buffer */ + ++capacity; + h->data = malloc( capacity * sizeof( JB4_INPUTBUFFER_ELEMENT ) ); + h->capacity = capacity; + h->writePos = 0; + h->readPos = 0; + h->compareFunction = compareFunction; + + return 0; +} + +int JB4_INPUTBUFFER_Enque( JB4_INPUTBUFFER_HANDLE h, JB4_INPUTBUFFER_ELEMENT element, + JB4_INPUTBUFFER_ELEMENT *replacedElement ) +{ + unsigned int size; + int low, high, middle, diff; + unsigned int insertPos; + unsigned int canMoveRight; + unsigned int canMoveLeft; + bool_t replace; + *replacedElement = NULL; + + size = JB4_INPUTBUFFER_Size( h ); + if(size >= h->capacity - 1) + { + return -1; + } + + /* appending the first element is straight forward */ + if( size == 0U ) + { + h->data[h->writePos] = element; + ++h->writePos; + if( h->writePos == h->capacity ) + { + h->writePos = 0; + } + 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; + ++h->writePos; + if( h->writePos == h->capacity ) + { + h->writePos = 0; + } + return 0; + } + + /* out of order: use binary search to get the position to insert */ + low = 0; + high = size - 1; + while( low <= high ) + { + middle = low + ( high - low ) / 2; + diff = h->compareFunction( element, JB4_INPUTBUFFER_Element( h, middle ), &replace ); + if( diff < 0 ) + { + high = middle - 1; + } + else if( diff > 0 ) + { + low = middle + 1; + } + else /* an element with same index is already stored */ + { + if(replace != 0) + { + *replacedElement = h->data[( h->readPos + middle ) % h->capacity]; + h->data[( h->readPos + middle ) % h->capacity] = element; + return 0; + } + return 1; + } + } + + assert( h->compareFunction( element, JB4_INPUTBUFFER_Element( h, low ), &replace ) != 0 ); + if( low > 0 ) + assert( h->compareFunction( element, JB4_INPUTBUFFER_Element( h, low - 1 ), &replace ) > 0 ); + assert( h->compareFunction( element, JB4_INPUTBUFFER_Element( h, low ), &replace ) < 0 ); + if( (unsigned int)(low + 1) < size ) + assert( h->compareFunction( element, JB4_INPUTBUFFER_Element( h, low + 1 ), &replace ) < 0 ); + + insertPos = ( h->readPos + low ) % h->capacity; + if( h->readPos < h->writePos ) + { + canMoveRight = 1; + canMoveLeft = h->readPos > 0; + } + else + { + canMoveRight = insertPos < h->writePos; + canMoveLeft = insertPos > h->writePos; + } + + assert( canMoveRight != 0 || canMoveLeft != 0 ); + (void)canMoveLeft; + if( canMoveRight ) + { + /* move higher elements to the right and insert at insertPos */ + memmove( h->data + insertPos + 1, h->data + insertPos, + ( h->writePos - insertPos ) * sizeof( JB4_INPUTBUFFER_ELEMENT ) ); + h->data[insertPos] = element; + ++h->writePos; + if( h->writePos == h->capacity ) + { + h->writePos = 0; + } + } + else + { + /* move lower elements to the left and insert before insertPos */ + memmove( h->data + h->readPos - 1, h->data + h->readPos, + low * sizeof( JB4_INPUTBUFFER_ELEMENT ) ); + h->data[insertPos-1] = element; + --h->readPos; + assert( h->readPos < 99999 ); + } + + return 0; +} + +int 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; + if( h->readPos == h->capacity ) + { + h->readPos = 0; + } + + 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]; + + return ret; +} + +/* Returns the last element. */ +JB4_INPUTBUFFER_ELEMENT JB4_INPUTBUFFER_Back( const JB4_INPUTBUFFER_HANDLE h ) +{ + JB4_INPUTBUFFER_ELEMENT ret; + + if( h->writePos != 0U ) + { + ret = h->data[h->writePos - 1]; + } + else + { + ret = h->data[h->capacity - 1]; + } + + return ret; +} + +/* Returns the element with the given index (0 means front element). */ +JB4_INPUTBUFFER_ELEMENT JB4_INPUTBUFFER_Element( const JB4_INPUTBUFFER_HANDLE h, unsigned int index ) +{ + JB4_INPUTBUFFER_ELEMENT ret; + + + /* return h->data[(h->readPos + index) % h->capacity] without error handling */ + if( h->readPos + index < h->capacity ) + { + ret = h->data[h->readPos + index]; + } + else + { + /* wrap around */ + ret = h->data[h->readPos + index - h->capacity]; + } + + return ret; +} + +int JB4_INPUTBUFFER_IsEmpty( const JB4_INPUTBUFFER_HANDLE h ) +{ + int ret; + + + ret = h->readPos == h->writePos; + + return ret; +} + +int JB4_INPUTBUFFER_IsFull( const JB4_INPUTBUFFER_HANDLE h ) +{ + int ret; + ret = 0; + if( JB4_INPUTBUFFER_Size( h ) == h->capacity - 1 ) + { + ret = 1; + } + return ret; +} + +unsigned int JB4_INPUTBUFFER_Size( const JB4_INPUTBUFFER_HANDLE h ) +{ + unsigned int ret; + + if( h->readPos <= h->writePos ) + { + ret = h->writePos - h->readPos; + } + else + { + /* wrap around */ + ret = h->writePos + h->capacity - h->readPos; + } + + return ret; +} diff --git a/lib_dec/jbm_jb4_inputbuffer.h b/lib_dec/jbm_jb4_inputbuffer.h new file mode 100644 index 000000000..0954a4413 --- /dev/null +++ b/lib_dec/jbm_jb4_inputbuffer.h @@ -0,0 +1,48 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +/** \file jbm_jb4_inputbuffer.h RTP input buffer with fixed capacity. */ + +#ifndef JBM_JB4_INPUTBUFFER_H +#define JBM_JB4_INPUTBUFFER_H JBM_JB4_INPUTBUFFER_H + +#include "jbm_types.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 */ +int 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 */ +int JB4_INPUTBUFFER_Init( JB4_INPUTBUFFER_HANDLE h, unsigned int capacity, + int (*compareFunction)( const JB4_INPUTBUFFER_ELEMENT newElement, const JB4_INPUTBUFFER_ELEMENT arrayElement, + bool_t *replaceWithNewElementIfEqual ) ); + +/** Add an element to the buffer. + * @return 0 if succeeded, -1 if buffer full, +1 if element with same index already stored. */ +int JB4_INPUTBUFFER_Enque( JB4_INPUTBUFFER_HANDLE h, JB4_INPUTBUFFER_ELEMENT element, JB4_INPUTBUFFER_ELEMENT *replacedElement ); +int 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, unsigned int index ); + +int JB4_INPUTBUFFER_IsEmpty( const JB4_INPUTBUFFER_HANDLE h ); +int JB4_INPUTBUFFER_IsFull( const JB4_INPUTBUFFER_HANDLE h ); +unsigned int 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 000000000..df7bb56d7 --- /dev/null +++ b/lib_dec/jbm_jb4_jmf.c @@ -0,0 +1,264 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +/** \file jbm_jb4_jmf.cpp jitter measure fifo - a fifo used for windowed measure of network status */ +#include "wmc_auto.h" + +/* system includes */ +#include +#include +#include +#include "options.h" +#define WMC_TOOL_SKIP +/* local includes */ +#include "jbm_jb4_jmf.h" +#include "jbm_jb4_circularbuffer.h" +/* instrumentation */ + + +/** jitter measure fifo - a fifo used for windowed measure of network status */ +struct JB4_JMF +{ + /** scale of system time and RTP time stamps */ + int timeScale; + /** the window size of the fifo as time in sysTimeScale */ + unsigned int maxWindowDuration; + /** considered fraction in 1/1000 units, e.g. 900 ignores 10% of the highest samples */ + unsigned int 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 */ + int firstPacketPushed; + /** last packets system time in microseconds */ + int32_t lastSysTime; + /** RTP time stamp of the last pushed packet */ + int32_t lastRtpTimeStamp; + /** last packets calculated delay value */ + int32_t lastDelay; + /** number of elements to ignore for percentile calculation - value set within init */ + int16_t nElementsToIgnore; +}; + + +/** helper function to add an entry at back of the buffer */ +static void JB4_JMF_pushBack( JB4_JMF_HANDLE h, int32_t delay, int32_t offset, uint32_t time ); +/** helper function to remove an entry from the front of the buffer */ +static void JB4_JMF_popFront( JB4_JMF_HANDLE h ); + + +int 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; + h->consideredFraction = 1000; + h->firstPacketPushed = 0; + h->lastSysTime = 0; + h->lastRtpTimeStamp = 0; + h->lastDelay = 0; + h->nElementsToIgnore = 0; + + *ph = h; + + return 0; +} + +void JB4_JMF_Destroy( JB4_JMF_HANDLE *ph ) +{ + JB4_JMF_HANDLE h; + + if( !ph ) + { + return; + } + h = *ph; + if( !h ) + { + return; + } + + JB4_CIRCULARBUFFER_Destroy( &h->fifo ); + JB4_CIRCULARBUFFER_Destroy( &h->offsetFifo ); + JB4_CIRCULARBUFFER_Destroy( &h->timeStampFifo ); + + free( h ); + *ph = NULL; +} + +/* function to set the window size of the fifo and the fraction which will be considered */ +int JB4_JMF_Init( JB4_JMF_HANDLE h, int timeScale, unsigned int windowSize, + unsigned int windowDuration, unsigned int consideredFraction ) +{ + + /* check parameters */ + if( windowSize != 0U && consideredFraction * windowSize / 1000 < 2 ) + { + return -1; + } + if( consideredFraction > 1000 ) + { + return -1; + } + + /* store values */ + h->timeScale = timeScale; + h->maxWindowDuration = windowDuration; + h->consideredFraction = consideredFraction; + + JB4_CIRCULARBUFFER_Init( h->fifo, windowSize ); + JB4_CIRCULARBUFFER_Init( h->offsetFifo, windowSize ); + JB4_CIRCULARBUFFER_Init( h->timeStampFifo, windowSize ); + + h->nElementsToIgnore = windowSize * ( 1000 - consideredFraction ) / 1000; + return 0; +} + +/* function to calculate delay for the current packet */ +int JB4_JMF_PushPacket( JB4_JMF_HANDLE h, uint32_t sysTime, uint32_t rtpTimeStamp ) +{ + int32_t rtpTimeDiff, sysTimeDiff; + int32_t offset, delay; + + + /* check if this is the first entry */ + if( h->firstPacketPushed == 0 ) + { + h->firstPacketPushed = 1; + h->lastSysTime = sysTime; + h->lastRtpTimeStamp = rtpTimeStamp; + return 0; + } + + rtpTimeDiff = rtpTimeStamp - h->lastRtpTimeStamp; + sysTimeDiff = sysTime - h->lastSysTime; + offset = sysTime - rtpTimeStamp; + + /* get the delay (yes, signed!!!!) */ + delay = sysTimeDiff - rtpTimeDiff + h->lastDelay; + + /* remember old values */ + h->lastSysTime = sysTime; + h->lastRtpTimeStamp = rtpTimeStamp; + /* reset delay if absolute value is greater than 60s + * to avoid overflow caused by clockdrift */ + if( delay > 60 * h->timeScale || delay < -60 * h->timeScale ) + { + h->lastDelay = 0; + } + else + { + h->lastDelay = delay; + } + + JB4_JMF_pushBack( h, delay, offset, rtpTimeStamp ); + + return 0; +} + +/* function to get the current jitter */ +int JB4_JMF_Jitter( const JB4_JMF_HANDLE h, uint32_t *jitter ) +{ + JB4_CIRCULARBUFFER_ELEMENT min, percentile; + + /* sanity check (must not be empty) and return invalid result if there is only one entry */ + if( JB4_CIRCULARBUFFER_Size( h->fifo ) < 2U ) + { + return -1; + } + + JB4_CIRCULARBUFFER_MinAndPercentile( h->fifo, h->nElementsToIgnore, &min, &percentile ); + + /* return the difference between the highest considered and the smallest value */ + *jitter = 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 */ +int JB4_JMF_MinOffset( const JB4_JMF_HANDLE h, int32_t *offset ) +{ + JB4_CIRCULARBUFFER_ELEMENT min; + + if( JB4_CIRCULARBUFFER_IsEmpty( h->offsetFifo ) ) + { + return -1; + } + + JB4_CIRCULARBUFFER_Min( h->offsetFifo, &min ); + + *offset = min; + + return 0; +} + + +/***************************************************************************** + **************************** private functions ****************************** + *****************************************************************************/ + +/* helper function to add entry at back of the buffer */ +static void JB4_JMF_pushBack( JB4_JMF_HANDLE h, int32_t delay, int32_t offset, uint32_t time ) +{ + int32_t minTime, maxTime; + uint32_t 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 ); + if( maxTime > minTime ) + { + duration = maxTime - minTime; + while( duration > h->maxWindowDuration ) + { + JB4_JMF_popFront( h ); + minTime = JB4_CIRCULARBUFFER_Front( h->timeStampFifo ); + if( maxTime <= minTime ) + { + break; + } + duration = 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 000000000..c5d65b5b4 --- /dev/null +++ b/lib_dec/jbm_jb4_jmf.h @@ -0,0 +1,42 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 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 "jbm_types.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 */ +/**@{ */ +int 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 + * @param windowSize the window size of the fifo in number of packets + * @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 */ +int JB4_JMF_Init( JB4_JMF_HANDLE h, int timeScale, unsigned int windowSize, + unsigned int windowDuration, unsigned int consideredFraction ); +/**@} */ + +/**@name functions to push packets and get the current jitter rate */ +/**@{ */ +/** function to calculate jitter for the current packet */ +int JB4_JMF_PushPacket( JB4_JMF_HANDLE h, uint32_t sysTime, uint32_t rtpTimeStamp ); +/** function to get the current jitter */ +int JB4_JMF_Jitter( const JB4_JMF_HANDLE h, uint32_t *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 */ +int JB4_JMF_MinOffset( const JB4_JMF_HANDLE h, int32_t *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 000000000..27fa1fca0 --- /dev/null +++ b/lib_dec/jbm_jb4sb.c @@ -0,0 +1,1389 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + + +#include "wmc_auto.h" +/*! \file jbm_jb4sb.c EVS Jitter Buffer Management Interface */ + +/* system headers */ +#include +#include +#include +#include "options.h" +#define WMC_TOOL_SKIP +/* instrumentation */ +/* local headers */ +#include "jbm_jb4_circularbuffer.h" +#include "jbm_jb4_inputbuffer.h" +#include "jbm_jb4_jmf.h" +#include "jbm_jb4sb.h" +#include "prot.h" + + +#define JB4_MIN(a,b) ((a)>(b) ? (b) : (a)) +#define JB4_MAX(a,b) ((a)>(b) ? (a) : (b)) + +#define MAXOFFSET 10 + +/*! Calculates the difference between two RTP timestamps - the diff is positive, if B 'later', negative otherwise */ +static int32_t JB4_rtpTimeStampDiff( uint32_t tsA, uint32_t tsB ); +/* function to calculate different options for the target playout delay */ +static void JB4_targetPlayoutDelay( const JB4_HANDLE h, uint32_t *targetMin, + uint32_t *targetMax, uint32_t *targetDtx, uint32_t *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 int JB4_adaptPlayout( JB4_HANDLE h, uint32_t sysTime, uint32_t extBufferedTime, + JB4_DATAUNIT_HANDLE *pDataUnit, uint32_t *scale, uint32_t *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, uint32_t sysTime, bool_t *prebuffer ); +/*! function for playout adaptation while active (no DTX) */ +static void JB4_adaptActivePlayout( JB4_HANDLE h, uint32_t sysTime, + uint32_t extBufferedTime, uint32_t *scale, uint32_t *maxScaling ); +/*! function for playout adaptation while DTX */ +static void JB4_adaptDtxPlayout( JB4_HANDLE h, uint32_t sysTime, bool_t *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 int JB4_inspectBufferForDropping( const JB4_HANDLE h, bool_t *dropEarly, uint32_t *buffered ); +/* function to look into the buffer and check if it makes sense to drop a data unit during DTX */ +static int JB4_checkDtxDropping( const JB4_HANDLE h ); +/*! function to estimate the short term jitter */ +static void JB4_estimateShortTermJitter( JB4_HANDLE h, uint32_t rcvTime, uint32_t rtpTimeStamp ); +/*! function to pop a data unit from the buffer */ +static void JB4_popFromBuffer( JB4_HANDLE h, uint32_t sysTime, JB4_DATAUNIT_HANDLE *pDataUnit ); +/*! function to drop a data unit from the buffer - updates nShrinked */ +static void JB4_dropFromBuffer( JB4_HANDLE h, uint32_t 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 int JB4_playoutDelay( const JB4_HANDLE h, uint32_t playTime, + uint32_t rtpTimeStamp, uint32_t *delay ); +/*! function to update lastPlayoutDelay and lastTargetTime after popFromBuffer() */ +static void JB4_updateLastTimingMembers( JB4_HANDLE h, uint32_t playTime, uint32_t rtpTimeStamp ); +/*! function to compare the RTP time stamps of two data units: newElement==arrayElement ? 0 : (newElement>arrayElement ? +1 : -1) */ +static int JB4_inputBufferCompareFunction( const JB4_INPUTBUFFER_ELEMENT newElement, + const JB4_INPUTBUFFER_ELEMENT arrayElement, bool_t *replaceWithNewElementIfEqual ); + + +/*! Jitter Buffer Management Interface */ +struct JB4 +{ + /*! @name statistics for user */ + /*@{ */ + /*! the number of late lost data units */ + uint32_t nLateLost; + /*! the number of data units that were available (not NULL) at playout time */ + uint32_t nAvailablePopped; + /*! the number of data units that were not available (NULL) at playout time */ + uint32_t nUnavailablePopped; + /*! the number of unavailable pops since the last available one - used as temp value for nLost and nStretched */ + uint32_t nLostOrStretched; + /*! the number of data units that were lost at playout time */ + uint32_t nLost; + /*! the number of empty data units inserted for playout adaptation */ + uint32_t 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. */ + uint32_t nShrinked; + /*! the number of data units that were returned to create comfort noice (including NULL) */ + uint32_t nComfortNoice; + /*! the number of jitter induced concealment operations (as defined in 3GPP TS 26.114) */ + uint32_t jitterInducedConcealments; + /*! the target playout delay of the last returned data unit */ + uint32_t targetPlayoutDelay; + /*! the target playout time of the last returned data unit */ + uint32_t lastTargetTime; + /*@} */ + /*! @name internal configuration values - do not change!!! */ + /*@{ */ + /*! internal time scale for all calculations */ + int timeScale; + /*! internal frame duration in timeScale units */ + uint32_t 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 */ + uint32_t stJitter; + /*@} */ + /*! @name jitter buffer data */ + /*@{ */ + /*! true, if a data unit was already popped from the buffer */ + bool_t firstDataUnitPopped; + /*! system time of the previous JB4_PopDataUnit() call */ + uint32_t prevPopSysTime; + /*! RTP timestamp of the last played/dropped data unit that was actually available */ + uint32_t lastReturnedTs; + /*! true, if the last popped data unit contained no active signal, i.e. silence -> hint for DTX */ + bool_t lastPoppedWasSilence; + /*! the playout time minus the minimum offset of the last played data unit in microseconds */ + int32_t lastPlayoutOffset; + /*! RTP time stamp of the next data unit that is expected to be fetched from the buffer */ + uint32_t nextExpectedTs; + Word16 rfOffset2Active; + Word16 rfOffset3Active; + Word16 rfOffset5Active; + Word16 rfOffset7Active; + Word32 rfDelay; + /*! long term jitter measure FIFO */ + JB4_JMF_HANDLE ltJmf; + + uint32_t FecOffWinLen; + uint32_t FecOffWin[10]; + uint32_t optimum_offset; + + float netLossRate; + Word32 nPartialCopiesUsed; + Word32 last_nLost; + Word32 last_ntot; + + uint32_t totWin; + bool_t pre_partial_frame; + /*@} */ + + /*! @name members to store the data units */ + /*@{ */ + /*! the data unit buffer */ + JB4_INPUTBUFFER_HANDLE inputBuffer; + struct JB4_DATAUNIT memorySlots[MAX_JBM_SLOTS]; + JB4_DATAUNIT_HANDLE freeMemorySlots[MAX_JBM_SLOTS]; + unsigned int nFreeMemorySlots; + /*@} */ +}; /* JB4 */ + + +int JB4_Create( JB4_HANDLE *ph ) +{ + JB4_HANDLE h = calloc( 1, sizeof( struct JB4 ) ); + short iter; + + /* statistics for user */ + h->nLateLost = 0; + h->nAvailablePopped = 0; + h->nUnavailablePopped = 0; + h->nLostOrStretched = 0; + h->nLost = 0; + h->nStretched = 0; + h->nShrinked = 0; + h->nComfortNoice = 0; + h->jitterInducedConcealments = 0; + h->targetPlayoutDelay = 0; + h->lastTargetTime = 0; + /* internal configuration values - do not change!!! */ + h->timeScale = 0; + h->frameDuration = 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 = 0; + /* jitter buffer data */ + h->firstDataUnitPopped = false; + h->prevPopSysTime = 0; + h->lastReturnedTs = 0; + h->lastPoppedWasSilence = false; + h->lastPlayoutOffset = 0; + h->nextExpectedTs = 0; + h->rfOffset2Active = 0; + h->rfOffset3Active = 0; + h->rfOffset5Active = 0; + h->rfOffset7Active = 0; + h->rfDelay = 0; + JB4_JMF_Create( &h->ltJmf ); + h->pre_partial_frame = 0; + + h->FecOffWinLen = 0; + for (iter = 0; iter < 10; iter++ ) + { + h->FecOffWin[iter] = 0; + } + h->optimum_offset = 3; + h->totWin = 0; + h->netLossRate = 0.0f; + 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]; + } + h->nFreeMemorySlots = MAX_JBM_SLOTS; + *ph = h; + return 0; +} + +void JB4_Destroy( JB4_HANDLE *ph ) +{ + JB4_HANDLE h; + unsigned int i; + + if( !ph ) + { + return; + } + h = *ph; + 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; + +} + +int JB4_Init( JB4_HANDLE h, Word16 safetyMargin ) +{ + unsigned int ltJmfSize, stFifoSize, stJmfSize, stJmfAllowedLateLoss; + unsigned int inputBufferCapacity; + + /* internal timescale is 1000, frame duration is 20ms */ + h->timeScale = 1000; /* ms */ + h->frameDuration = 20; /* ms */ + + /* jitter buffer configuration values */ + h->safetyMargin = safetyMargin; + + /* long term jitter measure FIFO: 500 frames and 10s */ + ltJmfSize = 10000; + JB4_JMF_Init( h->ltJmf, h->timeScale, ltJmfSize / 20, ltJmfSize, 1000 ); + /* short term jitter evaluation */ + stFifoSize = 200; + stJmfSize = 50; + stJmfAllowedLateLoss = 60; /* 6%, e.g. ignore three packets out of 50 */ + JB4_CIRCULARBUFFER_Init( h->stJitterFifo, stFifoSize ); + JB4_CIRCULARBUFFER_Init( h->stTimeStampFifo, stFifoSize ); + JB4_JMF_Init( h->stJmf, h->timeScale, + stJmfSize, h->timeScale /* 1s */, 1000 - stJmfAllowedLateLoss ); + + inputBufferCapacity = MAX_JBM_SLOTS - 2; + 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; + dataUnit = h->freeMemorySlots[h->nFreeMemorySlots]; + h->freeMemorySlots[h->nFreeMemorySlots] = NULL; + 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; + h->nFreeMemorySlots++; +} + +int JB4_PushDataUnit( JB4_HANDLE h, JB4_DATAUNIT_HANDLE dataUnit, uint32_t rcvTime ) +{ + JB4_DATAUNIT_HANDLE droppedDataUnit = NULL; + + assert( dataUnit->duration == h->frameDuration ); + assert( dataUnit->timeScale == (unsigned int)h->timeScale ); + + /* ignore frames from too far in future (3 seconds) */ + if( h->firstDataUnitPopped && JB4_rtpTimeStampDiff( h->lastReturnedTs, dataUnit->timeStamp ) >= + (int32_t) (50 * 3 * 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(dataUnit->partialCopyOffset == 0) + { + if(h->rfOffset2Active > 0) + --h->rfOffset2Active; + if(h->rfOffset3Active > 0) + --h->rfOffset3Active; + if(h->rfOffset5Active > 0) + --h->rfOffset5Active; + if(h->rfOffset7Active > 0) + --h->rfOffset7Active; + } + else if(dataUnit->partialCopyOffset == 2) + { + h->rfOffset2Active = 100; + h->rfOffset3Active = 0; + h->rfOffset5Active = 0; + h->rfOffset7Active = 0; + } + else if(dataUnit->partialCopyOffset == 3) + { + h->rfOffset2Active = 0; + h->rfOffset3Active = 100; + h->rfOffset5Active = 0; + h->rfOffset7Active = 0; + } + else if(dataUnit->partialCopyOffset == 5) + { + h->rfOffset2Active = 0; + h->rfOffset3Active = 0; + h->rfOffset5Active = 100; + h->rfOffset7Active = 0; + } + else if(dataUnit->partialCopyOffset == 7) + { + h->rfOffset2Active = 0; + h->rfOffset3Active = 0; + h->rfOffset5Active = 0; + h->rfOffset7Active = 100; + } + } + + if(dataUnit->partial_frame != 0) + { + /* check for "real" late loss: a frame with higher/same timestamp was already returned to be fed into decoder */ + 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( dataUnit->partialCopyOffset <= 3 && JB4_rtpTimeStampDiff( h->nextExpectedTs, dataUnit->timeStamp ) < 0) + { + JB4_FreeDataUnit(h, dataUnit); + return 0; + } + else if( dataUnit->partialCopyOffset == 5 && JB4_rtpTimeStampDiff( h->nextExpectedTs, dataUnit->timeStamp ) < -40) + { + JB4_FreeDataUnit(h, dataUnit); + return 0; + } + else if( dataUnit->partialCopyOffset == 7 && 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(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 */ + if( h->firstDataUnitPopped && JB4_rtpTimeStampDiff( h->lastReturnedTs, dataUnit->timeStamp ) <= 0 ) + { + if( !dataUnit->silenceIndicator ) + { + ++h->nLateLost; + /* deletion of a speech frame because it arrived at the JBM too late */ + ++h->jitterInducedConcealments; + } + 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; +} + + + +int JB4_getFECoffset(JB4_HANDLE h) +{ + return (int)h->optimum_offset; +} +short JB4_FECoffset(JB4_HANDLE h) +{ + if ( h->netLossRate < 0.05 ) + { + return (short)0; + } + else + { + return (short)1; + } +} + + + +int JB4_PopDataUnit( JB4_HANDLE h, uint32_t sysTime, uint32_t extBufferedTime, + JB4_DATAUNIT_HANDLE *pDataUnit, uint32_t *scale, uint32_t *maxScaling ) +{ + int ret; + + assert( sysTime >= h->prevPopSysTime ); + if( sysTime > h->prevPopSysTime + 20 ) + { + h->lastPlayoutOffset += 20; + } + h->prevPopSysTime = sysTime; + + + 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 int32_t JB4_rtpTimeStampDiff( uint32_t tsA, uint32_t tsB ) +{ + int32_t ret; + /* do not dare to inline this function, casting to int32_t is important here! */ + ret = (int32_t)(tsB - tsA); + return ret; +} + +/* function to get the number of data units contained in the buffer */ +unsigned int JB4_bufferedDataUnits( const JB4_HANDLE h ) +{ + return JB4_INPUTBUFFER_Size( h->inputBuffer ); +} + + +/***************************************************************************** + **************************** private functions ****************************** + *****************************************************************************/ + + +/* function to calculate different options for the target playout delay */ +static void JB4_targetPlayoutDelay( const JB4_HANDLE h, uint32_t *targetMin, + uint32_t *targetMax, uint32_t *targetDtx, uint32_t *targetStartUp ) +{ + uint32_t ltJitter, extraDelayReserve; + /* adapt target delay to partial copy offset */ + extraDelayReserve = 0; + h->rfDelay = 0; + if(h->rfOffset7Active != 0) + { + h->rfDelay = 140; + } + else if(h->rfOffset5Active != 0) + { + h->rfDelay = 100; + } + else if(h->rfOffset2Active == 0 && h->rfOffset3Active == 0) + { + /* keep some delay reserve for RF-off */ + extraDelayReserve = 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 = h->stJitter + h->safetyMargin + h->rfDelay; + *targetMin = JB4_MIN( ltJitter + 20 + h->rfDelay + extraDelayReserve, *targetMax ); + *targetDtx = JB4_MIN( ltJitter + extraDelayReserve, h->stJitter ); + *targetStartUp = ( *targetMin + *targetMax + extraDelayReserve / 4) / 2; + } + else + { + /* combine long term and short term jitter to calculate target delay values */ + *targetMax = h->safetyMargin; + *targetMin = JB4_MIN( 20, *targetMax ); + *targetDtx = 0; + *targetStartUp = ( *targetMin + *targetMax ) / 2; + } + if(*targetStartUp < 60) + { + *targetStartUp = 60; + } +} + +/* function to do playout adaptation before playing the next data unit */ +static int JB4_adaptPlayout( JB4_HANDLE h, uint32_t sysTime, uint32_t extBufferedTime, + JB4_DATAUNIT_HANDLE *pDataUnit, uint32_t *scale, uint32_t *maxScaling ) +{ + bool_t stretchTime; + /* reset scale */ + if( scale == NULL || maxScaling == NULL ) + { + return -1; + } + *scale = 100; + *maxScaling = 0; + stretchTime = false; + + /* 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; + if( h->firstDataUnitPopped ) + { + ++h->nUnavailablePopped; + if( !h->lastPoppedWasSilence ) + { + ++h->nStretched; + /* jitter-induced insertion (e.g. buffer underflow) */ + ++h->jitterInducedConcealments; + } + } + /* add one frame to last playout delay */ + 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, uint32_t sysTime, + uint32_t extBufferedTime, uint32_t *scale, uint32_t *maxScaling ) +{ + JB4_DATAUNIT_HANDLE nextDataUnit; + bool_t convertToLateLoss, dropEarly; + uint32_t targetMin, targetMax, targetDtx, targetStartUp, targetMaxStretch; + uint32_t currPlayoutDelay, gap, buffered; + uint32_t dropGapMax, dropRateMin, dropRateMax, rate; + int32_t minOffTicks, tsDiffToNextDataUnit; + + JB4_targetPlayoutDelay( h, &targetMin, &targetMax, &targetDtx, &targetStartUp ); + if( JB4_JMF_MinOffset( h->ltJmf, &minOffTicks ) != 0 ) + { + return; + } + h->targetPlayoutDelay = ( targetMin + targetMax ) / 2; + + convertToLateLoss = false; + dropEarly = false; + dropGapMax = 200; + dropRateMin = 5; + dropRateMax = 200; /* 20% */ + + /* calculate current playout delay */ + currPlayoutDelay = h->lastPlayoutOffset - minOffTicks + extBufferedTime; + 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; + /* time stretching is expected -> increase playout delay to allow dropping the late frame */ + currPlayoutDelay -= tsDiffToNextDataUnit; + currPlayoutDelay += 1; + } + } + + /* decided between shrinking/stretching */ + if( currPlayoutDelay > targetMax ) /* time shrinking */ + { + gap = currPlayoutDelay - h->targetPlayoutDelay; + /* check if gap is positive and dropping is allowed + * and buffer contains enough time (ignoring one frame) */ + if( gap > 0 && + JB4_inspectBufferForDropping( h, &dropEarly, &buffered ) == 0 && + ( convertToLateLoss || + ( buffered + h->frameDuration + extBufferedTime ) > targetMax ) ) + { + if( convertToLateLoss ) + { + JB4_dropFromBuffer( h, sysTime ); + } + else if( dropEarly ) + { + JB4_dropFromBuffer( h, sysTime ); + ++h->nLostOrStretched; + } + else + { + /* limit gap to [gapMin,gapMax] and calculate current drop rate from gap */ + rate = JB4_MIN( (uint32_t)(gap), dropGapMax ) * + ( dropRateMax - dropRateMin ) / dropGapMax + dropRateMin; + *scale = ( 1000 - rate ) / 10; + *maxScaling = currPlayoutDelay - targetMax; + } + } + } + else /* time stretching */ + { + uint32_t delayWithClearedExternalBuffer; + /* 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 = currPlayoutDelay - extBufferedTime + h->frameDuration; + targetMaxStretch = targetMax - h->frameDuration; + if( delayWithClearedExternalBuffer + h->frameDuration <= targetMaxStretch && + currPlayoutDelay < targetMaxStretch && currPlayoutDelay < (uint32_t)(110 + h->rfDelay / 4)) + { + *scale = 120; + *maxScaling = targetMaxStretch - currPlayoutDelay; + } + } + +} + +/* function for playout adaptation while DTX */ +static void JB4_adaptDtxPlayout( JB4_HANDLE h, uint32_t sysTime, bool_t *stretchTime ) +{ + JB4_DATAUNIT_HANDLE firstDu; + uint32_t firstTs; + uint32_t targetMin, targetMax, targetDtx, targetStartUp; + uint32_t currPlayoutDelay, headRoom; + int32_t minOffTicks, tsDiffToNextDataUnit; + + JB4_targetPlayoutDelay( h, &targetMin, &targetMax, &targetDtx, &targetStartUp ); + if( JB4_JMF_MinOffset( h->ltJmf, &minOffTicks ) != 0 ) + { + return; + } + + /* calculate current playout delay */ + currPlayoutDelay = h->lastPlayoutOffset - minOffTicks; + + /* check for startup after DTX */ + if( !JB4_INPUTBUFFER_IsEmpty( h->inputBuffer ) ) + { + firstDu = (JB4_DATAUNIT_HANDLE)JB4_INPUTBUFFER_Front( h->inputBuffer ); + firstTs = firstDu->timeStamp; + + tsDiffToNextDataUnit = JB4_rtpTimeStampDiff( h->nextExpectedTs, firstTs ); + /* 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 += tsDiffToNextDataUnit; + } + if( !firstDu->silenceIndicator ) + { + /* recalculate playout delay based on first buffered data unit */ + JB4_playoutDelay( h, sysTime, firstTs, &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 += tsDiffToNextDataUnit; + } + h->targetPlayoutDelay = targetStartUp; + headRoom = 600 * h->frameDuration / 1000; + /* decided between shrinking/stretching */ + if( currPlayoutDelay > targetStartUp + headRoom ) /* time shrinking */ + { + if( JB4_checkDtxDropping( h ) ) + { + JB4_dropFromBuffer( h, sysTime ); + } + } + else if( currPlayoutDelay + headRoom < targetStartUp ) /* time stretching */ + { + *stretchTime = true; + } + return; + } + } + + /* adapt while DTX */ + h->targetPlayoutDelay = targetDtx; + + /* decided between shrinking/stretching */ + if( currPlayoutDelay >= targetDtx + h->frameDuration ) /* time shrinking */ + { + if( JB4_checkDtxDropping( h ) ) + { + JB4_dropFromBuffer( h, sysTime ); + } + } + else if( currPlayoutDelay + 500 * h->frameDuration / 1000 < targetDtx ) /* time stretching */ + { + *stretchTime = true; + } + +} + +/* function to do playout adaptation before playing the first data unit */ +static void JB4_adaptFirstPlayout( JB4_HANDLE h, uint32_t sysTime, bool_t *prebuffer ) +{ + uint32_t currPlayoutDelay; + JB4_DATAUNIT_HANDLE firstDu; + uint32_t targetMin, targetMax, targetDtx, targetStartUp; + if( JB4_INPUTBUFFER_IsEmpty( h->inputBuffer ) ) + { + *prebuffer = true; + return; + } + JB4_targetPlayoutDelay( h, &targetMin, &targetMax, &targetDtx, &targetStartUp ); + if(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; + return; + } + if( currPlayoutDelay + h->frameDuration / 2 < targetStartUp ) /* time stretching */ + { + *prebuffer = true; + } + else /* no adaptation, start playout */ + { + *prebuffer = false; + } +} + +/* function to look into the buffer and check if it makes sense to drop a data unit */ +static int JB4_inspectBufferForDropping( const JB4_HANDLE h, bool_t *dropEarly, uint32_t *buffered ) +{ + unsigned int inputBufferSize; + int16_t seqNrDiff; + int32_t bufferedTs; + uint32_t firstTs; + uint64_t beginTs, endTs; + JB4_DATAUNIT_HANDLE firstDu, secondDu, lastDu; + + assert( !h->lastPoppedWasSilence ); + *dropEarly = false; + *buffered = 0; + inputBufferSize = JB4_INPUTBUFFER_Size( h->inputBuffer ); + if( inputBufferSize == 0U ) + { + return -1; + } + + firstDu = (JB4_DATAUNIT_HANDLE)JB4_INPUTBUFFER_Front( h->inputBuffer ); + firstTs = firstDu->timeStamp; + /* check for loss: sequence number diff is exactly 0 in the valid case */ + if( h->firstDataUnitPopped ) + { + seqNrDiff = JB4_rtpTimeStampDiff( h->nextExpectedTs, firstTs ) / + (int32_t)(h->frameDuration); + } + else + { + seqNrDiff = 0; + } + if( seqNrDiff <= 0 ) + { + /* preview data unit to play after dropping */ + if( inputBufferSize <= 1U ) + { + /* data unit to play missing, avoid drop followed by concealment */ + return -1; + } + secondDu = JB4_INPUTBUFFER_Element( h->inputBuffer, 1 ); + if( firstTs + h->frameDuration != secondDu->timeStamp ) + { + /* data unit to play is not available, avoid drop followed by concealment */ + return -1; + } + /* calculate buffered time span */ + bufferedTs = 0; + } + else if( seqNrDiff == 2 ) + { + /* 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; + /* data unit to drop (first one) is lost */ + bufferedTs = 0; + } + + /* add time stamp difference of last and first actually buffered data unit */ + if( inputBufferSize == 1U ) + { + bufferedTs += h->frameDuration; + } + else + { + lastDu = (JB4_DATAUNIT_HANDLE)JB4_INPUTBUFFER_Back( h->inputBuffer ); + beginTs = firstTs; + endTs = lastDu->timeStamp + h->frameDuration; + /* check for RTP time stamp wrap around */ + if( endTs < beginTs ) + { + endTs = endTs + 0xFFFFFFFF; + } + bufferedTs += (int32_t)(endTs - beginTs); + } + + /* the result should not be negative */ + if( bufferedTs < 0 ) + { + return -1; + } + *buffered = bufferedTs; + + return 0; +} + +/* function to look into the buffer and check if it makes sense to drop a data unit */ +static int JB4_checkDtxDropping( const JB4_HANDLE h ) +{ + unsigned int inputBufferSize; + int16_t seqNrDiff; + JB4_DATAUNIT_HANDLE firstDu; + int droppingAllowed; + + + assert( h->firstDataUnitPopped ); + assert( h->lastPoppedWasSilence ); + droppingAllowed = 1; + inputBufferSize = JB4_INPUTBUFFER_Size( h->inputBuffer ); + if( inputBufferSize > 0U ) + { + firstDu = (JB4_DATAUNIT_HANDLE)JB4_INPUTBUFFER_Front( h->inputBuffer ); + /* check for loss: sequence number diff is exactly 0 in the valid case */ + seqNrDiff = JB4_rtpTimeStampDiff( h->nextExpectedTs, firstDu->timeStamp ) / + (int32_t)(h->frameDuration); + if( seqNrDiff <= 0 ) + { + /* no not drop first active frame */ + droppingAllowed = 0; + } + } + /* else: buffer empty, allow dropping FRAME_NO_DATA */ + + return droppingAllowed; +} + +/* function to estimate the short term jitter */ +static void JB4_estimateShortTermJitter( JB4_HANDLE h, uint32_t rcvTime, uint32_t rtpTimeStamp ) +{ + uint32_t jitter, duration, maxDuration; + int32_t minTime, maxTime; + JB4_CIRCULARBUFFER_ELEMENT maxElement, dequedElement; + + + jitter = 0; + JB4_JMF_PushPacket( h->stJmf, rcvTime, rtpTimeStamp ); + /* save delta delay */ + if( JB4_JMF_Jitter( h->stJmf, &jitter ) == 0 ) + { + /* compensate difference between both offsets */ + int32_t stOffset, ltOffset; + JB4_JMF_MinOffset( h->stJmf, &stOffset ); + JB4_JMF_MinOffset( h->ltJmf, <Offset ); + jitter += stOffset - ltOffset; + assert( (int)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 ); + if( maxTime > minTime ) + { + duration = maxTime - minTime; + maxDuration = 4 * h->timeScale; + while( duration > maxDuration ) + { + JB4_CIRCULARBUFFER_Deque( h->stJitterFifo, &dequedElement ); + JB4_CIRCULARBUFFER_Deque( h->stTimeStampFifo, &dequedElement ); + minTime = JB4_CIRCULARBUFFER_Front( h->stTimeStampFifo ); + if( maxTime <= minTime ) + { + break; + } + duration = maxTime - minTime; + } + } + } + + /* update h->stJitter */ + if( !JB4_CIRCULARBUFFER_IsEmpty( h->stJitterFifo ) ) + { + JB4_CIRCULARBUFFER_Max( h->stJitterFifo, &maxElement ); + /* round up to full frame duration */ + h->stJitter = (uint32_t)ceil( (double)( maxElement ) / h->frameDuration ) * + h->frameDuration; + } + +} + +/* function to pop a data unit from the buffer */ +static void JB4_popFromBuffer( JB4_HANDLE h, uint32_t sysTime, JB4_DATAUNIT_HANDLE *pDataUnit ) +{ + JB4_DATAUNIT_HANDLE nextDataUnit; + uint32_t nStretched; + int32_t tsDiff; + + JB4_DATAUNIT_HANDLE tempDataUnit; + unsigned int readlen ; + unsigned short i; + int frameoffset; + unsigned int maxval; + + Word32 lost, total_rec ; + + + + JB4_DATAUNIT_HANDLE partialCopyDu; + unsigned int searchpos, endpos; + + + /* check if a data unit is available */ + if( JB4_INPUTBUFFER_IsEmpty( h->inputBuffer ) ) + { + /* no data unit available */ + *pDataUnit = NULL; + h->nextExpectedTs += h->frameDuration; + if( h->lastPoppedWasSilence ) + { + ++h->nComfortNoice; + } + else + { + ++h->nUnavailablePopped; + ++h->nLostOrStretched; + } + + 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; + /* adjust sequence numbers to avoid handling first packet as loss */ + h->nextExpectedTs = nextDataUnit->timeStamp; + } + + /* check if the next available data unit should already be used (time stamp order) */ + tsDiff = JB4_rtpTimeStampDiff( nextDataUnit->timeStamp, h->nextExpectedTs ); + + h->totWin += 1; + if ( ( h->totWin > 3000) || ( h->FecOffWinLen > 100 ) ) + { + maxval = h->FecOffWin[1]; + h->optimum_offset = 1; + for( i = 2; i < MAXOFFSET ; i++ ) + { + if ( h->FecOffWin[i] > maxval ) + { + maxval = h->FecOffWin[i] ; + h->optimum_offset = i ; + } + h->FecOffWin[i] = 0; + } + h->FecOffWin[0] = 0; + h->FecOffWin[1] = 0; + h->totWin = 0; + h->FecOffWinLen = 0; + + + lost =h->nLost+ h->nPartialCopiesUsed - h->last_nLost ; + total_rec = h->nAvailablePopped + h->nUnavailablePopped - h->last_ntot ; + + if ( lost != 0 && total_rec != 0 ) + { + h->netLossRate = (float)lost/(float)total_rec; + } + else + { + h->netLossRate = 0.0f; + } + 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 ); + for ( i=0; i < readlen; i++) + { + tempDataUnit = (JB4_DATAUNIT_HANDLE)JB4_INPUTBUFFER_Element( h->inputBuffer, i ); + if ( ! tempDataUnit->partial_frame && !h->lastPoppedWasSilence ) + { + frameoffset = JB4_rtpTimeStampDiff( h->nextExpectedTs, tempDataUnit->timeStamp )/20 ; + + if ( frameoffset > 0 && frameoffset < MAXOFFSET ) + { + h->FecOffWin[frameoffset] += 1; + } + } + } + h->FecOffWinLen += 1; + + /* next expected data unit is missing + * -> conceal network loss, do time stretching or create comfort noise */ + *pDataUnit = NULL; + + /* update statistics */ + h->nextExpectedTs += h->frameDuration; + if( h->lastPoppedWasSilence ) + { + ++h->nComfortNoice; + } + else + { + ++h->nUnavailablePopped; + ++h->nLostOrStretched; + } + return; + } + + /* fetch the next data unit from buffer */ + *pDataUnit = nextDataUnit; + nextDataUnit->nextCoderType = INACTIVE; + if ( h->pre_partial_frame || nextDataUnit->partial_frame ) + { + 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 ( partialCopyDu->timeStamp == nextDataUnit->timeStamp + partialCopyDu->duration ) + { + get_NextCoderType( partialCopyDu->data, &nextDataUnit->nextCoderType); + break; + } + } + } + JB4_INPUTBUFFER_Deque( h->inputBuffer, (void**)pDataUnit ); + + if ( nextDataUnit->partial_frame ) + { + h->nPartialCopiesUsed += 1; + + readlen = JB4_INPUTBUFFER_Size( h->inputBuffer ); + for ( i=0; i < readlen; i++) + { + tempDataUnit = (JB4_DATAUNIT_HANDLE)JB4_INPUTBUFFER_Element( h->inputBuffer, i ); + if ( ! tempDataUnit->partial_frame && !h->lastPoppedWasSilence ) + { + frameoffset = JB4_rtpTimeStampDiff( h->nextExpectedTs, tempDataUnit->timeStamp )/20 ; + + if ( frameoffset > 0 && frameoffset < MAXOFFSET ) + { + h->FecOffWin[frameoffset] += 1; + } + } + } + h->FecOffWinLen += 1; + } + + /* update statistics */ + if( h->nLostOrStretched != 0U ) + { + assert( h->lastPoppedWasSilence == false ); + /* separate concealments since last available pop in lost and stretched */ + nStretched = tsDiff / h->frameDuration; + assert( h->nLostOrStretched >= nStretched ); + h->nLost += h->nLostOrStretched - nStretched; + /* jitter-induced insertion (e.g. buffer underflow) */ + h->jitterInducedConcealments += nStretched; + h->nStretched += nStretched; + h->nLostOrStretched = 0; + } + h->lastReturnedTs = nextDataUnit->timeStamp; + JB4_updateLastTimingMembers( h, sysTime, nextDataUnit->timeStamp ); + h->nextExpectedTs = nextDataUnit->timeStamp + h->frameDuration; + if( nextDataUnit->silenceIndicator ) + { + h->lastPoppedWasSilence = true; + ++h->nComfortNoice; + } + else + { + h->lastPoppedWasSilence = false; + ++h->nAvailablePopped; + } +} + +/* function to drop a data unit from the buffer - updates nShrinked */ +static void JB4_dropFromBuffer( JB4_HANDLE h, uint32_t sysTime ) +{ + JB4_DATAUNIT_HANDLE nextDataUnit, dataUnit; + int32_t tsDiff; + uint32_t 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; + /* adjust sequence numbers to avoid handling first packet as loss */ + h->nextExpectedTs = nextDataUnit->timeStamp; + } + + /* 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 += h->frameDuration; + /* substract one frame from last playout delay */ + h->lastPlayoutOffset -= h->frameDuration; + if( !h->lastPoppedWasSilence ) + { + ++h->nShrinked; + /* modification of the output timeline due to link loss */ + ++h->nUnavailablePopped; + ++h->nLostOrStretched; + } + if( h->lastTargetTime != 0U ) + { + 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 = tsDiff / h->frameDuration; + assert( h->nLostOrStretched >= nStretched ); + + /* convert stretching followed by shrinking to late-loss */ + if( nStretched > 0U ) + { + --nStretched; + ++h->nLateLost; + h->nLost += h->nLostOrStretched - nStretched; + /* jitter-induced insertion (e.g. buffer underflow) */ + h->jitterInducedConcealments += nStretched; + if( !dataUnit->silenceIndicator ) + { + /* JBM induced removal of a speech frame (intentional frame dropping) */ + ++h->jitterInducedConcealments; + } + h->nStretched += nStretched; + } + else + { + h->nLost += h->nLostOrStretched; + ++h->nShrinked; + if( !dataUnit->silenceIndicator ) + { + /* JBM induced removal of a speech frame (intentional frame dropping) */ + ++h->jitterInducedConcealments; + } + } + h->nLostOrStretched = 0; + } + else + { + if( !dataUnit->silenceIndicator ) + { + ++h->nShrinked; + /* JBM induced removal of a speech frame (intentional frame dropping) */ + ++h->jitterInducedConcealments; + } + } + + h->lastReturnedTs = dataUnit->timeStamp; + h->lastPoppedWasSilence = dataUnit->silenceIndicator; + h->nextExpectedTs = dataUnit->timeStamp + h->frameDuration; + + /* substract one frame from last playout delay */ + h->lastPlayoutOffset -= h->frameDuration; + if( h->lastTargetTime != 0U ) + h->lastTargetTime += h->frameDuration; + JB4_FreeDataUnit(h, dataUnit); +} + +/* function to calculate the playout delay based on the current jitter */ +static int JB4_playoutDelay( const JB4_HANDLE h, uint32_t playTime, uint32_t rtpTimeStamp, uint32_t *delay ) +{ + int32_t minOffTicks; + + if( JB4_JMF_MinOffset( h->ltJmf, &minOffTicks ) != 0 ) + { + return -1; + } + + *delay = playTime - minOffTicks - rtpTimeStamp; + + return 0; +} + +/* function to update lastPlayoutDelay and lastTargetTime after popFromBuffer() */ +static void JB4_updateLastTimingMembers( JB4_HANDLE h, uint32_t playTime, + uint32_t rtpTimeStamp ) +{ + int32_t minOffTicks; + + if( JB4_JMF_MinOffset( h->ltJmf, &minOffTicks ) != 0 ) + { + return; + } + + /* playoutDelay = playTime - minOffset - timeStamp */ + h->lastPlayoutOffset = playTime - rtpTimeStamp; + /* targetTime = minOffset + timeStamp + targetDelay */ + h->lastTargetTime = (uint32_t)( minOffTicks + rtpTimeStamp + h->targetPlayoutDelay ); + +} + +/* function to compare the RTP time stamps of two data units: newElement==arrayElement ? 0 : (newElement>arrayElement ? +1 : -1) */ +static int JB4_inputBufferCompareFunction( const JB4_INPUTBUFFER_ELEMENT newElement, + const JB4_INPUTBUFFER_ELEMENT arrayElement, bool_t *replaceWithNewElementIfEqual ) +{ + JB4_DATAUNIT_HANDLE newDataUnit, arrayDataUnit; + int32_t diff; + int result; + + *replaceWithNewElementIfEqual = 0; + newDataUnit = (JB4_DATAUNIT_HANDLE)newElement; + arrayDataUnit = (JB4_DATAUNIT_HANDLE)arrayElement; + diff = JB4_rtpTimeStampDiff( arrayDataUnit->timeStamp, newDataUnit->timeStamp ); + if( diff > 0 ) + { + result = 1; + } + else if( diff < 0 ) + { + result = -1; + } + else /* equal timestamps */ + { + result = 0; + if(newDataUnit->partial_frame == 0 && arrayDataUnit->partial_frame == 1) + { + /* replace partial copy with primary copy */ + *replaceWithNewElementIfEqual = 1; + } + else if(newDataUnit->partial_frame == arrayDataUnit->partial_frame && + newDataUnit->dataSize > arrayDataUnit->dataSize) + { + /* if both are primary or partial: take the one with higher size (e.g. higher bitrate) */ + *replaceWithNewElementIfEqual = 1; + } + } + return result; +} diff --git a/lib_dec/jbm_jb4sb.h b/lib_dec/jbm_jb4sb.h new file mode 100644 index 000000000..1acbc4b0b --- /dev/null +++ b/lib_dec/jbm_jb4sb.h @@ -0,0 +1,73 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +/** \file jbm_jb4sb.h EVS Jitter Buffer Management Interface */ + +#ifndef JBM_JB4SB_H +#define JBM_JB4SB_H JBM_JB4SB_H + +#include "jbm_types.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) */ + uint16_t sequenceNumber; + /** the RTP time stamp (32 bits) of this chunk in timeScale() units */ + uint32_t timeStamp; + /** the duration of this chunk in timeScale() units */ + uint32_t duration; + /** the RTP time scale, which is used for timeStamp() and duration() */ + uint32_t timeScale; + /** the receive time of the RTP packet in milliseconds */ + uint32_t rcvTime; + /** true, if the data unit contains only silence */ + bool_t silenceIndicator; + Word16 isAMRWB_IOmode; + /** for EVS payload */ + Word16 frameTypeIndex; + /** Q bit for AMR-WB IO */ + Word16 qBit; + + /** the binary encoded access unit */ + uint8_t *data; + /** the size of the binary encoded access unit [bits] */ + uint32_t dataSize; + + /** identify if the data unit has a partial copy of a previous frame */ + bool_t partial_frame; + /** offset of the partial copy contained in that frame or zero */ + int16_t partialCopyOffset; + int16_t nextCoderType; +}; +/** handle for jitter buffer data units */ +typedef struct JB4_DATAUNIT* JB4_DATAUNIT_HANDLE; + + +int JB4_Create( JB4_HANDLE *ph ); +void JB4_Destroy( JB4_HANDLE *ph ); + +int 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 ); + +int JB4_PushDataUnit( JB4_HANDLE h, JB4_DATAUNIT_HANDLE dataUnit, uint32_t rcvTime ); +int JB4_PopDataUnit( JB4_HANDLE h, uint32_t sysTime, uint32_t extBufferedTime, + JB4_DATAUNIT_HANDLE *pDataUnit, uint32_t *scale, uint32_t *maxScaling ); + +int JB4_getFECoffset(JB4_HANDLE h); + +short JB4_FECoffset(JB4_HANDLE h); + + +/** function to get the number of data units contained in the buffer */ +unsigned int JB4_bufferedDataUnits( const JB4_HANDLE h ); + +#endif /* JBM_JB4SB_H */ diff --git a/lib_dec/jbm_pcmdsp_apa.c b/lib_dec/jbm_pcmdsp_apa.c new file mode 100644 index 000000000..242aae16e --- /dev/null +++ b/lib_dec/jbm_pcmdsp_apa.c @@ -0,0 +1,1303 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +/*! @file jbm_pcmdsp_apa.c Adaptive Playout for Audio (apa). */ +#include "wmc_auto.h" + +/* system headers */ +#include +#include +#include /* malloc(), free() */ +#include +#include "options.h" +#define WMC_TOOL_SKIP +/* instrumentation */ +/* local headers */ +#include "jbm_pcmdsp_apa.h" +#include "jbm_pcmdsp_similarityestimation.h" +#include "jbm_pcmdsp_window.h" +#include "jbm_types.h" +#include "cnst.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 +{ + /* output buffer */ + int16_t buf_out[APA_BUF]; + uint16_t l_buf_out; + + /* Hann window */ + Float win[APA_BUF]; + uint16_t l_halfwin; + + /* sampling rate [Hz] */ + uint16_t rate; + + /* length of a segment [samples] */ + uint16_t l_seg; + + /* length of a frame [samples] */ + uint16_t l_frm; + + /* total number of processed input samples since apa_reset() */ + uint32_t l_in_total; + + /* sum of inserted/removed samples since last apa_set_scale() */ + int32_t diffSinceSetScale; + /* number of input frames since last apa_set_scale() */ + uint32_t nFramesSinceSetScale; + + /* current and previous scaling ratio [%] */ + uint16_t scale; + + /* minimum pitch length [samples] */ + uint16_t p_min; + + /* search length [samples] */ + uint16_t l_search; + + uint16_t wss; /* waveform subsampling */ + uint16_t css; /* correlation subsampling */ + + Float targetQuality; + uint16_t qualityred; /* quality reduction threshold */ + uint16_t qualityrise; /* quality rising for adaptive quality thresholds */ + + uint16_t last_pitch; /* last pitch/sync position */ + uint16_t bad_frame_count; /* # frames before quality threshold is lowered */ + uint16_t good_frame_count; /* # scaled frames */ + + uint16_t num_channels; /* number of input/output channels */ +}; + + +/* prototypes for local functions */ + +/** Converts the correlation energy to dB. */ +float apa_corrEnergy2dB(float energy, uint16_t corr_len); + +/** Increases the calculated quality of signals with low energy. */ +float apa_getQualityIncreaseForLowEnergy(float energydB); + +static bool_t logarithmic_search(const apa_state_t * ps, + const int16_t * signal, + int16_t s_start, + uint16_t inlen, + uint16_t offset, + uint16_t fixed_pos, + uint16_t corr_len, + uint16_t wss, + uint16_t css, + int16_t * synchpos); + +static bool_t find_synch (apa_state_t * ps, + const int16_t * in, + uint16_t l_in, + int16_t s_start, + uint16_t s_len, + int16_t fixed_pos, + uint16_t corr_len, + uint16_t offset, + Float * energy, + Float * quality, + int16_t * synch_pos); + +static bool_t copy_frm (apa_state_t * ps, + const int16_t frm_in[], + int16_t frm_out[], + uint16_t * l_frm_out); + +static bool_t shrink_frm (apa_state_t * ps, + const int16_t frm_in[], + uint16_t maxScaling, + int16_t frm_out[], + uint16_t * l_frm_out); + +static bool_t extend_frm (apa_state_t * ps, + const int16_t frm_in[], + int16_t frm_out[], + uint16_t * l_frm_out); + +/* +******************************************************************************** +* PUBLIC PROGRAM CODE +******************************************************************************** +*/ + +/* Allocates memory for state struct and initializes elements. */ +uint8_t apa_init (apa_state_t ** pps) +{ + apa_state_t *ps = NULL; + + /* 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; + return 0; +} + +/* Sets state variables to initial value. */ +void apa_reset (apa_state_t * ps) +{ + /* init state struct */ + ps->l_buf_out = 0; + ps->l_halfwin = 0; + ps->rate = 0; + ps->l_seg = 0; + ps->l_frm = 0; + ps->l_in_total = 0; + ps->diffSinceSetScale = 0; + ps->nFramesSinceSetScale = 0; + ps->scale = 100; + ps->p_min = 0; + ps->l_search = 0; + ps->wss = 1; + ps->css = 1; + ps->targetQuality = 0.0f; + ps->qualityred = 0; + ps->qualityrise = 0; + ps->last_pitch = 0; + ps->bad_frame_count = 0; + ps->good_frame_count = 0; + ps->num_channels = 0; +} + +/* Sets the audio configuration. */ +bool_t apa_set_rate (apa_state_t * ps, uint16_t rate, uint16_t num_channels) +{ + /* make sure pointer is valid */ + if (ps == (apa_state_t *) NULL) + { + return 1; + } + + /* check range */ + if ((rate < APA_MIN_RATE) || (rate > APA_MAX_RATE)) + { + return 1; + } + + /* reset state struct */ + apa_reset (ps); + + /* copy rate to state struct */ + ps->rate = rate; + + /* set number of channels */ + ps->num_channels = num_channels; + + /* + * 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 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. */ + ps->l_seg = (ps->rate / 100) * ps->num_channels; + + /* 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 should be independent of + * number of channels - same window applied to all channels */ + ps->l_halfwin = ps->rate / 100; + hannWindow (ps->l_halfwin*2, ps->win); + + /* set frame size */ + /* set to 320 samples at 16 kHz */ + ps->l_frm = (ps->rate / 50) * ps->num_channels; + + /* 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) */ + ps->p_min = (ps->rate / 400) * ps->num_channels; + + /* 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) */ + ps->l_search = (ps->rate / 80) * ps->num_channels; + + return 0; +} + +/* Set scaling. */ +bool_t apa_set_scale (apa_state_t * ps, uint16_t scale) +{ + /* make sure pointer is valid */ + if (ps == (apa_state_t *) NULL) + { + return 1; + } + + /* check range */ + if ((scale < APA_MIN_SCALE) || (scale > APA_MAX_SCALE)) + { + return 1; + } + + /* do nothing if same scale is set multiple times */ + /* (otherwise scale control is confused) */ + if (ps->scale == scale) + { + return 0; + } + + /* copy to state struct */ + ps->scale = scale; + + /* reset scaling statistics */ + ps->diffSinceSetScale = 0; + ps->nFramesSinceSetScale = 0; + + 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) +* +******************************************************************************** +*/ +bool_t apa_set_quality( + apa_state_t *ps, + float quality, + uint16_t qualityred, + uint16_t qualityrise) +{ + assert(ps != (apa_state_t *) NULL); + assert(-2.0f <= quality && quality <= 3.1f); + assert(qualityred > 0 && qualityred <= 20); + assert(qualityrise > 0 && qualityrise <= 20); + + ps->targetQuality = quality; + ps->qualityred = qualityred; + ps->qualityrise = qualityrise; + ps->bad_frame_count = 0; + ps->good_frame_count = 0; + 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 +* +******************************************************************************** +*/ +bool_t apa_set_complexity_options (apa_state_t * ps, uint16_t wss, uint16_t css) +{ + /* make sure pointer is valid */ + if (ps == (apa_state_t *) NULL) + return 1; + if (wss == 0 || wss > 1000) + return 1; + if (css == 0 || css > 1000) + return 1; + ps->wss = wss; + ps->css = css; + 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. +* +******************************************************************************** +*/ +bool_t 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; + 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%. +* +******************************************************************************** +*/ +uint8_t apa_exec (apa_state_t * ps, /* i/o: state struct */ + const int16_t a_in[], /* i: input samples */ + uint16_t l_in, /* i: number of input samples */ + uint16_t maxScaling, /* i: allowed number of inserted/removed samples */ + int16_t a_out[], /* o: output samples */ + uint16_t * l_out /* o: number of output samples */) +{ + uint16_t i; + int16_t frm_in[APA_BUF]; + uint16_t l_frm_out; + int16_t l_rem; + int32_t dl_scaled, dl_copied, l_frm_out_target; + int32_t expScaling, actScaling; + uint32_t statsResetThreshold, statsResetShift; + + statsResetThreshold = 1637; + statsResetShift = 2; + + /* make sure no invalid output is used */ + *l_out = 0; + l_frm_out = 0; + + /* 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( l_in != ps->l_frm ) + { + return 3; + } + + /* get target length */ + if(ps->scale > 100) + { + expScaling = (int32_t)((ps->l_frm * (ps->scale - 100.0f) / 100.0f) * (ps->nFramesSinceSetScale + 1) + 0.5f); + } + else if(ps->scale < 100) + { + expScaling = (int32_t)((ps->l_frm * (ps->scale - 100.0f) / 100.0f) * (ps->nFramesSinceSetScale + 1) - 0.5f); + } + else + { + expScaling = 0; + } + actScaling = ps->diffSinceSetScale - ps->l_frm; + 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 (ps->l_buf_out < ps->l_frm) + { + for (i = 0; i < ps->l_frm; i++) + { + a_out[i] = a_in[i]; + } + l_frm_out = ps->l_frm; + } + else + { + int16_t * buf_out_ptr = &(ps->buf_out[ps->l_buf_out - ps->l_frm]); + int16_t * frm_in_ptr = &(frm_in[ps->l_frm]); + + /* fill input frame */ + /* 1st input frame: previous output samples */ + for (i = 0; i < ps->l_frm; i++) + { + frm_in[i] = buf_out_ptr[i]; + } + /* 2nd input frame: new input samples */ + for (i = 0; i < ps->l_frm; i++) + { + frm_in_ptr[i] = a_in[i]; + } + /* no scaling */ + if (ps->scale == 100) + { + copy_frm (ps, frm_in, a_out, &l_frm_out); + } + /* shrink */ + else if (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( l_frm_out != ps->l_frm ) + { + if( maxScaling != 0U && + abs( (int16_t)(ps->l_frm - l_frm_out) ) > maxScaling ) + { + /* maxScaling exceeded -> discard scaled frame */ + copy_frm (ps, frm_in, a_out, &l_frm_out); + } + else if( abs(l_frm_out_target) > ps->l_frm ) /* ignore small difference */ + { + dl_copied = l_frm_out_target - (int32_t) ps->l_frm; + dl_scaled = l_frm_out_target - (int32_t) l_frm_out; + /* discard scaled frame if copied frame is closer to target length */ + if( abs(dl_copied) < 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 ((ps->l_buf_out + l_frm_out) > APA_BUF) + { + int16_t * buf_out_ptr1 = ps->buf_out; + int16_t * buf_out_ptr2; + + l_rem = (ps->l_frm - l_frm_out); + if (l_rem < 0) + { + l_rem = 0; + } + buf_out_ptr2 = &(ps->buf_out[ps->l_buf_out - l_rem]); + for (i = 0; i < l_rem; i++) + { + buf_out_ptr1[i] = buf_out_ptr2[i]; + } + ps->l_buf_out = l_rem; + } + /* append new output samples */ + if ((ps->l_buf_out + l_frm_out) > APA_BUF) + { + return 5; + } + { + int16_t * 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]; + } + } + ps->l_buf_out += l_frm_out; + + *l_out = l_frm_out; + /* update time */ + ps->l_in_total += ps->l_frm; + + if( abs(ps->diffSinceSetScale) < (0x7FFFFF - (l_frm_out - ps->l_frm)) && + ps->nFramesSinceSetScale < statsResetThreshold ) + { + ps->diffSinceSetScale += l_frm_out - ps->l_frm; + ++ps->nFramesSinceSetScale; + } + else /* scale statistics down to avoid overflow */ + { + ps->diffSinceSetScale >>= statsResetShift; + ps->nFramesSinceSetScale >>= statsResetShift; + } + + return 0; +} + + +/* +******************************************************************************** +* LOCAL PROGRAM CODE +******************************************************************************** +*/ + + +/* +******************************************************************************** +* +* Function : get_scaling_quality +* Tables : +* Compile Defines : +* Return : 0 on success, 1 on failure +* Information : Uses pitch, half pitch, three halves and double pitch +* to evaluate the quality of the scaled frame by checking +* periodicity. +* Silence can be detected as additional feature. This must +* be set in global struct apa_state. +* +* If search length is very narrow then use fewer points +* to evaluate periodicity and silence. +* +* Computationally not very efficient by using normalized +* cross-correlation: Using sqrt() for energy calculation +* adds complexity. +* +* 03-AUG-04 S.Doehla initial version +* +******************************************************************************** +*/ +static void get_scaling_quality(const apa_state_t * ps, + const int16_t * signal, + uint16_t s_len, + uint16_t offset, + uint16_t corr_len, + uint16_t pitch, + Float * energydB, + Float * quality) +{ + Float maxEnergy = 0.0f; + Float qualityOfMaxEnergy = 0.0f; /* we measure the quality for all channels and select the one with highest energy */ + + Float half_pitch_cn = 0.0f; + Float pitch_cn = 0.0f; + Float three_halves_pitch_cn = 0.0f; + Float double_pitch_cn = 0.0f; + + Float pitch_energy = 0.0f; + Float half_pitch_energy = 0.0f; + Float three_halves_pitch_energy = 0.0f; + Float double_pitch_energy = 0.0f; + + uint16_t i = 0; + + for(i=0; inum_channels; i++) + { + Float energy; + offset = 0; + + pitch_cn = normalized_cross_correlation_self(signal, pitch+offset, offset, corr_len, + ps->num_channels * 2, &pitch_energy); + if(pitch_cn > 0.0f) + { + /* calculate correlation for double pitch */ + if( 2*pitch + offset + corr_len <= s_len ) + { + double_pitch_cn = normalized_cross_correlation_self(signal, 2*pitch + offset, + offset, corr_len, ps->num_channels * 2, &double_pitch_energy); + } + else + { + double_pitch_cn = pitch_cn; + double_pitch_energy = pitch_energy; + } + /* calculate correlation for three/half pitch */ + if( (3*pitch)/2 + offset + corr_len <= s_len ) + { + three_halves_pitch_cn = normalized_cross_correlation_self(signal, (3*pitch)/2 + offset, + offset, corr_len, ps->num_channels * 2, &three_halves_pitch_energy); + } + else + { + three_halves_pitch_cn = pitch_cn; + three_halves_pitch_energy = pitch_energy; + } + /* calculate correlation for half pitch */ + if( pitch/2 + offset + corr_len <= s_len ) + { + half_pitch_cn = normalized_cross_correlation_self(signal, pitch/2 + offset, + offset, corr_len, ps->num_channels * 2, &half_pitch_energy); + } + else + { + half_pitch_cn = pitch_cn; + half_pitch_energy = pitch_energy; + } + + /* combine correlation results */ + *quality = (half_pitch_cn * three_halves_pitch_cn) + (pitch_cn * double_pitch_cn); + energy = pitch_energy + half_pitch_energy + three_halves_pitch_energy + double_pitch_energy; + } + else + { + *quality = pitch_cn; /* value is negative, thus pass it */ + energy = pitch_energy; + } + + /* update the quality by the quality of the signal with the highest energy */ + if(energy > maxEnergy) + { + qualityOfMaxEnergy = *quality; + maxEnergy = energy; + } + + /* go to next channel */ + ++signal; + } + *quality = qualityOfMaxEnergy; + + /* increase calculated quality of signals with low energy */ + *energydB = apa_corrEnergy2dB(maxEnergy, corr_len); + *quality += apa_getQualityIncreaseForLowEnergy(*energydB); +} + +/* Converts the correlation energy to dB. */ +float apa_corrEnergy2dB(float energy, uint16_t corr_len) +{ + float energydB = 10.0f * (float)log10(energy / (32768.0f * 32768.0f * corr_len * 4.0f)); + return energydB; +} + +/* Increases the calculated quality of signals with low energy. */ +float apa_getQualityIncreaseForLowEnergy(float energydB) +{ + const float qualIncreaseMinEnergy = -65; + const float qualIncreaseMaxEnergy = -40; + float qualIncForLowEnergy = 0; + if(energydB < qualIncreaseMaxEnergy) + { + qualIncForLowEnergy = energydB; + if(qualIncForLowEnergy < qualIncreaseMinEnergy) + { + qualIncForLowEnergy = qualIncreaseMinEnergy; + } + if(qualIncForLowEnergy > qualIncreaseMaxEnergy) + { + qualIncForLowEnergy = qualIncreaseMaxEnergy; + } + qualIncForLowEnergy = (qualIncForLowEnergy - qualIncreaseMaxEnergy) / + (qualIncreaseMinEnergy - qualIncreaseMaxEnergy) * 2; + assert(qualIncForLowEnergy >= 0 && qualIncForLowEnergy <= 2); + } + 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 bool_t logarithmic_search(const apa_state_t * ps, + const int16_t * signal, + int16_t s_start, + uint16_t inlen, + uint16_t offset, + uint16_t fixed_pos, + uint16_t corr_len, + uint16_t wss, + uint16_t css, + int16_t * synchpos) +{ + int i; + Float coeff; + Float coeff_max; + int16_t s_start_old = 0; + uint16_t s_len_old = 0; + do + { + coeff_max = -FLT_MAX; /* will always be overwritten with result of first correlation */ + for (i = s_start; i < s_start+inlen; i += css) + { + if((wss == 1) && (ps->num_channels == 1)) + { + coeff = cross_correlation_self(signal, i+offset, fixed_pos+offset, corr_len); + } + else + { + coeff = cross_correlation_subsampled_self( signal, i+offset, fixed_pos+offset, + corr_len, wss*ps->num_channels); + } + + /* update max corr */ + if( ps->scale < 100 ) + { + /* shrinking: prefer greater synchpos for equal coeff */ + if (coeff >= coeff_max) + { + coeff_max = coeff; + *synchpos = i; + } + } + else + { + /* extending: prefer smaller synchpos for equal coeff */ + if (coeff > coeff_max) + { + coeff_max = coeff; + *synchpos = i; + } + } + } + /* backup old search range */ + s_start_old = s_start; + s_len_old = inlen; + + css = css/2; + inlen = inlen/2; + s_start = *synchpos - inlen/2; + if(s_start < s_start_old) + { + s_start = s_start_old; + } + if((s_start+inlen) > (s_start_old+s_len_old)) + { + inlen = s_start_old - s_start + s_len_old; + } + } + while (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. +* +* Typical example: +* +* 0 10 20 30 40 50 60 +* in[] = abcdefghijk_abcdefghijk_abcdefghijk_abcdEFGHIJk_abcdefghijk_a +* l_in = 61 +* offset = 30 | +* s_start = -20 <-------------------| +* s_len = 15 <-------------> | +* search range: *************** | +* fixed_pos = 10 |---------> +* corr_len = 6 | <----> +* template segment: | ****** +* synch_pos: -14 <-------------| +* +* All positions are given relative to offset. The +* search region starts at offset+s_start and ends +* at offset+s_start+s_len. The template segment +* starts at offset+fixed_pos and ends at +* offset+fixed_pos+corr_len. For correlation, the +* template segment (EFGHIJ) is matched against the +* segment in the search region, e.g., against (k_abcd) +* in the first search position. The search position +* with the best match (-14: EFGHIJ <-> efghij) is +* returned. +* +* 19-JUN-03 N.Faerber initial version +* 23-APR-04 S.Doehla added subsampling +* +******************************************************************************** +*/ +static bool_t find_synch (apa_state_t * ps, + const int16_t * in, + uint16_t l_in, + int16_t s_start, + uint16_t s_len, + int16_t fixed_pos, + uint16_t corr_len, + uint16_t offset, + Float * energy, + Float * quality, + int16_t * 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; + + logarithmic_search(ps, + in, + s_start, + s_len, + offset, + fixed_pos, + corr_len, + ps->wss, + ps->css * ps->num_channels, + synch_pos); + /* assert synch_pos is cleanly divisible by number of channels */ + assert( *synch_pos % ps->num_channels == 0 ); + + *quality = 0; + get_scaling_quality(ps, in, l_in, offset, corr_len, + abs(fixed_pos - *synch_pos), energy, quality); + ps->last_pitch = *synch_pos; + 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 bool_t copy_frm (apa_state_t * ps, + const int16_t frm_in[], int16_t frm_out[], uint16_t * l_frm_out) +{ + uint16_t 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]; + } + + /* set output length */ + *l_frm_out = ps->l_frm; + + 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 bool_t shrink_frm (apa_state_t * ps, + const int16_t frm_in[], uint16_t maxScaling, int16_t frm_out[], uint16_t * l_frm_out) +{ + bool_t findSynchResult = 0; + int16_t xtract, l_rem, s_start, s_end; + uint16_t i; + uint16_t over; + Float energy, quality = 0.0f; + uint16_t l_frm; + uint16_t l_seg; + + l_frm = ps->l_frm; + l_seg = ps->l_seg; + + /* only 2nd input frame is used */ + frm_in += l_frm; + + /* set search range */ + s_start = (ps->p_min / ps->num_channels) * ps->num_channels; + s_end = s_start + ps->l_search; + if ((s_end + l_seg) >= l_frm) + { + s_end = (l_frm - l_seg); + } + + /* calculate overlap position */ + if( isSilence( frm_in, l_seg, 10 ) ) + { + /* maximum scaling */ + energy = -65; + quality = 5; + if( maxScaling != 0U && s_end > maxScaling + 1 ) + { + xtract = maxScaling; + } + else + { + /* set to last valid element (i.e. element[len - 1] but note for stereo last element is last pair of samples) */ + xtract = s_end - ps->num_channels; + } + } + else + { + /* find synch */ + findSynchResult = find_synch (ps, frm_in, l_frm, + s_start, (uint16_t) (s_end - s_start), 0, + l_seg, 0, &energy, &quality, &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; + + /* test whether frame has sufficient quality */ + if(quality < (ps->targetQuality - (ps->bad_frame_count * 0.1f) + (ps->good_frame_count * 0.2f))) + { + /* not sufficient */ + over = 0; + if( ps->bad_frame_count < ps->qualityred ) + { + ++ps->bad_frame_count; + } + if( ps->good_frame_count > 0U ) + { + --ps->good_frame_count; + } + } + else + { + /* sufficient quality */ + if( ps->bad_frame_count > 0U ) + { + --ps->bad_frame_count; + } + if( ps->good_frame_count < ps->qualityrise ) + { + ++ps->good_frame_count; + } + } + + /* Calculate output data */ + if(over && xtract) + { + if (findSynchResult == 1) + { + return 1; + } + overlapAdd(frm_in, frm_in + xtract, frm_out, l_seg, ps->num_channels, + ps->win + ps->l_halfwin, ps->win); + } + else + { + xtract = 0; + for (i = 0; i < l_seg; i++) + { + frm_out[i] = frm_in[i]; + } + } + + /* append remaining samples */ + l_rem = l_frm - xtract - l_seg; + for (i = 0; i < l_rem; i++) + { + frm_out[l_seg + i] = frm_in[l_frm - l_rem + i]; + } + + /* set output length */ + *l_frm_out = 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 bool_t extend_frm (apa_state_t * ps, + const int16_t frm_in[], int16_t frm_out[], uint16_t * l_frm_out) +{ + bool_t findSynchResult = 0; + uint16_t l_frm_out_target; + uint16_t n, i; + int16_t N; + int16_t s[MAXN + 2], s_max, s_min; + int16_t xtract[MAXN + 2], sync_start, s_end; + uint16_t over[MAXN + 2]; + int16_t l_rem; + int16_t s_start = 0; + Float energy, quality = 0.0f; + uint16_t l_frm, l_seg; + const int16_t *fadeOut, *fadeIn; + int16_t *out; + + l_frm = ps->l_frm; + l_seg = ps->l_seg; + + /* number of segments/iterations */ + l_frm_out_target = (uint16_t) ((Float) l_frm * 1.5f); + N = (l_frm_out_target / l_seg) - 1; + if (N < 1) + { + N = 1; + } + if (N > MAXN) + { + return 1; + } + /* 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 = -(ps->l_search) - (ps->p_min); + /* (make sure not to exceed array dimension) */ + if (l_frm + s_min < 0) + { + s_min = -(l_frm); + } + s_max = l_frm - 2 * l_seg - ps->l_search; + if (s_max < s_min) + { + N = 1; + } + /* for just one segment start at s_min */ + if (N == 1) + { + s[2] = s_min; + } + /* else, spread linear in between s_min and s_max */ + /* (including s_min and s_max) */ + else + { + for (n = 2; n <= (N + 1); n++) + { + s[n] = s_min + ((s_max - s_min) * (n - 2)) / (N - 1); + } + } + + /* + * Planning Phase + */ + + xtract[1] = -(l_seg); /* make sync_start=0 in 1st iteration */ + n = 2; + { + /* define synch segment (to be correlated with search region) */ + sync_start = xtract[n - 1] + l_seg; + over[n] = 1; /* will be reset if overlap is not required */ + /* check end of search region: should be at least p_min */ + /* samples on the left of synch_start */ + if ((s[n] + ps->l_search) < (sync_start - (ps->p_min))) + { + s_start = s[n]; + s_end = s_start + ps->l_search; + } + else + { + /* shrink search region to enforce minimum shift */ + s_end = sync_start - (ps->p_min); + if (s[n] + ps->l_search < sync_start) + { + s_start = s[n]; /* just do it with normal start position */ + } + else if (n == (N + 1)) /* move search region left for last segment */ + { + s_start = s_end - (ps->l_search - ps->p_min); + } + else + { + over[n] = 0; /* don't search/overlap (just copy down) */ + } + } + + if (over[n]) + { + /* calculate overlap position */ + if( isSilence( frm_in, l_seg, 10 ) ) + { + /* maximum scaling */ + energy = -65; + quality = 5; + xtract[n] = s_start + ps->num_channels; + } + else + { + /* find synch */ + findSynchResult = find_synch( ps, frm_in, 2 * l_frm, + s_start, s_end - s_start, sync_start, + l_seg, l_frm, &energy, &quality, &xtract[n] ); + } + /* assert synch_pos is cleanly divisible by number of channels */ + assert( xtract[n] % ps->num_channels == 0 ); + + /* test for sufficient quality */ + if(quality < (ps->targetQuality - (ps->bad_frame_count * 0.1f) + (ps->good_frame_count * 0.2f))) + { + /* not sufficient */ + over[n] = 0; + xtract[n] = sync_start; + if( ps->bad_frame_count < ps->qualityred ) + { + ++ps->bad_frame_count; + } + if( ps->good_frame_count > 0U ) + { + --ps->good_frame_count; + } + } + else + { + /* sufficient quality */ + if( ps->bad_frame_count > 0U ) + { + --ps->bad_frame_count; + } + if( ps->good_frame_count < ps->qualityrise ) + { + ++ps->good_frame_count; + } + } + if (findSynchResult) + { + return 1; + } + } + else + { + xtract[n] = sync_start; + } + + } + + /* Calculate output data */ + for (n = 2; n <= N; n++) + { + if (over[n] && xtract[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 + (n - 2) * l_seg; + overlapAdd(fadeOut, fadeIn, out, l_seg, ps->num_channels, + ps->win + ps->l_halfwin, ps->win); + } + else + { + /* just copy down 1st half of current segment (= 2nd half of previous segment) */ + int16_t * frm_out_ptr; + const int16_t * frm_in_ptr; + frm_out_ptr = &(frm_out[(n - 2) * l_seg]); + frm_in_ptr = &(frm_in[l_frm + xtract[n]]); + for (i = 0; i < l_seg; i++) + { + frm_out_ptr[i] = frm_in_ptr[i]; + } + } + } + + /* append remaining samples */ + l_rem = l_frm - (xtract[N] + l_seg); + for (i = 0; i < l_rem; i++) + { + frm_out[(N - 1) * l_seg + i] = frm_in[2 * l_frm - l_rem + i]; + } + + /* set output length */ + *l_frm_out = (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 000000000..446c68002 --- /dev/null +++ b/lib_dec/jbm_pcmdsp_apa.h @@ -0,0 +1,105 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +/*! @file jbm_pcmdsp_apa.h Adaptive Playout for Audio (apa). */ + +#ifndef JBM_PCMDSP_APA_H +#define JBM_PCMDSP_APA_H JBM_PCMDSP_APA_H + +#include "jbm_types.h" + +/* +******************************************************************************** +* DEFINITION OF CONSTANTS +******************************************************************************** +*/ + +/* size of IO buffers (a_in[], a_out[]) for apa_exec() */ +#define APA_BUF 4096*3 + +/* min/max sampling rate [Hz] */ +#define APA_MIN_RATE 1000 +#define APA_MAX_RATE 48000 + +/* min/max scaling [%] */ +#define APA_MIN_SCALE 50 +#define APA_MAX_SCALE 150 + +#define APA_SM_SURROUND 1 +#define APA_SM_LOGARITHMIC 2 +#define APA_SM_FULLSUBSAMPLED 3 + +#define APA_SIM_CCF 11 +#define APA_SIM_NCCF 12 +#define APA_SIM_AMDF 13 +#define APA_SIM_SSE 14 + +/* +******************************************************************************** +* 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 */ +uint8_t 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! + * Typical sample rates: 8000, 16000, 22050, 44100. Must be in range [APA_MIN_RATE,APA_MAX_RATE]. + * 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 */ +bool_t apa_set_rate( + apa_state_t *ps, + uint16_t rate, + uint16_t 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 */ +bool_t apa_set_scale(apa_state_t *s, uint16_t scale); + +bool_t apa_set_complexity_options( + apa_state_t *s, + uint16_t wss, + uint16_t css); + +bool_t apa_set_quality( + apa_state_t *s, + float quality, + uint16_t qualityred, + uint16_t qualityrise); + +bool_t apa_exit( + apa_state_t **s); + +uint8_t apa_exec( + apa_state_t *s, + const int16_t a_in[], + uint16_t l_in, + uint16_t maxScaling, + int16_t a_out[], + uint16_t *l_out); + +#endif /* JBM_PCMDSP_APA_H */ diff --git a/lib_dec/jbm_pcmdsp_fifo.c b/lib_dec/jbm_pcmdsp_fifo.c new file mode 100644 index 000000000..14a5547b0 --- /dev/null +++ b/lib_dec/jbm_pcmdsp_fifo.c @@ -0,0 +1,164 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +/*! @file jbm_pcmdsp_fifo.c Ringbuffer (FIFO) with fixed capacity for audio samples */ +#include "wmc_auto.h" + +/* system headers */ +#include +#include +#include "options.h" +#define WMC_TOOL_SKIP +/* instrumentation */ +/* 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 */ + unsigned int size; + /** maximum allowed number of samples per channel */ + unsigned int capacity; + /** sample size in bytes per channel */ + unsigned int nBytesPerSampleSet; + + /** begin of the FIFO data (pointer to bytes) */ + uint8_t *dataBegin; + /** end of the FIFO data (pointer to bytes) */ + uint8_t *dataEnd; + /** position of next write operation (pointer to bytes) */ + uint8_t *dataWriteIterator; + /** position of next read operation (pointer to bytes) */ + uint8_t *dataReadIterator; +}; + + +/* Creates a FIFO. */ +int pcmdsp_fifo_create( PCMDSP_FIFO_HANDLE *ph ) +{ + PCMDSP_FIFO_HANDLE h = malloc( sizeof( struct PCMDSP_FIFO ) ); + + h->size = 0; + h->capacity = 0; + h->nBytesPerSampleSet = 0; + h->dataBegin = NULL; + h->dataEnd = NULL; + h->dataWriteIterator = NULL; + h->dataReadIterator = NULL; + + *ph = h; + + return 0; +} + +/* Destroys the FIFO. */ +void pcmdsp_fifo_destroy( PCMDSP_FIFO_HANDLE *ph ) +{ + PCMDSP_FIFO_HANDLE h; + + if( !ph ) + return; + h = *ph; + if( !h ) + return; + + if( h->dataBegin ) + free( h->dataBegin ); + free( h ); + *ph = NULL; + +} + +/* Initializes the FIFO with a fixed maximum allowed number audio samples. */ +int pcmdsp_fifo_init( PCMDSP_FIFO_HANDLE h, unsigned int nSamples, + unsigned int nChannels, unsigned int nBytesPerSample ) +{ + unsigned int nDataBytes; + + h->capacity = nSamples; + h->nBytesPerSampleSet = nChannels * nBytesPerSample; + nDataBytes = nSamples * h->nBytesPerSampleSet; + h->dataBegin = malloc(nDataBytes); + h->dataEnd = h->dataBegin + nDataBytes; + h->dataWriteIterator = h->dataBegin; + h->dataReadIterator = h->dataBegin; + + return 0; +} + +/* Writes the given audio data to the FIFO. */ +int pcmdsp_fifo_write( PCMDSP_FIFO_HANDLE h, const uint8_t *samples, unsigned int nSamplesPerChannel ) +{ + unsigned int nBytesToWrite; + + /* check for empty input buffer */ + if( nSamplesPerChannel == 0U ) + return 0; + /* check, if enough space left */ + if( nSamplesPerChannel > h->capacity - h->size ) + return -1; + + nBytesToWrite = nSamplesPerChannel * h->nBytesPerSampleSet; + if( h->dataWriteIterator + nBytesToWrite > h->dataEnd ) + { + /* wrap around: writing two parts */ + unsigned int bytesOfFirstPart, secondSize; + bytesOfFirstPart = h->dataEnd - h->dataWriteIterator; + secondSize = nBytesToWrite - bytesOfFirstPart; + memcpy( h->dataWriteIterator, samples, bytesOfFirstPart ); + memcpy( h->dataBegin, samples + bytesOfFirstPart, secondSize ); + h->dataWriteIterator = h->dataBegin + secondSize; + } + else + { + /* no wrap around: simple write */ + memcpy( h->dataWriteIterator, samples, nBytesToWrite ); + h->dataWriteIterator += nBytesToWrite; + } + h->size += nSamplesPerChannel; + + return 0; +} + +/* Reads the given number of audio samples from the FIFO. */ +int pcmdsp_fifo_read( PCMDSP_FIFO_HANDLE h, unsigned int nSamplesPerChannel, uint8_t *samples ) +{ + unsigned int nBytesToRead; + + /* check for empty output buffer */ + if( nSamplesPerChannel == 0U ) + return 0; + /* check, if enough bytes readable */ + if( nSamplesPerChannel > h->size ) + return -1; + + nBytesToRead = nSamplesPerChannel * h->nBytesPerSampleSet; + if( h->dataReadIterator + nBytesToRead > h->dataEnd ) + { + /* wrap around: reading two parts */ + unsigned int bytesOfFirstPart, nBytesOfSecondPart; + bytesOfFirstPart = h->dataEnd - h->dataReadIterator; + nBytesOfSecondPart = nBytesToRead - bytesOfFirstPart; + memcpy( samples, h->dataReadIterator, bytesOfFirstPart ); + memcpy( samples + bytesOfFirstPart, h->dataBegin, nBytesOfSecondPart ); + h->dataReadIterator = h->dataBegin + nBytesOfSecondPart; + } + else + { + /* no wrap around: simple read */ + memcpy( samples, h->dataReadIterator, nBytesToRead ); + h->dataReadIterator += nBytesToRead; + } + h->size -= nSamplesPerChannel; + + return 0; +} + +/* Returns the number of samples per channel that can be read (number of currently stored samples). */ +unsigned int 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 000000000..6a795930b --- /dev/null +++ b/lib_dec/jbm_pcmdsp_fifo.h @@ -0,0 +1,44 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +/*! @file jbm_pcmdsp_fifo.h Ringbuffer (FIFO) with fixed capacity for audio samples. */ + +#ifndef JBM_PCMDSP_FIFO_H +#define JBM_PCMDSP_FIFO_H JBM_PCMDSP_FIFO_H + +/* local headers */ +#include "jbm_types.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 */ +int 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) + * @param[in] nChannels number of audio channels + * @param[in] nBytesPerSample size in bytes per sample per channel + * @return 0 if succeeded */ +int pcmdsp_fifo_init( PCMDSP_FIFO_HANDLE h, unsigned int nSamples, + unsigned int nChannels, unsigned int 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 */ +int pcmdsp_fifo_write( PCMDSP_FIFO_HANDLE h, const uint8_t *samples, unsigned int 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 */ +int pcmdsp_fifo_read( PCMDSP_FIFO_HANDLE h, unsigned int nSamplesPerChannel, uint8_t *samples ); + +/** Returns the number of samples per channel that can be read (number of currently stored samples). */ +unsigned int pcmdsp_fifo_nReadableSamples( const PCMDSP_FIFO_HANDLE h ); + +#endif /* JBM_PCMDSP_FIFO_H */ diff --git a/lib_dec/jbm_pcmdsp_similarityestimation.c b/lib_dec/jbm_pcmdsp_similarityestimation.c new file mode 100644 index 000000000..7e921c604 --- /dev/null +++ b/lib_dec/jbm_pcmdsp_similarityestimation.c @@ -0,0 +1,102 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +/*! @file jbm_pcmdsp_similarityestimation.c Algorithms for correlation and similarity estimation. */ +#include "wmc_auto.h" + +/* system headers */ +#include +#include +#include "options.h" +#define WMC_TOOL_SKIP +/* local headers */ +#include "jbm_pcmdsp_similarityestimation.h" + + +/* Calculates cross correlation coefficient for template segment. */ +Float cross_correlation_self(const int16_t * signal, + uint16_t x, uint16_t y, uint16_t corr_len) +{ + Float c_c; + int j; + + c_c = 0.0f; + for (j = 0; j < corr_len; j++) + { + c_c += ((Float) signal[j + x] * (Float) signal[j + y]); + } + return c_c; +} + +/* Calculates cross correlation coefficient for template segment. */ +Float cross_correlation_subsampled_self(const int16_t * signal, + uint16_t x, uint16_t y, uint16_t corr_len, uint16_t subsampling) +{ + Float c_c; + int j; + + c_c = 0.0f; + for (j = 0; j < corr_len; j += subsampling) + { + c_c += ((Float) signal[j + x] * (Float) signal[j + y]); + } + return c_c; +} + +/* Calculates normalized cross correlation coefficient for template segment. */ +Float normalized_cross_correlation_self(const int16_t * signal, + uint16_t x, uint16_t y, uint16_t corr_len, + uint16_t subsampling, Float * energy) +{ + Float32 c_c; + Float32 energy_xy, energy_x, energy_y; + uint16_t j; + const int16_t *signal_a, *signal_b; + + c_c = 0.0f; + energy_x = 0.0f; + energy_y = 0.0f; + signal_a = &signal[x]; + signal_b = &signal[y]; + for (j = 0; j < corr_len; j += subsampling) + { + c_c += ((Float32) signal_a[j] * (Float32) signal_b[j]); + energy_x += ((Float32) signal_a[j]) * ((Float32) signal_a[j]); + energy_y += ((Float32) signal_b[j]) * ((Float32) signal_b[j]); + } + energy_xy = (Float32)sqrt((Float32)energy_x * (Float32)energy_y); + if(energy_xy < 1.0f) + { + energy_xy = 1.0f; /* conceal silent frames */ + } + + c_c = c_c / energy_xy; + *energy = energy_xy; + return c_c; +} + +/* Splits the signal into segments and checks if all of them have very low energy. */ +bool_t isSilence(const int16_t * signal, uint32_t len, uint32_t segments) +{ + uint32_t i, samplesPerSegment; + Float energy; + + energy = 0; + samplesPerSegment = len / segments; + for(i = 0; i < len; i++) + { + energy += (signal[i] / 32768.f) * (signal[i] / 32768.f); + if( ( i != 0U && i % samplesPerSegment == 0U ) || i + 1 == len ) + { + /* check energy of current segment */ + energy = 10 * (Float)log10( energy / samplesPerSegment ); + if( energy > -65 ) + { + return false; + } + energy = 0; + } + } + return true; +} diff --git a/lib_dec/jbm_pcmdsp_similarityestimation.h b/lib_dec/jbm_pcmdsp_similarityestimation.h new file mode 100644 index 000000000..8630df5de --- /dev/null +++ b/lib_dec/jbm_pcmdsp_similarityestimation.h @@ -0,0 +1,120 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +/*! @file jbm_pcmdsp_similarityestimation.h Algorithms for correlation and similarity estimation. */ + +#ifndef JBM_PCMDSP_SIMILARITYESTIMATION_H +#define JBM_PCMDSP_SIMILARITYESTIMATION_H JBM_PCMDSP_SIMILARITYESTIMATION_H + +/* local headers */ +#include "jbm_types.h" + +/* +******************************************************************************** +* +* 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 +* +* +* 23-JUL-04 S.Doehla initial version +* +******************************************************************************** +*/ +Float cross_correlation_self(const int16_t * signal, + uint16_t x, + uint16_t y, + uint16_t 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 +* +* +* 23-JUL-04 S.Doehla initial version +* +******************************************************************************** +*/ +Float cross_correlation_subsampled_self(const int16_t * signal, + uint16_t x, + uint16_t y, + uint16_t corr_len, + uint16_t 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. +* +* Complexity is very high due to many floating point +* operations and using squared root! +* +* 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 +* +* +* 23-JUL-04 S.Doehla initial version +* +******************************************************************************** +*/ +Float normalized_cross_correlation_self(const int16_t * signal, + uint16_t x, + uint16_t y, + uint16_t corr_len, + uint16_t subsampling, + Float * energy); + +/* Splits the signal into segments and checks if all of them have very low energy. */ +bool_t isSilence(const int16_t * signal, uint32_t len, uint32_t segments); + +#endif /* JBM_PCMDSP_SIMILARITYESTIMATION_H */ diff --git a/lib_dec/jbm_pcmdsp_window.c b/lib_dec/jbm_pcmdsp_window.c new file mode 100644 index 000000000..5f8ccd70b --- /dev/null +++ b/lib_dec/jbm_pcmdsp_window.c @@ -0,0 +1,90 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#define WMC_TOOL_SKIP +#include "jbm_pcmdsp_window.h" +#include "cnst.h" + +/*-----------------------------------------------------------------------* +* hannWindow() +* +* Generates a Hann window (cos-shaped) of length n +*-----------------------------------------------------------------------*/ + +void hannWindow( + uint16_t n, + Float * w +) +{ + uint16_t i; + Float arg; + + for (i = 0; i < n/2; i++) + { + arg = ((2.0f * EVS_PI) * i) / (Float) (n); + w[i] = (Float) ((1.0f - cos (arg)) / 2.0f); + } + + for ( ; i < n; i++) + { + w[i] = 1.0f - w[i-n/2]; + } + + return; +} + + +/*-----------------------------------------------------------------------* +* overlapAdd() +* +* Overlap/Add of two signal with a given window +*-----------------------------------------------------------------------*/ + +void overlapAdd( + const int16_t *fadeOut, + const int16_t *fadeIn, + int16_t *out, + uint16_t n, + uint16_t nChannels, + const float *fadeOutWin, + const float *fadeInWin +) +{ + float fdOutVal, fdInVal; + int16_t i, j, hannIter; + int32_t combinedVal; + + for(j = 0; j < nChannels; j++) + { + /* reset Hann window iterator to beginning (both channels use same window) */ + hannIter = 0; + for(i = j; i < n; i += nChannels) + { + fdOutVal = fadeOut[i] * fadeOutWin[hannIter]; + fdInVal = fadeIn[i] * fadeInWin[hannIter]; + /* round combinedVal value (taking care of sign) */ + combinedVal = (int32_t)( (fdInVal + fdOutVal) + 0.5 ); + + if( fdInVal + fdOutVal < 0.0 ) + combinedVal = (int32_t)( (fdInVal + fdOutVal) - 0.5 ); + /* saturate value */ + if (combinedVal > 32767) + { + combinedVal = 32767; + } + else if (combinedVal < -32768) + { + combinedVal = -32768; + } + out[i] = (int16_t) combinedVal; + hannIter++; + } + } + + return; +} diff --git a/lib_dec/jbm_pcmdsp_window.h b/lib_dec/jbm_pcmdsp_window.h new file mode 100644 index 000000000..95dc06586 --- /dev/null +++ b/lib_dec/jbm_pcmdsp_window.h @@ -0,0 +1,35 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +/*! @file jbm_jbm_pcmdsp_window.h Window functions. */ + +#ifndef JBM_PCMDSP_WINDOW_H +#define JBM_PCMDSP_WINDOW_H JBM_PCMDSP_WINDOW_H + +/* local headers */ +#include "jbm_types.h" + +/*! Generates a Hann window (cos-shaped) of length n. + * Roughly: + * + * 1 __ + * / \ + * 0 _/ \_ + * <------> + * n + */ +void hannWindow(uint16_t n, Float * w); + +/** 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 int16_t *fadeOut, const int16_t *fadeIn, int16_t *out, + uint16_t n, uint16_t nChannels, const float *fadeOutWin, const float *fadeInWin); + +#endif /* JBM_PCMDSP_WINDOW_H */ diff --git a/lib_dec/jbm_types.h b/lib_dec/jbm_types.h new file mode 100644 index 000000000..620093e5a --- /dev/null +++ b/lib_dec/jbm_types.h @@ -0,0 +1,70 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +/*! @file jbm_types.h Data types used for JBM. */ + +#ifndef JBM_TYPES_H +#define JBM_TYPES_H JBM_TYPES_H + +/************************** +* internally used types +***************************/ +#ifndef _WIN32 +#include /* part of C99 */ +#else + +#ifndef _UINT8_T +#define _UINT8_T +typedef unsigned char uint8_t; +#endif /* _UINT8_T */ + +#ifndef _INT8_T +#define _INT8_T +typedef signed char int8_t; +#endif /* _INT8_T */ + +#ifndef _UINT16_T +#define _UINT16_T +typedef unsigned short uint16_t; +#endif /* _UINT16_T */ + +#ifndef _INT16_T +#define _INT16_T +typedef signed short int16_t; +#endif /* _INT16_T */ + +#ifndef _UINT32_T +#define _UINT32_T +typedef unsigned int uint32_t; +#endif /* _UINT32_T */ + +#ifndef _INT32_T +#define _INT32_T +typedef signed int int32_t; +#endif /* _INT32_T */ + +#ifndef _UINT64_T +#define _UINT64_T +typedef unsigned __int64 uint64_t; +#endif /* _UINT64_T */ + +#ifndef _INT64_T +#define _INT64_T +typedef signed __int64 int64_t; +#endif /* _INT64_T */ + +#endif +#ifndef _BOOL_T +#define _BOOL_T +typedef unsigned char bool_t; +#endif /* _BOOL_T */ + +#define true (1) +#define false (0) + +typedef float Float; + +#include "typedef.h" + +#endif /* JBM_TYPES_H */ diff --git a/lib_dec/lead_deindexing.c b/lib_dec/lead_deindexing.c new file mode 100644 index 000000000..4425ab27c --- /dev/null +++ b/lib_dec/lead_deindexing.c @@ -0,0 +1,251 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include "rom_dec.h" + +/*-------------------------------------------------------------------* + * Local function prototype + *-------------------------------------------------------------------*/ +static void fcb_decode_pos(int index, int pos_vector[], int pulse_num, int pos_num); + +/*-------------------------------------------------------------------* + * re8_decode_base_index + * + * Decode RE8 base index + *-------------------------------------------------------------------*/ + +void re8_decode_base_index( + int n, /* i : codebook number (*n is an integer defined in {0,2,3,4,..,n_max}) */ + long I, /* i : index of c (pointer to unsigned 16-bit word) */ + int *x /* o : point in RE8 (8-dimensional integer vector) */ +) +{ + int i,j,k1,l,m,m1,m2; + int setor_8p_temp[8],setor_8p_temp_1[8],setor_8p_temp_2[8]= {0}; + int sign_8p; + int code_level; + const int *a1,*a2; + + int ka; + int offset; + int code_index; + int element_a10,element_a11,element_a12; + + + element_a11 = 0, + element_a12 = 0; + if (n < 2) + { + for (i=0; i<8; i++) + { + x[i]=0; + } + } + else + { + if ( I > 65519L ) + { + I = 0; + } + /*-------------------------------------------------------------------* + * 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 ( n <= 3 ) + { + for (i=1; i> k1 ; + + m = 0; + m1 = 0; + m2 = 0; + + element_a10 = a1[0]; + switch (code_level) + { + case 4: + + m2 = 1; /*a2[4];*/ + i = code_index & 1; + if (i == 0) + { + setor_8p_temp_2[0] = 0; + } + else + { + setor_8p_temp_2[0] = 1; + } + code_index = code_index >> 1; + + case 3: + + m = a2[2]; + m1 = a2[3]; + l = select_table22[m1][m]; + j = ( code_index * mult_avq_tab[l] ) >> shift_avq_tab[l]; + code_index = code_index - j * l; + fcb_decode_pos(code_index,setor_8p_temp_1,m,m1); + code_index = j; + element_a12 = a1[2]; + + case 2: + + m = a2[2]; + fcb_decode_pos(code_index,setor_8p_temp,8,m); + element_a11 = a1[1]; + } + + for (i=0; i<8; i++) + { + x[i] = element_a10; + } + + for (i=0; i 0 ) ) + { + m2 = 7; + } + for (i = 0; i < m2; i++) + { + if ( x[i] != 0) + { + if ( ( sign_8p >> m1 ) & 1 ) + { + x[i] *= -1; + } + m1 --; + } + } + + /*--------------------------------------------------------------------* + * recover the sign of last element if needed + *--------------------------------------------------------------------*/ + if ( k1 == 7 ) + { + m1 = 0; + + for (i=0; i<8; i++) + { + m1 += x[i] ; + } + if ( m1 & 3 ) + { + x[7] *= -1; + } + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * fcb_decode_pos + * + * base function for decoding position index + *-------------------------------------------------------------------*/ + +void fcb_decode_pos( + int index, /* i : Index to decoder */ + int pos_vector[], /* o : Position vector */ + int pulse_num, /* i : Number of pulses */ + int pos_num /* i : Number of positions */ +) +{ + int i,k,l; + int temp1,temp2; + + const int *select_table23; + const int *select_table24; + + k = index; + l = 0; + temp1 = pos_num; + temp2 = pulse_num+1; + + for( i=0; i= ACELP_11k60 ) + { + lp_flag = (short)get_next_indice( st, 1 ); + } + else + { + lp_flag = FULL_BAND; + } + } + + /*--------------------------------------------------------------------* + * Find pitch excitation with LP filter + *--------------------------------------------------------------------*/ + + if ( lp_flag == LOW_PASS ) + { + /* pointer positionning to avoid doing it inside the loop */ + if( codec_mode == MODE2 && L_frame == L_FRAME16k ) + { + for (i=0; i +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" +#include "basop_proto_func.h" + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ +static void lsf_mid_dec( Decoder_State *st, const float int_fs, float qlsp0[], float qlsp1[], short coder_type, float qlsp[], + const long core_brate, short ppp_mode, short nelp_mode, short prev_bfi, short *mid_lsf_int, short safety_net ); + +static void dqlsf_CNG( Decoder_State *st, float *lsf_q, unsigned int *p_offset_scale1, unsigned int *p_offset_scale2, short *p_no_scales ); + +/*---------------------------------------------------------------------* + * lsf_dec() + * + * LSF decoder + *---------------------------------------------------------------------*/ + +void lsf_dec( + Decoder_State *st, /* i/o: State structure */ + const short tc_subfr, /* i : TC subframe index */ + const short L_frame, /* i : length of the frame */ + const short coder_type, /* i : coding type */ + const short bwidth, /* i : input signal bandwidth */ + float *Aq, /* o : quantized A(z) for 4 subframes */ + short *LSF_Q_prediction, /* o : LSF prediction mode */ + float *lsf_new, /* o : de-quantized LSF vector */ + float *lsp_new, /* o : de-quantized LSP vector */ + float *lsp_mid /* o : de-quantized mid-frame LSP vector */ +) +{ + short i, nBits = 0; + float int_fs; + float tmp_old[M+1], tmp_new[M+1], enr_old = 0.0f, enr_new = 0.0f; + float lsf_diff = 0.0f; + + /* initialize */ + if( L_frame == L_FRAME ) + { + int_fs = INT_FS_12k8; + } + else /* L_frame == L_FRAME16k */ + { + int_fs = INT_FS_16k; + } + + /* Find the number of bits for LSF quantization */ + if ( st->core_brate == SID_2k40 ) + { + nBits = LSF_BITS_CNG; + } + else + { + if ( st->nelp_mode_dec == 0 && st->ppp_mode_dec == 0 ) + { + nBits = LSF_bits_tbl[LSF_BIT_ALLOC_IDX(st->core_brate, coder_type)]; + } + else if ( st->nelp_mode_dec == 1 ) + { + if ( coder_type == UNVOICED ) + { + if ( bwidth == NB ) + { + nBits = 32; + + } + else + { + nBits = 30; + + + } + } + } + else if ( st->ppp_mode_dec == 1 ) + { + nBits = 26; + + } + } + + /* LSF de-quantization */ + lsf_end_dec( st, coder_type, st->bwidth, nBits, lsf_new, st->mem_AR,st->mem_MA, int_fs, st->core_brate, + &st->offset_scale1[0][0], &st->offset_scale2[0][0], &st->offset_scale1_p[0][0], &st->offset_scale2_p[0][0], + &st->no_scales[0][0], &st->no_scales_p[0][0], &st->safety_net, NULL, LSF_Q_prediction, NULL ); + + /* convert quantized LSFs to LSPs */ + lsf2lsp( lsf_new, lsp_new, M, int_fs ); + + if( st->core_brate == 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; ilsf_adaptive_mean[i] = (st->lsfoldbfi1[i] + st->lsfoldbfi0[i] + lsf_new[i]) / 3; + } + + if( st->prev_bfi && (coder_type == TRANSITION) && (tc_subfr == (L_frame-L_SUBFR)) ) + { + lsf_diff = int_fs / (float)(2*(M+1)); + st->lsf_old[0] = lsf_diff; + + for ( i=1; ilsf_old[i] = st->lsf_old[i-1] + lsf_diff; + } + lsf2lsp( st->lsf_old, st->lsp_old, M, int_fs ); + } + + /*-------------------------------------------------------------------------------------* + * Mid-frame LSF decoding + * LSP interpolation and conversion of LSPs to A(z) + *-------------------------------------------------------------------------------------*/ + if( st->rate_switching_reset ) + { + /* extrapolation in case of unstable LSF convert */ + mvr2r( lsp_new, st->lsp_old, M ); + mvr2r( lsf_new, st->lsf_old, M ); + } + + lsf_mid_dec( st, int_fs, st->lsp_old, lsp_new, coder_type, lsp_mid, st->core_brate, st->ppp_mode_dec, st->nelp_mode_dec, + st->prev_bfi, &(st->mid_lsf_int), st->safety_net ); + + if ( !( st->prev_bfi && (coder_type == TRANSITION) && (tc_subfr == (L_frame-L_SUBFR)) ) ) + { + if (st->prev_bfi) + { + /* check, if LSP interpolation can be relaxed */ + lsp2a_stab( st->lsp_old, tmp_old, M); + enr_old = enr_1_Az( tmp_old, 2*L_SUBFR ); + + lsp2a_stab( lsp_new, tmp_new, M); + enr_new = enr_1_Az( tmp_new, 2*L_SUBFR ); + } + + if (st->prev_bfi) + { + if ( enr_new/enr_old < 0.3f ) + { + st->relax_prev_lsf_interp = -1; + if ( st->clas_dec == UNVOICED_CLAS || st->clas_dec == SIN_ONSET || st->clas_dec == INACTIVE_CLAS || coder_type == GENERIC || coder_type == TRANSITION ) + { + st->relax_prev_lsf_interp = 1; + } + } + } + } + + if( st->last_core == HQ_CORE && st->core == ACELP_CORE ) + { + /* update old LSPs/LSFs in case of HQ->ACELP core switching */ + mvr2r( lsp_mid, st->lsp_old, M ); + lsp2lsf( lsp_mid, st->lsf_old, M, int_fs ); + } + + /* LSP interpolation and conversion of LSPs to A(z) */ + int_lsp4( L_frame, st->lsp_old, lsp_mid, lsp_new, Aq, M, st->relax_prev_lsf_interp ); + + /*------------------------------------------------------------------* + * Check LSF stability (distance between old LSFs and current LSFs) + *------------------------------------------------------------------*/ + + st->stab_fac = lsf_stab( lsf_new, st->lsf_old, 0, st->L_frame); + + return; +} + + + +/*------------------------------------------------------------------------------------------* + * lsf_end_dec() + * + * De-quantize frame end LSF vector + *------------------------------------------------------------------------------------------*/ + +void lsf_end_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const short coder_type_org, /* i : coding type */ + const short bwidth, /* i : input signal bandwidth */ + const short nBits_in, /* i : number of bits used for ISF quantization*/ + float *qlsf, /* o : quantized LSFs in the cosine domain */ + float *mem_AR, /* i/o: quantizer memory for AR model */ + float *mem_MA, /* i/o: quantizer memory for MA model */ + const float int_fs, /* i : sampling frequency */ + long core_brate, /* i : Coding Bit Rate */ + unsigned int *p_offset_scale1, + unsigned int *p_offset_scale2, + unsigned int *p_offset_scale1_p, + unsigned int *p_offset_scale2_p, + short *p_no_scales, + short *p_no_scales_p, + short *safe_net, + int *lpc_param, + short *LSF_Q_prediction, /* o : LSF prediction mode */ + int * nb_indices +) +{ + float pred0[M]; /* Prediction for the safety-net quantizer (usually mean)*/ + float pred1[M], pred2[M]; /* Prediction for the predictive quantizer*/ + short stages0; /* Amount of stages used by safety-net quantizer*/ + short stages1; /* Amount of stages used by predictive quantizer*/ + short levels0[MAX_VQ_STAGES]; /* Sizes of different codebook stages for safety-net quantizer*/ + short levels1[MAX_VQ_STAGES]; /* Sizes of different codebook stages for predictive quantizer*/ + short i; + short TCQIdx[M/2+4]; + short bits0[MAX_VQ_STAGES], bits1[MAX_VQ_STAGES]; + int cumleft; + short lindice[MAX_VQ_STAGES+3]; /* Predictor selector needs 1 bit and the LVQ indice uses 3 shorts */ + short mode_lvq, mode_lvq_p; + short safety_net, predmode, stages, *levels; + const short *Bit_alloc1 = NULL, *bits; + short num_bits; + int * p_lpc_param; + + int nr_ind; + short nBits; + + short coder_type; + nBits = nBits_in; + + if( (coder_type_org == GENERIC) && (int_fs == INT_FS_16k) && (st->codec_mode == MODE1) ) + { + coder_type = (short)get_next_indice( st, 1 ); + coder_type += 2; + if( coder_type == GENERIC ) + { + nBits--; + } + } + else + { + coder_type = coder_type_org; + } + + /*--------------------------------------------------------------------------------* + * LSF de-quantization of SID frames + *--------------------------------------------------------------------------------*/ + + if ( core_brate == SID_2k40 ) + { + dqlsf_CNG( st, qlsf, p_offset_scale1, p_offset_scale2, p_no_scales ); + v_sort( qlsf, 0, M-1); + reorder_lsf( qlsf, MODE1_LSF_GAP, M, int_fs ); + + return; + } + + predmode = find_pred_mode(coder_type, bwidth, int_fs, &mode_lvq, &mode_lvq_p, st->total_brate); + + /*----------------------------------------------------------------* + * Calculate number of stages and levels for each stage based on the allowed bit allocation + * (subtract one bit for LSF predictor selection) + *----------------------------------------------------------------*/ + + lsf_allocate( nBits-(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; + if( predmode == 0 ) + { + safety_net = 1; + } + else if ( predmode == 1 ) + { + safety_net = 0; + } + else + { + if( st->codec_mode == MODE2 ) + { + nr_ind ++; + /* read from param_lpc */ + safety_net = p_lpc_param[0]; + p_lpc_param++; + } + else + { + safety_net = (short)get_next_indice( st, 1 ); + } + } + + *safe_net = safety_net; + + /*--------------------------------------------------------------------------* + * Read indices from array + *--------------------------------------------------------------------------*/ + + if ( safety_net ) + { + stages = stages0; + levels = levels0; + bits = bits0; + } + else + { + stages = stages1; + levels = levels1; + bits = bits1; + } + + if( st->codec_mode == MODE2 ) + { + /* VOICED_WB@16kHz */ + if ( int_fs == INT_FS_16k && coder_type == VOICED ) + { + *nb_indices = 10; + for(i=0; i<*nb_indices; i++) + { + TCQIdx[i] = (short)lpc_param[i]; + } + } + else + { + for ( i=0; i 0 ) + { + if ( cumleft > LEN_INDICE ) + { + cumleft -= LEN_INDICE; + num_bits = LEN_INDICE; + } + else + { + num_bits = (short)cumleft; + cumleft = 0; + } + + lindice[i+1] = *p_lpc_param++; + nr_ind++; + i++; + } + *nb_indices = nr_ind; + } + } + else + { + /* VOICED_WB@16kHz */ + if ( int_fs == INT_FS_16k && coder_type == VOICED ) + { + Bit_alloc1 = &BC_TCVQ_BIT_ALLOC_40B[1]; + TCQIdx[0] = safety_net; + for ( i=0; i 0 ) + { + if ( cumleft > LEN_INDICE ) + { + cumleft -= LEN_INDICE; + num_bits = LEN_INDICE; + } + else + { + num_bits = (short)cumleft; + cumleft = 0; + } + + lindice[i+1] = (short)get_next_indice( st, num_bits ); + i++; + } + } + } + + if( st->reset_mem_AR == 1 ) + { + for( i=0; imem_AR[i] = ModeMeans[mode_lvq][i]; + } + st->reset_mem_AR = 0; + } + + /*------------------------------------------------------------------------------------------* + * De-quantize LSF vector + *------------------------------------------------------------------------------------------*/ + + *LSF_Q_prediction = SAFETY_NET; + + /* VOICED_WB@16kHz */ + if( int_fs == INT_FS_16k && coder_type == VOICED ) + { + /* BC-TCVQ decoder */ + safety_net = qlsf_ARSN_tcvq_Dec_16k ( qlsf, TCQIdx, nBits-1 ); + + /* Update mem_MA */ + mvr2r( qlsf, mem_MA, M ); + + if( safety_net ) + { + mvr2r( ModeMeans[mode_lvq], pred0, M ); + } + else + { + for(i = 0; i < M; i++) + { + pred0[i] = ModeMeans[mode_lvq][i] + Predictors[mode_lvq_p][i]*(mem_AR[i]-ModeMeans[mode_lvq][i]); + } + *LSF_Q_prediction = AUTO_REGRESSIVE; + } + v_add( qlsf, pred0, qlsf, M ); + } + else + { + /* Safety-net */ + mvr2r( ModeMeans[mode_lvq], pred0, M ); + + /* for mem_MA update */ + for (i=0; iBER_detect = st->BER_detect | + vq_dec_lvq( 1, qlsf, &lindice[1], stages0, M, mode_lvq, levels0[stages0-1], + p_offset_scale1, p_offset_scale2, p_offset_scale1_p, p_offset_scale2_p, p_no_scales, p_no_scales_p ); + + v_add( qlsf, pred0, qlsf, M ); + v_sub( qlsf, pred1, mem_MA, M); + } + else + { + st->BER_detect = st->BER_detect | + vq_dec_lvq( 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 ); + + if( predmode == 1 ) /* MA only */ + { + mvr2r(qlsf, mem_MA, M); + v_add( qlsf, pred1, qlsf, M ); + *LSF_Q_prediction = MOVING_AVERAGE; + } + else + { + /* AR */ + for ( i=0; imode_lvq = mode_lvq; + + + return; +} + + +/*-------------------------------------------------------------------* + * lsf_mid_dec() + * + * Decode mid-frame LSFs + *-------------------------------------------------------------------*/ + +void lsf_mid_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const float int_fs, /* i : internal (ACELP) sampling frequency */ + float qlsp0[], /* i : quantized LSPs from frame beginning */ + float qlsp1[], /* i : quantized LSPs from frame end */ + short coder_type, /* i : Coder type */ + float qlsp[], /* o : quantized LSPs */ + const long core_brate, /* i : core bitrate */ + short ppp_mode, + short nelp_mode, + short prev_bfi, + short *mid_lsf_int, + short safety_net +) +{ + short j, idx; + short nb_bits; + float qlsf0[M], qlsf1[M], qlsf[M]; + const float *ratio = NULL; + short bad_spacing; + + bad_spacing = 0; + + /* Convert LSPs to LSFs */ + lsp2lsf( qlsp0, qlsf0, M, int_fs ); + lsp2lsf( qlsp1, qlsf1, M, int_fs ); + + /* Codebook selection */ + if( ppp_mode == 1 ) + { + nb_bits = 1; + ratio = &(tbl_mid_voi_wb_1b[0]); + } + else if( nelp_mode == 1 ) + { + nb_bits = 4; + ratio = &(tbl_mid_unv_wb_4b[0]); + } + else + { + nb_bits = mid_LSF_bits_tbl[LSF_BIT_ALLOC_IDX(core_brate, coder_type)]; + + /* codebook selection */ + if( coder_type == VOICED ) + { + switch ( nb_bits ) + { + case 5: + { + ratio = tbl_mid_voi_wb_5b; + break; + } + case 4: + { + ratio = tbl_mid_voi_wb_4b; + break; + } + } + } + else if( coder_type == UNVOICED ) + { + ratio = tbl_mid_unv_wb_5b; + } + else + { + /* GENERIC, TRANSITION, AUDIO and INACTIVE */ + switch ( nb_bits ) + { + case 5: + { + ratio = tbl_mid_gen_wb_5b; + break; + } + case 2: + { + ratio = tbl_mid_gen_wb_2b; + break; + } + } + } + } + + /* Retrieve mid-frame LSF index */ + idx = (short)get_next_indice( st, nb_bits ); + + /* Calculation of mid-LSF vector */ + for(j=0; j 0 && j < M && qlsf[j] < qlsf[j-1] + LSF_GAP_MID ) + { + qlsf[j] = qlsf[j-1] + LSF_GAP_MID; + } + + } + } + else + { + /* otherwise, use regular LSF spacing and ordering as in the encoder */ + for (j=0; j 0 && j < M && qlsf[j] < qlsf[j-1] + LSF_GAP_MID ) + { + qlsf[j] = qlsf[j-1] + LSF_GAP_MID; + } + + } + } + + if( prev_bfi ) + { + /* continue redoing mid-LSF interpolation with 0.4 in order not to propagate the error */ + *mid_lsf_int = 1; + } + + if( safety_net ) + { + /* safety-net encountered -> stop redoing mid-LSF interpolation with 0.4 */ + *mid_lsf_int = 0; + } + + reorder_lsf( qlsf, LSF_GAP_MID, M, int_fs ); + /* convert back to LSPs */ + lsf2lsp( qlsf, qlsp, M, int_fs ); + + return; +} + +/*----------------------------------------------------------------------------------------------* + * dqlsf_CNG() + * + * 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( + Decoder_State *st, /* i/o: decoder state structure */ + float *lsf_q, /* o : decoded LSFs */ + unsigned int *p_offset_scale1, /* i : offset for 1st LVQ subvector */ + unsigned int *p_offset_scale2, /* i : offset for second LVQ subvector */ + short *p_no_scales /* i : number of scales for LVQ struct */ +) +{ + short indice[4]; + + indice[0] = (short)get_next_indice( st, 4 ); + indice[1] = (short)get_next_indice( st, LEN_INDICE ); + indice[2] = (short)get_next_indice( st, LSF_BITS_CNG - 4 - LEN_INDICE ); + + st->BER_detect = st->BER_detect | + deindex_lvq_cng( &indice[1], lsf_q, indice[0], LSF_BITS_CNG-4, p_offset_scale1, p_offset_scale2, p_no_scales ); + /* 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_q). If the last decoded LSF coefficient (lsf_q[15]) 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. */ + + v_add( lsf_q, &CNG_SN1[indice[0]*M], lsf_q, M ); + + if( ((st->L_frame == L_FRAME16k)&&(lsf_q[M-1]<=WB_LIMIT_LSF)) || ((st->L_frameWB_LIMIT_LSF)) ) + { + st->BER_detect = 1; + } + return; +} diff --git a/lib_dec/lsf_msvq_ma_dec.c b/lib_dec/lsf_msvq_ma_dec.c new file mode 100644 index 000000000..6b258d907 --- /dev/null +++ b/lib_dec/lsf_msvq_ma_dec.c @@ -0,0 +1,262 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include "basop_proto_func.h" + +/*---------------------------------------------------------------------* + * lsf_msvq_ma_decprm() + * + * + *---------------------------------------------------------------------*/ + +int lsf_msvq_ma_decprm( + Decoder_State *st, + int *param_lpc, + int core, + int acelp_mode, + int acelp_midLpc, + int narrowBand, + int sr_core +) +{ + int i, nbits_lpc; + int bits_midlpc=5; + short bits0[MAX_VQ_STAGES], bits1[MAX_VQ_STAGES], stages0, stages1, stages, + levels0[MAX_VQ_STAGES], levels1[MAX_VQ_STAGES], * bits; + short predmode, mode_lvq, mode_lvq_p, safety_net; + + + if( (sr_core==INT_FS_16k)&&(acelp_mode==UNVOICED) ) + { + predmode = find_pred_mode(GENERIC, 1-narrowBand/*st->bwidth*/, sr_core, + &mode_lvq, &mode_lvq_p, st->total_brate); + } + else + { + if (core == TCX_20_CORE) + { + predmode = find_pred_mode(AUDIO, 1-narrowBand/*st->bwidth*/, sr_core, + &mode_lvq, &mode_lvq_p, st->total_brate ); + } + else + { + predmode = find_pred_mode(acelp_mode, 1-narrowBand/*st->bwidth*/, sr_core, + &mode_lvq, &mode_lvq_p, st->total_brate ); + } + } + + lsf_allocate( 31-(predmode>>1), mode_lvq, mode_lvq_p, &stages0, &stages1, levels0, levels1, bits0, bits1 ); + + nbits_lpc = 0; + + if (predmode == 2) + { + /* there is choice between SN and AR prediction */ + safety_net = get_next_indice(st, 1); + + if (safety_net==1) + { + stages = stages0; + bits = bits0; + } + else + { + stages = stages1; + bits = bits1; + } + *param_lpc = safety_net; + param_lpc++; + nbits_lpc++; + + } + else + { + stages = stages1; + bits = bits1; + } + + for (i=0; inext_bit_pos; + + for (i=0; inext_bit_pos - start_bit_pos; +} diff --git a/lib_dec/nelp_dec.c b/lib_dec/nelp_dec.c new file mode 100644 index 000000000..0e4d364aa --- /dev/null +++ b/lib_dec/nelp_dec.c @@ -0,0 +1,184 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*-------------------------------------------------------------------* + * nelp_decoder() + * + * NELP decoder + *-------------------------------------------------------------------*/ + +void nelp_decoder( + Decoder_State *st, /* i/o: decoder static memory */ + float *exc_nelp, /* o : adapt. excitation/total exc*/ + float *exc, /* o : adapt. excitation exc */ + short bfi, /* i : frame error rate */ + const short coder_type, /* i : coding type */ + float *gain_buf +) +{ + int i, fid = 0; + float ptr[L_FRAME], filtRes[L_FRAME], gain_fac; + float Gains[10],Gain,E3,E2,R; + float ptr_tmp[L_FRAME]; + int iG1, iG2[2]; + + if ((st->last_nelp_mode_dec == 1) && (st->bwidth != st->last_bwidth)) + { + st->last_nelp_mode_dec = 0; + } + + if ( coder_type == UNVOICED && st->bwidth == NB ) + { + if ( st->last_nelp_mode_dec != 1 ) + { + set_f( st->bp1_filt_mem_nb_dec, 0, 7*2 ); + } + } + else if ( coder_type == UNVOICED && (st->bwidth == WB || st->bwidth == SWB) ) + { + if ( st->last_nelp_mode_dec != 1 ) + { + set_f( st->bp1_filt_mem_wb_dec, 0, 4*2 ); + } + } + + if (st->last_nelp_mode_dec != 1) + { + set_f( st->shape1_filt_mem_dec, 0, 20 ); + set_f( st->shape2_filt_mem_dec, 0, 20 ); + set_f( st->shape3_filt_mem_dec, 0, 20 ); + } + + if (bfi == 0) + { + if(st->rf_frame_type == RF_NELP && st->use_partial_copy) + { + iG1 = st->rf_indx_nelp_iG1; + iG2[0] = st->rf_indx_nelp_iG2[0]; + iG2[1] = st->rf_indx_nelp_iG2[1]; + } + else + { + /* Do Unvoiced/NELP Decoding */ + iG1 = get_next_indice( st, 5 ); + iG2[0] = get_next_indice( st, 6 ); + iG2[1] = get_next_indice( st, 6 ); + } + + if ( coder_type == UNVOICED && (st->bwidth == WB || st->bwidth == SWB) ) + { + if( st->rf_frame_type == RF_NELP && st->use_partial_copy ) + { + fid = st->rf_indx_nelp_fid; + } + else + { + fid = get_next_indice( st, 2 ); + } + } + + dequantize_uvg( iG1, iG2, Gains, st->bwidth ); + } + else + { + for (i=1,Gain=0.001f; i<=L_SUBFR; i++) + { + Gain += SQR(exc[-i]); + } + + Gain = (float) (sqrt(Gain/L_SUBFR)); + Gain *= 0.8f;/* Some scale down of energy since it is an erasure */ + + set_f(Gains, Gain, 10); + } + + if ( coder_type == UNVOICED && (st->bwidth == WB || st->bwidth == SWB) ) + { + gain_fac = 1.16f; + } + else + { + gain_fac = 1.37f; + } + + generate_nelp_excitation( &(st->nelp_dec_seed), Gains, ptr, gain_fac ); + + if ( coder_type == UNVOICED && (st->bwidth == WB || st->bwidth == SWB) ) + { + polezero_filter( ptr, ptr_tmp, L_FRAME, bp1_num_coef_wb, bp1_den_coef_wb, 4, st->bp1_filt_mem_wb_dec ); + mvr2r( ptr_tmp, ptr, L_FRAME ); + } + + if ( coder_type == UNVOICED && st->bwidth == NB ) + { + polezero_filter( ptr, ptr_tmp, L_FRAME, bp1_num_coef_nb_fx_order7, bp1_den_coef_nb_fx_order7, 7, st->bp1_filt_mem_nb_dec ); + mvr2r(ptr_tmp,ptr,L_FRAME); + } + + for( i=0, E3=0.001f; ibwidth == WB || st->bwidth == SWB) ) + { + polezero_filter( ptr, ptr_tmp, L_FRAME, shape1_num_coef, shape1_den_coef, 10, st->shape1_filt_mem_dec ); + mvr2r( ptr_tmp, ptr, L_FRAME ); + + switch(fid) + { + case 1: + /* Update other filter memory */ + polezero_filter( ptr, filtRes, L_FRAME, shape3_num_coef, shape3_den_coef, 10, st->shape3_filt_mem_dec ); + + /* filter the residual to desired shape */ + polezero_filter( ptr, ptr_tmp, L_FRAME, shape2_num_coef, shape2_den_coef, 10, st->shape2_filt_mem_dec ); + mvr2r( ptr_tmp, ptr, L_FRAME ); + + break; + case 2: + /* Update other filter memory */ + polezero_filter( ptr, filtRes, L_FRAME, shape2_num_coef, shape2_den_coef, 10, st->shape2_filt_mem_dec ); + + /* filter the residual to desired shape */ + polezero_filter( ptr, ptr_tmp, L_FRAME, shape3_num_coef, shape3_den_coef, 10, st->shape3_filt_mem_dec ); + + mvr2r( ptr_tmp, ptr, L_FRAME ); + + break; + default: + /* Update other filter memory */ + polezero_filter( ptr, filtRes, L_FRAME, shape2_num_coef, shape2_den_coef, 10, st->shape2_filt_mem_dec ); + + polezero_filter( ptr, filtRes, L_FRAME, shape3_num_coef, shape3_den_coef, 10, st->shape3_filt_mem_dec ); + + break; + } + + for (i=0, E2=0.001f; i +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*------------------------------------------------------------------------* + * Local functions + *------------------------------------------------------------------------*/ + +static void dequant_peaks( Decoder_State *st, float *vect_out, const float *peak_gain ); + +static short hvq_dec_pos( Decoder_State *st, short *pos_vec, const short length, const short num_peaks ); +static short sparse_dec_pos(Decoder_State *st, short *out, const short length ); + +/*-------------------------------------------------------------------------- + * hvq_dec() + * + * HVQ decoder + *--------------------------------------------------------------------------*/ + +void hvq_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const short num_bits, /* i : Number of available bits */ + const long core_brate, /* i : Core bit-rate */ + const short *ynrm, /* i : Envelope coefficients */ + short *R, /* i/o: Bit allocation/updated bit allocation */ + float *noise_level, /* o : Noise level */ + short *peak_idx, /* o : Peak position vector */ + short *Npeaks, /* o : Total number of peaks */ + float *coefsq_norm, /* o : Output vector */ + const short core +) +{ + short i; + short bits; + short noise_level_idx; + + bits = num_bits; + + for( i = 0; i < HVQ_BWE_NOISE_BANDS; i++ ) + { + noise_level_idx = (short) get_next_indice( st, 2 ); + noise_level[i] = usdequant( noise_level_idx, 0.0f, 0.1f ); + + bits -= 2; + } + + peak_vq_dec( st, coefsq_norm, (short)core_brate, bits, ynrm, R, peak_idx, + Npeaks, core ); +} + +/*-------------------------------------------------------------------------- + * peak_vq_dec() + * + * Vector de-quantization of MDCT peaks + *--------------------------------------------------------------------------*/ + +void peak_vq_dec( + Decoder_State *st, /* i/o: decoder state structure */ + float *coefs_out, /* o : Output coefficient vector */ + const short brate, /* i : Core bitrate */ + const short num_bits, /* i : Number of bits for HVQ */ + const short *ynrm, /* i : Envelope coefficients */ + short *R, /* i/o: Bit allocation/updated bit allocation */ + short *vq_peak_idx, /* o : Peak position vector */ + short *Npeaks, /* o : Number of peaks */ + const short core /* i : Core type */ +) +{ + short vq_peaks, i, j, k, FlagN, hcode_l, diff; + short bin_th, max_peaks, pvq_bands; + short nf_seed = RANDOM_INITSEED; + short nf_gains_idx[HVQ_NF_GROUPS], pgain_difidx[HVQ_MAX_PEAKS_32k], pvq_norm[MAX_PVQ_BANDS]; + short gain_bits_array[MAX_PVQ_BANDS]; + short pos_bits; + float nf_gains[HVQ_NF_GROUPS], peak_gains[HVQ_MAX_PEAKS_32k]; + int manE_peak, manPkEnrg; /* (man, exp) representation ported from BASOP for interoperability */ + short expE_peak, expPkEnrg; + float pvq_vector[HVQ_PVQ_BUF_LEN]; + short res_vec[HVQ_THRES_BIN_32k]; + short k_sort[HVQ_MAX_PVQ_WORDS]; + short pvq_inp_vector[HVQ_PVQ_BUF_LEN]; + short npulses[MAX_PVQ_BANDS]; + short pvq_bits, Rk[MAX_PVQ_BANDS]; + float fg_pred[NB_SFM_MAX]; + short Rk_f[MAX_PVQ_BANDS]; /* Q3 */ + short sel_bnds[HVQ_NUM_SFM_24k]; + short n_sel_bnds; + short hvq_band_end[MAX_PVQ_BANDS]; + short hvq_band_start[MAX_PVQ_BANDS]; + short hvq_band_width[MAX_PVQ_BANDS]; + short n; + short s; + float normq; + + set_s( gain_bits_array, 0, MAX_PVQ_BANDS ); + set_f( pvq_vector, 0.0f, HVQ_PVQ_BUF_LEN ); + set_s( npulses, 0, MAX_PVQ_BANDS ); + set_s( pvq_inp_vector, 0, HVQ_PVQ_BUF_LEN ); + + /* Set bitrate dependent variables */ + if (brate == HQ_24k40) + { + max_peaks = HVQ_MAX_PEAKS_24k; + bin_th = HVQ_THRES_BIN_24k; + } + else + { + max_peaks = HVQ_MAX_PEAKS_32k; + bin_th = HVQ_THRES_BIN_32k; + } + + /* Get number of peaks */ + vq_peaks = (short) get_next_indice( st, 5 ); + vq_peaks = max_peaks - vq_peaks; + *Npeaks = vq_peaks; + diff = 5; + + /* safety check in case of bit errors */ + if( *Npeaks < HVQ_MIN_PEAKS ) + { + st->BER_detect = 1; + vq_peaks = HVQ_MIN_PEAKS; + *Npeaks = HVQ_MIN_PEAKS; + } + + /* De-quantize peak positions */ + for (i = 0; i < bin_th; i++) + { + res_vec[i] = 0; + } + + /* Unpack HVQ codewords */ + pos_bits = hvq_dec_pos(st, res_vec, bin_th, vq_peaks); + diff += pos_bits; + + for (i = 0, j = 0; i < bin_th && j < vq_peaks; i++) /* safety check in case of bit errors */ + { + if (res_vec[i]) + { + vq_peak_idx[j++] = i; + } + } + + /* safety check in case of bit errors */ + if( j < vq_peaks ) + { + st->BER_detect = 1; + vq_peaks = j - 1; + *Npeaks = j - 1; + } + + /* Huffman or differential coding */ + FlagN = (short) get_next_indice( st, 1 ); + + /* De-quantize peak gains */ + pgain_difidx[0] = (short) get_next_indice( st, GAIN0_BITS ); + + /* safety check in case of bit errors */ + if( pgain_difidx[0] > 44 ) + { + st->BER_detect = 1; + pgain_difidx[0] = 44; + } + peak_gains[0] = dicn_pg[pgain_difidx[0]]*sign((float) res_vec[vq_peak_idx[0]]); + + hcode_l = 0; + if(FlagN) + { + huff_dec( st, 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 += pgain_huffsizn[pgain_difidx[i]]; + } + } + else + { + for (i = 1; i < vq_peaks; i++) + { + pgain_difidx[i] = (short) get_next_indice( st, GAINI_BITS ); + hcode_l += GAINI_BITS; + } + } + + for (i = 1; i < vq_peaks; i++) + { + pgain_difidx[i] += pgain_difidx[i - 1] - 15; + + /* safety check in case of bit errors */ + if( pgain_difidx[i] > 44 || pgain_difidx[i] < 0) + { + st->BER_detect = 1; + pgain_difidx[i] = 44; + } + + peak_gains[i] = dicn_pg[pgain_difidx[i]]*sign((float) res_vec[vq_peak_idx[i]]); + } + + /* Scale up peak gains and accumulate peak energy */ + /* Simulating BASOP code for interoperability */ + manE_peak = 0; + expE_peak = 32; + for (i = 0; i < vq_peaks; i++) + { + peak_gains[i] *= 4.0f; + manPkEnrg = manPkEnrg_tbl[pgain_difidx[i]]; + expPkEnrg = expPkEnrg_tbl[pgain_difidx[i]]; + floating_point_add(&manE_peak, &expE_peak, manPkEnrg, expPkEnrg); + } + + /* Number of bits used for peak gain quantization */ + diff += FLAGN_BITS + GAIN0_BITS + hcode_l; + + /* De-quantize peaks */ + for (i = 0; i < vq_peaks; i++) + { + dequant_peaks( st, &coefs_out[vq_peak_idx[i]-2], &peak_gains[i] ); + + diff += 9; + } + + for (i = 0; i < HVQ_NF_GROUPS; i++) + { + nf_gains_idx[i] = (short) get_next_indice( st, 5 ); + nf_gains[i] = 0.5f*dicn[nf_gains_idx[i]]; + diff += 5; + } + + pvq_bits = num_bits - diff; + + /* Calculate number of PVQ bands to code and assign bits */ + pvq_bands = hvq_pvq_bitalloc(pvq_bits, brate, st->bwidth, ynrm, manE_peak, expE_peak, Rk, R, sel_bnds, &n_sel_bnds ); + + /* safety check in case of bit errors */ + if (pvq_bands == 0) + { + st->BER_detect = 1; + } + + pvq_bits -= HVQ_PVQ_GAIN_BITS*pvq_bands; + + /* Get band limits for concatenated PVQ target */ + hvq_concat_bands( pvq_bands, sel_bnds, n_sel_bnds, hvq_band_start, hvq_band_width, hvq_band_end ); + + s = 0; + for (k = 0; k < pvq_bands; k++) + { + k_sort[k] = k; + Rk_f[k] = Rk[k] * 8; + } + + pvq_decode_frame( st, pvq_vector, npulses, pvq_inp_vector, hvq_band_start, + hvq_band_end, hvq_band_width, pvq_bands, Rk_f, pvq_bits, core ); + + fine_gain_pred( hvq_band_start, hvq_band_end, hvq_band_width, k_sort, npulses, NULL, NULL, + pvq_bands, pvq_vector, pvq_inp_vector, fg_pred, core ); + + fine_gain_dec( st, k_sort, pvq_bands, gain_bits_array, fg_pred ); + + apply_gain(k_sort, hvq_band_start, hvq_band_end, pvq_bands, fg_pred, pvq_vector ); + + i = 0; + n = 0; + s = 0; + for (k = 0; k < pvq_bands; k++) + { + pvq_norm[k] = (short) get_next_indice( st, HVQ_PVQ_GAIN_BITS ); + pvq_norm[k] += 8; + + diff += HVQ_PVQ_GAIN_BITS; + + j = 0; + if( k >= pvq_bands - n_sel_bnds) + { + i = band_start_harm[sel_bnds[s++]]; + } + while (j < hvq_band_width[k]) + { + normq = dicn[pvq_norm[k]]; + if (coefs_out[i] == 0) + { + coefs_out[i] = pvq_vector[n] * normq; + j++; + n++; + } + i++; + } + } + /* Noise fill unqantized coeffs with one gain per group */ + for (i = 0; i < HVQ_NF_GROUPS; i++) + { + for (j = i*(bin_th/HVQ_NF_GROUPS); j < (i+1)*(bin_th/HVQ_NF_GROUPS); j++) + { + if (coefs_out[j] == 0) + { + coefs_out[j] = ((float)own_random(&nf_seed)/MAX16B)*nf_gains[i]; + } + } + } + + return; +} + +/*-------------------------------------------------------------------------- + * dequant_peaks() + * + * Reads codebook vector and scales peak + *--------------------------------------------------------------------------*/ + +static void dequant_peaks( + Decoder_State *st, /* i/o: decoder state structure */ + float *vect_out, /* o : Quantized vector */ + const float *peak_gain /* i : Peak gain */ +) +{ + float xq[4]; + const float *tmp; + short i, hvq_cb_rev; + short cb_idx; + + hvq_cb_rev = (short) get_next_indice( st, 1 ); + cb_idx = (short) get_next_indice( st, 8 ); + + if( hvq_cb_rev ) + { + tmp = &hvq_peak_cb[cb_idx*4+3]; + for (i = 0; i < 4; i++) + { + xq[i] = tmp[-i]; + } + } + else + { + mvr2r(&hvq_peak_cb[cb_idx*4], xq, 4); + } + if(vect_out[0] == 0) + { + vect_out[0] = xq[0] **peak_gain; + vect_out[1] = xq[1] **peak_gain; + } + else + { + if( fabs(peak_gain[-1]) <= fabs(*peak_gain) ) + { + vect_out[0] = xq[0] **peak_gain; + vect_out[1] = xq[1] **peak_gain; + } + else + { + if(vect_out[1] == 0 || fabs(peak_gain[-1]) <= fabs(*peak_gain)) + { + vect_out[1] = xq[1] **peak_gain; + } + } + } + vect_out[2] = *peak_gain; + vect_out[3] = xq[2] **peak_gain; + vect_out[4] = xq[3] **peak_gain; + + return; +} + +/*-------------------------------------------------------------------------- + * hvq_dec_pos() + * + * HVQ decode peak positions + *--------------------------------------------------------------------------*/ + +static short hvq_dec_pos( + Decoder_State *st, /* i/o: decoder state structure */ + short *pos_vec, + const short length, + const short num_peaks +) +{ + short peak_idx[HVQ_MAX_PEAKS_32k]; + short delta[HVQ_MAX_PEAKS_32k]; + short sign_vec[HVQ_MAX_PEAKS_32k]; + + short mode; + short num_bits; + short i, j; + + num_bits = 0; + set_s(pos_vec, 0, length); + + mode = (short)get_next_indice(st, 1); + num_bits += 1; + + if (mode == HVQ_CP_DELTA) + { + huff_dec(st, 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 += hvq_cp_huff_len[delta[i]]; + } + + peak_idx[0] = delta[0] - HVQ_CP_HUFF_OFFSET; + /* safety check in case of bit errors */ + if (peak_idx[0] < 2) + { + peak_idx[0] = 2; + st->BER_detect = 1; + } + for (i = 1; i < num_peaks; i++) + { + peak_idx[i] = delta[i] + peak_idx[i-1] + HVQ_CP_HUFF_OFFSET; + /* safety check in case of bit errors */ + if (peak_idx[i] >= HVQ_THRES_BIN_32k) + { + peak_idx[i] = HVQ_THRES_BIN_32k - 1; + st->BER_detect = 1; + } + } + + for (i = 0; i < num_peaks; i++) + { + pos_vec[peak_idx[i]] = 1; + } + } + else + { + num_bits += sparse_dec_pos(st, pos_vec, length); + } + + for (i = 0; i < num_peaks; i++) + { + sign_vec[i] = (get_next_indice_1(st) == 0) ? -1 : 1; + } + num_bits += num_peaks; + + for (i = 0, j = 0; i < length && j < num_peaks; i++) /* safety check in case of bit errors */ + { + if (pos_vec[i]) + { + pos_vec[i] *= sign_vec[j++]; + } + } + + return num_bits; +} + +/*-------------------------------------------------------------------------- + * sparse_dec_pos() + * + * Sparse decode positions + *--------------------------------------------------------------------------*/ + +static short sparse_dec_pos( + Decoder_State *st, /* i/o: decoder state structure */ + short *out, + const short length +) +{ + short layer2[HVQ_CP_L2_MAX]; + short layer_length; + short i, j; + short bits; + short idx, val; + + set_s(layer2, 0, HVQ_CP_L2_MAX); + set_s(out, 0, length); + bits = 0; + + layer_length = (short)((float)length/HVQ_CP_L1_LEN + 0.5); + + for (i = 0; i < layer_length; i++) + { + layer2[i] = (short)get_next_indice_1(st); + } + bits += layer_length; + + for (j = 0; j < layer_length; j++) + { + if (layer2[j]) + { + idx = (short)get_next_indice(st, HVQ_CP_MAP_IDX_LEN); + bits += HVQ_CP_MAP_IDX_LEN; + + val = hvq_cp_layer1_map5[idx]; + + /* safety check in case of bit errors */ + if ( j == 0 && val > 4 ) /* out[0] and out[1] are invalid positions */ + { + st->BER_detect = 1; + val = 4; + } + for (i = min((j+1)*HVQ_CP_L1_LEN, length)-1; i >= j*HVQ_CP_L1_LEN; i--) + { + out[i] = val&1; + val >>= 1; + } + } + } + + return bits; +} diff --git a/lib_dec/pit_dec.c b/lib_dec/pit_dec.c new file mode 100644 index 000000000..6392585da --- /dev/null +++ b/lib_dec/pit_dec.c @@ -0,0 +1,786 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include "options.h" + + +/*----------------------------------------------------------* + * pit_decode() + * + * Decode OL pitch lag + *----------------------------------------------------------*/ + +float pit_decode( /* o : floating pitch value */ + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : core bitrate */ + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short L_frame, /* i : length of the frame */ + short i_subfr, /* i : subframe index */ + const short coder_type, /* i : coding type */ + short *limit_flag, /* i/o: restrained(0) or extended(1) Q limits */ + short *T0, /* o : close loop integer pitch */ + short *T0_frac, /* o : close loop fractional part of the pitch */ + short *T0_min, /* i/o: delta search min */ + short *T0_max, /* i/o: delta search max */ + const short L_subfr /* i : subframe length */ +) +{ + float pitch; + short pitch_index, nBits, pit_flag; + + pitch_index = 0; + + /*----------------------------------------------------------------* + * Set pit_flag = 0 for every subframe with absolute pitch search + *----------------------------------------------------------------*/ + + pit_flag = i_subfr; + if( i_subfr == 2*L_SUBFR ) + { + pit_flag = 0; + } + + /*-------------------------------------------------------* + * Retrieve the pitch index + *-------------------------------------------------------*/ + + if( !Opt_AMR_WB ) + { + /*----------------------------------------------------------------* + * pitch Q: Set limit_flag to 0 for restrained limits, and 1 for extended limits + *----------------------------------------------------------------*/ + + if( i_subfr == 0 ) + { + *limit_flag = 1; + + if( coder_type == VOICED ) + { + *limit_flag = 2; /* double-extended limits */ + } + + if( coder_type == GENERIC && core_brate == ACELP_7k20 ) + { + *limit_flag = 0; + } + } + else if( i_subfr == 2*L_SUBFR && coder_type == GENERIC && core_brate <= ACELP_13k20 ) + { + if( *T0 > (PIT_FR1_EXTEND_8b + PIT_MIN)>>1 ) + { + *limit_flag = 0; + } + } + + /*-------------------------------------------------------* + * Retrieve the number of Q bits + *-------------------------------------------------------*/ + + nBits = 0; + if( coder_type != AUDIO ) + { + /* find the number of bits */ + if( L_frame == L_FRAME ) + { + nBits = ACB_bits_tbl[BIT_ALLOC_IDX(core_brate, coder_type, i_subfr, 0)]; + } + else /* L_frame == L_FRAME16k */ + { + nBits = ACB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ(core_brate, coder_type, i_subfr, 0)]; + } + + pitch_index = (short)get_next_indice( st, nBits ); + } + + /*-------------------------------------------------------* + * Pitch decoding in AUDIO mode + * (both ACELP@12k8 and ACELP@16k cores) + *-------------------------------------------------------*/ + + if( coder_type == AUDIO ) + { + if( L_subfr == L_FRAME/2 && i_subfr != 0 ) + { + pit_flag = L_SUBFR; + } + + if( pit_flag == 0 ) + { + nBits = 10; + } + else + { + nBits = 6; + } + + pitch_index = (short)get_next_indice( st, nBits ); + + if( L_subfr == L_FRAME/2 && i_subfr != 0 && pitch_index >= 32 ) /* safety check in case of bit errors */ + { + pitch_index = pitch_index>>1; + st->BER_detect = 1; + } + + pit_Q_dec( 0, pitch_index, nBits, 4, pit_flag, *limit_flag, T0, T0_frac, T0_min, T0_max, &st->BER_detect ); + } + else if( coder_type == VOICED ) + { + /*-------------------------------------------------------* + * Pitch decoding in VOICED mode + * (ACELP@12k8 core only) + *-------------------------------------------------------*/ + + if( i_subfr == 2*L_SUBFR ) + { + pit_flag = i_subfr; + } + + pit_Q_dec( 0, pitch_index, nBits, 4, pit_flag, *limit_flag, T0, T0_frac, T0_min, T0_max, &st->BER_detect ); + } + else + { + /*-------------------------------------------------------* + * Pitch decoding in GENERIC mode + * (both ACELP@12k8 and ACELP@16k cores) + *-------------------------------------------------------*/ + + if( L_frame == L_FRAME ) + { + pit_Q_dec( 0, pitch_index, nBits, 8, pit_flag, *limit_flag, T0, T0_frac, T0_min, T0_max, &st->BER_detect ); + } + else + { + pit16k_Q_dec( pitch_index, nBits, *limit_flag, T0, T0_frac, T0_min, T0_max, &st->BER_detect ); + } + } + } + + /*-------------------------------------------------------* + * Pitch decoding in AMR-WB IO mode + *-------------------------------------------------------*/ + + else + { + *limit_flag = 0; + + if( i_subfr == 0 || ( i_subfr == 2*L_SUBFR && core_brate == ACELP_8k85 ) ) + { + nBits = 8; + } + else + { + nBits = 5; + } + + if( core_brate > ACELP_8k85 ) + { + nBits = 6; + + if( i_subfr == 0 || i_subfr == 2*L_SUBFR ) + { + nBits = 9; + } + } + + pitch_index = (short)get_next_indice( st, nBits ); + + pit_Q_dec( 1, pitch_index, nBits, 8, pit_flag, *limit_flag, T0, T0_frac, T0_min, T0_max, &st->BER_detect ); + } + + /*-------------------------------------------------------* + * Compute floating pitch output + *-------------------------------------------------------*/ + + pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + + return pitch; +} + + +/*---------------------------------------------------------------------* + * abs_pit_dec() + * + * Decode the absolute pitch + *---------------------------------------------------------------------*/ + +void abs_pit_dec( + const short fr_steps, /* i: fractional resolution steps (0, 2, 4) */ + short pitch_index, /* i: pitch index */ + const short limit_flag, /* i : restrained(0) or extended(1) limits */ + short *T0, /* o: integer pitch lag */ + short *T0_frac /* o: pitch fraction */ +) +{ + if( limit_flag == 0 ) + { + if( fr_steps == 2 ) + { + if( pitch_index < (PIT_FR1_8b-PIT_MIN)*2 ) + { + *T0 = PIT_MIN + (pitch_index/2); + *T0_frac = pitch_index - ((*T0 - PIT_MIN)*2); + *T0_frac *= 2; + } + else + { + *T0 = pitch_index + PIT_FR1_8b - ((PIT_FR1_8b-PIT_MIN)*2); + *T0_frac = 0; + } + } + else if( fr_steps == 4 ) + { + if( pitch_index < (PIT_FR2_9b-PIT_MIN)*4 ) + { + *T0 = PIT_MIN + (pitch_index/4); + *T0_frac = pitch_index - (*T0 - PIT_MIN)*4; + } + else if( pitch_index < ( (PIT_FR2_9b-PIT_MIN)*4 + (PIT_FR1_9b-PIT_FR2_9b)*2) ) + { + pitch_index -= (PIT_FR2_9b-PIT_MIN)*4; + *T0 = PIT_FR2_9b + (pitch_index/2); + *T0_frac = pitch_index - (*T0 - PIT_FR2_9b)*2; + (*T0_frac) *= 2; + } + else + { + *T0 = pitch_index + PIT_FR1_9b - ((PIT_FR2_9b-PIT_MIN)*4) - ((PIT_FR1_9b-PIT_FR2_9b)*2); + *T0_frac = 0; + } + } + else /* fr_steps == 0 */ + { + /* not used in the codec */ + } + } + else if( limit_flag == 1 ) /* extended Q range */ + { + if( fr_steps == 2 ) + { + if( pitch_index < (PIT_FR1_EXTEND_8b-PIT_MIN_EXTEND)*2 ) + { + *T0 = PIT_MIN_EXTEND + (pitch_index/2); + *T0_frac = pitch_index - ((*T0 - PIT_MIN_EXTEND)*2); + *T0_frac *= 2; + } + else + { + *T0 = pitch_index + PIT_FR1_EXTEND_8b - ((PIT_FR1_EXTEND_8b-PIT_MIN_EXTEND)*2); + *T0_frac = 0; + } + } + else if( fr_steps == 4 ) + { + if( pitch_index < (PIT_FR2_EXTEND_9b-PIT_MIN_EXTEND)*4 ) + { + *T0 = PIT_MIN_EXTEND + (pitch_index/4); + *T0_frac = pitch_index - (*T0 - PIT_MIN_EXTEND)*4; + } + else if( pitch_index < ( (PIT_FR2_EXTEND_9b-PIT_MIN_EXTEND)*4 + (PIT_FR1_EXTEND_9b-PIT_FR2_EXTEND_9b)*2) ) + { + pitch_index -= (PIT_FR2_EXTEND_9b-PIT_MIN_EXTEND)*4; + *T0 = PIT_FR2_EXTEND_9b + (pitch_index/2); + *T0_frac = pitch_index - (*T0 - PIT_FR2_EXTEND_9b)*2; + (*T0_frac) *= 2; + } + 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); + *T0_frac = 0; + } + } + else /* fr_steps == 0 */ + { + /* not used in the codec */ + } + } + else /* limit_flag == 2 */ + { + if( fr_steps == 2 ) + { + if( pitch_index < (PIT_FR1_DOUBLEEXTEND_8b-PIT_MIN_DOUBLEEXTEND)*2 ) + { + *T0 = PIT_MIN_DOUBLEEXTEND + (pitch_index/2); + *T0_frac = pitch_index - ((*T0 - PIT_MIN_DOUBLEEXTEND)*2); + *T0_frac *= 2; + } + else + { + *T0 = pitch_index + PIT_FR1_DOUBLEEXTEND_8b - ((PIT_FR1_DOUBLEEXTEND_8b-PIT_MIN_DOUBLEEXTEND)*2); + *T0_frac = 0; + } + } + else if( fr_steps == 4 ) + { + if( pitch_index < (PIT_FR2_DOUBLEEXTEND_9b-PIT_MIN_DOUBLEEXTEND)*4 ) + { + *T0 = PIT_MIN_DOUBLEEXTEND + (pitch_index/4); + *T0_frac = pitch_index - (*T0 - PIT_MIN_DOUBLEEXTEND)*4; + } + else if( pitch_index < ( (PIT_FR2_DOUBLEEXTEND_9b-PIT_MIN_DOUBLEEXTEND)*4 + (PIT_FR1_DOUBLEEXTEND_9b-PIT_FR2_DOUBLEEXTEND_9b)*2) ) + { + pitch_index -= (PIT_FR2_DOUBLEEXTEND_9b-PIT_MIN_DOUBLEEXTEND)*4; + *T0 = PIT_FR2_DOUBLEEXTEND_9b + (pitch_index/2); + *T0_frac = pitch_index - (*T0 - PIT_FR2_DOUBLEEXTEND_9b)*2; + (*T0_frac) *= 2; + } + else + { + *T0 = pitch_index + PIT_FR1_DOUBLEEXTEND_9b - ((PIT_FR2_DOUBLEEXTEND_9b-PIT_MIN_DOUBLEEXTEND)*4) - ((PIT_FR1_DOUBLEEXTEND_9b-PIT_FR2_DOUBLEEXTEND_9b)*2); + *T0_frac = 0; + } + } + else /* fr_steps == 0 */ + { + /* not used in the codec */ + } + } + + return; +} + + +/*---------------------------------------------------------------------* + * delta_pit_dec() + * + * Decode delta pitch + *---------------------------------------------------------------------*/ + +void delta_pit_dec( + const short fr_steps, /* i : fractional resolution steps (0, 2, 4) */ + const short pitch_index, /* i : pitch index */ + short *T0, /* o : integer pitch lag */ + short *T0_frac, /* o : pitch fraction */ + const short T0_min /* i : delta search min */ +) +{ + if( fr_steps == 0 ) + { + *T0 = T0_min + pitch_index; + *T0_frac = 0; + } + else if( fr_steps == 2 ) + { + *T0 = T0_min + pitch_index/2; + *T0_frac = pitch_index - (*T0 - T0_min)*2; + *T0_frac *= 2; + } + else if( fr_steps == 4 ) + { + *T0 = T0_min + pitch_index/4; + *T0_frac = pitch_index - (*T0 - T0_min)*4; + } + + return; +} + + +/*-------------------------------------------------* + * pit_Q_dec() + * + * pitch decoding + *-------------------------------------------------*/ + +void pit_Q_dec( + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short pitch_index, /* i : pitch index */ + const short nBits, /* i : # of Q bits */ + const short delta, /* i : Half the CL searched interval */ + const short pit_flag, /* i : absolute(0) or delta(1) pitch Q */ + const short limit_flag, /* i : restrained(0) or extended(1) Q limits */ + short *T0, /* o : integer pitch lag */ + short *T0_frac, /* o : pitch fraction */ + short *T0_min, /* i/o: delta search min */ + short *T0_max /* i/o: delta search max */ + ,short *BER_detect /* o : BER detect flag */ +) +{ + if( nBits == 10 ) /* absolute decoding with 10 bits */ + { + if( limit_flag == 0 ) + { + *T0 = PIT_MIN + (pitch_index/4); + *T0_frac = pitch_index - (*T0 - PIT_MIN)*4; + } + else if( limit_flag == 1 ) + { + *T0 = PIT_MIN_EXTEND + (pitch_index/4); + *T0_frac = pitch_index - (*T0 - PIT_MIN_EXTEND)*4; + } + else /* limit_flag == 2 */ + { + *T0 = PIT_MIN_DOUBLEEXTEND + (pitch_index/4); + *T0_frac = pitch_index - (*T0 - PIT_MIN_DOUBLEEXTEND)*4; + } + } + else if( nBits == 9 ) /* absolute decoding with 9 bits */ + { + abs_pit_dec( 4, pitch_index, limit_flag, T0, T0_frac ); + + /* find T0_min and T0_max for delta search */ + if( Opt_AMR_WB ) + { + limit_T0( L_FRAME, delta, pit_flag, 0, *T0, 0, T0_min, T0_max ); /* T0_frac==0 to keep IO with AMR-WB */ + } + } + else if( nBits == 8 ) /* absolute decoding with 8 bits */ + { + abs_pit_dec( 2, pitch_index, limit_flag, T0, T0_frac ); + + /* find T0_min and T0_max for delta search */ + if( Opt_AMR_WB ) + { + limit_T0( L_FRAME, delta, pit_flag, 0, *T0, 0, T0_min, T0_max ); /* T0_frac==0 to keep IO with AMR-WB */ + } + } + else if( nBits == 6 ) /* relative decoding with 6 bits */ + { + delta_pit_dec( 4, pitch_index, T0, T0_frac, *T0_min ); + } + else if( nBits == 5 ) /* relative decoding with 5 bits */ + { + if( delta == 8 ) + { + delta_pit_dec( 2, pitch_index, T0, T0_frac, *T0_min ); + } + else /* delta == 4 */ + { + delta_pit_dec( 4, pitch_index, T0, T0_frac, *T0_min ); + } + } + else /* nBits == 4 */ /* relative decoding with 4 bits */ + { + if( delta == 8 ) + { + delta_pit_dec( 0, pitch_index, T0, T0_frac, *T0_min ); + } + else /* delta == 4 */ + { + delta_pit_dec( 2, pitch_index, T0, T0_frac, *T0_min ); + } + } + + /* biterror detection mechanism */ + if( ((*T0<<2) + *T0_frac) > (PIT_MAX<<2)+2 && pit_flag == 0 && !Opt_AMR_WB ) + { + *T0 = L_SUBFR; + *T0_frac = 0; + *BER_detect = 1; + } + + if( !Opt_AMR_WB ) + { + /* find T0_min and T0_max for delta search */ + limit_T0( 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( + const short pitch_index, /* i : pitch index */ + const short nBits, /* i : # of Q bits */ + const short limit_flag, /* i : restrained(0) or extended(1) limits */ + short *T0, /* o : integer pitch lag */ + short *T0_frac, /* o : pitch fraction */ + short *T0_min, /* i/o: delta search min */ + short *T0_max /* i/o: delta search max */ + ,short *BER_detect /* o : BER detect flag */ +) +{ + short index; + + if( nBits == 10 ) /* absolute decoding with 10 bits */ + { + { + if( pitch_index < (PIT16k_FR2_EXTEND_10b-PIT16k_MIN_EXTEND)*4 ) + { + *T0 = PIT16k_MIN_EXTEND + (pitch_index/4); + *T0_frac = pitch_index - ((*T0 - PIT16k_MIN_EXTEND)*4); + } + else + { + index = pitch_index - (PIT16k_FR2_EXTEND_10b-PIT16k_MIN_EXTEND)*4; + *T0 = PIT16k_FR2_EXTEND_10b + (index/2); + *T0_frac = index - (*T0 - PIT16k_FR2_EXTEND_10b)*2; + (*T0_frac) *= 2; + } + } + + } + else if( nBits == 9 ) /* absolute decoding with 9 bits */ + { + { + if (pitch_index < (PIT16k_FR2_EXTEND_9b-PIT16k_MIN_EXTEND)*4) + { + *T0 = PIT16k_MIN_EXTEND + (pitch_index/4); + *T0_frac = pitch_index - (*T0 - PIT16k_MIN_EXTEND)*4; + } + else if (pitch_index < ( (PIT16k_FR2_EXTEND_9b-PIT16k_MIN_EXTEND)*4 + (PIT16k_FR1_EXTEND_9b-PIT16k_FR2_EXTEND_9b)*2) ) + { + index = pitch_index - (PIT16k_FR2_EXTEND_9b-PIT16k_MIN_EXTEND)*4; + *T0 = PIT16k_FR2_EXTEND_9b + (index/2); + *T0_frac = index - (*T0 - PIT16k_FR2_EXTEND_9b)*2; + (*T0_frac) *= 2; + } + else + { + *T0 = pitch_index + PIT16k_FR1_EXTEND_9b - ((PIT16k_FR2_EXTEND_9b-PIT16k_MIN_EXTEND)*4) - ((PIT16k_FR1_EXTEND_9b-PIT16k_FR2_EXTEND_9b)*2); + *T0_frac = 0; + } + } + } + else /* nBits == 6 */ /* relative decoding with 6 bits */ + { + delta_pit_dec( 4, pitch_index, T0, T0_frac, *T0_min ); + } + + /* biterror detection mechanism */ + if( ((*T0<<2) + *T0_frac) > (PIT16k_MAX<<2) && nBits >= 9 ) + { + *T0 = L_SUBFR; + *T0_frac = 0; + *BER_detect = 1; + } + + /* find T0_min and T0_max for delta search */ + limit_T0( L_FRAME16k, 8, L_SUBFR, limit_flag, *T0, *T0_frac, T0_min, T0_max ); + + return; +} + + +/*----------------------------------------------------------* + * Mode2_pit_decode + * + * Decode pitch lag + *----------------------------------------------------------*/ + +float Mode2_pit_decode( /* o: floating pitch value */ + const short coder_type, /* i: coding model */ + short i_subfr, /* i: subframe index */ + int L_subfr, + int **pt_indice, /* i/o: quantization indices pointer */ + int *T0, /* i/o: close loop integer pitch */ + int *T0_frac, /* o: close loop fractional part of the pitch */ + int *T0_res, /* i/o: pitch resolution */ + int *T0_min, /* i/o: lower limit for close-loop search */ + int *T0_min_frac, /* i/o: lower limit for close-loop search */ + int *T0_max, /* i/o: higher limit for close-loop search */ + int *T0_max_frac, /* i/o: higher limit for close-loop search */ + int pit_min, + int pit_fr1, + int pit_fr1b, + int pit_fr2, + int pit_max, + int pit_res_max +) +{ + float pitch; + + if( coder_type == 0 ) /*Unvoiced Coding do nothing*/ + { + + *T0 = L_subfr; + *T0_frac = 0; + *T0_res = 1; + } + else if(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, 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 = (pit_res_max>>1); + Mode2_delta_pit_dec( T0, T0_frac, *T0_res, T0_min, T0_min_frac, pt_indice); + } + } + else if(coder_type == 2) /* 8/5/8/5 (EVS) */ + { + + if ( ( i_subfr == 0 ) || ( i_subfr == 2*L_subfr ) ) + { + 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, 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 = (pit_res_max>>1); + Mode2_delta_pit_dec( T0, T0_frac, *T0_res, T0_min, T0_min_frac, pt_indice); + } + } + else if(coder_type == 3) /* 9/6/6/6 (HRs- VC) */ + { + int pit_res_max2 = pit_res_max; + if ( pit_min==PIT_MIN_16k ) + { + pit_res_max2 = 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; + Mode2_delta_pit_dec( T0, T0_frac, *T0_res, T0_min, T0_min_frac, pt_indice); + } + } + else if(coder_type == 4) /* 9/6/9/6 (AMRWB) */ + { + int pit_res_max2 = pit_res_max; + if ( pit_min==PIT_MIN_16k ) + { + pit_res_max2 = pit_res_max >> 1; + } + + if ( ( i_subfr == 0 ) || ( i_subfr == 2*L_subfr ) ) + { + 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; + Mode2_delta_pit_dec( T0, T0_frac, *T0_res, T0_min, T0_min_frac, pt_indice); + } + } + else if(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, 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 = (pit_res_max>>1); + Mode2_delta_pit_dec( T0, T0_frac, *T0_res, T0_min, T0_min_frac, pt_indice); + } + } + else if(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, 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 = (pit_res_max>>1); + Mode2_delta_pit_dec( T0, T0_frac, *T0_res, T0_min, T0_min_frac, pt_indice); + } + } + else /*RCELP 8 bits pitch delay*/ + { + assert(0); + } + + /*-------------------------------------------------------* + * Compute floating pitch output + *-------------------------------------------------------*/ + + pitch = (float)(*T0) + (float)(*T0_frac)/(float)(*T0_res); /* save subframe pitch values */ + + return pitch; +} + + +/*---------------------------------------------------------------------* + * Mode2_abs_pit_dec + * + * Decode the absolute pitch + *---------------------------------------------------------------------*/ +void Mode2_abs_pit_dec( + int *T0, /* o: integer pitch lag */ + int *T0_frac, /* o: pitch fraction */ + int *T0_res, /* o: pitch resolution */ + int **pt_indice, /* i/o: pointer to Vector of Q indexes */ + int pit_min, + int pit_fr1, + int pit_fr2, + int pit_res_max +) +{ + int index; + int pit_res_max_half; + + index = **pt_indice; + (*pt_indice)++; + pit_res_max_half = pit_res_max>>1; + + if (index < (pit_fr2-pit_min)*pit_res_max) + { + + *T0 = pit_min + (index/pit_res_max); + + *T0_frac = index - (*T0 - pit_min)*pit_res_max; + *T0_res = pit_res_max; + } + else if (index < ( (pit_fr2-pit_min)*pit_res_max + (pit_fr1-pit_fr2)*pit_res_max_half) ) + { + index -= (pit_fr2-pit_min)*pit_res_max; + + *T0 = pit_fr2 + (index/pit_res_max_half); + + *T0_frac = index - (*T0 - pit_fr2)*pit_res_max_half; + *T0_res = pit_res_max_half; + } + else + { + *T0 = index + pit_fr1 - ((pit_fr2-pit_min)*pit_res_max) - ((pit_fr1-pit_fr2)*pit_res_max_half); + *T0_frac = 0; + *T0_res = 1; + } + + return; +} + + +/*---------------------------------------------------------------------* + * Routine Mode2_delta_pit_dec() + * + * Decode delta pitch + *---------------------------------------------------------------------*/ +void Mode2_delta_pit_dec( + int *T0, /* o: integer pitch lag */ + int *T0_frac, /* o: pitch fraction */ + int T0_res, /* i: pitch resolution */ + int *T0_min, /* i/o: delta search min */ + int *T0_min_frac, /* i: delta search min */ + int **pt_indice /* i/o: pointer to Vector of Q indexes */ +) +{ + int index; + + index = **pt_indice; + (*pt_indice)++; + + *T0 = *T0_min + (index+*T0_min_frac)/T0_res; + + *T0_frac = index+*T0_min_frac - (*T0 - *T0_min)*T0_res; + + return; +} diff --git a/lib_dec/pitch_extr.c b/lib_dec/pitch_extr.c new file mode 100644 index 000000000..27b82ae89 --- /dev/null +++ b/lib_dec/pitch_extr.c @@ -0,0 +1,299 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "cnst.h" +#include "prot.h" +#include "options.h" +#include "basop_util.h" + + + + +/*-----------------------------------------------------------------* + * Pitch prediction for frame erasure using linear fitting * + *-----------------------------------------------------------------*/ +void pitch_pred_linear_fit( + const short nbLostCmpt, /* i: bfi counter */ + const short last_good, /* i: last classification type */ + float *old_pitch_buf, /* i: pitch lag buffer */ + float *old_fpitch, /* i: */ + float *T0_out, /* o: estimated close loop pitch */ + int pit_min, /* i: Minimum pitch lag */ + int pit_max, /* i: Maximum pitch lag */ + float *mem_pitch_gain, /* i: pitch gain [0] is the most recent subfr gain */ + int limitation, + short plc_use_future_lag, /* i: */ + short *extrapolationFailed,/* o: flag if extrap decides not to change the pitch */ + int nb_subfr /* i: number of ACELP subframes */ +) +{ + float T0 = 0; + float mdy, dy[5], ftmp; + short lcor = 5; + short imax, i; + float pg[8], ml[8]; /* local buffer for pitch gain and mem_lag*/ + short no_subfr_pred; + float mem_lag[2*NB_SUBFR16k+2]; + + + if( nb_subfr == 4 ) + { + for (i=0; i<2*NB_SUBFR+2; i++) + { + mem_lag[i] = old_pitch_buf[2*NB_SUBFR+1 - i]; + } + } + 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]; + } + } + + if( (int) *old_fpitch > pit_max ) + { + *extrapolationFailed = 1; + *T0_out = pit_max; + printf("\n WARNING: (int)*old_fpitch > pit_max : old_fpitch = %f, pit_max = %i \n\n",*old_fpitch, pit_max ); + return; + } + + if (nbLostCmpt == 1 && last_good >= UNVOICED_TRANSITION && last_good < ONSET) + { + if (plc_use_future_lag) + { + no_subfr_pred = 2; + } + else + { + no_subfr_pred = 4; + } + + /* copy to local buffers, depending on availability of info about future subframes */ + mvr2r(mem_pitch_gain+no_subfr_pred-2,pg,8); + mvr2r(mem_lag+no_subfr_pred-2,ml,8); + + mdy = 0.0f; + for (i = (lcor-1); i >= 0; i--) + { + dy[i] = (ml[i] - ml[i+1]); + mdy += dy[i]; + } + + /*---------------------------------------------------* + * remove maximum variation + *---------------------------------------------------*/ + ftmp = (float)fabs(dy[0]); + imax = 0; + for (i = 1; i Q9*/),mult_r(pg_fx[3],16384/*Q12->Q11*/))/*Q5*/; + a4 = mac_r(L_mac(L_mult( mult_r(-12*2048,pg_fx[0])/*Q8*/,pg_fx[3] /*Q12*/)/*Q5+16*/,mult_r(-6*2048,pg_fx[1])/*Q8*/,pg_fx[3]/*Q12*/)/*Q5+16*/,mult_r(-2*2048,pg_fx[2])/*Q8*/,pg_fx[3]/*Q12*/)/*Q5*/; + a3 = mac_r(L_mac(L_mult( mult_r(-8*2048,pg_fx[0]) /*Q8*/,pg_fx[2]),mult_r(-3*2048,pg_fx[1])/*Q8*/,pg_fx[2]),mult_r(pg_fx[2],4096/*Q12->Q9*/),mult_r(pg_fx[3],16384/*12->Q11*/));/*Q5*/ + a2 = mac_r(L_mac(L_mult( mult_r(2*2048,pg_fx[1]) /*Q8*/,pg_fx[2])/*Q5+16*/,mult_r(2*2048,pg_fx[1])/*Q8*/,pg_fx[3])/*Q5+16*/,mult_r(-4*2048,pg_fx[0])/*Q8*/,pg_fx[1]/*Q12*/)/*Q5*/; + a1 = mac_r(L_mac(L_mult( mult_r(3*2048,pg_fx[0]) /*Q8*/,pg_fx[1])/*Q5+16*/,mult_r(4*2048,pg_fx[0])/*Q8*/,pg_fx[2]/*Q12*/)/*Q5+16*/,mult_r(3*2048,pg_fx[0])/*Q8*/,pg_fx[3]/*Q12*/)/*Q5*/; + + a = L_mac(L_mac(L_mac(L_mac(L_mult(a1 + , round_fx(L_shl(ml_fx[0],4)))/*Q4*/ + , round_fx(L_shl(ml_fx[1],4)) /*Q4*/, a2) + , round_fx(L_shl(ml_fx[2],4)) /*Q4*/, a3) + , round_fx(L_shl(ml_fx[3],4)) /*Q4*/, a4) + , round_fx(L_shl(ml_fx[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; */ + + /*magic numbers in Q13 if not DIRECTLY marked otherwise*/ + b1 = mac_r(L_mac(L_mac(L_mult(mult_r(pg_fx[1],pg_fx[0]),32768/4)/*Q7+16*/,mult_r(2*8192,pg_fx[0])/*Q10*/,pg_fx[2]/*Q12*/)/*Q7+16*/,mult_r(3*8192,pg_fx[0])/*Q10*/,pg_fx[3]/*Q12*/)/*Q7+16*/, /*mult_r(4*8192,pg_fx[0])*/ pg_fx[0]/*Q10*/,pg_fx[4]/*Q12*/)/*Q7*/; + b2 = mac_r(L_mac(L_mac(L_mult(mult_r(pg_fx[2],pg_fx[1]),32768/4)/*Q7+16*/,mult_r(2*8192,pg_fx[1]),pg_fx[3]),mult_r(3*8192,pg_fx[1]),pg_fx[4])/*Q7+16*/,mult_r(pg_fx[1],-32768/2/*Q12->Q12*/),mult_r(pg_fx[0],32768/2/*Q12->Q10*/))/*Q7*/; + b3 = mac_r(L_mac(L_mac(L_mult(mult_r(-2*8192,pg_fx[0]),pg_fx[2])/*Q7+16*/,mult_r(pg_fx[2],-32768/2),mult_r(pg_fx[1],32768/2)),mult_r(pg_fx[3],32768/2),mult_r(pg_fx[2],32768/2))/*Q5+16*/,mult_r(2*8192,pg_fx[2]),pg_fx[4])/*Q7*/; + b4 = mac_r(L_mac(L_mac(L_mult(mult_r(-3*8192,pg_fx[0]),pg_fx[3]),mult_r(-2*8192,pg_fx[1]),pg_fx[3]),mult_r(-32768/2,pg_fx[3]),mult_r(32768/2,pg_fx[2])),mult_r(32768/2,pg_fx[4]),mult_r(32768/2,pg_fx[3]));/*Q7*/ + b5 = mac_r(L_mac(L_mac(L_mult(mult_r(-32768/*(-4*8192)*/,pg_fx[0]),pg_fx[4]),mult_r(-3*8192,pg_fx[1]),pg_fx[4]),mult_r(-2*8192,pg_fx[2]),pg_fx[4]),mult_r(-32768/2,pg_fx[4]),mult_r(32768/2,pg_fx[3]))/*Q7*/; + + b = L_mac(L_mac(L_mac(L_mac(L_mult(b1 + , round_fx(L_shl(ml_fx[0],4)))/*Q4*/ + , round_fx(L_shl(ml_fx[1],4)) /*Q4*/, b2) + , round_fx(L_shl(ml_fx[2],4)) /*Q4*/, b3) + , round_fx(L_shl(ml_fx[3],4)) /*Q4*/, b4) + , round_fx(L_shl(ml_fx[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*/ +#undef WMC_TOOL_SKIP + /* convert pitch back to float precision */ + T0 = (float)pit*pow(2.f, -31+15); + + /*limit pitch to allowed range*/ + if( T0 > pit_max ) + { + T0 = (float)pit_max; + } + + if( T0 < pit_min ) + { + T0 = (float)pit_min; + } + + *extrapolationFailed = 0; + } + else + { + T0 = 0; + *extrapolationFailed = 1; + } + } + else + { + T0 = 0; + *extrapolationFailed = 1; + } + } + else + { + T0 = *old_fpitch; + *extrapolationFailed = 1; + } + + *T0_out = T0; + + return; +} + +void get_subframe_pitch( + int nSubframes, /* i: number of subframes */ + float pitchStart, /* i: starting pitch lag (in subframe -1) */ + float pitchEnd, /* i: ending pitch lag (in subframe nSubframes-1) */ + float *pitchBuf /* o: interpolated pitch lag per subframe */ +) +{ + int i; + float pitchDelta; + + assert((nSubframes > 0) && (pitchBuf != NULL) && (pitchStart >= 0) && (pitchEnd > 0)); + + pitchDelta = (pitchEnd - pitchStart)/nSubframes; + pitchBuf[0] = pitchStart+pitchDelta; + for (i = 1; i < nSubframes; i++) + { + pitchBuf[i] = pitchBuf[i-1] + pitchDelta; + } + + return; +} diff --git a/lib_dec/post_dec.c b/lib_dec/post_dec.c new file mode 100644 index 000000000..2aeef547d --- /dev/null +++ b/lib_dec/post_dec.c @@ -0,0 +1,446 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "options.h" +#include "prot.h" +#include "rom_com.h" + + +/*---------------------------------------------------------------------* + * Function prototypes + *---------------------------------------------------------------------*/ + +static void bass_pf_1sf_delay( float *syn, const int *T_sf, const float *gainT_sf, const short l_frame, + const short l_subfr, float *bpf_noise_buf, int *gain_factor_param, + const short disable_bpf, float *mem_deemph_err, float *lp_ener ); + + +/*---------------------------------------------------------------------* + * post_decoder() + * + * Perform post-processing + *---------------------------------------------------------------------*/ + +void post_decoder( + Decoder_State *st, /* i/o: decoder memory state pointer */ + const short coder_type, /* i : coder type */ + float synth_buf[], + const float pit_gain[], + const int pitch[], + float signal_out[], + float *bpf_noise_buf +) +{ + short L_frame, nb_subfr, i; + float *synth2; + float *synth; + short pfstat_on_previous; + int pitch_gain_adjust[NB_SUBFR16k]; + float synth_buf2[NBPSF_PIT_MAX+L_FRAME_MAX+M]; + long bitrate; + float A[M+1]; + float pitch_buf[NB_SUBFR16k]; + float tmp; + short L_subfr; + + L_frame = st->L_frame; + nb_subfr = st->nb_subfr; + bitrate = (st->core_brate > SID_2k40 )? st->total_brate: st->last_active_brate; + pfstat_on_previous = st->pfstat.on; + st->pfstat.on = 0; + set_i( pitch_gain_adjust, st->bpf_gain_param, nb_subfr ); + synth = synth_buf + st->old_synth_len; + synth2 = synth_buf2 + NBPSF_PIT_MAX; + mvr2r( st->pst_old_syn, synth_buf2, NBPSF_PIT_MAX ); + + if( st->tcxonly ) + { + /* High bitrates (48kbps and above), high sampling rates (25.6kHz and above) */ + + mvr2r( synth, synth2, L_frame ); + + if( pfstat_on_previous ) + { + /* Past frame was low-bitrate with formant post-filter */ + lsp2a_stab( st->lsp_old, A, M ); + mvr2r( st->pfstat.mem_pf_in+L_SYN_MEM-M, synth-M, M ); + L_subfr = st->L_frame/st->nb_subfr; + residu( A, M, synth, synth_buf, L_subfr ); + syn_filt ( A, M, synth_buf, synth2, L_subfr, st->pfstat.mem_stp+L_SYN_MEM-M, 0 ); + scale_st ( synth, synth2, &st->pfstat.gain_prec, L_subfr, -1 ); + blend_subfr2(synth2+L_subfr/2, synth+L_subfr/2, synth2+L_subfr/2); + } + } + else + { + /* Low bitrates (32kbps and below), low sampling rates (12.8kHz and 16kHz) */ + if( st->last_bwidth == NB ) + { + /* NB Post-filter (pitch+formant post-filter) */ + mvr2r( synth, synth_buf, L_frame ); + tmp = synth[-1]; + preemph( synth_buf, st->preemph_fac, L_frame, &tmp ); + + tmp = 0.0f; + for( i=0; i< nb_subfr; i ++ ) + { + pitch_buf[i] = pitch[i]; + } + + if( pfstat_on_previous == 0 ) + { + st->pfstat.reset = 1; + } + + if( st->bwidth == NB ) + { + st->pfstat.on = 1; + nb_post_filt( L_frame, L_SUBFR, &(st->pfstat), &tmp, 0, synth_buf, st->mem_Aq, pitch_buf, GENERIC, st->BER_detect, + st->lp_noise>LP_NOISE_THRESH? 1:((st->core != ACELP_CORE)||(coder_type==UNVOICED)) ); + } + else + { + st->pfstat.on = 0; + nb_post_filt( L_frame, L_SUBFR, &(st->pfstat), &tmp, 0, synth_buf, st->mem_Aq, pitch_buf, AUDIO, st->BER_detect, + st->lp_noise>LP_NOISE_THRESH? 1:((st->core != ACELP_CORE)||(coder_type==UNVOICED)) ); + } + + + mvr2r( synth_buf, synth2, L_frame ); + tmp = synth2[-1]; + deemph( synth2, st->preemph_fac, L_frame, &tmp ); + } + else + { + /* Formant Post-filter */ + if( pfstat_on_previous == 0 ) + { + st->pfstat.reset = 1; + } + + if( st->bwidth >= WB ) + { + st->pfstat.on = 1; + formant_post_filt( &(st->pfstat), synth, st->mem_Aq, synth2, L_frame, L_SUBFR, st->lp_noise, bitrate, 0 ); + } + else + { + st->pfstat.on = 0; + formant_post_filt( &(st->pfstat), synth, st->mem_Aq, synth2, L_frame, L_SUBFR, st->lp_noise, bitrate, 1 ); + } + } + + /*Bass Post-filter */ + bass_pf_1sf_delay( synth2, pitch, pit_gain, L_frame, L_SUBFR, bpf_noise_buf, pitch_gain_adjust, + (st->lp_noise>LP_NOISE_THRESH && st->narrowBand)? 1: 0, &(st->pst_mem_deemp_err), &(st->pst_lp_ener) ); + } + + /* Output */ + mvr2r( synth2, signal_out, L_frame ); + + /* Update synth2 memory */ + mvr2r( synth_buf2 + L_frame, st->pst_old_syn, NBPSF_PIT_MAX ); + + return; +} + + +/*---------------------------------------------------------------------* + * bass_pf_1sf_delay() + * + * Perform low-frequency postfiltering + *---------------------------------------------------------------------*/ + +static void bass_pf_1sf_delay( + float *syn, /* i : synthesis to postfilter */ + const int *T_sf, /* i : Pitch period for all subframes (T_sf[4]) */ + const float *gainT_sf, /* i : Pitch gain for all subframes (gainT_sf[4]) */ + const short L_frame, /* i : frame length (multiple of l_subfr) */ + const short L_subfr_in, /* i : sub-frame length (80/64) */ + float *bpf_noise_buf, /* i : harmoninc filtered signal */ + int *gain_factor_param, /* i : gain factor param 0-> minimum BPF, 3-> full BPF */ + const short disable_bpf, /* i : flag to disable BPF */ + float *mem_deemph_err, /* i/o: Error deemphasis memory */ + float *lp_ener /* i/o: long_term error signal energy */ +) +{ + short i, sf, i_subfr, T, lg, L_subfr; + float tmp, corr, ener, gain; + float noise_buf[(2*L_SUBFR)], *noise_in; + float error[L_SUBFR]; + float ener2; + + noise_in = noise_buf; + + sf = 0; + L_subfr = L_subfr_in; + + for( i_subfr = 0; i_subfr < L_frame; i_subfr += L_subfr, sf++ ) + { + if( i_subfr == 0 ) + { + L_subfr = L_subfr_in; + } + else if( i_subfr == L_frame ) + { + L_subfr = 0; + } + else + { + L_subfr = L_subfr_in; + } + + T = T_sf[sf]; + gain = gainT_sf[sf]; + + if (gain > 1.0f) + { + gain = 1.0f; + } + if (gain < 0.0f) + { + gain = 0.0f; + } + + lg = L_frame - T - i_subfr; + if (lg < 0) + { + lg = 0; + } + if (lg > L_subfr) + { + lg = L_subfr; + } + + if( !disable_bpf && gain > 0 ) + { + corr = 0.01f; + ener = 0.01f; + + for( i=0; i 1.f ) + { + gain = 1.0f; + } + else if( gain<0.f ) + { + gain = 0.f; + } + + ener2 = 0.01f; + for( i=0; i 0.5f ) + { + tmp = 0.5f; + } + else if( tmp < 0.f ) + { + tmp = 0.0f; + } + + /*Adjust gain*/ + /* full gain = gainLTP*0.5*/ + /* adaptive gain = gainLTP*0.5*gain_factor*0.5*/ + tmp *= max(0.5f*gain_factor_param[sf],0.125f); + + /* calculate noise based on voiced pitch */ + for( i=0; i reduce nrg of noise_in and avoid too much post-filtering*/ + /*noise_in[i] = tmp * (syn[i+i_subfr] - 0.5f*syn[i+i_subfr-T] - 0.5f*syn[i+i_subfr]);*/ + /*->noise_in[i] = tmp * 0.5f * (syn[i+i_subfr] - syn[i+i_subfr-T]);*/ + noise_in[i] *= 0.5f; + } + } + else + { + set_zero( noise_in, L_subfr ); + } + + /* copy bpf noise signal to buffer */ + mvr2r( noise_in, bpf_noise_buf + i_subfr, L_subfr ); + + } + + return; +} +/*---------------------------------------------------------------------* + * cldfb_synth_set_bandsToZero() + * + * + *---------------------------------------------------------------------*/ + +void cldfb_synth_set_bandsToZero( + Decoder_State *st, + float **rAnalysis, + float **iAnalysis, + const short nTimeSlots +) +{ + float nrg_bwddec, nrg_band[CLDFB_NO_CHANNELS_MAX], thr_bwddwc, max_nrg, realQ1, imagQ1; + short flag, offset, WBcnt, i, k, update_perc; + float perc_detect, perc_miss; + + realQ1 = 0.0f; + imagQ1 = 0.0f; + + set_f( nrg_band, 0.0f, CLDFB_NO_CHANNELS_MAX ); + max_nrg = 0.0f; + + offset = 250; + WBcnt = 20; + perc_miss = 0.83f; + perc_detect = 0.93f; + + if(st->VAD==1) + { + st->active_frame_cnt_bwddec++; + st->total_frame_cnt_bwddec++; + if(st->active_frame_cnt_bwddec > 99) + { + st->active_frame_cnt_bwddec = 100; + } + if(st->total_frame_cnt_bwddec > 500) + { + st->total_frame_cnt_bwddec = 500; + } + + for (i = 0; i < (st->cldfbSyn->no_channels - st->cldfbSyn->bandsToZero); i++) + { + nrg_bwddec = 0.0f; + for (k = 0; k < nTimeSlots; k++) + { + realQ1 = rAnalysis[k][i]; + imagQ1 = iAnalysis[k][i]; + nrg_bwddec += (realQ1*realQ1); + nrg_bwddec += (imagQ1*imagQ1); + } + nrg_band[i] = (nrg_bwddec); + if( (nrg_band[i] > max_nrg) && (i > 11) ) + { + max_nrg = nrg_band[i]; + } + } + for(; i < st->cldfbSyn->no_channels; i++) + { + nrg_band[i] = 0; + } + + nrg_bwddec = 0; + for(i = 2; i < 9; i++) + { + nrg_bwddec += (nrg_band[i]/7.0f); + } + + thr_bwddwc = (nrg_bwddec/512.0f); + + st->avg_nrg_LT = 0.98999f*st->avg_nrg_LT + 0.009979f*thr_bwddwc; + update_perc = 1; + if(st->ini_frame >= 25 && thr_bwddwc < st->avg_nrg_LT*0.005f) + { + update_perc = 0; + } + + flag = 1; + if(max_nrg >= thr_bwddwc) + { + flag = 0; + } + + for(i = 0; i < WBcnt-1; i++) + { + st->flag_buffer[i] = st->flag_buffer[i+1]; + } + st->flag_buffer[WBcnt-1] = flag; + + /*long term percentage*/ + if(update_perc == 1) + { + st->perc_bwddec += (flag - st->perc_bwddec)/st->active_frame_cnt_bwddec; + } + if((st->total_frame_cnt_bwddec > offset) && (st->active_frame_cnt_bwddec > 50) ) + { + if( (st->perc_bwddec >= perc_detect || (st->perc_bwddec >= perc_miss && st->last_flag_filter_NB)) && (sum_s(st->flag_buffer, WBcnt) != 0)) /*decision hysterysis*/ + { + st->cldfbSyn->bandsToZero = ( st->cldfbSyn->no_channels - 10 ); + st->last_flag_filter_NB = 1; /*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; + } + } + else + { + st->last_flag_filter_NB = 0; + } + if(sum_s(st->flag_buffer, WBcnt) == 0) + { + st->perc_bwddec = 0.0f; + st->active_frame_cnt_bwddec = 0; + st->total_frame_cnt_bwddec = 0; + st->last_flag_filter_NB = 0; + } + } + else + { + if(st->last_flag_filter_NB == 1) + { + st->cldfbSyn->bandsToZero = st->last_active_bandsToZero_bwdec; + } + st->total_frame_cnt_bwddec++; + if(st->total_frame_cnt_bwddec > 500) + { + st->total_frame_cnt_bwddec = 500; + } + } + + st->last_active_bandsToZero_bwdec = st->cldfbSyn->bandsToZero; + + return; +} diff --git a/lib_dec/ppp_dec.c b/lib_dec/ppp_dec.c new file mode 100644 index 000000000..ecd94d406 --- /dev/null +++ b/lib_dec/ppp_dec.c @@ -0,0 +1,77 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*------------------------------------------------------------------- + * ppp_quarter_decoder() + * + * PPP quarter decoder + *-------------------------------------------------------------------*/ + +void ppp_quarter_decoder( + Decoder_State *st, /* i/o: decoder state structure */ + DTFS_STRUCTURE *CURRCW_Q_DTFS, /* i/o: Current CW DTFS */ + int prevCW_lag, /* i : Previous lag */ + float *lastLgainD, /* i/o: Last gain lowband */ + float *lastHgainD, /* i/o: Last gain highwband */ + float *lasterbD, /* i/o: Last ERB vector */ + short bfi, /* i : FER flag */ + DTFS_STRUCTURE PREV_CW_D /* i : Previous DTFS */ +) +{ + DTFS_STRUCTURE *PREVDTFS = DTFS_new(); + + float tmp, temp_pl = (float) prevCW_lag, temp_l = (float) CURRCW_Q_DTFS->lag; + int l = CURRCW_Q_DTFS->lag; + int POWER_IDX,AMP_IDX[2]; + float Erot = 0.0, z = 0.0; + short num_erb = 24; + + if ( CURRCW_Q_DTFS->upper_cut_off_freq == 4000.0 ) + { + num_erb = 22; + } + else if ( CURRCW_Q_DTFS->upper_cut_off_freq == 6400.0 ) + { + num_erb = 24; + } + + DTFS_copy(PREVDTFS, PREV_CW_D); + if( bfi == 0 ) + { + POWER_IDX = get_next_indice( st, 6 ); + AMP_IDX[0] = get_next_indice( st, 6 ); + AMP_IDX[1] = get_next_indice( st, 6 ); + + /* Amplitude Dequantization */ + DTFS_dequant_cw(prevCW_lag,POWER_IDX,AMP_IDX, lastLgainD, lastHgainD, lasterbD,CURRCW_Q_DTFS,num_erb); + } + + /* Copying phase spectrum over */ + DTFS_adjustLag(PREVDTFS,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)))); + + DTFS_phaseShift(PREVDTFS,(float)(PI2*Erot/CURRCW_Q_DTFS->lag)) ; + DTFS_car2pol(PREVDTFS); + + mvr2r(PREVDTFS->b, CURRCW_Q_DTFS->b, (short)(CURRCW_Q_DTFS->lag>>1)+1); + + DTFS_pol2car(CURRCW_Q_DTFS); + + tmp = (float) get_next_indice( st, 3 ); + DTFS_phaseShift(CURRCW_Q_DTFS,(float)(PI2*(tmp-3)/CURRCW_Q_DTFS->lag)) ; + + free( PREVDTFS ); + + return; +} diff --git a/lib_dec/pvq_core_dec.c b/lib_dec/pvq_core_dec.c new file mode 100644 index 000000000..8c8803485 --- /dev/null +++ b/lib_dec/pvq_core_dec.c @@ -0,0 +1,429 @@ + +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "wmc_auto.h" +#include +#include +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" +#include "stl.h" + +static short get_pvq_splits( Decoder_State *st, const short band_bits, const short sfmsize, short *bits ); + +static void densitySymbolIndexDecode(Decoder_State *st, short density, short opp_sz, short near_sz,short *index_phi); + +static void pvq_decode_band( + Decoder_State *st, + short *pulse_vector, + short *npulses, + float *coefs_quant, + const short sfmsize, + const short band_bits, + short *bits_left, + const short strict_bits +) +{ + short K_val; + short j, Np; + short part_start[MAX_SPLITS+1], dim_part[MAX_SPLITS+1], bits_part[MAX_SPLITS+1]; + short pool_tot, pool_part, dim_parts; + float g_part[MAX_SPLITS]; + short g_part_s[MAX_SPLITS]; + short sg_part[MAX_SPLITS+1]; + short idx_sort[MAX_SPLITS+1]; + short js, band_bits_tot, split_bit; + + Np = get_pvq_splits(st, band_bits, sfmsize, &split_bit); + band_bits_tot = band_bits - split_bit; + + dim_parts = intLimCDivPos( (int)sfmsize,Np) ; + set_s(dim_part,dim_parts,Np-1); + dim_part[Np-1] = sfmsize-dim_parts*(Np-1); + + part_start[0] = 0; + for(j = 1; j 1 ) + { + decode_energies( st, Np, dim_part, bits_part, g_part_s, band_bits_tot, bits_left, sfmsize, strict_bits ); + } + else + { + bits_part[0] = band_bits_tot; + } + + pool_tot = 0; + pool_part = 0; + + for (j = 0; j < Np; j++) + { + g_part[j] = -((float)g_part_s[j])/32768; + g_part_s[j] = -g_part_s[j]; + } + + srt_vec_ind(g_part_s,sg_part,idx_sort,Np); + for(j = 0; j= 1 ) + { + pvq_decode(st, coefs_quant + part_start[js], pulse_vector + part_start[js], K_val, dim_part[js], g_part[js]); + } + else + { + set_f(coefs_quant + part_start[js],0.0f,dim_part[js]); + set_s(pulse_vector + part_start[js],0,dim_part[js]); + } + } + + return; +} + +void pvq_decode_frame( + Decoder_State *st, + float *coefs_quant, /* o : quantized coefficients */ + short *npulses, /* o : number of pulses per band */ + short *pulse_vector, /* o : non-normalized pulse shapes */ + const short *sfm_start, /* i : indices of first coefficients in the bands */ + const short *sfm_end, /* i : indices of last coefficients in the bands */ + const short *sfmsize, /* i : band sizes */ + const short nb_sfm, /* i : total number of bands */ + const short *R, /* i : bitallocation per band (Q3) */ + const short pvq_bits, /* i : number of bits avaiable */ + const short core /* i : core */ +) +{ + short i, j; + short band_bits, bits_left; + short bit_pool = 0; + short coded_bands, bands_to_code; + short curr_bits; + short R_sort[NB_SFM]; /*Q3*/ + short is, i_sort[NB_SFM]; + short strict_bits; + + rc_dec_init(st, pvq_bits); + curr_bits = (pvq_bits - RC_BITS_RESERVED)<<3; + bands_to_code = 0; + for (i = 0; i < nb_sfm; i++) + { + if (R[i] > 0) + { + bands_to_code++; + } + } + + if (core == ACELP_CORE) + { + strict_bits = 1; + srt_vec_ind (R, R_sort, i_sort, nb_sfm); + } + else + { + strict_bits = 0; + for(i=0; i 0) + { + bandBitsAdjustment(st->rc_num_bits, st->rc_range, curr_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( st, &pulse_vector[sfm_start[is]], &npulses[is], + &coefs_quant[sfm_start[is]], sfmsize[is], band_bits, + &bits_left, strict_bits); + + /* Updates */ + coded_bands++; + } + else + { + for (j = sfm_start[is]; j < sfm_end[is]; j++) + { + coefs_quant[j] = 0.0f; + pulse_vector[j] = 0; + } + } + } + + rc_dec_finish(st); +} + +/*-------------------------------------------------------------------* + * pvq_core_dec() + * + *-------------------------------------------------------------------*/ + +short pvq_core_dec ( + Decoder_State *st, + const short *sfm_start, + const short *sfm_end, + const short *sfmsize, + float coefs_quant[], /* o : output MDCT */ + short bits_tot, + short nb_sfm, + short *R, + short *Rs, + short *npulses, + short *maxpulse, + const short core +) +{ + short i; + short R_upd; + short ord[NB_SFM_MAX]; + short pulse_vector[L_FRAME48k]; + short pvq_bits; + short gain_bits_array[NB_SFM]; + float fg_pred[NB_SFM_MAX]; + + st->ber_occured_in_pvq = 0; + + R_upd = bits_tot * 8; + assign_gain_bits( core, nb_sfm, sfmsize, R, gain_bits_array, &R_upd ); + + pvq_bits = R_upd >> 3; + + pvq_decode_frame(st, coefs_quant, npulses, pulse_vector, sfm_start, + sfm_end, sfmsize, nb_sfm, R, pvq_bits, core ); + + if( Rs != NULL ) + { + for(i=0; i 0); /* Update Rs in case no pulses were assigned */ + } + } + + for(i=0; i 0); /* Update in case no pulses were assigned */ + } + + get_max_pulses( sfm_start, sfm_end, ord, npulses, nb_sfm, pulse_vector, maxpulse ); + + fine_gain_pred( sfm_start, sfm_end, sfmsize, ord, npulses, maxpulse, R, + nb_sfm, coefs_quant, pulse_vector, fg_pred, core ); + + fine_gain_dec(st, ord, nb_sfm, gain_bits_array, fg_pred); + + if( st->ber_occured_in_pvq != 0 ) + { + set_f( fg_pred, (1.0f/8192.0f), nb_sfm ); /* low complex ECU action in case of detetected BER in PVQ decoding */ + } + + apply_gain(ord, sfm_start, sfm_end, nb_sfm, fg_pred, coefs_quant); + + return (short)bits_tot; +} + +void decode_energies( + Decoder_State *st, + short Np, + short *dim_part, + short *bits_part, + short *g_part, + short qband, + short *bits_left, + short dim, + const short strict_bits +) +{ + short res; + short i, l_Np, r_Np; + short l_bits, r_bits, l_dim, r_dim; + short il, ir; + short oppRQ3, qzero; + short index_phi=-1; + l_Np = Np>>1; + r_Np = Np-l_Np; + + l_bits = 0; + l_dim = 0; + for(i=0; irc_num_bits, st->rc_range, &qzero); + densitySymbolIndexDecode( st, res, r_dim, l_dim, &index_phi); + densityAngle2RmsProjDec(res, index_phi, &ir,&il, &oppRQ3); + for(i = 0; i> 15; + } + + for(i = l_Np; i> 15; + } + + + NearOppSplitAdjustment( qband, qzero, st->rc_num_bits, st->rc_range, *bits_left, + strict_bits, Np, dim_part[0], dim_part[Np-1], + l_dim, r_dim, oppRQ3, + &l_bits, &r_bits, bits_left); + if(l_Np > 1) + { + decode_energies( st, l_Np, dim_part, bits_part, g_part, l_bits, bits_left, l_dim, strict_bits ); + } + else + { + bits_part[0] = l_bits; + } + + if(r_Np > 1) + { + decode_energies( st, 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; + } + return; +} + + +static void densitySymbolIndexDecode(Decoder_State *st, + short density, + short opp_sz, + short near_sz, + short *index_phi + ) +{ + + long tmp1; + short tmp2 ; + int sym_freq = 1, cum_freq = 0, tot, dec_freq; + short angle , c ; + short res1, res2, res_c, res_alpha; + short res=density; + short r_dim =opp_sz; + short l_dim =near_sz; + short alpha ; + + if( (0xFFFE&density) == 0 ) + { + /* odd density exit */ + *index_phi = -1; + return; + } +#define WMC_TOOL_SKIP + 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(res, angle); +#undef WMC_TOOL_SKIP + + res_c = res-c; + if(c == 0) + { + tot = res*(res+1) + 1; + dec_freq = rc_decode(st, tot); + alpha = (short) floor_sqrt_exact((unsigned int)(res+1)*(res+1)-dec_freq) + res+1; + sym_freq = 2*(res-alpha) + 1; + cum_freq = alpha*(2*(res+1)-alpha); + } + else if(c == res) + { + tot = res*(res+1) + 1; + dec_freq = rc_decode(st, tot); + alpha = (short) floor_sqrt_exact((unsigned int)dec_freq); + sym_freq = 2*alpha + 1; + cum_freq = alpha*alpha; + } + else + { + tot = res*c*(res-c) + res+1; + dec_freq = rc_decode(st, tot); + if(dec_freq < tot -(res+1) - (res-(c+1))*(res-c)*c + c+1 ) + { + alpha = (res_c-1+(short)floor_sqrt_exact((unsigned int)res_c*(res_c+4*dec_freq - 2) + 1))/(2*res_c); + sym_freq = 2*alpha*res_c + 1; + cum_freq = alpha*((alpha-1)*res_c + 1); + } + else + { + res1 = res+1; + res2 = 2*res+1; + tmp1 = (c*res2+1)*(c*res2+1) + 4*c*((tot-dec_freq-res1) -c*(res*res1)); + tmp2 = (short)floor_sqrt_exact((unsigned int) tmp1 ); + if(tmp2*tmp2 != tmp1) + { + tmp2++; /* convert to ceil */ + } + + alpha = (c*(2*res+1)+1-tmp2)/(2*c); + + res_alpha = res-alpha; + sym_freq = 2*res_alpha*c + 1; + cum_freq = tot -(res+1) - res_alpha*(res_alpha+1)*c + alpha; + } + } + rc_dec_update(st, cum_freq, sym_freq); + + *index_phi = alpha; + return; +} + + +/*--------------------------------------------------------------------------* + * get_pvq_splits() + * + * Retrieve the number of segments + *--------------------------------------------------------------------------*/ + +static short get_pvq_splits( /* o : Number of segments */ + Decoder_State *st, /* i/o: Decoder state */ + const short band_bits, /* i : Band bit rate */ + const short sfmsize, /* i : Band width */ + short *bits /* o : Used bits */ +) +{ + short Np; + unsigned int flag; + + Np = (short)(intLimCDivPos( (int)band_bits, 67)>>2); + if (band_bits - 268*Np != 0 || Np == 0 ) /* L_msu */ + { + Np++; /* ceil */ + } + *bits = 0; + if ( Np < MAX_SPLITS && (band_bits - (8*sfmsize * THR_ADD_SPLIT ) > 0)) + { + flag = rc_dec_bits(st, 1); + *bits = 8; + if( flag ) + { + Np += 1; + } + } + + Np = max(Np, (short)(ceil((float)sfmsize/PVQ_MAX_BAND_SIZE))); + Np = min(MAX_SPLITS, Np); + Np = min((short)floor((float)sfmsize/MIN_BAND_SIZE), Np); + return Np; +} diff --git a/lib_dec/pvq_decode.c b/lib_dec/pvq_decode.c new file mode 100644 index 000000000..c4159e26d --- /dev/null +++ b/lib_dec/pvq_decode.c @@ -0,0 +1,75 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "prot.h" +#include "rom_com.h" +#include "math.h" + + +/*-------------------------------------------------------------------* + * Function pvq_decode() * + * * + * PVQ subvector decoding algorithm * + *-------------------------------------------------------------------*/ + +void pvq_decode( + Decoder_State *st, + float *xq, /* o: decoded vector (scaled float) */ + short *y, /* o: decoded vector (non-scaled short)*/ + const short k_val, /* i: number of allocated pulses */ + const short dim, /* i: Length of vector */ + const float gain /* i: Gain */ +) +{ + short i; + float gain_fac; + float yy; + short output[PVQ_MAX_BAND_SIZE]; /* short interface as in STL-FIP */ + unsigned int h_mem[1+KMAX_NON_DIRECT+1]; /* allocate max offset memory for dim 6 */ + PvqEntry entry; + + entry = get_size_mpvq_calc_offset(dim, k_val, h_mem); /* get size & prepare H(adaptive table for entry.size=N_MPVQ(dim,k_val) */ + + if( dim != 1) + { + entry.lead_sign_ind = (short)rc_dec_bits(st, 1); + entry.index = rc_dec_uniform(st, entry.size); /* NB so far no PVQ-size wc is exactly 2^32-1 */ + /* safety check in case of bit errors */ + if( entry.index >= entry.size || st->ber_occured_in_pvq != 0 ) + { + st->ber_occured_in_pvq = 1; + st->BER_detect = 1; + entry.index = 0; /* a zero index will essentially disable PVQ index decompostion complexity */ + } + + } + else + { + entry.lead_sign_ind = (short)rc_dec_bits(st, 1); /* always a single sign bit */ + entry.index = 0; + } + mpvq_decode_vec(&entry, h_mem, output); + + for(i=0; i +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + + +static short rc_dec_read( Decoder_State *st ); + +/*-------------------------------------------------------------------* + * rc_dec_init() + * + * Initialize range coder + *-------------------------------------------------------------------*/ + +void rc_dec_init( + Decoder_State *st, /* i/o: Decoder State */ + short tot_bits /* i : Total bit budget */ +) +{ + short i; + + st->rc_low = 0; + st->rc_range = 0xffffffff; + st->rc_num_bits = 0; + st->rc_offset = tot_bits + st->next_bit_pos; + st->rc_end = st->rc_offset; + + for (i = 0; i < 4; i++) + { + st->rc_low = (st->rc_low << 8) + rc_dec_read(st); + } + + return; +} + +/*-------------------------------------------------------------------* + * rc_decode() + * + * Decode symbol + *-------------------------------------------------------------------*/ + +unsigned int rc_decode( /* o : Decoded cumulative frequency */ + Decoder_State *st, /* i/o: Decoder State */ + unsigned int tot /* i : Total cumulative frequency */ +) +{ + unsigned int inv, val; + short exp; + + inv = UL_inverse(tot, &exp); + st->rc_help = UMult_32_32(st->rc_range, inv); + st->rc_help = st->rc_help >> (exp - 32); + + /* safety check in case of bit errors */ + val = st->rc_low/st->rc_help; + if (val > tot) + { + st->BER_detect = 1; + return 0; + } + return val; +} + +/*-------------------------------------------------------------------* + * rc_dec_update() + * + * Update range coder + *-------------------------------------------------------------------*/ + +void rc_dec_update( + Decoder_State *st, /* i/o: Decoder State */ + unsigned int cum_freq, /* i : Cumulative frequency */ + unsigned int sym_freq /* i : Symbol frequency */ +) +{ + st->rc_low = st->rc_low - cum_freq*st->rc_help; + st->rc_range = st->rc_help*sym_freq; + + while (st->rc_range < (1<<24)) + { + st->rc_num_bits += 8; + st->rc_low = (st->rc_low << 8) + rc_dec_read(st); + st->rc_range <<= 8; + } + + return; +} + +/*-------------------------------------------------------------------* + * rc_dec_bits() + * + * Encode bits + *-------------------------------------------------------------------*/ + +unsigned int rc_dec_bits( /* i : Decoded value */ + Decoder_State *st, /* i/o: Decoder State */ + short bits /* i : Number of bits */ +) +{ + unsigned int value; + + st->rc_num_bits += bits; + + if (bits > 16) + { + st->rc_offset -= bits - 16; + value = get_indice(st, st->rc_offset, bits - 16) << 16; + st->rc_offset -= 16; + value |= get_indice(st, st->rc_offset, 16); + } + else + { + st->rc_offset -= bits; + value = get_indice(st, st->rc_offset, bits); + + } + + return value; +} + +/*-------------------------------------------------------------------* + * rc_dec_uniform() + * + * Encode with uniform distribution + *-------------------------------------------------------------------*/ + +unsigned int rc_dec_uniform( /* i : Decoded value */ + Decoder_State *st, /* i/o: Decoder State */ + unsigned int tot /* i : Maximum value */ +) +{ + unsigned int value; + short n; +#define WMC_TOOL_SKIP + ADD(2); MOVE(1); + n = 32 - norm_ul(tot - 1); /* aligned to BASOP */ +#undef WMC_TOOL_SKIP + if (n <= 8) + { + value = rc_decode(st, tot); + rc_dec_update(st, value, 1); + } + else + { + n -= 8; + value = rc_decode(st, (tot >> n) + 1); + rc_dec_update(st, value, 1); + value <<= n; + value |= rc_dec_bits(st, n); + } + + return value; +} + +/*-------------------------------------------------------------------* + * rc_dec_finish() + * + * Finalize range decoder + *-------------------------------------------------------------------*/ + +void rc_dec_finish(Decoder_State *st) +{ + st->next_bit_pos = st->rc_end; +} + + +/*-------------------------------------------------------------------* + * rc_dec_read() + * + * Read a byte from bit stream + *-------------------------------------------------------------------*/ + +static short rc_dec_read(Decoder_State *st) +{ + short bits; + + bits = st->rc_end - st->next_bit_pos; + + /* If the end of the buffer has been reached, pad the last byte with zeros */ + if (bits < 8) + { + return (short)(get_next_indice(st, bits) << (8-bits)); + } + else + { + return (short)get_next_indice(st, 8); + } +} diff --git a/lib_dec/re8_dec.c b/lib_dec/re8_dec.c new file mode 100644 index 000000000..4fc3f1938 --- /dev/null +++ b/lib_dec/re8_dec.c @@ -0,0 +1,73 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * Function prototypes + *-------------------------------------------------------------------*/ +void re8_decode_base_index(int n, long I, int *x); + +/*-------------------------------------------------------------------------- + re8_dec(n, I, k, y) + MULTI-RATE INDEXING OF A POINT y in THE LATTICE RE8 (INDEX DECODING) + (i) n: codebook number (*n is an integer defined in {0,2,3,4,..,n_max}) + (i) I: index of c (pointer to unsigned 16-bit word) + (i) k: index of v (8-dimensional vector of binary indices) = Voronoi index + (o) y: point in RE8 (8-dimensional integer vector) + 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(int n, long I, int k[], int y[]) +{ + int 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 (n <= 4) + { + re8_decode_base_index(n, I, y); + } + else + { + /*--------------------------------------------------------------------* + * compute the Voronoi modulo m = 2^r where r is extension order + *--------------------------------------------------------------------*/ + m = 1; + while (n > 4) + { + m *= 2; + n -= 2; + } + + /*--------------------------------------------------------------------* + * 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(n, I, y); + + /*--------------------------------------------------------------------* + * decode Voronoi index k[] into v + *--------------------------------------------------------------------*/ + re8_k2y(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]; + } + } + + return; +} diff --git a/lib_dec/rom_dec.c b/lib_dec/rom_dec.c new file mode 100644 index 000000000..1c0f6fbd9 --- /dev/null +++ b/lib_dec/rom_dec.c @@ -0,0 +1,214 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" + +/*----------------------------------------------------------------------------------* + * LP filter for filtering periodic part of excitation in artificial onset + * construction after frame error concealment + *----------------------------------------------------------------------------------*/ + +const float h_low[5] = { -0.0125f, 0.1090f, 0.7813f, 0.1090f, -0.0125f }; + +/* RE8 related tables */ +const int mult_avq_tab[7] = {1,1,1,342,1,1,171}; +const int shift_avq_tab[7] = {0,0,1, 10,2,0, 10}; + +const short hntable[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 short hetable[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 short hestable[15]= +{ + 0X11, 0X21, -0X04, 0X21, -0X03, 0X21, -0X02, -0X05, 0X11, 0X21, -0X01, -0X06, + 0X11, -0X07, -0X00 +}; + +const float lsf_tab[LPC_SHB_ORDER] = +{ + 0.070633653f, 0.11962059f, 0.16925794f, 0.20627696f, 0.24345790f, + 0.31293656f, 0.34594478f, 0.38072862f, 0.410051247f, 0.44525622f +}; + +/* frequency group start bins for transient analysis */ +/* 125 375 750 1250 2000 4000 8000 16000 24000 */ +const short gw[LGW_MAX] = { 1, 3, 6, 10, 16, 32, 64, 128, 192 }; + +/* 31.25 343.75 718.75 1218.75 1968.75 4000 8000 16000 24000 */ +const short gwlpr[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 }; + +const float w_hamm48k_2[L_TRANA48k/2] = +{ + 0.080000000000000f, 0.080061898522781f, 0.080247577432747f, 0.080556986759243f, 0.080990043232791f, 0.081546630307495f, 0.082226598192408f, 0.083029763891845f, + 0.083955911254630f, 0.085004791032270f, 0.086176120946031f, 0.087469585762906f, 0.088884837380455f, 0.090421494920485f, 0.092079144831552f, 0.093857341000262f, + 0.095755604871328f, 0.097773425576361f, 0.099910260071357f, 0.102165533282844f, 0.104538638262646f, 0.107028936351231f, 0.109635757349585f, 0.112358399699582f, + 0.115196130672791f, 0.118148186567665f, 0.121213772915079f, 0.124392064692135f, 0.127682206544200f, 0.131083313015096f, 0.134594468785406f, 0.138214728918801f, + 0.141943119116349f, 0.145778635978722f, 0.149720247276233f, 0.153766892226636f, 0.157917481780606f, 0.162170898914830f, 0.166525998932624f, 0.170981609771997f, + 0.175536532321084f, 0.180189540740855f, 0.184939382795015f, 0.189784780187013f, 0.194724428904063f, 0.199756999568084f, 0.204881137793469f, 0.210095464551578f, + 0.215398576541875f, 0.220789046569584f, 0.226265423929784f, 0.231826234797829f, 0.237469982625987f, 0.243195148546199f, 0.249000191778843f, 0.254883550047394f, + 0.260843639998870f, 0.266878857629950f, 0.272987578718653f, 0.279168159261450f, 0.285418935915708f, 0.291738226447335f, 0.298124330183510f, 0.304575528470374f, + 0.311090085135560f, 0.317666246955443f, 0.324302244126969f, 0.330996290743956f, 0.337746585277719f, 0.344551311061912f, 0.351408636781431f, 0.358316716965264f, + 0.365273692483159f, 0.372277691045950f, 0.379326827709445f, 0.386419205381703f, 0.393552915333588f, 0.400726037712459f, 0.407936642058840f, 0.415182787825961f, + 0.422462524902000f, 0.429773894134909f, 0.437114927859666f, 0.444483650427822f, 0.451878078739195f, 0.459296222775571f, 0.466736086136265f, 0.474195666575400f, + 0.481672956540759f, 0.489165943714067f, 0.496672611552554f, 0.504190939831653f, 0.511718905188695f, 0.519254481667438f, 0.526795641263308f, 0.534340354469178f, + 0.541886590821560f, 0.549432319447051f, 0.556975509608890f, 0.564514131253475f, 0.572046155556704f, 0.579569555469978f, 0.587082306265726f, 0.594582386082315f, + 0.602067776468170f, 0.609536462925001f, 0.616986435449943f, 0.624415689076500f, 0.631822224414129f, 0.639204048186324f, 0.646559173767056f, 0.653885621715418f, + 0.661181420308344f, 0.668444606071246f, 0.675673224306430f, 0.682865329619155f, 0.690018986441185f, 0.697132269551692f, 0.704203264595389f, 0.711230068597719f, + 0.718210790476997f, 0.725143551553344f, 0.732026486054283f, 0.738857741616868f, 0.745635479786192f, 0.752357876510168f, 0.759023122630418f, 0.765629424369165f, + 0.772175003811978f, 0.778658099386259f, 0.785076966335314f, 0.791429877187917f, 0.797715122223211f, 0.803931009930835f, 0.810075867466152f, 0.816148041100446f, + 0.822145896665987f, 0.828067819995822f, 0.833912217358185f, 0.839677515885409f, 0.845362163997224f, 0.850964631818323f, 0.856483411590088f, 0.861917018076364f, + 0.867263988963175f, 0.872522885252262f, 0.877692291648358f, 0.882770816940072f, 0.887757094374303f, 0.892649782024062f, 0.897447563149619f, 0.902149146552868f, + 0.906753266924821f, 0.911258685186131f, 0.915664188820559f, 0.919968592201292f, 0.924170736910022f, 0.928269492048706f, 0.932263754543917f, 0.936152449443706f, + 0.939934530206900f, 0.943608978984751f, 0.947174806894860f, 0.950631054287315f, 0.953976791002949f, 0.957211116623676f, 0.960333160714807f, 0.963342083059310f, + 0.966237073883933f, 0.969017354077129f, 0.971682175398738f, 0.974230820681355f, 0.976662604023336f, 0.978976870973391f, 0.981172998706713f, 0.983250396192597f, + 0.985208504353495f, 0.987046796215483f, 0.988764777050081f, 0.990361984507393f, 0.991837988740540f, 0.993192392521341f, 0.994424831347216f, 0.995534973539285f, + 0.996522520331626f, 0.997387205951684f, 0.998128797691797f, 0.998747095971820f, 0.999241934392838f, 0.999613179781951f, 0.999860732228111f, 0.999984525109009f +}; + +const float w_hamm32k_2[L_TRANA32k/2] = +{ + 0.080000000000000f, 0.080139632090179f, 0.080558443590627f, 0.081256180242538f, 0.082232418452750f, 0.083486565550910f, 0.085017860149273f, 0.086825372604947f, + 0.088908005584270f, 0.091264494728999f, 0.093893409423896f, 0.096793153665248f, 0.099961967029797f, 0.103397925743485f, 0.107098943849369f, 0.111062774473996f, + 0.115287011191475f, 0.119769089484404f, 0.124506288300781f, 0.129495731705944f, 0.134734390628539f, 0.140219084699457f, 0.145946484182623f, 0.151913111996467f, + 0.158115345824847f, 0.164549420316138f, 0.171211429369169f, 0.178097328504598f, 0.185202937320297f, 0.192523942029263f, 0.200055898078497f, 0.207794232847276f, + 0.215734248423172f, 0.223871124454139f, 0.232199921074925f, 0.240715581906049f, 0.249412937123505f, 0.258286706597345f, 0.267331503097225f, 0.276541835562968f, + 0.285912112438167f, 0.295436645064799f, 0.305109651136783f, 0.314925258210395f, 0.324877507269410f, 0.334960356342792f, 0.345167684172755f, 0.355493293930949f, + 0.365930916980537f, 0.376474216681854f, 0.387116792239357f, 0.397852182587524f, 0.408673870313343f, 0.419575285613002f, 0.430549810280395f, 0.441590781725011f, + 0.452691497016760f, 0.463845216955300f, 0.475045170161378f, 0.486284557187706f, 0.497556554646881f, 0.508854319353835f, 0.520170992480304f, 0.531499703718800f, + 0.542833575453544f, 0.554165726935838f, 0.565489278461346f, 0.576797355546729f, 0.588083093103121f, 0.599339639603893f, 0.610560161244195f, 0.621737846089724f, + 0.632865908212225f, 0.643937591809204f, 0.654946175305346f, 0.665884975433158f, 0.676747351290353f, 0.687526708371517f, 0.698216502571607f, 0.708810244158849f, + 0.719301501714632f, 0.729683906037996f, 0.739951154012344f, 0.750097012432047f, 0.760115321786592f, 0.770000000000000f, 0.779745046123229f, 0.789344543977327f, + 0.798792665745119f, 0.808083675509254f, 0.817211932734458f, 0.826171895691878f, 0.834958124823446f, 0.843565286044212f, 0.851988153980648f, 0.860221615142946f, + 0.868260671029406f, 0.876100441160999f, 0.883736166044290f, 0.891163210060907f, 0.898377064281809f, 0.905373349204632f, 0.912147817412476f, 0.918696356152490f, + 0.925014989832710f, 0.931099882435622f, 0.936947339846999f, 0.942553812098577f, 0.947915895523229f, 0.953030334821319f, 0.957894025036981f, 0.962504013443125f, + 0.966857501334024f, 0.970951845724403f, 0.974784560953977f, 0.978353320196492f, 0.981655956872329f, 0.984690465963826f, 0.987455005232518f, 0.989947896337551f, + 0.992167625854595f, 0.994112846194642f, 0.995782376422118f, 0.997175202971826f, 0.998290480264278f, 0.999127531219040f, 0.999685847665791f, 0.999965090652822f +}; + +const float w_hamm16k_2[L_TRANA16k/2] = +{ + 0.080000000000000f, 0.080562848541440f, 0.082250016781061f, 0.085057375935460f, 0.088978055926352f, 0.094002462192807f, 0.100118299170741f, 0.107310600382232f, + 0.115561765060989f, 0.124851601224384f, 0.135157375086613f, 0.146453866692083f, 0.158713431632863f, 0.171906068699192f, 0.185999493297458f, 0.200959216456013f, + 0.216748629225465f, 0.233329092266912f, 0.250660030408878f, 0.268699031941561f, 0.287401952405387f, 0.306723022619904f, 0.326614960688639f, 0.347029087705815f, + 0.367915446881795f, 0.389222925795719f, 0.410899381476157f, 0.432891768003705f, 0.455146266323232f, 0.477608415948132f, 0.500223248234257f, 0.522935420897402f, + 0.545689353445147f, 0.568429363191639f, 0.591099801522450f, 0.613645190076067f, 0.636010356508734f, 0.658140569510427f, 0.679981672741539f, 0.701480217362516f, + 0.722583592832128f, 0.743240155654278f, 0.763399355758289f, 0.783011860203399f, 0.802029673904734f, 0.820406257085326f, 0.838096639166738f, 0.855057528819616f, + 0.871247419904816f, 0.886626693045890f, 0.901157712584333f, 0.914804918680351f, 0.927534914333744f, 0.939316547111965f, 0.950120985385339f, 0.959921788882895f, + 0.968694973396140f, 0.976419069472435f, 0.983075174954342f, 0.988647001236375f, 0.993120913125941f, 0.996485962210947f, 0.998733913652397f, 0.999859266336418f +}; + +const float w_hamm8k_2[L_TRANA8k/2] = +{ + 0.080000000000000f, 0.082285843331915f, 0.089120655589670f, 0.100436509338375f, 0.116120942539613f, 0.136018076249695f, 0.159930163814642f, 0.187619556165270f, + 0.218811063680407f, 0.253194691144983f, 0.290428718621751f, 0.330143097617545f, 0.371943128791458f, 0.415413384654218f, 0.460121838273212f, 0.505624156950245f, + 0.551468118199513f, 0.597198104137843f, 0.642359629619905f, 0.686503859115775f, 0.729192067440081f, 0.770000000000000f, 0.808522089228003f, 0.844375485294555f, + 0.877203861041720f, 0.906680953322544f, 0.932513805550792f, 0.954445679235113f, 0.972258605561518f, 0.985775551665376f, 0.994862180063559f, 0.999428183760704f, +}; + +const float w_hamm_sana48k_2[L_PROT_HAMM_LEN2_48k] = +{ + 0.080000000000000f, 0.080027462973758f, 0.080109848615839f, 0.080247147089046f, 0.080439341999361f, 0.080686410397899f, 0.080988322783646f, 0.081345043106986f, + 0.081756528774001f, 0.082222730651560f, 0.082743593073186f, 0.083319053845701f, 0.083949044256652f, 0.084633489082516f, 0.085372306597683f, 0.086165408584215f, + 0.087012700342376f, 0.087914080701944f, 0.088869442034286f, 0.089878670265216f, 0.090941644888610f, 0.092058238980796f, 0.093228319215714f, 0.094451745880830f, + 0.095728372893819f, 0.097058047820012f, 0.098440611890594f, 0.099875900021559f, 0.101363740833430f, 0.102903956671715f, 0.104496363628120f, 0.106140771562514f, + 0.107836984125627f, 0.109584798782499f, 0.111384006836658f, 0.113234393455047f, 0.115135737693669f, 0.117087812523972f, 0.119090384859956f, 0.121143215586007f, + 0.123246059585445f, 0.125398665769793f, 0.127600777108759f, 0.129852130660926f, 0.132152457605149f, 0.134501483272651f, 0.136898927179823f, 0.139344503061711f, + 0.141837918906203f, 0.144378876988888f, 0.146967073908615f, 0.149602200623714f, 0.152283942488898f, 0.155011979292835f, 0.157785985296381f, 0.160605629271474f, + 0.163470574540687f, 0.166380479017425f, 0.169334995246772f, 0.172333770446984f, 0.175376446551605f, 0.178462660252227f, 0.181592043041866f, 0.184764221258970f, + 0.187978816132029f, 0.191235443824805f, 0.194533715482165f, 0.197873237276507f, 0.201253610454792f, 0.204674431386151f, 0.208135291610080f, 0.211635777885218f, + 0.215175472238683f, 0.218753952015982f, 0.222370789931481f, 0.226025554119419f, 0.229717808185479f, 0.233447111258894f, 0.237213018045087f, 0.241015078878844f, + 0.244852839778006f, 0.248725842497672f, 0.252633624584921f, 0.256575719434027f, 0.260551656342175f, 0.264560960565666f, 0.268603153376600f, 0.272677752120042f, + 0.276784270271653f, 0.280922217495778f, 0.285091099704000f, 0.289290419114133f, 0.293519674309662f, 0.297778360299609f, 0.302065968578839f, 0.306381987188769f, + 0.310725900778505f, 0.315097190666374f, 0.319495334901855f, 0.323919808327907f, 0.328370082643670f, 0.332845626467550f, 0.337345905400666f, 0.341870382090660f, + 0.346418516295861f, 0.350989764949788f, 0.355583582225999f, 0.360199419603261f, 0.364836725931051f, 0.369494947495359f, 0.374173528084809f, 0.378871909057071f, + 0.383589529405564f, 0.388325825826447f, 0.393080232785873f, 0.397852182587524f, 0.402641105440390f, 0.407446429526807f, 0.412267581070735f, 0.417103984406268f, + 0.421955062046372f, 0.426820234751838f, 0.431698921600448f, 0.436590540056336f, 0.441494506039550f, 0.446410233995788f, 0.451337136966322f, 0.456274626658076f, + 0.461222113513879f, 0.466179006782852f, 0.471144714590954f, 0.476118644011648f, 0.481100201136704f, 0.486088791147110f, 0.491083818384099f, 0.496084686420271f, + 0.501090798130810f, 0.506101555764784f, 0.511116361016516f, 0.516134615097028f, 0.521155718805537f, 0.526179072601003f, 0.531204076673714f, 0.536230131016910f, + 0.541256635498423f, 0.546282989932337f, 0.551308594150653f, 0.556332848074950f, 0.561355151788038f, 0.566374905605590f, 0.571391510147749f, 0.576404366410692f, + 0.581412875838160f, 0.586416440392922f, 0.591414462628186f, 0.596406345758937f, 0.601391493733196f, 0.606369311303187f, 0.611339204096419f, 0.616300578686650f, + 0.621252842664750f, 0.626195404709433f, 0.631127674657866f, 0.636049063576134f, 0.640958983829565f, 0.645856849152894f, 0.650742074720264f, 0.655614077215060f, + 0.660472274899558f, 0.665316087684385f, 0.670144937197788f, 0.674958246854690f, 0.679755441925542f, 0.684535949604939f, 0.689299199080028f, 0.694044621598654f, + 0.698771650537277f, 0.703479721468629f, 0.708168272229108f, 0.712836742985904f, 0.717484576303842f, 0.722111217211948f, 0.726716113269708f, 0.731298714633038f, + 0.735858474119933f, 0.740394847275806f, 0.744907292438496f, 0.749395270802946f, 0.753858246485539f, 0.758295686588082f, 0.762707061261442f, 0.767091843768804f, + 0.771449510548575f, 0.775779541276891f, 0.780081418929751f, 0.784354629844749f, 0.788598663782413f, 0.792813013987120f, 0.796997177247615f, 0.801150653957089f, + 0.805272948172839f, 0.809363567675482f, 0.813422024027731f, 0.817447832632716f, 0.821440512791844f, 0.825399587762201f, 0.829324584813474f, 0.833215035284397f, + 0.837070474638713f, 0.840890442520641f, 0.844674482809841f, 0.848422143675885f, 0.852132977632196f, 0.855806541589490f, 0.859442396908678f, 0.863040109453242f, + 0.866599249641071f, 0.870119392495760f, 0.873600117697347f, 0.877041009632507f, 0.880441657444176f, 0.883801655080607f, 0.887120601343857f, 0.890398099937691f, + 0.893633759514900f, 0.896827193724033f, 0.899978021255524f, 0.903085865887227f, 0.906150356529334f, 0.909171127268689f, 0.912147817412476f, 0.915080071531290f, + 0.917967539501574f, 0.920809876547428f, 0.923606743281775f, 0.926357805746886f, 0.929062735454256f, 0.931721209423824f, 0.934332910222545f, 0.936897526002284f, + 0.939414750537061f, 0.941884283259609f, 0.944305829297265f, 0.946679099507180f, 0.949003810510844f, 0.951279684727920f, 0.953506450409391f, 0.955683841670007f, + 0.957811598520034f, 0.959889466896295f, 0.961917198692508f, 0.963894551788914f, 0.965821290081179f, 0.967697183508596f, 0.969522008081546f, 0.971295545908249f, + 0.973017585220782f, 0.974687920400358f, 0.976306352001886f, 0.977872686777781f, 0.979386737701038f, 0.980848323987568f, 0.982257271117780f, 0.983613410857422f, + 0.984916581277667f, 0.986166626774449f, 0.987363398087044f, 0.988506752315891f, 0.989596552939653f, 0.990632669831523f, 0.991614979274757f, 0.992543363977448f, + 0.993417713086533f, 0.994237922201026f, 0.995003893384487f, 0.995715535176712f, 0.996372762604660f, 0.996975497192592f, 0.997523666971448f, 0.998017206487434f, + 0.998456056809844f, 0.998840165538090f, 0.999169486807964f, 0.999443981297112f, 0.999663616229731f, 0.999828365380479f, 0.999938209077610f, 0.999993134205322f +}; + +const float w_hamm_sana32k_2[L_PROT_HAMM_LEN2_32k] = +{ + 0.080000000000000f, 0.080061898522781f, 0.080247577432747f, 0.080556986759243f, 0.080990043232791f, 0.081546630307495f, 0.082226598192408f, 0.083029763891845f, + 0.083955911254630f, 0.085004791032270f, 0.086176120946031f, 0.087469585762906f, 0.088884837380455f, 0.090421494920485f, 0.092079144831552f, 0.093857341000262f, + 0.095755604871328f, 0.097773425576361f, 0.099910260071357f, 0.102165533282844f, 0.104538638262646f, 0.107028936351231f, 0.109635757349585f, 0.112358399699582f, + 0.115196130672791f, 0.118148186567665f, 0.121213772915079f, 0.124392064692135f, 0.127682206544200f, 0.131083313015096f, 0.134594468785406f, 0.138214728918801f, + 0.141943119116349f, 0.145778635978722f, 0.149720247276233f, 0.153766892226636f, 0.157917481780606f, 0.162170898914830f, 0.166525998932624f, 0.170981609771997f, + 0.175536532321084f, 0.180189540740855f, 0.184939382795015f, 0.189784780187013f, 0.194724428904063f, 0.199756999568084f, 0.204881137793469f, 0.210095464551578f, + 0.215398576541875f, 0.220789046569584f, 0.226265423929784f, 0.231826234797829f, 0.237469982625987f, 0.243195148546199f, 0.249000191778843f, 0.254883550047394f, + 0.260843639998870f, 0.266878857629950f, 0.272987578718653f, 0.279168159261450f, 0.285418935915708f, 0.291738226447335f, 0.298124330183510f, 0.304575528470374f, + 0.311090085135560f, 0.317666246955443f, 0.324302244126969f, 0.330996290743956f, 0.337746585277719f, 0.344551311061912f, 0.351408636781431f, 0.358316716965264f, + 0.365273692483159f, 0.372277691045950f, 0.379326827709445f, 0.386419205381703f, 0.393552915333588f, 0.400726037712459f, 0.407936642058840f, 0.415182787825961f, + 0.422462524902000f, 0.429773894134909f, 0.437114927859666f, 0.444483650427822f, 0.451878078739195f, 0.459296222775571f, 0.466736086136265f, 0.474195666575400f, + 0.481672956540759f, 0.489165943714067f, 0.496672611552554f, 0.504190939831653f, 0.511718905188695f, 0.519254481667438f, 0.526795641263308f, 0.534340354469178f, + 0.541886590821560f, 0.549432319447051f, 0.556975509608890f, 0.564514131253475f, 0.572046155556704f, 0.579569555469978f, 0.587082306265726f, 0.594582386082315f, + 0.602067776468170f, 0.609536462925001f, 0.616986435449943f, 0.624415689076500f, 0.631822224414129f, 0.639204048186324f, 0.646559173767056f, 0.653885621715418f, + 0.661181420308344f, 0.668444606071246f, 0.675673224306430f, 0.682865329619155f, 0.690018986441185f, 0.697132269551692f, 0.704203264595389f, 0.711230068597719f, + 0.718210790476997f, 0.725143551553344f, 0.732026486054283f, 0.738857741616868f, 0.745635479786192f, 0.752357876510168f, 0.759023122630418f, 0.765629424369165f, + 0.772175003811978f, 0.778658099386259f, 0.785076966335314f, 0.791429877187917f, 0.797715122223211f, 0.803931009930835f, 0.810075867466152f, 0.816148041100446f, + 0.822145896665987f, 0.828067819995822f, 0.833912217358185f, 0.839677515885409f, 0.845362163997224f, 0.850964631818323f, 0.856483411590088f, 0.861917018076364f, + 0.867263988963175f, 0.872522885252262f, 0.877692291648358f, 0.882770816940072f, 0.887757094374303f, 0.892649782024062f, 0.897447563149619f, 0.902149146552868f, + 0.906753266924821f, 0.911258685186131f, 0.915664188820559f, 0.919968592201292f, 0.924170736910022f, 0.928269492048706f, 0.932263754543917f, 0.936152449443706f, + 0.939934530206900f, 0.943608978984751f, 0.947174806894860f, 0.950631054287315f, 0.953976791002949f, 0.957211116623676f, 0.960333160714807f, 0.963342083059310f, + 0.966237073883933f, 0.969017354077129f, 0.971682175398738f, 0.974230820681355f, 0.976662604023336f, 0.978976870973391f, 0.981172998706713f, 0.983250396192597f, + 0.985208504353495f, 0.987046796215483f, 0.988764777050081f, 0.990361984507393f, 0.991837988740540f, 0.993192392521341f, 0.994424831347216f, 0.995534973539285f, + 0.996522520331626f, 0.997387205951684f, 0.998128797691797f, 0.998747095971820f, 0.999241934392838f, 0.999613179781951f, 0.999860732228111f, 0.999984525109009f +}; + +const float w_hamm_sana16k_2[L_PROT_HAMM_LEN2_16k] = +{ + 0.080000000000000f, 0.080248875229243f, 0.080995231617495f, 0.082238261557724f, 0.083976620009229f, 0.086208425953062f, 0.088931264427414f, 0.092142189140766f, + 0.095837725659970f, 0.100013875169814f, 0.104666118800010f, 0.109789422514906f, 0.115378242560646f, 0.121426531463883f, 0.127927744575542f, 0.134874847152564f, + 0.142260321969963f, 0.150076177454966f, 0.158313956334418f, 0.166964744786114f, 0.176019182084144f, 0.185467470727822f, 0.195299387043225f, 0.205504292245887f, + 0.216071143952672f, 0.226988508130357f, 0.238244571468020f, 0.249827154159818f, 0.261723723084350f, 0.273921405366317f, 0.286407002305832f, 0.299167003660284f, + 0.312187602263317f, 0.325454708965093f, 0.338953967877692f, 0.352670771909129f, 0.366590278569198f, 0.380697426030022f, 0.394976949423959f, 0.409413397361190f, + 0.423991148649151f, 0.438694429195694f, 0.453507329077705f, 0.468413819756689f, 0.483397771422710f, 0.498442970447917f, 0.513533136930761f, 0.528651942311926f, + 0.543783027042910f, 0.558910018288144f, 0.574016547641481f, 0.589086268837895f, 0.604102875441222f, 0.619050118488809f, 0.633911824073957f, 0.648671910847171f, + 0.663314407417236f, 0.677823469633322f, 0.692183397729409f, 0.706378653312465f, 0.720393876176025f, 0.734213900920944f, 0.747823773365368f, 0.761208766726146f, + 0.774354397554188f, 0.787246441406510f, 0.799870948238030f, 0.812214257496436f, 0.824263012903808f, 0.836004176908999f, 0.847425044795124f, 0.858513258426909f, + 0.869256819623006f, 0.879644103138828f, 0.889663869245825f, 0.899305275893620f, 0.908557890441822f, 0.917411700948838f, 0.925857127005450f, 0.933885030101461f, + 0.941486723514159f, 0.948653981707932f, 0.955379049234843f, 0.961654649126531f, 0.967473990768381f, 0.972830777247415f, 0.977719212165966f, 0.982134005913770f, + 0.986070381391670f, 0.989524079180756f, 0.992491362151336f, 0.994969019506760f, 0.996954370257714f, 0.998445266123226f, 0.999440093855253f, 0.999937776984316f +}; + + +/* er_dec_tcx.c */ +const float h_high3_32[L_FIR_FER2] = {-0.0517f, -0.0587f, -0.0820f, -0.1024f, -0.1164f, 0.8786f, -0.1164f, -0.1024f, -0.0820f, -0.0587f, -0.0517f}; +const float h_high3_16[L_FIR_FER2] = { 0.f, -0.0205f, -0.0651f, -0.1256f, -0.1792f, 0.8028f, -0.1792f, -0.1256f, -0.0651f, -0.0205f, 0.f }; diff --git a/lib_dec/rom_dec.h b/lib_dec/rom_dec.h new file mode 100644 index 000000000..8dc88d502 --- /dev/null +++ b/lib_dec/rom_dec.h @@ -0,0 +1,38 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#ifndef ROM_DEC_H +#define ROM_DEC_H + +#include +#include "options.h" +#include "cnst.h" + +extern const float h_low[]; /* LP filter for filtering periodic part of excitation in artificial onset construction after FEC */ + +extern const int mult_avq_tab[]; +extern const int shift_avq_tab[]; + +extern const short hntable[55]; +extern const short hetable[57]; +extern const short hestable[15]; + +extern const float lsf_tab[LPC_SHB_ORDER]; + +extern const short gw[LGW_MAX]; +extern const short gwlpr[LGW_MAX]; +extern const float w_hamm32k_2[L_TRANA32k/2]; +extern const float w_hamm16k_2[L_TRANA16k/2]; +extern const float w_hamm8k_2[L_TRANA8k/2]; +extern const float w_hamm_sana32k_2[L_PROT_HAMM_LEN2_32k]; +extern const float w_hamm_sana16k_2[L_PROT_HAMM_LEN2_16k]; +extern const float w_hamm48k_2[L_TRANA48k/2]; +extern const float w_hamm_sana48k_2[L_PROT_HAMM_LEN2_48k]; + +extern const float h_high3_32[L_FIR_FER2]; +extern const float h_high3_16[L_FIR_FER2]; + + +#endif + diff --git a/lib_dec/rst_dec.c b/lib_dec/rst_dec.c new file mode 100644 index 000000000..4004543f1 --- /dev/null +++ b/lib_dec/rst_dec.c @@ -0,0 +1,59 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*----------------------------------------------------------------------------------* + * CNG_reset_dec() + * + * Reset decoder static variables in case of CNG frame + *----------------------------------------------------------------------------------*/ + +void CNG_reset_dec( + Decoder_State *st, /* i/o: decoder state structure */ + float *pitch_buf, /* o : floating pitch for each subframe */ + float *voice_factors /* o : voicing factors */ +) +{ + mvr2r( UVWB_Ave, st->mem_AR, M ); + set_f(st->mem_MA, 0, M ); + set_f( st->dispMem, 0, 8 ); + st->tilt_code = 0.0f; + st->gc_threshold = 0.0f; + + /* last good received frame for FEC in ACELP */ + st->clas_dec = UNVOICED_CLAS; + st->last_good = UNVOICED_CLAS; + + /* LP-filtered pitch gain set to 0 */ + st->lp_gainp = 0.0f; + + /* convert CNG energy into CNG gain for ACELP FEC */ + st->lp_gainc = (float)sqrt( st->lp_ener ); + + /* reset the pitch buffer in case of FRAME_NO_DATA or SID frames */ + if(st->L_frame == L_FRAME ) + { + set_f( pitch_buf, (float)L_SUBFR, NB_SUBFR ); + } + else /* st->L_frame == L_FRAME16k */ + { + set_f( pitch_buf, (float)L_SUBFR16k, NB_SUBFR16k ); + } + + set_f( voice_factors, 1.0, NB_SUBFR16k ); + + /* deactivate bass post-filter */ + st->bpf_off = 1; + + /* Reset active frame counter */ + st->act_cnt2 = 0; + + return; +} diff --git a/lib_dec/rtpdump.c b/lib_dec/rtpdump.c new file mode 100644 index 000000000..57553086c --- /dev/null +++ b/lib_dec/rtpdump.c @@ -0,0 +1,352 @@ + /*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + + #include + #include "wmc_auto.h" + #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 000000000..c0aabe498 --- /dev/null +++ b/lib_dec/rtpdump.h @@ -0,0 +1,75 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 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.h b/lib_dec/stat_dec.h new file mode 100644 index 000000000..55c1c7858 --- /dev/null +++ b/lib_dec/stat_dec.h @@ -0,0 +1,1017 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#ifndef STAT_DEC_H +#define STAT_DEC_H + + +#include "options.h" +#include "stat_com.h" /* Common structures */ +#include "cnst.h" + +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; + + +/* Arrays and variables specific to decoder */ +typedef struct +{ + HANDLE_FD_CNG_COM hFdCngCom; + + float msPeriodog[NPART_SHAPING]; /* Periodogram */ + float msBminWin[NPART_SHAPING]; + float msBminSubWin[NPART_SHAPING]; + float msPsd[NPART_SHAPING]; /* Power Spectral Density estimate (i.e., smoothed periodogram) */ + float msAlpha[NPART_SHAPING]; /* Optimal smoothing parameter */ + float msMinBuf[MSNUMSUBFR*NPART_SHAPING]; /* Buffer of minima */ + float msCurrentMinOut[NPART_SHAPING]; + float msCurrentMin[NPART_SHAPING]; + float msCurrentMinSubWindow[NPART_SHAPING]; + int msLocalMinFlag[NPART_SHAPING]; + int msNewMinFlag[NPART_SHAPING]; + float msPsdFirstMoment[NPART_SHAPING]; + float msPsdSecondMoment[NPART_SHAPING]; + float msNoiseFloor[NPART_SHAPING]; /* Estimated noise floor */ + float msNoiseEst[NPART_SHAPING]; /* Estimated noise level */ + float msLogPeriodog[NPART_SHAPING]; /* Periodogram */ + float msLogNoiseEst[NPART_SHAPING]; /* Estimated noise level */ + int npart_shaping; /* Number of partitions */ + int nFFTpart_shaping; /* Number of hybrid spectral partitions */ + int part_shaping[NPART_SHAPING]; /* Partition upper boundaries (band indices starting from 0) */ + int midband_shaping[NPART_SHAPING]; /* Central band of each partition */ + float psize_shaping[NPART_SHAPING]; /* Partition sizes */ + float psize_inv_shaping[NPART_SHAPING]; /* Inverse of partition sizes */ + float bandNoiseShape[FFTLEN2];/* CNG spectral shape computed at the decoder */ + float partNoiseShape[NPART];/* CNG spectral shape computed at the decoder */ + + short flag_dtx_mode; + float lp_speech; + float lp_noise; + + float msPeriodogBuf[MSBUFLEN*NPART_SHAPING]; + int msPeriodogBufPtr; + +} +FD_CNG_DEC; +typedef FD_CNG_DEC *HANDLE_FD_CNG_DEC; + +typedef struct +{ + int FrameSize; + + int Pitch; + int T_bfi; + + int Transient[MAX_POST_LEN]; + int TCX_Tonality[DEC_STATE_LEN]; + + float outx_new_n1; + float nsapp_gain; + float nsapp_gain_n; + float data_reci2[L_FRAME_MAX]; + float data_noise[L_FRAME_MAX]; + float ener_mean; + float ener; + int zp; + float recovery_gain; + float step_concealgain; + + int concealment_method; + int subframe; + int nbLostCmpt; + + short 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 +{ + unsigned int nSamples; + unsigned int nSamplesCore; + Float32 * spectralData; + float * scaleFactors; + int blockIsValid; + int blockIsConcealed; + int tonalConcealmentActive; +} blockData; + +typedef struct +{ + unsigned int numIndexes; + unsigned short int indexOfTonalPeak[MAX_NUMBER_OF_IDX]; + unsigned short int lowerIndex[MAX_NUMBER_OF_IDX]; + unsigned short int upperIndex[MAX_NUMBER_OF_IDX]; + Float32 phaseDiff[MAX_NUMBER_OF_IDX]; /* This one can be stored with 16 bits in range 0..2*PI */ + Float32 phase_currentFramePredicted[MAX_NUMBER_OF_IDX*GROUP_LENGTH]; /* This one can be stored with 16 bits in range 0..2*PI, but the code has to be adapted to use moduo(2*PI) after adding */ +} TonalComponentsInfo; + +typedef void (*ApplyScaleFactorsPointer)(float x[], int lg, float const scaleFactors[]); + +struct tonalmdctconceal +{ + TCX_config * tcx_cfg; + void * pMDSTData; + unsigned int nSamples; + unsigned int nSamplesCore; + unsigned int nNonZeroSamples; + unsigned int nScaleFactors; + + float lastPitchLag; + + blockData lastBlockData; + blockData secondLastBlockData; + + Float32 scaleFactorsBuffers[2][FDNS_NPTS]; /* Contains also global gain. If it can not be stored in 16 bits with global gain included, then store global gain separately. */ + Float32 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. */ + Float32 timeDataBuffer[(3*L_FRAME_MAX)/2]; + Float32 * lastPcmOut; + Float32 * secondLastPcmOut; + float * secondLastPowerSpectrum; + + float nFramesLost; + + TonalComponentsInfo * pTCI; +}; + +typedef struct tonalmdctconceal* TonalMDCTConcealPtr; + +typedef enum SIGNAL_CLASSIFER_MODE +{ + CLASSIFIER_ACELP, + CLASSIFIER_TCX +} SIGNAL_CLASSIFIER_MODE; + +/*---------------------------------------------------------------* + * Structures for IGF decoder * + *---------------------------------------------------------------*/ + +/* IGFSCFDecoder.h */ +typedef struct +{ + int bitsRead; /* after a call bitsRead contains the number of bits consumed by the decoder */ + int prev[64]; /* no more than 64 SCFs for the IGF energy envelope of one block */ + int scfCountLongBlock; + int t; + int bitrate; + const unsigned short *cf_se00; + const unsigned short *cf_se01; + short cf_off_se01; + const unsigned short *cf_se02; + const short *cf_off_se02; + const unsigned short *cf_se10; + short cf_off_se10; + const unsigned short *cf_se11; + const short *cf_off_se11; + Tastat acState; +} IGFSCFDEC_INSTANCE, *IGFSCFDEC_INSTANCE_HANDLE; + +/* IGFDec.h */ +typedef struct igfdec_private_data_struct +{ + + IGF_INFO igfInfo; + /* envelope reconstruction: */ + float igf_sN[IGF_MAX_SFB]; /* only with short blocks as static needed */ + float igf_pN[IGF_MAX_SFB]; /* only with short blocks as static needed */ + int igf_curr[IGF_MAX_SFB]; /* current igf energies */ + int igf_prev[IGF_MAX_SFB]; /* needed for concealment or indepflag==0 */ + int igf_curr_subframe[IGF_MAX_SUBFRAMES][IGF_TRANS_FAK][IGF_MAX_SFB]; /* current igf energies per subframe*/ + int igf_prev_subframe[IGF_MAX_SUBFRAMES][IGF_MAX_SFB]; /* needed for concealment or indepflag==0 */ + int igf_flatteningTrigger_subframe[IGF_MAX_SUBFRAMES]; + + /* spectral whitening: */ + float pSpecFlat[IGF_START_MX]; + int currWhiteningLevel[IGF_MAX_TILES]; + int prevWhiteningLevel[IGF_MAX_TILES]; /* needed for concealment */ + int currWhiteningLevel_subframe[IGF_MAX_SUBFRAMES][IGF_MAX_TILES]; + int prevWhiteningLevel_subframe[IGF_MAX_SUBFRAMES][IGF_MAX_TILES]; /* needed for concealment */ + + float totalNoiseNrg; + int n_noise_bands; + + float totalNoiseNrg_off; + int n_noise_bands_off; + + /* IGF SCF decoding: */ + IGFSCFDEC_INSTANCE hArithSCFdec; + + /* concealment: */ + int frameLossCounter; + +} IGFDEC_PRIVATE_DATA,*IGF_DEC_PRIVATE_DATA_HANDLE; + +typedef struct igfdec_instance_struct +{ + int isIGFActive; + int infoIGFAllZero; + int infoIGFStopLine; + int infoIGFStartLine; + int infoIGFStopFreq; + int infoIGFStartFreq; + unsigned char infoTCXNoise[IGF_START_MX]; + int flag_sparse[N_MAX_TCX-IGF_START_MN]; + float virtualSpec[N_MAX_TCX-IGF_START_MN]; + int flatteningTrigger; + IGFDEC_PRIVATE_DATA igfData; +} IGFDEC_INSTANCE, *IGF_DEC_INSTANCE_HANDLE; + +/*----------------------------------------------------------------------------------* + * + * Main decoder structure + * + *----------------------------------------------------------------------------------*/ + +typedef struct Decoder_State +{ + + /*----------------------------------------------------------------------------------* + * Common parameters + *----------------------------------------------------------------------------------*/ + + short codec_mode; /* Mode 1 or 2 */ + short mdct_sw_enable; /* MDCT switching enable flag */ + short mdct_sw; /* MDCT switching indicator */ + short last_codec_mode; /* last used codec mode */ + + unsigned short bit_stream[MAX_BITS_PER_FRAME+16]; + short next_bit_pos; /* position of the next bit to be read from the bitstream */ + short bitstreamformat; /* Bitstream format flag (G.192/MIME/VOIP_G192_RTP/VOIP_RTPDUMP) */ + short sdp_hf_only; /* RTP payload format parameter: only Header-Full format without zero padding for size collision avoidance */ + short amrwb_rfc4867_flag; /* MIME from rfc4867 is used */ + short BER_detect; /* flag to signal detected bit error in the bitstream */ + int output_Fs; /* output sampling rate */ + long total_brate; /* total bitrate in kbps of the codec */ + long last_total_brate; /* last total bitrate in kbps of the codec */ + long last_total_brate_ber; /* last total bitrate in kbps of the codec - used only when first frame is lost and BER is detected afterwards */ + short core; /* core (ACELP_CORE, TCX_20_CORE, TCX_10_CORE, HQ_CORE, AMR_WB_CORE) */ + long core_brate; /* core bitrate */ + long last_core_brate; /* previous frame core bitrate */ + short extl; /* extension layer */ + short last_extl; /* previous extension layer */ + long extl_brate; /* extension layer bitrate */ + short L_frame; /* ACELP core internal frame length */ + short bwidth; /* encoded signal bandwidth */ + short Opt_AMR_WB; /* flag indicating AMR-WB IO mode */ + short Opt_VOIP; /* flag indicating VOIP mode with JBM */ + short ini_frame; /* initialization frames counter */ + Word16 CNG; /* RXDTX handler: CNG=1, nonCNG=0 */ + Word16 prev_ft_speech; /* RXDTX handler: previous frametype flag for G.192 format AMRWB SID_FIRST detection */ + + /*----------------------------------------------------------------------------------* + * ACELP core parameters + *----------------------------------------------------------------------------------*/ + + float old_exc[L_EXC_MEM_DEC]; /* old excitation */ + float old_excFB[L_FRAME48k]; /* old excitation FB */ + float lsp_old[M]; /* old LSP vector at the end of the frame */ + float lsf_old[M]; /* old LSF vector at the end of the frame */ + unsigned int offset_scale1[MAX_NO_MODES+1][MAX_NO_SCALES+1]; /* offsets for LSF LVQ structure 1st 8-dim subvector*/ + unsigned int offset_scale2[MAX_NO_MODES+1][MAX_NO_SCALES+1]; /* offsets for LSF LVQ structure 2nd 8-dim subvector*/ + unsigned int offset_scale1_p[MAX_NO_MODES_p+1][MAX_NO_SCALES+1]; /* offsets for LSF LVQ structure, pred. case, 1st 8-dim subvector*/ + unsigned int offset_scale2_p[MAX_NO_MODES_p+1][MAX_NO_SCALES+1]; /* offsets for LSF LVQ structure, pred. case, 2nd 8-dim subvector*/ + short no_scales[MAX_NO_MODES][2]; /* LSF LVQ structure */ + short no_scales_p[MAX_NO_MODES_p][2]; /* LSF LVQ structure */ + float tilt_code; /* tilt of code */ + float mem_syn1[M]; /* synthesis filter memory (for core switching and FD BWE) */ + float mem_syn2[M]; /* synthesis filter memory */ + float mem_syn3[M]; + float mem_deemph; /* deemphasis filter memory */ + float mem_hp20_out[4]; /* HP filter memory for synthesis */ + float mem_AR[M]; /* AR memory of LSF quantizer (past quantized LSFs without mean) */ + float mem_MA[M]; /* MA memory of LSF quantizer (past quantized residual) */ + float stab_fac; /* LSF stability factor */ + float stab_fac_smooth; /* low-pass filtered stability factor */ + short last_coder_type; /* previous coder type */ + float agc_mem2[2]; /* memory of AGC for saturation control */ + float past_qua_en[GAIN_PRED_ORDER]; /* gain quantization memory (used also in AMR-WB IO mode) */ + short mid_lsf_int; + short safety_net; + + short seed_tcx ; /* AC mode (GSC) - seed for noise fill*/ + short GSC_noisy_speech; /* AC mode (GSC) - flag to indicate GSC osn SWB noisy speech */ + short Last_GSC_noisy_speech_flag; /* AC mode (GSC) - mem of the past flag to indicate GSC osn SWB noisy speech */ + short cor_strong_limit; /* AC mode (GSC) - Indicator about high spectral correlation per band */ + float old_y_gain[MBANDS_GN]; /* AC mode (GSC) - AR mem for low rate gain quantization */ + short noise_lev; /* AC mode (GSC) - noise level */ + float lt_ener_per_band[MBANDS_GN]; + float Last_frame_ener; /* AC mode (GSC) - last frame energy */ + float Last_GSC_spectrum[L_FRAME]; /* AC mode (GSC) - Last good GSC spectrum */ + short Last_GSC_pit_band_idx; /* AC mode (GSC) - Last pitch band index */ + float last_exc_dct_in[L_FRAME]; /* AC mode (GSC) - previous excitation */ + float last_ener; /* AC mode (GSC) - previous energy */ + short last_bitallocation_band[6]; /* AC mode (GSC) - previous bit allocation of each band */ + + float gc_threshold; /* Noise enhancer - threshold for gain_code */ + float dispMem[8]; /* Noise enhancer - phase dispersion algorithm memory */ + + float prev_r; /* HF BWE - previous sub-frame gain */ + float fmerit_w_sm; /* HF BWE - fmerit parameter memory */ + short frame_count; /* HF BWE - frame count */ + float ne_min; /* HF BWE - minimum Noise gate - short-term energy */ + float fmerit_m_sm; /* HF BWE - memory of fmerit_m param */ + float voice_fac_amr_wb_hf; /* HF BWE - voice factor */ + float unvoicing; /* HF BWE - unvoiced parameter */ + float unvoicing_sm; /* HF BWE - smoothed unvoiced parameter */ + short unvoicing_flag; /* HF BWE - unvoiced flag */ + short voicing_flag; /* HF BWE - voiced flag */ + short start_band_old; /* HF BWE - previous start point for copying frequency band */ + float OptCrit_old; /* HF BWE - previous criterion value for deciding the start point */ + + short seed2; /* HF (6-7kHz) BWE - seed for random signal generator */ + float mem_hp400[4]; /* HF (6-7kHz) BWE - hp400 filter memory */ + float mem_hf[(L_FIR-1)]; /* HF (6-7kHz) BWE - band-pass filter memory */ + float mem_syn_hf[M]; /* HF (6-7kHz) BWE - synthesis filter memory */ + float delay_syn_hf[NS2SA(16000,DELAY_CLDFB_NS)]; /* HF (6-7kHz) BWE - To synchronise BWE content with postfiltered synthesis */ + float mem_hp_interp[INTERP_3_1_MEM_LEN]; /* HF (6-7 kHz) BWE - interp. memory */ + + short unv_cnt; /* Stationary noise UV modification - unvoiced frame counter */ + short uv_count; /* Stationary noise UV modification - unvoiced counter */ + short act_count; /* Stationary noise UV modification - activation counter */ + float ge_sm; /* Stationary noise UV modification - smoothed excitation gain */ + float lspold_s[M]; /* Stationary noise UV modification - old LSP vector */ + short noimix_seed; /* Stationary noise UV modification - mixture seed */ + float min_alpha; /* Stationary noise UV modification - minimum alpha */ + float exc_pe; /* Stationary noise UV modification - memory of the preemphasis filter */ + + short bfi; /* FEC - bad frame indicator */ + short prev_bfi; /* FEC - previous bad frame indicator */ + short prev_old_bfi; /* FEC - previous old bad frame indicator */ + short seed; /* FEC - seed for random generator for excitation */ + float lp_ener_bfi; /* FEC - long-term active-signal average energy */ + short last_good; /* FEC - clas of last good received */ + float lp_gainp; /* FEC - low-pass filtered pitch gain */ + float lp_gainc; /* FEC - low-pass filtered code gain */ + float lp_ener; /* FEC - low-pass filtered energy */ + float enr_old; /* FEC - energy of the concealed frame */ + float bfi_pitch; /* FEC - pitch for FEC */ + short bfi_pitch_frame; /* FEC - frame length when pitch for FEC is saved */ + float old_pitch_buf[2*NB_SUBFR16k+2]; /* FEC - buffer of old subframe pitch values */ + short upd_cnt; /* FEC - counter of frames since last update */ + short scaling_flag; /* FEC - flag to indicate energy control of syn */ + float lp_ener_FEC_av; /* FEC - averaged voiced signal energy */ + float lp_ener_FEC_max; /* FEC - averaged voiced signal energy */ + float old_enr_LP; /* FEC - LP filter gain */ + short prev_nbLostCmpt; /* FEC - compt for number of consecutive lost frame at the previous frame*/ + short mode_lvq; /* FEC - index for LSF mean vector */ + float lsfoldbfi0[M]; /* FEC - LSF vector of the previous frame */ + float lsfoldbfi1[M]; /* FEC - LSF vector of the past previous frame */ + float lsf_adaptive_mean[M]; /* FEC - adaptive mean LSF vector for FEC */ + short decision_hyst; /* FEC - hysteresis of the music/speech decision */ + float old_exc2[L_EXC_MEM]; /* FEC - old excitation2 used in fast recovery */ + float old_syn2[L_EXC_MEM]; /* FEC - old syn speech used in fast recovery */ + short relax_prev_lsf_interp; + float mem_syn_clas_estim[L_SYN_MEM_CLAS_ESTIM]; /* FEC - memory of the synthesis signal for frame class estimation */ + float tilt_swb_fec; /* FEC - SWB TBE TILT */ + + short cng_seed; /* DTX/CNG - seed for white noise random generator */ + float lspCNG[M]; /* DTX/CNG - LP filtered ISPs */ + short first_CNG; /* DTX/CNG - first CNG frame flag */ + float Enew; /* DTX/CNG - decoded residual energy */ + short old_enr_index; /* DTX/CNG - index of last encoded CNG energy */ + short cng_ener_seed; /* DTX/CNG - seed for random generator for variation of excitation energy */ + short cng_ener_seed1; + short last_allow_cn_step; + short ho_hist_size; /* DTX/CNG - size of DTX hangover history buffer for averaging, <0,HO_HIST_SIZE> */ + short ho_hist_ptr; /* DTX/CNG - pointer for averaging buffers */ + long ho_sid_bw; /* DTX/CNG - SID bandwidth flags */ + float ho_lsp_hist[HO_HIST_SIZE*M]; /* DTX/CNG - old LSP buffer for averaging */ + float ho_ener_hist[HO_HIST_SIZE]; /* DTX/CNG - energy buffer for averaging */ + float ho_env_hist[HO_HIST_SIZE*NUM_ENV_CNG]; + short act_cnt; /* DTX/CNG - counter of active frames */ + short ho_circ_size; /* DTX/CNG - size of DTX hangover history buffer for averaging, <0,HO_HIST_SIZE> */ + short ho_circ_ptr; /* DTX/CNG - pointer for averaging buffers */ + float ho_lsp_circ[HO_HIST_SIZE*M]; /* DTX/CNG - old LSP buffer for averaging */ + float ho_ener_circ[HO_HIST_SIZE]; /* DTX/CNG - energy buffer for averaging */ + float ho_env_circ[HO_HIST_SIZE*NUM_ENV_CNG]; + short num_ho; /* DTX/CNG - number of selected hangover frames */ + short ho_16k_lsp[HO_HIST_SIZE]; /* DTX/CNG - 16k LSPs flags */ + short CNG_mode; /* DTX/CNG - mode for DTX configuration */ + long last_active_brate; /* DTX/CNG - last active frame bitrate used for CNG_mode control */ + short last_CNG_L_frame; /* DTX/CNG - last CNG frame length */ + short act_cnt2; /* DTX/CNG - counter of active frames for CNG_mode switching */ + short cng_type; /* DTX/CNG - flag indicating LP or CLDFB based SID/CNG */ + short last_cng_type; /* DTX/CNG - flag indicating last frame LP or CLDFB based SID/CNG */ + float old_env[20]; + float lp_env[20]; + float exc_mem[24]; + float exc_mem1[30]; + + short bpf_off; /* Bass post-filter - do not use BPF when this flag is set to 1 */ + float pst_old_syn[NBPSF_PIT_MAX]; /* Bass post-filter - old synthesis buffer 1 */ + float pst_mem_deemp_err; /* Bass post-filter - filter memory of noise LP filter */ + float pst_lp_ener; /* Bass post-filter - long-term energy */ + short Track_on_hist[L_TRACK_HIST]; /* Bass post-filter - History of half frame usage */ + short vibrato_hist[L_TRACK_HIST]; /* Bass post-filter - History of frames declared as vibrato */ + float psf_att; /* Bass post-filter - post filter attenuation factor */ + float mem_mean_pit[L_TRACK_HIST]; /* Bass post-filter - average pitch memory */ + + HANDLE_CLDFB_FILTER_BANK cldfbAna; /* main analysis filter bank handle */ + HANDLE_CLDFB_FILTER_BANK cldfbBPF; /* BPF analysis filter bank handle */ + HANDLE_CLDFB_FILTER_BANK cldfbSyn; /* main synthesis filter bank handle */ + + short last_active_bandsToZero_bwdec; + short flag_NB_bwddec; + short last_flag_filter_NB; + float perc_bwddec; + int active_frame_cnt_bwddec; + short flag_buffer[20]; + int total_frame_cnt_bwddec; + float avg_nrg_LT; + float ng_ener_ST; /* Noise gate - short-term energy */ + + short last_L_frame; /* ACELP@16kHz - last value of st->L_frame */ + float mem_preemp_preQ; /* ACELP@16kHz - prequantizer preemhasis memory */ + short last_nq_preQ; /* ACELP@16kHz - AVQ subquantizer number of the last sub-band of the last subframe */ + short use_acelp_preq; /* ACELP@16kHz - flag of prequantizer usage */ + + /* Improvement of unvoiced and audio signals in AMR-WB IO mode */ + short UV_cnt; /* number of consecutives frames classified as UV */ + float LT_UV_cnt; /* long-term consecutives frames classified as UV */ + float Last_ener; /* last_energy frame */ + float lt_diff_etot[MAX_LT]; /* stability estimation - long-term total energy variation */ + float old_Aq[NB_SUBFR*(M+1)]; /* old LPC filter coefficient */ + float lt_voice_fac; /* average voice factor over 4 sub-frames */ + + /* NB and formant post-filter */ + PFSTAT pfstat; /* NB and formant post-filter states */ + float psf_lp_noise; /* NB post-filter - long-term noise */ + + /*----------------------------------------------------------------------------------* + * SC-VBR + *----------------------------------------------------------------------------------*/ + + /* PPP decoder variables */ + short last_ppp_mode_dec; + short ppp_mode_dec; + short last_nelp_mode_dec; + short nelp_mode_dec; + int firstTime_voiceddec; + + /* DTFS variables */ + float dtfs_dec_a[MAXLAG_WI]; + float dtfs_dec_b[MAXLAG_WI]; + int dtfs_dec_lag; + int dtfs_dec_nH; + int dtfs_dec_nH_4kHz; + float dtfs_dec_upper_cut_off_freq_of_interest; + float dtfs_dec_upper_cut_off_freq; + float ph_offset_D; + float lastLgainD; /* previous gain value for the low band */ + float lastHgainD; /* previous gain value for the high band */ + float lasterbD[NUM_ERB_WB]; /* previous amplitude spectrum (ERB) */ + + /* NELP decoder variables */ + float bp1_filt_mem_nb_dec[14]; + float bp1_filt_mem_wb_dec[8]; + float shape1_filt_mem_dec[20]; + float shape2_filt_mem_dec[20]; + float shape3_filt_mem_dec[20]; + + short nelp_dec_seed; + float FadeScale; + float prev_gain_pit_dec; + float prev_tilt_code_dec; + short vbr_hw_BWE_disable_dec; + short last_vbr_hw_BWE_disable_dec; + + /*----------------------------------------------------------------------------------* + * channel-aware mode + *----------------------------------------------------------------------------------*/ + + float tilt_code_dec[NB_SUBFR16k]; + + short rf_frame_type; + short use_partial_copy; + short prev_use_partial_copy; + short rf_flag; + short rf_flag_last; + + short rf_fec_offset; + short next_coder_type; + short prev_rf_frame_type; + short rf_target_bits; + + short rf_indx_nelp_fid; + short rf_indx_nelp_iG1; + short rf_indx_nelp_iG2[2]; + short rf_indx_tbeGainFr; + + /*----------------------------------------------------------------------------------* + * HR SWB BWE parameters + *----------------------------------------------------------------------------------*/ + + short bwe_highrate_seed; + float t_audio_prev[2*END_FREQ_BWE_FULL_FB/50 - NUM_NONTRANS_START_FREQ_COEF]; + short old_is_transient_hr_bwe; + float mem_EnergyLT; + + + /*----------------------------------------------------------------------------------* + * HQ core parameters + *----------------------------------------------------------------------------------*/ + + float synth_history[L_PROT48k + L_FRAME_MAX]; /* unified synthesis memory */ + float *old_synthFB; + float old_out[L_FRAME48k]; /* HQ core - previous synthesis for OLA */ + + float old_outLB[L_FRAME32k]; + float old_coeffs[L_FRAME8k]; /* HQ core - old coefficients (for FEC) */ + float oldIMDCTout[L_FRAME8k/2]; + float prev_oldauOut[L_FRAME8k]; + float diff_energy; + short stat_mode_out; + short stat_mode_old; + short phase_mat_flag; + short phase_mat_next; + short old_Min_ind; + float old_auOut_2fr[L_FRAME8k*2]; + short old_is_transient[3]; /* HQ core - previous transient flag (for FEC) */ + float old_out_pha[2][N_LEAD_NB]; /* FEC for HQ Core, 0-phase matching old_out, 1-overlapping original old_out and phase matching old_out*/ + short old_bfi_cnt; /* HQ core - # of bfi until previous frame(for FEC) */ + float ynrm_values[MAX_SB_NB][MAX_PGF]; + float r_p_values[MAX_SB_NB][MAX_ROW]; + float Norm_gain[SFM_N_NB]; + short HQ_FEC_seed; + float energy_MA_Curr[2]; + + short last_core; + short last_core_bs; + short prev_last_core; + short last_hq_core_type; + short last_L_frame_ori; + float previoussynth[L_FRAME48k]; + float old_synth_sw[NS2SA(48000,FRAME_SIZE_NS-ACELP_LOOK_NS-DELAY_BWE_TOTAL_NS)]; + float delay_buf_out[HQ_DELTA_MAX*HQ_DELAY_COMP]; + short mem_norm[SFM_N_ENV_STAB]; + short mem_env_delta; /* Q12 */ + short no_att_hangover; + float energy_lt; + short hq_generic_seed; + float prev_noise_level[2]; + short prev_hqswb_clas; + short prev_R; /* the table of bit allocation of last frame */ + float prev_coeff_out[L_HQ_WB_BWE]; /* the highest coefficients of last frame */ + short prev_SWB_peak_pos[SPT_SHORTEN_SBNUM]; + float old_Aq_12_8[M+1]; /* old Aq[] for core switching */ + float old_Es_pred; /* old Es_pred for core switching */ + + short HqVoicing; + float fer_samples[L_FRAME48k]; + float prev_normq[SFM_N_WB]; /* previous norms */ + float prev_env[SFM_N_WB]; /* previous noise envelopes */ + + float last_ni_gain[BANDS_MAX]; + float last_env[BANDS_MAX]; + short last_max_pos_pulse; + + /* pre-echo reduction */ + float memfilt_lb; + float mean_prev_hb; + float smoothmem; + float mean_prev; + float mean_prev_nc; + float wmold_hb; + short prevflag; + short pastpre; + short prev_frm_hfe2; + short prev_stab_hfe2; + float prev_ni_ratio; + float prev_En_sb[NB_SWB_SUBBANDS]; + + /* PVQ range coder state */ + unsigned int rc_low; + unsigned int rc_range; + unsigned int rc_help; + short rc_num_bits; + short rc_offset; + short rc_end; + + /*----------------------------------------------------------------------------------* + * TBE parameters + *----------------------------------------------------------------------------------*/ + + /* states for the filters used in generating SHB excitation from WB excitation */ + float state_lpc_syn[LPC_SHB_ORDER]; + float mem_csfilt [2]; + + /* states for the filters used in generating SHB signal from SHB excitation*/ + float state_syn_shbexc[L_SHB_LAHEAD]; + float syn_overlap[L_SHB_LAHEAD]; /* overlap buffer used to Adjust SHB Frame Gain*/ + + /* previous frame parameters for frame error concealment */ + float lsp_prevfrm[ LPC_SHB_ORDER]; + float GainFrame_prevfrm; + float GainShape_Delay[NUM_SHB_SUBFR/2]; + float GainAttn; + + float old_bwe_exc[PIT16k_MAX * 2]; /* old excitation */ + short bwe_seed[2]; + float bwe_non_lin_prev_scale; + float old_bwe_exc_extended[NL_BUFF_OFFSET]; + float last_voice_factor; + + float genSHBsynth_Hilbert_Mem[HILBERT_MEM_SIZE]; + + float mem_genSHBexc_filt_down_shb[(2*ALLPASSSECTIONS_STEEP+1)]; + float mem_genSHBexc_filt_down_wb2[(2*ALLPASSSECTIONS_STEEP+1)]; + float mem_genSHBexc_filt_down_wb3[(2*ALLPASSSECTIONS_STEEP+1)]; + float genSHBsynth_state_lsyn_filt_shb_local[ 2 * ALLPASSSECTIONS_STEEP ]; + float state_lsyn_filt_shb[ 2 * ALLPASSSECTIONS_STEEP]; + float state_lsyn_filt_dwn_shb[ 2 * ALLPASSSECTIONS_STEEP]; + float mem_resamp_HB[INTERP_3_1_MEM_LEN]; + float mem_resamp_HB_32k[2*ALLPASSSECTIONS_STEEP+1]; + float prev_synth_buffer[NS2SA(48000,DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS)]; + float hb_prev_synth_buffer[NS2SA(48000, DELAY_BWE_TOTAL_NS)]; + short old_bwe_delay; + + short syn_dm_phase; + float fbbwe_hpf_mem[4][4]; + float prev_wb_bwe_frame_pow; + float prev_swb_bwe_frame_pow; + float prev_ener; + float prev_GainShape; + float fb_state_lpc_syn[LPC_SHB_ORDER]; + float fb_tbe_demph; + float prev_fbbwe_ratio; + + /* WB/SWB bandwidth switching */ + float tilt_wb; + float tilt_swb; + float prev_ener_shb; + float enerLH; + float prev_enerLH; + float enerLL; + float prev_enerLL; + short prev_fractive; + short prev_bws_cnt; + short bws_cnt; + short bws_cnt1; + float attenu1; + short last_inner_frame; + short last_bwidth; + float prev_weight1; + float t_audio_q[L_FRAME]; + float tbe_demph; + float tbe_premph; + float mem_stp_swb[LPC_SHB_ORDER]; + float *ptr_mem_stp_swb; + float gain_prec_swb; + float mem_zero_swb[LPC_SHB_ORDER]; + + float swb_lsp_prev_interp[LPC_SHB_ORDER]; + float prev1_shb_ener_sf, prev2_shb_ener_sf, prev3_shb_ener_sf, prev_res_shb_gshape, prev_mixFactors; + float tilt_mem; /* Formant factor adaptation tilt smoothing memory */ + float prev_lsf_diff[LPC_SHB_ORDER-2]; + float prev_tilt_para; + float cur_sub_Aq[M+1]; + + /* quantized data */ + short lsf_idx[NUM_Q_LSF]; + short m_idx; + short grid_idx; + short idxSubGains; + short idxFrameGain; + short idx_shb_fr_gain; + short idx_res_gs[NB_SUBFR16k]; + short idx_mixFac; + + short lsf_WB; + short gFrame_WB; + + short idxGain; + + float old_core_synth[L_FRAME16k]; + float old_tbe_synth[L_SHB_TRANSITION_LENGTH]; + + float int_3_over_2_tbemem_dec[INTERP_3_2_MEM_LEN]; + float interpol_3_2_cng_dec[INTERP_3_2_MEM_LEN]; + + /*----------------------------------------------------------------------------------* + * SWB BWE parameters + *----------------------------------------------------------------------------------*/ + + float old_wtda_swb[L_FRAME48k]; + float old_syn_12k8_16k[NS2SA(16000, DELAY_FD_BWE_ENC_NS)]; + float mem_deemph_old_syn; + short prev_mode; + float prev_SWB_fenv[SWB_FENV]; + float prev_Energy; + float prev_Energy_wb; + short prev_L_swb_norm; + short Seed; + short prev_frica_flag; + float mem_imdct[L_FRAME48k]; + float prev_td_energy; + float prev_weight; + short prev_coder_type; + short prev_flag; + float last_wb_bwe_ener; + float prev_fb_ener_adjust; + + /*----------------------------------------------------------------------------------* + * SWB DTX/CNG parameters + *----------------------------------------------------------------------------------*/ + + float shb_cng_ener; + float wb_cng_ener; + float last_wb_cng_ener; + float last_shb_cng_ener; + short swb_cng_seed; + float lsp_shb_prev_prev[LPC_SHB_ORDER]; + float lsp_shb_prev[LPC_SHB_ORDER]; + short shb_dtx_count; + short last_vad; + short trans_cnt; + short burst_cnt; + float last_shb_ener; + + /*----------------------------------------------------------------------------------* + * HQ FEC + *----------------------------------------------------------------------------------*/ + float *prev_good_synth; + short prev_sign_switch[HQ_FEC_SIGN_SFM]; + short prev_sign_switch_2[HQ_FEC_SIGN_SFM]; + + /* HQ PHASE ECU internal state */ + short time_offs; + float X_sav[PH_ECU_SPEC_SIZE]; + short num_p; + short plocs[MAX_PLOCS]; + float plocsi[MAX_PLOCS]; + float env_stab; + short mem_norm_hqfec[SFM_N_ENV_STAB]; + short mem_env_delta_hqfec; /* Q12 */ + float env_stab_plc; + float env_stab_state_p[NUM_ENV_STAB_PLC_STATES]; + short envstabplc_hocnt; + + float mag_chg_1st[LGW_MAX]; /* i/o: per band magnitude modifier for transients*/ + float Xavg[LGW_MAX]; /* Frequency group average gain to fade to */ + float beta_mute; /* Factor for long-term mute */ + + short last_fec; + short ph_ecu_HqVoicing; + short oldHqVoicing; + float oldgapsynth[L_FRAME48k]; + short ph_ecu_active; /* Set to 1 if Phase ECU was used in last bad frame; Set to 2 if TCX TD PLC was used */ + short ni_seed_forfec; + short ber_occured_in_pvq; /* flag for BER detection from PVQ routines */ + + /*----------------------------------------------------------------------------------* + * LD music post-filter + *----------------------------------------------------------------------------------*/ + + float LDm_mem_etot; /* LD music post-filter - total energy memory */ + short LDm_last_music_flag; /* LD music post-filter - last music flag */ + short LDm_nb_thr_1; /* LD music post-filter - number of consecutive frames of level 1 */ + short LDm_nb_thr_3; + float dct_post_old_exc[DCT_L_POST-OFFSET2]; + float LDm_thres[4]; /* LD music post-filter - Classification threshold */ + float LDm_lt_diff_etot[MAX_LT]; /* LD music post-filter - long-term total energy variation */ + float LDm_enh_lp_gbin[VOIC_BINS_HR]; /* LD music post-filter - smoothed suppression gain, per bin FFT */ + float LDm_enh_lf_EO[VOIC_BINS_HR]; /* LD music post-filter - old per bin E for previous half frame */ + float LDm_enh_min_ns_gain; /* LD music post-filter - minimum suppression gain */ + float LDm_bckr_noise[MBANDS_GN_LD]; /* LD music post-filter - background noise estimation per critical band */ + float filt_lfE[DCT_L_POST]; + short last_nonfull_music; + + + /*ACELP config*/ + short 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; + int L_frameTCX; + + /*dec_prm.c*/ + int bits_frame; /*bit per frame overall */ + int bits_frame_core; /*bit per frame for the core*/ + int narrowBand; + + int last_is_cng; + + float old_syn_Overl[L_FRAME32k/2]; + + float syn_Overl_TDAC[L_FRAME32k/2]; + float syn_Overl_TDACFB[L_FRAME_MAX/2]; + + float syn_Overl[L_FRAME32k/2]; + float syn_OverlFB[L_FRAME_MAX/2]; + + float *acelp_zir; + float old_synth[OLD_SYNTH_INTERNAL_DEC];/* synthesis memory */ + int old_synth_len; + int old_synth_lenFB; + float syn[M+1]; + + /* bass_pf.c */ + int bpf_gain_param; /* bass post-filter gain factor parameter (0->noBpf)*/ + + int L_frame_past; + int L_frameTCX_past; + + float lsfold_uw[M]; /* old lsf (unweighted) */ + float lspold_uw[M]; /* old lsp (unweighted) */ + short seed_tcx_plc; /* seed memory (for random function in TCX PLC) */ + float past_gpit; /* past gain of pitch (for frame recovery) */ + float past_gcode; /* past energy (!) of code (for frame recovery) */ + float lsf_cng[M]; /* lsf coefficients used for CNG generation (long term) */ + float lspold_cng[M]; /* lsp coefficients used for CNG generation (long term) */ + float lsp_q_cng[M]; /* lsp coefficients used for CNG generation (short term interpolated) */ + float old_lsp_q_cng[M]; /* lsp coefficients used for CNG generation (short term interpolated) */ + float lsf_q_cng[M]; /* lsf coefficients used for CNG generation (short term interpolated) */ + float old_lsf_q_cng[M]; /* lsf: old quantized lsfs for background noise */ + float Aq_cng[(NB_SUBFR16k+1)*(M+1)]; /* LPC coefficients derived from CNG estimate */ + float mem_syn_unv_back[M]; /* filter memory for unvoiced synth */ + int plcBackgroundNoiseUpdated; /* flag: Is background noise estimate updated? */ + float last_gain_syn_deemph; + float last_concealed_gain_syn_deemph; + + int enableTcxLpc; /* global toggle for the TCX LPC quantizer */ + int envWeighted; /* are is{p,f}_old[] weighted or not? */ + + /* variables for framing */ + int nb_subfr; + + int fscale; + int fscale_old; + int sr_core; + + int pit_min; + int pit_fr1; + int pit_fr1b; + int pit_fr2; + int pit_max; + int pit_res_max; + int pit_res_max_past; + + int pit_min_TCX; + int pit_max_TCX; + + /*Preemphasis factor*/ + float preemph_fac; + float gamma; + + /*for AMR-WB like 6.4 to 7 kHz upsampling and noise filling*/ + float mem_Aq[NB_SUBFR16k*(M+1)]; + + /* Error concealment */ + int last_core_bfi; /* PLC - mode in previous frame */ + int nbLostCmpt; /* PLC - compt for number of consecutive lost frame */ + int noise_filling_index; /* PLC - last decoded noise filling index */ + float old_fpitch; /* PLC - last pitch of previous frame (as transmitted) */ + float old_fpitchFB; /* PLC - last pitch of previous FB frame (depends on output sr) */ + short clas_dec; /* PLC - frame class at the decoder */ + float mem_pitch_gain[2*NB_SUBFR16k+2]; /* PLC - Pitch gain memory */ + short plc_use_future_lag; /* PLC - flag indicating if info (pitch lag / pitch gain) about + future frame is usable */ + int prev_widow_left_rect; + float CngLevelBackgroundTrace_bfi; /* PLC - long term gain estimate for background level, used for PLC fade out */ + /* state variables for the minimum statistics used for PLC */ + float NoiseLevelMemory_bfi[PLC_MIN_STAT_BUFF_SIZE]; + int NoiseLevelIndex_bfi; + int CurrLevelIndex_bfi; + float LastFrameLevel_bfi; + float old_gaintcx_bfi; + float cummulative_damping; + float cngTDLevel; + float conceal_eof_gain; + float damping; + float gainHelper; + float stepCompensate; + int reset_mem_AR; + short tcxConceal_recalc_exc; + + short rate_switching_init; + + /* LPC quantization */ + int lpcQuantization; + int numlpc; + + /* Bandwidth */ + float TcxBandwidth; + + float voice_fac; + + int tcxonly; + + /*TCX resisual Q*/ + int resQBits[NB_DIV]; /* number of bits read for the residual Quantization in TCX*/ + + int last_ctx_hm_enabled; + + /* TCX-LTP */ + int tcxltp; /* TCX LTP enabled for operation mode */ + float tcxltp_gain; + int tcxltp_pitch_int; + int tcxltp_pitch_fr; + + float tcxltp_mem_in[TCXLTP_MAX_DELAY]; + float tcxltp_mem_out[L_FRAME48k]; + int tcxltp_pitch_int_post_prev; + int tcxltp_pitch_fr_post_prev; + float tcxltp_gain_post_prev; + int tcxltp_filt_idx_prev; + + struct tonalmdctconceal tonalMDCTconceal; + int tonal_mdct_plc_active; + int last_tns_active; + int second_last_tns_active; + float cummulative_damping_tcx; + int second_last_core; + float tcxltp_second_last_pitch; + float tcxltp_third_last_pitch; + float tcxltp_last_gain_unmodified; + + float FBTCXdelayBuf[111]; /* 2.3125ms at 48kHz -> 111 samples */ + + /* parameters for switching */ + float mem_syn_r[L_SYN_MEM]; /*LPC synthesis memory needed for rate switching*/ + short rate_switching_reset; + + float bpf_noise_buf[L_FRAME16k]; + float *p_bpf_noise_buf; + + int enableGplc; + int flagGuidedAcelp; + int T0_4th; + int guidedT0; + + short enablePlcWaveadjust; + short tonality_flag; + T_PLCInfo plcInfo; + + short VAD; + short flag_cna; + short last_flag_cna; + + float lp_noise; + + short seed_acelp; + int core_ext_mode; /*GC,VC,UC,TC: core extended mode used for PLC or Acelp-external modules.*/ + + short dec_glr; + short dec_glr_idx; + + short tcx_hm_LtpPitchLag; + short tcx_lpc_shaped_ari; + + DEC_MODE m_decodeMode; + unsigned char m_frame_type; /*ZERO_FRAME/SID_FRAME/ACTIVE_FRAME*/ + unsigned char m_old_frame_type; /*ZERO_FRAME/SID_FRAME/ACTIVE_FRAME*/ + + /*Frequency-domain-based CNG*/ + HANDLE_FD_CNG_DEC hFdCngDec; + + IGFDEC_INSTANCE hIGFDec; + short igf; + + short tec_tfa; + short tec_flag; + short tfa_flag; + TEMPORAL_ENVELOPE_CODING_DECODER tecDec; + + short old_ppp_mode; + float old_hb_synth[L_FRAME48k]; + short con_tcx; + short last_con_tcx; + + short writeFECoffset; + + +} Decoder_State; + +#endif + diff --git a/lib_dec/stat_noise_uv_dec.c b/lib_dec/stat_noise_uv_dec.c new file mode 100644 index 000000000..23b83812a --- /dev/null +++ b/lib_dec/stat_noise_uv_dec.c @@ -0,0 +1,76 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "prot.h" + + +/*---------------------------------------------------------* + * stat_noise_uv_dec() + * + * Modifies excitation signal in UC mode when the noise is stationary + *---------------------------------------------------------*/ + +void stat_noise_uv_dec( + Decoder_State *st, /* i/o: decoder static memory */ + const short coder_type, /* i : coding type */ + float *lsp_new, /* i : end-frame LSP vector */ + float *lsp_mid, /* i : mid-frame LSP vector */ + float *Aq, /* o : A(z) quantized for the 4 subframes */ + float *exc2 /* i/o: excitation buffer */ +) +{ + short i; + float ftmp, noisiness = 0; + + /*-----------------------------------------------------------------* + * Decode the VAD flag + *-----------------------------------------------------------------*/ + + if( coder_type == UNVOICED || ( coder_type == INACTIVE && st->core_brate <= ACELP_9k60 ) ) + { + /* read the noisiness parameter */ + noisiness = (float)get_next_indice( st, 5 ); + } + + /*-----------------------------------------------------------------* + * Update long-term energies for FEC + * Update LSP vector for CNG + *-----------------------------------------------------------------*/ + + if( coder_type == INACTIVE ) + { + if( st->unv_cnt > 20 ) + { + ftmp = st->lp_gainc * st->lp_gainc; + st->lp_ener = 0.7f * st->lp_ener + 0.3f * ftmp; + for( i=0; ilspCNG[i] = (float)(0.9f * st->lspCNG[i] + 0.1f * lsp_new[i]); + } + } + else + { + st->unv_cnt++; + } + } + else + { + st->unv_cnt = 0; + } + + /*-----------------------------------------------------------------* + * Modify the excitation signal + *-----------------------------------------------------------------*/ + + if ( !st->Opt_AMR_WB ) + { + stat_noise_uv_mod( coder_type, noisiness, st->lsp_old, lsp_new, lsp_mid, Aq, exc2, 0, &st->ge_sm, + &st->uv_count, &st->act_count, st->lspold_s, &st->noimix_seed, &st->min_alpha, + &st->exc_pe, st->core_brate, st->bwidth ); + } + + return; +} diff --git a/lib_dec/swb_bwe_dec.c b/lib_dec/swb_bwe_dec.c new file mode 100644 index 000000000..cf4d9b24b --- /dev/null +++ b/lib_dec/swb_bwe_dec.c @@ -0,0 +1,665 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include "basop_util.h" +#include "basop_proto_func.h" + + +/*-------------------------------------------------------------------* + * para_pred_bws() + * + * predict SWB parameters for bandwidth switching + *-------------------------------------------------------------------*/ +static short para_pred_bws( + Decoder_State *st, /* i/o: decoder state structure */ + float *signal_wb, /* i : wideband frequency signal */ + float *SWB_fenv, /* o : frequency-domain BWE envelope */ + short coder_type /* i : coding type */ +) +{ + short i, j, k; + short mode; + float *input_hi; + float peak, mean[7], mag, min; + float avrg1, avrg2; + float att; + + mode = NORMAL; + + k = 0; + input_hi = &signal_wb[SHARP_WIDTH]; + for(i = 0; i < 7; i ++) + { + peak = 0.0f; + mean[i] = 0; + for(j = 0; j < SHARP_WIDTH; j ++) + { + mag = (float) fabs(*input_hi); + if (mag > peak) + { + peak = mag; + } + mean[i] += mag; + input_hi ++; + } + + if (peak*(SHARP_WIDTH+3.5f) > 4.5f*mean[i] && peak > 8.0f) + { + k += 1; + } + } + + avrg1 = 0.0f; + avrg2 = 0.0f; + for(i=1; i<4; i++) + { + avrg1 += mean[i]; + avrg2 += mean[i+3]; + } + avrg1 /= 3; + avrg2 /= 3; + + min = FLT_MAX; + peak = 0.0f; + for(i = 4; i < 7; i ++) + { + if(mean[i] > 2.0f*avrg2) + { + mean[i] *= 2*avrg2/mean[i]; + } + if(mean[i] < min) + { + min = mean[i]; + } + if(mean[i] > peak) + { + peak = mean[i]; + } + } + + if(st->tilt_wb > 8) + { + min = min(st->tilt_wb/15.0f, 1.0f)*peak; + } + + if( peak == 0 || min == 0 ) + { + set_f( SWB_fenv, 0, SWB_FENV ); + } + else + { + for(i = 0; i < SWB_FENV; i ++) + { + SWB_fenv[i] = min*mean[i/5+4]/(64*peak); + } + } + + for(j = 0, i = SWB_FENV/2; i < SWB_FENV; i ++) + { + SWB_fenv[i] *= (1.0f - (float)j++/SWB_FENV); + } + + if(avrg1 > 8.0f*avrg2) + { + for(i = 0; i < SWB_FENV; i ++) + { + SWB_fenv[i] *= 0.5f; + } + } + if( st->last_core != HQ_CORE && st->last_codec_mode == MODE1 && + (st->enerLH > 0.5f*st->prev_enerLH && st->enerLH < 2.0f*st->prev_enerLH) && + (st->enerLL > 0.5f*st->prev_enerLL && st->enerLL < 2.0f*st->prev_enerLL) ) + { + for(i=0; iprev_coder_type != coder_type && SWB_fenv[i] > 2.0f*st->prev_SWB_fenv[i] ) + { + SWB_fenv[i] = 0.1f * SWB_fenv[i] + 0.9f * st->prev_SWB_fenv[i]; + } + else + { + SWB_fenv[i] = st->attenu1 * SWB_fenv[i] + (1.0f - st->attenu1) * st->prev_SWB_fenv[i]; + } + } + + if( st->attenu1 < 0.9f ) + { + st->attenu1 += 0.05f; + } + } + else + { + if( st->core_brate != st->last_core_brate || (st->enerLH > 0.5f*st->prev_enerLH && st->enerLH < 2.0f*st->prev_enerLH) || + (st->enerLL > 0.5f*st->prev_enerLL && st->enerLL < 2.0f*st->prev_enerLL) ) + { + for(i=0; i 2.0f*st->prev_SWB_fenv[i]) + { + SWB_fenv[i] = st->prev_SWB_fenv[i]; + } + } + } + + for(i=0; iprev_SWB_fenv[i]; + } + + st->attenu1 = 0.1f; + } + + if( k > 3 ) + { + mode = HARMONIC; + } + + att = ((float)N_WS2N_FRAMES - (float)st->bws_cnt) / (float)N_WS2N_FRAMES; + if(st->L_frame == L_FRAME16k ) + { + for( i = 0; i < 4; i++ ) + { + SWB_fenv[i] *= att; + } + } + + for( i=4; iold_wtda_swb, ALDO_WINDOW,ALDO_WINDOW, output_frame ); + direct_transform( wtda_synth, ysynth, 0, output_frame ); + + if( !st->bfi ) + { + if( st->total_brate == ACELP_13k20 ) + { + /* de-quantization */ + mode = WB_BWE_gain_deq( st, WB_fenv ); + st->last_wb_bwe_ener = 0.5f*(WB_fenv[0] + WB_fenv[1]); + } + else + { + if( st->last_extl != WB_BWE ) + { + st->prev_SWB_fenv[0] = 0.0f; + } + + mode = WB_BWE_gain_pred( WB_fenv, ysynth, coder_type, st->prev_coder_type, st->prev_SWB_fenv[0], voice_factors, pitch_buf, + st->last_core_brate, st->last_wb_bwe_ener, st->last_extl + ,st->tilt_wb + ); + } + } + else + { + /* FEC */ + mode = NORMAL; + for( i=0; i<2; i++ ) + { + WB_fenv[i] = 0.75f*st->prev_SWB_fenv[i]; + } + } + + if( st->last_extl != WB_BWE || st->bfi ) + { + mvr2r( WB_fenv, st->prev_SWB_fenv, 2 ); + } + + /* reconstruction of MDCT spectrum of the error signal */ + WB_BWE_decoding( ysynth, WB_fenv, yerror, L_FRAME16k, mode, st->last_extl, + &st->prev_Energy_wb, st->prev_SWB_fenv, &st->prev_L_swb_norm, st->extl, + coder_type, st->total_brate, &st->Seed, &st->prev_flag, st->prev_coder_type ); + + if ( st->output_Fs == 32000) + { + set_f( &yerror[L_FRAME16k], 0, L_FRAME16k ); + } + else if ( st->output_Fs == 48000 ) + { + set_f( &yerror[L_FRAME16k], 0, L_FRAME32k ); + } + + inverse_transform( yerror, wtda_synth, 0, output_frame, -1 ); + + window_ola( wtda_synth, hb_synth, st->mem_imdct, output_frame,ALDO_WINDOW,ALDO_WINDOW, 0,0,0 ); + + st->prev_mode = mode; + + return; +} + +/*-------------------------------------------------------------------* + * swb_bwe_gain_deq() + * + * Decoding of SWB parameters + *-------------------------------------------------------------------*/ + +short swb_bwe_gain_deq( /* o : BWE class */ + Decoder_State *st, /* i/o: decoder state structure */ + const short core, /* i : core */ + float *SWB_tenv, /* o : time-domain BWE envelope */ + float *SWB_fenv, /* o : frequency-domain BWE envelope */ + const short hr_flag, /* i : high rate flag */ + const short hqswb_clas /* i : HQ BWE class */ +) +{ + short index, mode, n_band; + short indice[6]; + float quant_tmp[SWB_FENV/2], quant_tmp2[SWB_FENV/2]; + short nb_bits[6]; + short nenv; + + if ( hqswb_clas > 0) + { + mode = (short)get_next_indice( st, 1 ); + if (mode == 0) + { + mode = (short)get_next_indice( st, 1 ); + } + else + { + mode = HQ_GENERIC_SP_EXC; + } + } + else + { + mode = (short)get_next_indice( st, 2 ); + } + + if( mode == 1 && core == ACELP_CORE ) + { + for( n_band = 0; n_band < SWB_TENV; n_band++ ) + { + index = (short)get_next_indice( st, 4 ); + SWB_tenv[n_band] = (float)(1 << index); + } + + indice[0] = (short)get_next_indice( st, 7 ); + indice[1] = (short)get_next_indice( st, 6 ); + + for(n_band = 0; n_band < DIM_TR1; n_band++) + { + quant_tmp[2*n_band]= Env_TR_Cdbk1[indice[0]*DIM_TR1+n_band]; + } + + quant_tmp[1] = (quant_tmp[0]+quant_tmp[2])*0.5f+Env_TR_Cdbk2[indice[1]*DIM_TR2]; + quant_tmp[3] = quant_tmp[2]+Env_TR_Cdbk2[indice[1]*DIM_TR2+1]; + + for(n_band = 0; n_band < SWB_FENV_TRANS; n_band++) + { + SWB_fenv[n_band] = (float)pow(10, 0.025f*(quant_tmp[n_band]+Mean_env_tr[n_band])); + } + + /* in case of band-width switching, attenuate frame gain */ + if( st->bws_cnt1 > 0 ) + { + for(n_band = 0; n_band < SWB_TENV; n_band++) + { + SWB_tenv[n_band] *= (float)st->bws_cnt1 / (float)N_NS2W_FRAMES; + } + + for (n_band = 0; n_band < SWB_FENV_TRANS; n_band++) + { + SWB_fenv[n_band] *= (float)st->bws_cnt1 / (float)N_NS2W_FRAMES; + } + } + } + else + { + nb_bits[0] = 5; + nb_bits[1] = 7; + nb_bits[2] = 6; + nb_bits[3] = 5; + + if ( hr_flag == 1 ) + { + nb_bits[4] = 5; + nenv = SWB_FENV - 2; + } + else + { + nb_bits[4] = 6; + nenv = SWB_FENV; + } + + for (n_band = 0; n_band < 5; n_band++) + { + indice[n_band] = (short) get_next_indice( st, nb_bits[n_band] ); + } + + if ( hqswb_clas == HQ_GEN_FB ) + { + indice[n_band] = (short) get_next_indice( st, 5 ); + } + + mvr2r( &EnvCdbk11[indice[0] * DIM11], quant_tmp, DIM11 ); + mvr2r( &EnvCdbk1st[indice[1] * DIM1ST], quant_tmp2, DIM1ST ); + mvr2r( &EnvCdbk2nd[indice[2] * DIM2ND], quant_tmp2+DIM1ST, DIM2ND ); + + for( n_band = 0; n_band < DIM11-1; n_band++ ) + { + quant_tmp[n_band] += quant_tmp2[n_band]; + SWB_fenv[n_band*2] = quant_tmp[n_band]; + } + + if ( hr_flag == 1 ) + { + quant_tmp[6] += quant_tmp2[6]; + SWB_fenv[11] = quant_tmp[6]; + + + mvr2r( &EnvCdbk3rd[indice[3] * DIM3RD], quant_tmp2, DIM3RD ); + mvr2r( &EnvCdbk3rd[indice[4] * DIM3RD], quant_tmp2+DIM3RD, DIM3RD ); + + for(n_band = 0; n_band < 5; n_band++) + { + SWB_fenv[n_band*2+1] = ((quant_tmp[n_band]+quant_tmp[n_band+1])/2.f)+quant_tmp2[n_band+1]; + } + + SWB_fenv[0] += quant_tmp2[0]; + } + else + { + quant_tmp[DIM11-1]+=quant_tmp2[DIM11-1]; + SWB_fenv[(DIM11-1)*2] = quant_tmp[DIM11-1]; + + mvr2r( &EnvCdbk3rd[indice[3] * DIM3RD], quant_tmp2, DIM3RD ); + mvr2r( &EnvCdbk4th[indice[4] * DIM4TH], quant_tmp2+DIM3RD, DIM4TH ); + + for( n_band = 0; n_band < DIM12-1; n_band++ ) + { + SWB_fenv[n_band*2+1] = ((quant_tmp[n_band]+quant_tmp[n_band+1])/2.f)+quant_tmp2[n_band]; + } + + SWB_fenv[n_band*2+1] = quant_tmp[n_band]+quant_tmp2[n_band]; + } + + for( n_band = 0; n_band < nenv; n_band++ ) + { + Word16 tmp,frac,exp; + Word32 L_tmp; + tmp = add((short)(SWB_fenv[n_band]*256),(short)(Mean_env[n_band]*256)); /*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); + tmp = shl(tmp, add(exp,1)); /*Q1 */ + SWB_fenv[n_band] = (float)tmp*0.5f; /*Q1 */ + } + + if ( hqswb_clas == HQ_GEN_FB ) + { + mvr2r( &EnvCdbkFB[indice[5] * DIM_FB], &SWB_fenv[nenv], DIM_FB ); + for( n_band = 0; n_band < DIM_FB; n_band++ ) + { + Word16 tmp,frac,exp; + Word32 L_tmp; + + tmp = add((short)(SWB_fenv[n_band + nenv]*128),(short)(Mean_env_fb[n_band]*128)); /*Q7 */ + 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); + tmp = shl(tmp, add(exp,1)); + move16(); + SWB_fenv[add(n_band,nenv)] = (float)tmp*0.5f; + } + } + + } + + return mode; +} + +/*-------------------------------------------------------------------* + * swb_bwe_dec() + * + * SWB BWE decoder (only for 32kHz signals) + *-------------------------------------------------------------------*/ + +void swb_bwe_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const float *synth, /* i : ACELP core synthesis/final synthesis */ + float *hb_synth, /* o : SHB synthesis/final synthesis */ + const short output_frame /* i : frame length */ + ,short coder_type /* i : coding type */ +) +{ + short i, l_subfr; + float ysynth[L_FRAME48k]; + float yerror[L_FRAME48k]; + float wtda_synth[2*L_FRAME48k]; + float SWB_tenv[SWB_TENV]; + float SWB_fenv[SWB_FENV]; + short L; + short mode; + short frica_flag = 0; + float fb_ener_adjust = 0.0f; + short j = 0; + float ener_adjust_quan; + short idxGain; + + /*---------------------------------------------------------------------* + * SWB BWE decoding + *---------------------------------------------------------------------*/ + + /* windowing of the ACELP core synthesis */ + wtda( synth, wtda_synth, st->old_wtda_swb, ALDO_WINDOW, ALDO_WINDOW, output_frame ); + + /* DCT of the ACELP core synthesis */ + direct_transform( wtda_synth, ysynth, 0, output_frame ); + + if( !st->bfi ) + { + if( st->bws_cnt > 0 ) + { + /* estimate parameters */ + mode = para_pred_bws( st, ysynth, SWB_fenv, coder_type ); + } + else + { + /* de-quantization */ + mode = swb_bwe_gain_deq( st, ACELP_CORE, SWB_tenv, SWB_fenv, 0, -1 ); + } + + L = mode == TRANSIENT ? SWB_FENV_TRANS : SWB_FENV; + st->prev_ener_shb = 0.0f; + for(i=0; iprev_ener_shb += SWB_fenv[i]; + } + st->prev_ener_shb /= L; + } + else + { + /* SHB FEC */ + if( st->prev_mode != TRANSIENT ) + { + mode = st->prev_mode; + } + else + { + mode = NORMAL; + } + + mvr2r( st->prev_SWB_fenv, SWB_fenv, SWB_FENV ); + } + + /* reconstruction of MDCT spectrum of the error signal */ + set_f( yerror, 0, output_frame ); + + if (st->L_frame == L_FRAME16k ) + { + SWB_BWE_decoding( ysynth, SWB_fenv, yerror, L_FRAME32k-80, mode, &frica_flag, &st->prev_Energy, st->prev_SWB_fenv, + &st->prev_L_swb_norm, st->tilt_wb, &st->Seed, 80, &st->prev_weight, st->extl + ,st->last_extl + ); + } + else + { + SWB_BWE_decoding( ysynth, SWB_fenv, yerror, L_FRAME32k-80, mode, &frica_flag, &st->prev_Energy, st->prev_SWB_fenv, + &st->prev_L_swb_norm, st->tilt_wb, &st->Seed, 6, &st->prev_weight, st->extl + ,st->last_extl + ); + } + + if ( st->prev_frica_flag == 1 && frica_flag == 0 ) + { + for( i = 0; i < L_SUBFR; i++ ) + { + st->mem_imdct[i] *= 1.0f - i*0.015625f; + } + + for( ; i < output_frame; i++ ) + { + st->mem_imdct[i] = 0.0f; + } + } + + /* decode information */ + if ( st->extl == FB_BWE ) + { + if( !st->bfi ) + { + idxGain = (short)get_next_indice( st,NUM_BITS_FB_FRAMEGAIN); + fb_ener_adjust = usdequant(idxGain, FB_GAIN_QLOW, FB_GAIN_QDELTA); + } + else if( st->bfi ) + { + fb_ener_adjust = st->prev_fb_ener_adjust; + } + + st->prev_fb_ener_adjust = fb_ener_adjust; + if(mode == TRANSIENT) + { + ener_adjust_quan = fb_ener_adjust; + } + else + { + if(SWB_fenv[7] < 0.01f) + { + ener_adjust_quan = 0.0f; + } + else + { + ener_adjust_quan = min(SWB_fenv[13]/SWB_fenv[7], 4.0f); + } + } + for( i = FB_BAND_BEGIN; i < FB_BAND_BEGIN+DE_OFFSET1; i++ ) + { + yerror[i] = yerror[i-FB_BAND_WIDTH] * ((1.0f-j*FB_GAIN_QDELTA)*ener_adjust_quan + j*FB_GAIN_QDELTA*fb_ener_adjust); + j++; + } + for(; i < FB_BAND_END; i++ ) + { + yerror[i] = yerror[i-FB_BAND_WIDTH] * fb_ener_adjust; + } + } + + /* iDCT of the error signal */ + inverse_transform( yerror, wtda_synth, 0, output_frame, -1 ); + + /* inverse windowing of the error signal */ + window_ola( wtda_synth, hb_synth, st->mem_imdct, output_frame,ALDO_WINDOW,ALDO_WINDOW, 0,0,0 ); + l_subfr = output_frame/4; + + if( mode == TRANSIENT ) + { + for(i = 0; i < SWB_TENV; i++) + { + SWB_tenv[i] *= 0.8f; + } + + /* time envelope shaping when the current frame is TRANSIENT frame */ + time_envelop_shaping( hb_synth, SWB_tenv, output_frame ); + + st->prev_td_energy = SWB_tenv[3]; + } + else if( frica_flag == 1 && st->prev_frica_flag == 0 ) + { + time_reduce_pre_echo( synth, hb_synth, st->prev_td_energy, l_subfr ); + } + else + { + st->prev_td_energy = 0.0f; + for( i=0; iprev_td_energy += hb_synth[3*l_subfr+i]*hb_synth[3*l_subfr+i]; + } + st->prev_td_energy = (float)sqrt(st->prev_td_energy/l_subfr); + } + + st->prev_frica_flag = frica_flag; + st->prev_mode = mode; + + return; +} diff --git a/lib_dec/swb_bwe_dec_hr.c b/lib_dec/swb_bwe_dec_hr.c new file mode 100644 index 000000000..3188d2b0f --- /dev/null +++ b/lib_dec/swb_bwe_dec_hr.c @@ -0,0 +1,757 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "prot.h" +#include "rom_com.h" + +/*-------------------------------------------------------------------* + * swb_bwe_dec_hr() + * + * HR SWB BWE decoder + *-------------------------------------------------------------------*/ + +void swb_bwe_dec_hr( + Decoder_State *st, /* i/o: decoder state structure */ + const float *syn_12k8_16k, /* i : ACELP core synthesis @16kHz */ + float *hb_synth, /* o : SHB synthesis */ + const short output_frame, /* i : frame length */ + const short unbits, /* i : number of core unused bits */ + const float pitch_buf[] /* i : pitch buffer */ +) +{ + short i, j, k, nBits, nBits_total, nBits_block, Nsv, Nsv2, width_noncoded; + short is_transient, tmpS, incr, IsTransient, pos; + int x_norm[NSV_MAX*(WIDTH_BAND+1)], x_norm1[NSV_MAX*(WIDTH_BAND+1)]; + float t_audio[L_FRAME48k], t_audio_tmp[L_FRAME48k]; + float gain = 0.0f, gain2, en_band[N_BANDS_BWE_HR]; + short ind1, ind2; + float EnergyLT, Energy; + short nq[NSV_MAX], nq2[NSV_MAX], nq_tmp[NSV_MAX]; + float tilt_wb, min_env, max_env; + float tmpF, tmp2, pitch, alpha; + float en_noncoded; + float env = 0.0f; + + /*---------------------------------------------------------------------* + * initializations + *---------------------------------------------------------------------*/ + + set_f( t_audio, 0.0f, output_frame ); + + st->bwe_highrate_seed = (short)((short)(pitch_buf[0]*64.0f)*(short)(pitch_buf[3]*64.0f)); + + ind2 = 0; /* only to suppress warnings */ + Nsv2 = 0; /* only to suppress warnings */ + gain2 = 0 ; /* only to suppress warnings */ + + /* reset memories in case that last frame was a different technology */ + if( st->last_core == HQ_CORE || st->last_extl != st->extl ) + { + set_f( st->old_wtda_swb, 0, L_FRAME48k ); + } + + /* calculate SWB BWE bit-budget */ + nBits = (short)(st->extl_brate) / 50 + unbits; + nBits_total = nBits; + + /*---------------------------------------------------------------------* + * calculate tilt of the core synthesis + *---------------------------------------------------------------------*/ + calc_tilt_bwe( syn_12k8_16k, &tilt_wb, L_FRAME16k ); + pitch = sum_f( pitch_buf, NB_SUBFR16k ) + EPSILON; + + + /*---------------------------------------------------------------------* + * FEC, or good frame decoding + *---------------------------------------------------------------------*/ + + if( st->bfi ) + { + is_transient = st->old_is_transient_hr_bwe; + + /* Replication of the last spectrum, with an attenuation */ + if( (st->clas_dec == VOICED_CLAS || st->clas_dec == INACTIVE_CLAS) && st->nbLostCmpt <= 3 ) + { + alpha = 0.8f; + } + else if( is_transient ) + { + alpha = 0.15f; + } + else + { + alpha = 0.3f; + } + + if( is_transient ) + { + /* set BWE spectrum length */ + if( output_frame == L_FRAME32k ) + { + tmpS = L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_START_FREQ_COEF; + } + else /* output_frame == L_FRAME48k */ + { + tmpS = (2*END_FREQ_BWE_FULL_FB/50)/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_START_FREQ_COEF; + } + + /* reconstruct */ + for( k=0; kt_audio_prev[i + k*tmpS]; + } + /* save transform coefficients for the next frame (needed in case of frame erasures) */ + mvr2r( t_audio + NUM_TRANS_START_FREQ_COEF + k*output_frame/NUM_TIME_SWITCHING_BLOCKS, st->t_audio_prev + k*tmpS, tmpS ); + } + } + else + { + /* set BWE spectrum length */ + if( output_frame == L_FRAME32k ) + { + tmpS = L_FRAME32k - NUM_NONTRANS_START_FREQ_COEF; + } + else /* output_frame == L_FRAME48k */ + { + tmpS = 2*END_FREQ_BWE_FULL_FB/50 - NUM_NONTRANS_START_FREQ_COEF; + } + + /* reconstruct */ + for( i=0; it_audio_prev[i]; + } + /* Save transform coefficients for the next frame (needed in case of frame erasures) */ + mvr2r( t_audio + NUM_NONTRANS_START_FREQ_COEF, st->t_audio_prev, tmpS ); + } + st->mem_EnergyLT *= alpha; + gain = (float)(2.0f*sqrt(st->mem_EnergyLT/output_frame)); + env = 1.0f; + } + else + { + /*---------------------------------------------------------------------* + * get transient frame flag + *---------------------------------------------------------------------*/ + + is_transient = (short) get_next_indice( st, 1 ); + + if( is_transient ) + { + nBits = -1; /* is_transient flag */ + nBits_block = nBits_total / NUM_TIME_SWITCHING_BLOCKS; + nBits += nBits_total % NUM_TIME_SWITCHING_BLOCKS; + + /* set width of noncoded (blind estimated) spectrum */ + if( st->extl == SWB_BWE_HIGHRATE || output_frame == L_FRAME32k ) + { + width_noncoded = L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_END_FREQ_COEF; + tmpS = L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_END_FREQ_COEF_EFF; + } + else /* st->extl == FB_BWE_HIGHRATE */ + { + width_noncoded = (2*END_FREQ_BWE_FULL_FB/50)/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_END_FREQ_COEF; + tmpS = (2*END_FREQ_BWE_FULL_FB/50)/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_END_FREQ_COEF_EFF; + } + + /*---------------------------------------------------------------------* + * transient frames: processing in blocks (subframes) + *---------------------------------------------------------------------*/ + + for( k = 0; k < NUM_TIME_SWITCHING_BLOCKS; k++ ) + { + nBits += nBits_block; + + /*---------------------------------------------------------------------* + * global gain and envelope decoding + *---------------------------------------------------------------------*/ + + /* get global gain */ + ind1 = (short) get_next_indice( st, NBITS_GLOB_GAIN_BWE_HR ); + gain = gain_dequant( ind1, MIN_GLOB_GAIN_BWE_HR, MAX_GLOB_GAIN_BWE_HR, NBITS_GLOB_GAIN_BWE_HR ); + nBits -= NBITS_GLOB_GAIN_BWE_HR; + + /* get energy per band */ + if( k == 0 ) + { + ind1 = (short) get_next_indice( st, NBITS_ENVELOPE_BWE_HR_TR ); + ind2 = ind1; + nBits -= NBITS_ENVELOPE_BWE_HR_TR; + } + else + { + if( ind2 < 8 ) + { + ind1 = (short) get_next_indice( st, NBITS_ENVELOPE_BWE_HR_TR - 1 ); + } + else + { + ind1 = (short) get_next_indice( st, NBITS_ENVELOPE_BWE_HR_TR - 1 ) + NUM_ENVLOPE_CODE_HR_TR2; + } + nBits -= (NBITS_ENVELOPE_BWE_HR_TR - 1); + } + + en_band[0] = swb_hr_env_code3[2 * ind1]; + en_band[1] = swb_hr_env_code3[2 * ind1 + 1]; + env = 0.5f*(en_band[0] + en_band[1]); + + /*---------------------------------------------------------------------* + * estimate energy of noncoded spectrum (14.4-20kHz) + *---------------------------------------------------------------------*/ + + en_noncoded = en_band[N_BANDS_TRANS_BWE_HR-1]; + + if( st->extl == FB_BWE_HIGHRATE ) + { + ind1 = (short) get_next_indice( st, NBITS_HF_GAIN_BWE_HR ); + nBits -= NBITS_HF_GAIN_BWE_HR; + + if( ind1 == 1 ) + { + en_noncoded *= BWE_HR_TRANS_EN_LIMIT1; + } + else if( ind1 == 2 ) + { + en_noncoded *= BWE_HR_TRANS_EN_LIMIT2; + } + else if( ind1 == 3 ) + { + en_noncoded *= BWE_HR_TRANS_EN_LIMIT3; + } + } + + /*---------------------------------------------------------------------* + * AVQ decoding (dequantize normalized spectrum) + *---------------------------------------------------------------------*/ + + Nsv = (NUM_TRANS_END_FREQ_COEF - NUM_TRANS_START_FREQ_COEF) / WIDTH_BAND; + AVQ_demuxdec( st, x_norm, &nBits, Nsv, nq ); + + for( i=0; i < Nsv*WIDTH_BAND; i++ ) + { + t_audio[k*output_frame/NUM_TIME_SWITCHING_BLOCKS + NUM_TRANS_START_FREQ_COEF + i] = (float) (x_norm[i]); + } + + /* apply noise-fill */ + swb_hr_noise_fill( is_transient, NUM_TRANS_START_FREQ_COEF, NUM_TRANS_END_FREQ_COEF, tilt_wb, pitch, nq, Nsv, &st->bwe_highrate_seed, + t_audio + NUM_TRANS_START_FREQ_COEF + k*output_frame/NUM_TIME_SWITCHING_BLOCKS ); + + /*---------------------------------------------------------------------* + * reconstruction + *---------------------------------------------------------------------*/ + + /* reconstruct 14-16(20) kHz spectrum */ + for( j = 0; j < tmpS; j++ ) + { + t_audio[k*output_frame/NUM_TIME_SWITCHING_BLOCKS + NUM_TRANS_END_FREQ_COEF_EFF + j] = 0.5f*t_audio[k*output_frame/NUM_TIME_SWITCHING_BLOCKS + NUM_TRANS_END_FREQ_COEF_EFF - tmpS + j]; + } + + /* envelope denormalization */ + for( i=0; it_audio_prev + k*(L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_START_FREQ_COEF), L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_START_FREQ_COEF ); + } + else /* output_frame == L_FRAME48k */ + { + mvr2r( t_audio + NUM_TRANS_START_FREQ_COEF + k*output_frame/NUM_TIME_SWITCHING_BLOCKS, st->t_audio_prev + k*((2*END_FREQ_BWE_FULL_FB/50)/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_START_FREQ_COEF), (2*END_FREQ_BWE_FULL_FB/50)/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_START_FREQ_COEF ); + } + + /* attenuate HFs in case of band-width switching */ + if( st->bws_cnt1 > 0 ) + { + if( output_frame == L_FRAME32k ) + { + j = L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_START_FREQ_COEF; + } + else /* output_frame == L_FRAME48k */ + { + j = (2*END_FREQ_BWE_FULL_FB/50)/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_START_FREQ_COEF; + } + + for( i=0; ibws_cnt1 / (float)N_NS2W_FRAMES; + } + } + } + } + else /* !is_transient */ + { + /* subtract one bit for is_transient flag */ + nBits--; + + /*---------------------------------------------------------------------* + * global gain and envelope decoding + *---------------------------------------------------------------------*/ + + /* get global gain */ + ind1 = (short) get_next_indice( st, NBITS_GLOB_GAIN_BWE_HR ); + gain = gain_dequant( ind1, MIN_GLOB_GAIN_BWE_HR, MAX_GLOB_GAIN_BWE_HR, NBITS_GLOB_GAIN_BWE_HR ); + + /* get energy per band */ + ind1 = (short) get_next_indice( st, NBITS_ENVELOPE_BWE_HR1 ); + ind2 = (short) get_next_indice( st, NBITS_ENVELOPE_BWE_HR2 ); + + en_band[0] = swb_hr_env_code1[2 * ind1]; + en_band[1] = swb_hr_env_code1[2 * ind1 + 1]; + en_band[2] = swb_hr_env_code2[2 * ind2]; + en_band[3] = swb_hr_env_code2[2 * ind2 + 1]; + env = 0.25f*(en_band[0] + en_band[1] + en_band[2] + en_band[3]); + + /*---------------------------------------------------------------------* + * choose sub-bands to be dequantized + *---------------------------------------------------------------------*/ + + /* find the subband with the min envelope */ + pos = 0; + min_env = en_band[0]; + max_env = en_band[0]; + for (j = 1; j < N_BANDS_BWE_HR; j++) + { + if(en_band[j] < min_env) + { + pos = j; + min_env = en_band[j]; + } + if(en_band[j] > max_env) + { + max_env = en_band[j]; + } + } + + /* decide the spectrum to be dequantized */ + if( nBits_total > NBITS_THRESH_BWE_HR ) + { + i = NUM_NONTRANS_END_FREQ_COEF - NUM_NONTRANS_START_FREQ_COEF; + } + else + { + i = NUM_NONTRANS_END_FREQ_COEF - NUM_NONTRANS_START_FREQ_COEF - 64 - 8*(pos%2); + } + + nBits -= NBITS_GLOB_GAIN_BWE_HR + NBITS_ENVELOPE_BWE_HR1 + NBITS_ENVELOPE_BWE_HR2; + + /*---------------------------------------------------------------------* + * estimate energy of noncoded spectrum (14.4-20kHz) + *---------------------------------------------------------------------*/ + + en_noncoded = 0.5f * min_env; + + if( st->extl == FB_BWE_HIGHRATE ) + { + ind1 = (short) get_next_indice( st, NBITS_HF_GAIN_BWE_HR ); + nBits -= NBITS_HF_GAIN_BWE_HR; + + if( ind1 == 1 ) + { + en_noncoded *= BWE_HR_NONTRANS_EN_LIMIT1; + } + else if( ind1 == 2 ) + { + en_noncoded *= 2.0f * BWE_HR_NONTRANS_EN_LIMIT2; + } + else if( ind1 == 3 ) + { + en_noncoded *= 2.0f * BWE_HR_NONTRANS_EN_LIMIT3; + } + } + + /*---------------------------------------------------------------------* + * AVQ decoding (dequantize normalized spectrum) + *---------------------------------------------------------------------*/ + + Nsv = i / WIDTH_BAND; + AVQ_demuxdec( st, x_norm, &nBits, Nsv, nq ); + + /*---------------------------------------------------------------------* + * second stage decoding + *---------------------------------------------------------------------*/ + + if( nBits >= 9 + NBITS_GLOB_GAIN_BWE_HR && sum_s( nq, Nsv) > 0 ) + { + ind1 = (short) get_next_indice( st, NBITS_GLOB_GAIN_BWE_HR ); + gain2 = gain_dequant( ind1, MIN_GLOB_GAIN_BWE_HR, MAX_GLOB_GAIN_BWE_HR, NBITS_GLOB_GAIN_BWE_HR ); + gain2 *= 0.0625f; + + /* calculate the number of subbands according to the rest bits */ + if( nBits > 396 ) + { + Nsv2 = 33; + } + else + { + Nsv2 = nBits/12; + } + + nBits -= NBITS_GLOB_GAIN_BWE_HR; + AVQ_demuxdec( st, x_norm1, &nBits, Nsv2, nq2 ); + } + + /*---------------------------------------------------------------------* + * dequantization + *---------------------------------------------------------------------*/ + + for( i=0; i Nsv ) + { + /* Safety check, happens rarely */ + set_s( nq_tmp + Nsv, 0, Nsv2 - Nsv ); + } + + k = 0; + incr = 0; + for( i=0; i= Nsv2 ) + { + break; + } + + if( nq_tmp[i] != 0 ) + { + for( j=0; j NBITS_THRESH_BWE_HR ) + { + mvr2r( t_audio_tmp, t_audio + NUM_NONTRANS_START_FREQ_COEF, NUM_NONTRANS_END_FREQ_COEF - NUM_NONTRANS_START_FREQ_COEF ); + } + else + { + ind1 = (pos*64 + pos/2 * WIDTH_BAND); + mvr2r( t_audio_tmp, t_audio + NUM_NONTRANS_START_FREQ_COEF, ind1 ); + + ind2 = ((pos+1)*64 + (pos+1)/2 * WIDTH_BAND); + mvr2r( t_audio_tmp + ind1, t_audio + NUM_NONTRANS_START_FREQ_COEF + ind2, NUM_NONTRANS_END_FREQ_COEF - NUM_NONTRANS_START_FREQ_COEF - ind2 ); + + /* reconstruct non-encoded subband */ + if( pos == 3 ) + { + mvr2r( t_audio + NUM_NONTRANS_START_FREQ_COEF + 128, t_audio + NUM_NONTRANS_START_FREQ_COEF + 200, 72 ); + + mvs2s( nq + 16, nq + 25, 9 ); + } + else + { + pos %= 2; + mvr2r( t_audio + NUM_NONTRANS_START_FREQ_COEF + ind2, t_audio + NUM_NONTRANS_START_FREQ_COEF + ind1, 64 + pos*WIDTH_BAND ); + ind1 /= WIDTH_BAND; + ind2 /= WIDTH_BAND; + + j = 0; + for( i=Nsv-1; i>=ind1; i-- ) + { + nq[33 - j++] = nq[i]; + } + + mvs2s( nq + ind2, nq + ind1, WIDTH_BAND+pos ); + } + } + + /* apply noise-fill */ + if( nBits < 200 ) + { + swb_hr_noise_fill( is_transient, NUM_NONTRANS_START_FREQ_COEF, NUM_NONTRANS_END_FREQ_COEF, tilt_wb, + pitch, nq, Nsv, &st->bwe_highrate_seed, t_audio + NUM_NONTRANS_START_FREQ_COEF ); + } + + /*---------------------------------------------------------------------* + * reconstruction + *---------------------------------------------------------------------*/ + + /* smoothing 12.6-12.8kHz */ + if( pos == 3 && nBits_total <= 400 ) + { + tmpF = sum2_f( t_audio + NUM_NONTRANS_START_FREQ_COEF + 200 - WIDTH_BAND, WIDTH_BAND ) + EPSILON; + tmp2 = sum2_f( t_audio + NUM_NONTRANS_START_FREQ_COEF + 200, WIDTH_BAND ) + EPSILON; + tmpF = (float)sqrt( tmpF/tmp2 ); + for( i=0; iextl == SWB_BWE_HIGHRATE || output_frame == L_FRAME32k ) + { + width_noncoded = L_FRAME32k - NUM_NONTRANS_END_FREQ_COEF; + } + else /* st->extl == FB_BWE_HIGHRATE */ + { + width_noncoded = 2*END_FREQ_BWE_FULL_FB/50 - NUM_NONTRANS_END_FREQ_COEF; + } + mvr2r( t_audio + NUM_NONTRANS_END_FREQ_COEF - width_noncoded, t_audio + NUM_NONTRANS_END_FREQ_COEF, width_noncoded ); + + /* smoothing 14.4-14.8kHz */ + tmpF = sum2_f( t_audio + NUM_NONTRANS_END_FREQ_COEF - WIDTH_BAND, WIDTH_BAND ) + EPSILON; + tmp2 = sum2_f( t_audio + NUM_NONTRANS_END_FREQ_COEF, WIDTH_BAND ) + EPSILON; + tmpF = (float)sqrt( tmpF/tmp2 ); + for( i=0; iextl == SWB_BWE_HIGHRATE || tmpF < 2.2f ) + { + for( j=0; jt_audio_prev, L_FRAME32k - NUM_NONTRANS_START_FREQ_COEF ); + } + else /* output_frame == L_FRAME48k */ + { + mvr2r( t_audio + NUM_NONTRANS_START_FREQ_COEF, st->t_audio_prev, 2*END_FREQ_BWE_FULL_FB/50 - NUM_NONTRANS_START_FREQ_COEF ); + } + + /* attenuate HFs in case of band-width switching */ + if( st->bws_cnt1 > 0 ) + { + if( output_frame == L_FRAME32k ) + { + j = L_FRAME32k - NUM_NONTRANS_START_FREQ_COEF; + } + else /* output_frame == L_FRAME48k */ + { + j = 2*END_FREQ_BWE_FULL_FB/50 - NUM_NONTRANS_START_FREQ_COEF; + } + + for( i=0; ibws_cnt1 / (float)N_NS2W_FRAMES; + } + } + } + } + + st->prev_ener_shb = gain*env; + for(i=0; iprev_SWB_fenv[i] = gain*env; + } + + /*---------------------------------------------------------------------* + * iOLA and iMDCT + *---------------------------------------------------------------------*/ + + inverse_transform( t_audio, t_audio_tmp, is_transient, output_frame, output_frame ); + window_ola( t_audio_tmp, hb_synth, st->old_wtda_swb, output_frame, ALDO_WINDOW, ALDO_WINDOW, 0,0,0 ); + + /*---------------------------------------------------------------------* + * final adjustments + *---------------------------------------------------------------------*/ + + if( !st->bfi ) + { + IsTransient = 0; + EnergyLT = st->mem_EnergyLT; + pos = 0; + for( j=0; j<4; j++ ) + { + Energy = sum2_f( hb_synth + j*(output_frame/4), output_frame/4 ) + EPSILON; + if( Energy > 12.5f * EnergyLT ) + { + IsTransient = 1; + pos = j; + } + + EnergyLT = 0.75f*EnergyLT + 0.25f*Energy; + } + + if( IsTransient == 1 && pos > 0 && tilt_wb < 3.0f && pitch > 500 ) + { + Nsv = pos*(output_frame/4); + Energy = sum2_f( hb_synth, Nsv ) + EPSILON; + if( st->last_extl != st->extl ) + { + st->mem_EnergyLT = Energy; + } + gain = (float)sqrt( pos*st->mem_EnergyLT/Energy ); + + gain *= 0.2f; + for( i=0; imem_EnergyLT = EnergyLT; + st->old_is_transient_hr_bwe = is_transient; + } + + /* post-processing in case of TD/FD switching */ + if( st->last_core == HQ_CORE || st->last_extl != st->extl ) + { + if( tilt_wb < 3.0f ) + { + gain = td_postprocess( hb_synth, output_frame, st->last_extl ); + + for( i=0; iold_wtda_swb[i] *= gain; + } + + tmpS = L_FRAME32k - NUM_NONTRANS_START_FREQ_COEF; + if( output_frame == L_FRAME48k ) + { + tmpS = 2*END_FREQ_BWE_FULL_FB/50 - NUM_NONTRANS_START_FREQ_COEF; + } + + for( i=0; it_audio_prev[i] *= gain; + } + } + } + + return; +} diff --git a/lib_dec/swb_bwe_dec_lr.c b/lib_dec/swb_bwe_dec_lr.c new file mode 100644 index 000000000..ac32aeaf7 --- /dev/null +++ b/lib_dec/swb_bwe_dec_lr.c @@ -0,0 +1,279 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include "stat_com.h" + + + +/*-------------------------------------------------------------------* + * DecodeSWBGenericParameters() + * + * Decoding of generic subband coding parameters + *-------------------------------------------------------------------*/ + +static void DecodeSWBGenericParameters( + Decoder_State *st, /* i/o: decoder state structure */ + short *lagIndices, /* o : lowband index for each subband */ + const short nBands_search, /* i : number of subbnads for SSearch */ + const short BANDS, /* i : total number of subbands per frame */ + const short *p2a_flags, /* i : HF tonal flag */ + const short hq_swb_clas /* i : mode of operation HQ_NORMAL or HQ_HARMONIC */ +) +{ + short sb; + + /* lag index for each subband (except last two) */ + for (sb = 0; sb < nBands_search; sb++) + { + if( hq_swb_clas == HQ_HARMONIC ) + { + lagIndices[sb] = (short)get_next_indice( st, bits_lagIndices_mode0_Har[sb]); + } + else + { + if( p2a_flags[BANDS-NB_SWB_SUBBANDS+sb] == 0 ) + { + lagIndices[sb] = (short)get_next_indice( st, bits_lagIndices_modeNormal[sb] ); + } + else + { + lagIndices[sb] = 0; + } + } + } + + 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( + Decoder_State *st, /* i/o: decoder state structure */ + float *spectra, /* i/o: MDCT domain spectrum */ + const short fLenLow, /* i : lowband length */ + const short fLenHigh, /* i : highband length */ + const short nBands, /* i : number of subbands */ + const short *sbWidth, /* i : subband lengths */ + short *lagIndices, + float *lagGains, /* i : first gain for each subband */ + short BANDS, /* i : number subbands per frame */ + short *band_start, /* i : band start of each SB */ + short *band_end, /* i : band end of each SB */ + float *band_energy, /* i : band energy of each SB */ + short *p2a_flags, /* i : HF tonal indicator */ + const short hqswb_clas, /* i : class information */ + const short har_bands, /* i : number of LF harmonic bands */ + const short *subband_search_offset, + short *prev_frm_hfe2, + short *prev_stab_hfe2, + short band_width[], /* i : subband band widths */ + const short *subband_offsets, /* i : subband offsets for sparse filling */ + const float spectra_ni[], /* i : core coder with sparseness filled */ + short *ni_seed /* i/o: random seed for search buffer NI */ +) +{ + short i; + short k; + float sspectra[L_FRAME32k]; + float sspectra_ni[L_FRAME32k],sspectra_diff[L_FRAME32k], th_g[NB_SWB_SUBBANDS]; + float ss_min=1.0f,g ,be_tonal[SWB_HAR_RAN1], xSynth_har[L_FRAME32k]; + GainItem pk_sf[(NB_SWB_SUBBANDS)*8]; + short lagIndices_real[NB_SWB_SUBBANDS]; + short pul_res[NB_SWB_SUBBANDS],cnt,imin; + short har_freq_est1 = 0; + short har_freq_est2 = 0; + short flag_dis = 1; + short pos_max_hfe2=0; + + set_s(pul_res,0,NB_SWB_SUBBANDS); + set_f( xSynth_har, 0.0f, fLenHigh ); + + + if( hqswb_clas == HQ_HARMONIC ) + { + /* Harmonic Structure analysis */ + pos_max_hfe2 = har_est( spectra, fLenLow, &har_freq_est1, &har_freq_est2, &flag_dis, prev_frm_hfe2, subband_search_offset, sbWidth, prev_stab_hfe2 ); + /* Spectrum normalization for the corecoder */ + noise_extr_corcod( spectra, spectra_ni, sspectra, sspectra_diff, sspectra_ni, fLenLow, st->prev_hqswb_clas, &st->prev_ni_ratio ); + /* Harmonic Structure analysis */ + + if(flag_dis == 0) + { + if(har_freq_est2 != SWB_HAR_RAN1 || har_freq_est2 != *prev_frm_hfe2) + { + har_freq_est2 +=lagIndices[0]; + } + } + /*Generate HF noise*/ + genhf_noise( sspectra_diff, xSynth_har, sspectra, BANDS, har_bands, har_freq_est2, pos_max_hfe2,pul_res,pk_sf,fLenLow, + fLenHigh, sbWidth, lagIndices, subband_offsets, subband_search_offset ); + + imin =(short) get_next_indice( st, 2); + g = (float)pow( 10.0f, gain_table_SWB_BWE[imin] ); + /* tonal energy estimation*/ + ton_ene_est( xSynth_har, be_tonal, band_energy, band_start, band_end, band_width, fLenLow, fLenHigh, BANDS, har_bands, g, pk_sf, pul_res ); + + /*HF Spectrum Generation*/ + Gettonl_scalfact( xSynth_har, spectra_ni, fLenLow, fLenHigh, har_bands, BANDS, band_energy, band_start, band_end, p2a_flags, be_tonal, pk_sf, pul_res); + if(flag_dis == 0) + { + *prev_frm_hfe2 = 0; + } + else + { + *prev_frm_hfe2 = har_freq_est2; + } + + for( k = har_bands; kprev_En_sb, p2a_flags, BANDS, band_start, band_end, fLenLow ); + /* xSynth is the reconstructed high-band */ + for( k = BANDS-NB_SWB_SUBBANDS; k +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include "rom_dec.h" + +/*-----------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------*/ + +static void dequantizeSHBparams( Decoder_State *st, const short extl, long extl_brate, float *Q_lsf, float *Q_subgain, + float *Q_framegrain, short *uv_flag, float *Q_shb_ener_sf, float *Q_shb_res_gshape, float *Q_mixFactors ); +static void Dequant_lower_LSF( const short lsf_idx[], float lsf_q[] ); +static void Map_higher_LSF(float lsf_q[], const float m, const float grid_in[]); +static void Dequant_mirror_point(const float lsf_q[], const short m_idx, float *m); + +void InitSWBdecBuffer( + Decoder_State *st /* i/o: SHB decoder structure */ +) +{ + set_f(st->old_bwe_exc, 0.0f, (PIT16k_MAX * 2)); + st->bwe_seed[0] = 23; /* 1; */ + st->bwe_seed[1] = 59; /* 10000; */ + set_f( st->old_bwe_exc_extended, 0.0f, NL_BUFF_OFFSET ); + st->bwe_non_lin_prev_scale = 0; + st->last_voice_factor = 0.0f; + + set_f(st->genSHBsynth_Hilbert_Mem, 0.0f,HILBERT_MEM_SIZE); + set_f(st->genSHBsynth_state_lsyn_filt_shb_local, 0.0f,2 * ALLPASSSECTIONS_STEEP); + + st->syn_dm_phase = 0; + st->prev_fbbwe_ratio = 1.0f; + st->prev_wb_bwe_frame_pow = 0.001f; + st->prev_swb_bwe_frame_pow = 0.001f; + st->prev_fb_ener_adjust = 0.0f; + + return; +} + +void ResetSHBbuffer_Dec( + Decoder_State *st /* i/o: SHB encoder structure */ +) +{ + short i; + float f; + float inc; + + if ( st->extl != WB_TBE ) + { + f = 1.0f/22.0f; + inc = 1.0f/22.0f; + } + else + { + f = 1.0f/6.0f; + inc = 1.0f/6.0f; + } + + /* states for the filters used in generating SHB excitation from WB excitation*/ + set_f(st->mem_csfilt,0,2); + + /* states for the filters used in generating SHB signal from SHB excitation*/ + set_f(st->state_syn_shbexc,0,L_SHB_LAHEAD); + set_f( st->state_lpc_syn, 0, LPC_SHB_ORDER); + if( sub(st->extl, FB_TBE) == 0 ) + { + set_f( st->fb_state_lpc_syn, 0, LPC_SHB_ORDER ); + st->fb_tbe_demph = 0; + fb_tbe_reset_synth( st->fbbwe_hpf_mem,&st->prev_fbbwe_ratio); + } + /* states for the filters used in generating SHB signal from SHB excitation in wideband*/ + set_f( st->mem_genSHBexc_filt_down_shb, 0.0f, (2*ALLPASSSECTIONS_STEEP+1) ); + set_f( st->mem_genSHBexc_filt_down_wb2, 0.0f, (2*ALLPASSSECTIONS_STEEP+1) ); + set_f( st->mem_genSHBexc_filt_down_wb3, 0.0f, (2*ALLPASSSECTIONS_STEEP+1) ); + + set_f( st->state_lsyn_filt_shb,0, 2 * ALLPASSSECTIONS_STEEP ); + set_f( st->state_lsyn_filt_dwn_shb,0, 2 * ALLPASSSECTIONS_STEEP ); + set_f( st->mem_resamp_HB, 0, INTERP_3_1_MEM_LEN ); + + /* States for the local synthesis filters */ + set_f(st->syn_overlap,0,L_SHB_LAHEAD); + + /* States for FEC */ + if ( st->extl != WB_TBE ) + { + for (i=0; ilsp_prevfrm[i] = f; + f += inc; + } + } + else + { + for (i=0; ilsp_prevfrm[i] = f; + f += inc; + } + for( ; ilsp_prevfrm[i] = 0.0f; + } + } + + st->GainFrame_prevfrm = 0.0f; + st->GainAttn = 1.0; + st->tbe_demph = 0.0f; + st->tbe_premph = 0.0f; + set_f(st->mem_stp_swb, 0, LPC_SHB_ORDER); + st->gain_prec_swb = 1.0f; + set_f( &st->GainShape_Delay[0], 0, NUM_SHB_SUBFR/2 ); + + set_f(st->old_core_synth, 0, L_FRAME16k); + set_f(st->old_tbe_synth, 0, L_SHB_TRANSITION_LENGTH); + st->tilt_swb_fec = 0.0f; + + return; +} + +/*-------------------------------------------------------------------* + * wb_tbe_dec() + * + * WB TBE decoder, 6 - 8 kHz band decoding module + *-------------------------------------------------------------------*/ + +void wb_tbe_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const short coder_type, /* i : coding type */ + const float *bwe_exc_extended,/* i : bandwidth extended excitation */ + const float voice_factors[], /* i : voicing factors */ + float *synth /* o : WB synthesis/final synthesis */ +) +{ + short i; + float shaped_wb_excitation [ (L_FRAME16k + L_SHB_LAHEAD)/4 ]; + float exc4kWhtnd [L_FRAME16k / 4]; + float lsf_wb[LPC_SHB_ORDER_WB], lpc_wb[LPC_SHB_ORDER_WB + 1], GainShape[NUM_SHB_SUBFR], GainFrame ; + float error[L_FRAME16k]; + float upsampled_synth[L_FRAME48k]; + float prev_pow, curr_pow, scale; + float temp, curr_frame_pow; + short j; + float vf_modified[NB_SUBFR16k]; + short uv_flag = 0; + + if( st->bws_cnt == 0 ) + { + + if( !st->bfi ) + { + if( st->use_partial_copy ) + { + if(st->last_extl != WB_TBE) + { + st->GainFrame_prevfrm = 0; + st->lsp_prevfrm[0] = 0.1f; + for (i=1; ilsp_prevfrm[i] = st->lsp_prevfrm[i-i] + 0.1f; + } + } + + mvr2r( st->lsp_prevfrm, lsf_wb, LPC_SHB_ORDER_LBR_WB ); + set_f( GainShape, RECIP_ROOT_EIGHT, NUM_SHB_SUBFR/2 ); + + if( st->rf_frame_type == RF_NELP ) + { + /* Frame gain */ + /* only four LSBs are valid */ + st->rf_indx_tbeGainFr &= 0xF; + mvr2r( SHBCB_FrameGain16 + st->rf_indx_tbeGainFr, &GainFrame, 1 ); + if( st->core == ACELP_CORE && st->last_core == ACELP_CORE && !st->prev_use_partial_copy && st->prev_coder_type == UNVOICED && GainFrame != st->GainFrame_prevfrm && st->last_extl == WB_TBE) + { + GainFrame = 0.2f*GainFrame + 0.8f*st->GainFrame_prevfrm; + } + } + else + { + /* Frame gain */ + temp = 0.0f; + switch (st->rf_indx_tbeGainFr) + { + case 0: + GainFrame = 0.5f; + if (st->GainFrame_prevfrm <= 1.25) + { + temp = 0.8f; + } + break; + case 1: + GainFrame = 2.0f; + if (st->GainFrame_prevfrm > 1.25 && st->GainFrame_prevfrm <= 3) + { + temp = 0.8f; + } + break; + case 2: + GainFrame = 4.0f; + if (st->GainFrame_prevfrm > 3 && st->GainFrame_prevfrm <= 6) + { + temp = 0.8f; + } + break; + case 3: + GainFrame = 8.0f; + if (st->GainFrame_prevfrm > 6 && st->GainFrame_prevfrm <= 16) + { + temp = 0.8f; + } + break; + default: + GainFrame = 1.0f; + fprintf(stderr, "RF WB-TBE gain bits not supported."); + break; + } + + if(st->last_extl == WB_TBE) + { + GainFrame = (1 - temp)*GainFrame + temp*(st->GainFrame_prevfrm); + } + + if (st->core == ACELP_CORE && st->last_core == ACELP_CORE) + { + if (!st->prev_use_partial_copy && st->last_coder_type == VOICED && st->rf_frame_type == RF_GENPRED + && st->prev_tilt_code_dec < 0.046f && st->prev_tilt_code_dec > 0.006f ) + { + GainFrame *= 0.3f; + } + } + } + } + else + { + /* de-quantization */ + dequantizeSHBparams( st, st->extl, st->extl_brate, lsf_wb, GainShape, &GainFrame, &uv_flag, 0, 0, 0 ); + } + } + else + { + if ( st->extl_brate == WB_TBE_0k35 ) + { + mvr2r( st->lsp_prevfrm, lsf_wb, LPC_SHB_ORDER_LBR_WB ); + } + else + { + mvr2r( st->lsp_prevfrm, lsf_wb, LPC_SHB_ORDER_WB ); + } + set_f( GainShape, RECIP_ROOT_EIGHT, NUM_SHB_SUBFR/2 ); + st->GainAttn *= 0.85f; + if( st->codec_mode == MODE1 ) + { + GainFrame = st->GainAttn * st->GainFrame_prevfrm; + } + else + { + GainFrame = st->GainFrame_prevfrm; + } + } + + if ( st->extl_brate == WB_TBE_0k35 ) + { + /* convert LSPs back into LP coeffs */ + lsp2a( lpc_wb, lsf_wb, LPC_SHB_ORDER_LBR_WB ); + set_f( lpc_wb + LPC_SHB_ORDER_LBR_WB+1, 0.0f, (LPC_SHB_ORDER_WB - LPC_SHB_ORDER_LBR_WB) ); + } + else + { + /* convert LSPs back into LP coeffs */ + lsp2a( lpc_wb, lsf_wb, LPC_SHB_ORDER_WB ); + } + lpc_wb[0] = 1.0f; + mvr2r( voice_factors, vf_modified, NB_SUBFR16k ); + if( coder_type == VOICED ) + { + for (i = 1; i < NB_SUBFR; i++) + { + vf_modified[i] = 0.8f * voice_factors[i] + 0.2f * voice_factors[i-1]; + } + + if(st->L_frame != L_FRAME ) + { + vf_modified[4] = 0.8f * voice_factors[4] + 0.2f * voice_factors[3]; + } + } + + if(st->use_partial_copy && st->nelp_mode_dec) + { + set_f( vf_modified, 0.0f, NB_SUBFR16k ); + } + + /* From low band excitation, generate highband excitation */ + mvr2r( st->state_syn_shbexc, shaped_wb_excitation, L_SHB_LAHEAD / 4); + + GenShapedWBExcitation( shaped_wb_excitation+ L_SHB_LAHEAD / 4, lpc_wb, exc4kWhtnd, st->mem_csfilt, st->mem_genSHBexc_filt_down_shb, + st->mem_genSHBexc_filt_down_wb2, st->mem_genSHBexc_filt_down_wb3, st->state_lpc_syn, coder_type, + bwe_exc_extended, st->bwe_seed, vf_modified, uv_flag, st->igf ); + + prev_pow = sum2_f( shaped_wb_excitation, L_SHB_LAHEAD/4 ); + curr_pow = sum2_f( shaped_wb_excitation + L_SHB_LAHEAD/4, L_SHB_LAHEAD/4 ); + + if( voice_factors[0] > 0.75f ) + { + curr_pow *= 0.25; + } + + if( prev_pow == 0 ) + { + scale = 0; + } + else + { + scale = sqrt(curr_pow / prev_pow); + } + for (i=0; istate_syn_shbexc, L_SHB_LAHEAD/4 ); + + /* Adjust the subframe and frame gain of the synthesized shb signal */ + /* Scale the shaped excitation */ + ScaleShapedSHB( SHB_OVERLAP_LEN/2, shaped_wb_excitation, st->syn_overlap, GainShape, GainFrame, window_wb, subwin_wb ); + + curr_frame_pow = sum2_f( shaped_wb_excitation, L_FRAME16k/4 ) + 0.001f; + curr_frame_pow = min( curr_frame_pow, FLT_MAX ); + + if( !st->bfi && (st->prev_bfi || st->prev_use_partial_copy) ) + { + if( curr_frame_pow > 2.0f * st->prev_wb_bwe_frame_pow ) + { + scale = root_a_over_b( st->prev_wb_bwe_frame_pow, curr_frame_pow ); + temp = (float) pow(scale, 0.125f); + } + else + { + scale = 1.0f; + temp = 1.0f; + } + + for( j=0; j<8; j++ ) + { + GainShape[2*j] *= scale; + GainShape[2*j+1] *= scale; + for( i=0; iprev_wb_bwe_frame_pow = curr_frame_pow; + + /* generate 16kHz SHB signal (6 - 8 kHz) from 2kHz signal */ + GenWBSynth( shaped_wb_excitation, error , st->state_lsyn_filt_shb, st->state_lsyn_filt_dwn_shb ); + + mvr2r( error + L_FRAME16k - L_SHB_TRANSITION_LENGTH, st->old_tbe_synth, L_SHB_TRANSITION_LENGTH ); + + for ( i=0; ilast_wb_bwe_ener = 0.0f; + for( i=0; ilast_wb_bwe_ener += synth[i]*synth[i]; + } + st->last_wb_bwe_ener = (float)sqrt(st->last_wb_bwe_ener/L_FRAME16k); + + if( st->output_Fs == 32000 ) /* 32kHz sampling rate, but only WB output - interpolate */ + { + Interpolate_allpass_steep( synth, st->mem_resamp_HB, L_FRAME16k, upsampled_synth ); + mvr2r( upsampled_synth, synth, L_FRAME32k ); + } + else if(st->output_Fs == 48000 ) + { + interpolate_3_over_1_allpass( synth, L_FRAME16k, upsampled_synth, st->mem_resamp_HB, allpass_poles_3_ov_2 ); + mvr2r( upsampled_synth, synth, L_FRAME48k ); + } + } + else + { + for ( i = 0; i < LPC_SHB_ORDER_WB; i++ ) + { + lsf_wb[i] = (i + 1)/6.f; + } + GainFrame = 0; + + st->prev_wb_bwe_frame_pow = 0.001f; + } + + /* Update previous frame parameters for FEC */ + if( st->extl_brate == WB_TBE_0k35 ) + { + mvr2r( lsf_wb, st->lsp_prevfrm, LPC_SHB_ORDER_LBR_WB ); + } + else + { + mvr2r( lsf_wb, st->lsp_prevfrm, LPC_SHB_ORDER_WB ); + } + st->GainFrame_prevfrm = GainFrame; + + if( !st->bfi ) + { + st->GainAttn = 1.0f; + } + + return; +} + +/*-------------------------------------------------------------------* + * swb_tbe_dec() + * + * SWB TBE decoder, 6 - 14 kHz (or 7.5 - 15.5 kHz) band decoding module + *-------------------------------------------------------------------*/ + +void swb_tbe_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const short coder_type, /* i : coding type */ + const float *bwe_exc_extended,/* i : bandwidth extended excitation */ + const float voice_factors[], /* i : voicing factors */ + const float old_syn_12k8_16k[],/*i : low band synthesis*/ + float *White_exc16k, /* o : shaped white excitation for the FB TBE */ + float *synth, /* o : SHB synthesis/final synthesis */ + float *pitch_buf +) +{ + short i, j; + short stemp; + float shaped_shb_excitation [ L_FRAME16k + L_SHB_LAHEAD ]; + float lsf_shb[LPC_SHB_ORDER], lpc_shb[LPC_SHB_ORDER + 1], GainShape[NUM_SHB_SUBFR], GainFrame; + float error[L_FRAME32k]; + float ener; + short is_fractive; + float prev_pow, curr_pow, scale; + float curr_frame_pow, temp; + float GainShapeTemp[NUM_SHB_SUBFR/4], GainGrad0[3], GainGrad1[3], GainGradFEC[4]; + float vf_modified[NB_SUBFR16k]; + float f, inc; + float GainFrame_prevfrm; + float tilt_swb_fec; + float prev_ener_ratio; + float lsp_shb_1[LPC_SHB_ORDER], lsp_shb_2[LPC_SHB_ORDER], lsp_temp[LPC_SHB_ORDER]; + float lpc_shb_sf[4*(LPC_SHB_ORDER+1)]; + const float *ptr_lsp_interp_coef; + float shb_ener_sf; + float shb_res_gshape[NB_SUBFR16k]; + float mixFactors; + short vind; + float shb_res_dummy[L_FRAME16k]; + float shaped_shb_excitationTemp[L_FRAME16k]; + float ener_tmp[NUM_SHB_SUBGAINS]; + float GainShape_tmp[NUM_SHB_SUBGAINS]; + float pitch; + short l_subframe; + float formant_fac; + float synth_scale; + float lsf_diff[LPC_SHB_ORDER], w[LPC_SHB_ORDER]; + float refl[M]; + float tilt_para; + + /* initializations */ + GainFrame = 0.0f; + mixFactors = 0.0f; + shb_ener_sf = 0.0f; + set_f( shaped_shb_excitationTemp, 0.0f, L_FRAME16k ); + st->shb_dtx_count = 0; + is_fractive = 0; + + /* find tilt */ + calc_tilt_bwe( old_syn_12k8_16k, &tilt_swb_fec, L_FRAME); + + if( st->bfi && st->clas_dec != UNVOICED_CLAS ) + { + tilt_swb_fec = st->tilt_swb_fec; + } + /* WB/SWB bandwidth switching */ + if( (st->tilt_wb > 5 && st->clas_dec == UNVOICED_CLAS) || st->tilt_wb > 10 ) + { + if( (st->prev_fractive == 0 + && st->prev_enerLH < 2.0f*st->enerLH && st->prev_enerLH > 0.5f*st->enerLH + && st->prev_enerLL < 2.0f*st->enerLL && st->prev_enerLL > 0.5f*st->enerLL ) + || (st->prev_fractive == 1 && st->prev_enerLH > 3.0f*st->enerLH) + || (st->enerLL > 1.5f*st->enerLH && st->tilt_wb < 10.0f) ) + { + is_fractive = 0; + } + else + { + is_fractive = 1; + } + } + + /* WB/SWB bandwidth switching */ + if( st->bws_cnt > 0 ) + { + f = 1.0f/22.0f; + inc = 1.0f/22.0f; + + if ( is_fractive == 1 ) + { + mvr2r(lsf_tab, st->lsp_prevfrm, LPC_SHB_ORDER); + } + else + { + for (i=0; ilsp_prevfrm[i] = f; + f += inc; + } + } + if( (st->last_extl != SWB_TBE && st->last_extl != FB_TBE && !(st->prev_enerLH < 2.0f*st->enerLH && st->prev_enerLH > 0.5f*st->enerLH)) + || st->last_core != ACELP_CORE || (st->last_core == ACELP_CORE && labs(st->last_core_brate - st->core_brate) > 3600) || (is_fractive ^ st->prev_fractive) == 1 ) + { + set_f( GainShape, 0.3536f, NUM_SHB_SUBFR ); + } + else + { + st->prev_GainShape = (st->prev_GainShape > 0.3536f) ? 0.353f : st->prev_GainShape; + set_f( GainShape, st->prev_GainShape, NUM_SHB_SUBFR ); + } + + /* this never happens */ + mvr2r( st->lsp_prevfrm, lsf_shb, LPC_SHB_ORDER ); + set_f( shb_res_gshape, 0.2f, NB_SUBFR16k ); + } + else + { + if ( st->last_extl != SWB_TBE && st->last_extl != FB_TBE ) + { + f = 1.0f/22.0f; + inc = 1.0f/22.0f; + for (i=0; ilsp_prevfrm[i] = f; + f += inc; + } + } + + if( !st->bfi ) + { + if( st->use_partial_copy ) + { + if(st->last_extl != SWB_TBE) + { + st->GainFrame_prevfrm = 0; + f = 1.0f/22.0f; + inc = 1.0f/22.0f; + for (i=0; ilsp_prevfrm[i] = f; + f += inc; + } + } + mvr2r( st->lsp_prevfrm, lsf_shb, LPC_SHB_ORDER ); + set_f( GainShape, RECIP_ROOT_EIGHT, NUM_SHB_SUBFR ); + + if( st->rf_frame_type == RF_NELP ) + { + /* Frame gain */ + GainFrame = usdequant(st->rf_indx_tbeGainFr, SHB_GAIN_QLOW, SHB_GAIN_QDELTA); + GainFrame = (float) pow(10.0, GainFrame); + if( st->core == ACELP_CORE && st->last_core == ACELP_CORE && !st->prev_use_partial_copy + && st->prev_coder_type == UNVOICED && GainFrame != st->GainFrame_prevfrm && st->next_coder_type != GENERIC && st->last_extl == SWB_TBE ) + { + GainFrame = 0.2f*GainFrame + 0.8f*st->GainFrame_prevfrm; + } + } + else + { + temp = 0.0f; + /* Frame gain */ + switch (st->rf_indx_tbeGainFr) + { + case 0: + GainFrame = 0.5f; + if (st->GainFrame_prevfrm <= 1.25) + { + temp = 0.8f; + } + break; + case 1: + GainFrame = 2.0f; + if (st->GainFrame_prevfrm > 1.25 && st->GainFrame_prevfrm <= 3) + { + temp = 0.8f; + } + break; + case 2: + GainFrame = 4.0f; + if (st->GainFrame_prevfrm > 3 && st->GainFrame_prevfrm <= 6) + { + temp = 0.8f; + } + break; + case 3: + GainFrame = 8.0f; + if (st->GainFrame_prevfrm > 6 && st->GainFrame_prevfrm <= 16) + { + temp = 0.8f; + } + break; + default: + fprintf(stderr, "RF SWB-TBE gain bits not supported."); + } + if(st->last_extl == SWB_TBE) + { + GainFrame = (1 - temp)*GainFrame + temp*(st->GainFrame_prevfrm); + } + + if( st->core == ACELP_CORE && st->last_core == ACELP_CORE ) + { + if( !st->prev_use_partial_copy && st->last_coder_type == VOICED && st->rf_frame_type == RF_GENPRED && GainFrame > 8.0f && GainFrame < 11.67f ) + { + GainFrame *= 0.3f; + } + } + } + } + else + { + /* de-quantization */ + dequantizeSHBparams( st, st->extl, st->extl_brate, lsf_shb, GainShape, &GainFrame, &stemp, &shb_ener_sf, shb_res_gshape, &mixFactors ); + } + } + else + { + mvr2r( st->lsp_prevfrm, lsf_shb, LPC_SHB_ORDER ); + + if( st->codec_mode == MODE1 ) + { + /* the previous frame gainshape gradient and the gainshape gradient pattern for the current frame */ + for(j=0; j<3; j++) + { + GainGrad0[j] = st->GainShape_Delay[j+1] - st->GainShape_Delay[j]; + GainGrad1[j] = st->GainShape_Delay[j+5] - st->GainShape_Delay[j+4]; + GainGradFEC[j+1] = GainGrad0[j]*0.4f + GainGrad1[j]*0.6f; + } + + /* gradient for the first gainshape */ + if( ( GainGrad1[2] > 2 * GainGrad1[1] && GainGrad1[1] > 2 * GainGrad1[0] ) || + ( GainGrad1[2] < 2 * GainGrad1[1] && GainGrad1[1] < 2 * GainGrad1[0] ) ) + { + GainGradFEC[0] = GainGrad1[1] * 0.1f + GainGrad1[2] * 0.9f; + } + else + { + GainGradFEC[0] = GainGrad1[0] * 0.2f + GainGrad1[1] * 0.3f + GainGrad1[2] * 0.5f; + } + + /* get the first gainshape template */ + if( (st->prev_coder_type == UNVOICED || st->last_good == UNVOICED_CLAS) && GainGradFEC[0] > 0 ) + { + GainShapeTemp[0] = st->GainShape_Delay[7] + GainGradFEC[0]; + } + else if( GainGradFEC[0] > 0 ) + { + GainShapeTemp[0] = st->GainShape_Delay[7] + GainGradFEC[0] * 0.5f; + } + else + { + GainShapeTemp[0] = st->GainShape_Delay[7]; + } + + /*Get the second the third and the fourth gainshape template*/ + if( ( GainGrad1[2] > 10.0f * GainGrad1[1] ) && GainGrad1[1] > 0 ) + { + for(i=1; i 10.0f * GainGrad1[1] ) && GainGrad1[1] < 0 ) + { + for( i=1; iprev_coder_type == UNVOICED || st->last_good == UNVOICED_CLAS) && st->nbLostCmpt == 1 ) + { + for( i=0; iGainAttn *= 0.95f; + } + else if( st->prev_coder_type == UNVOICED || st->last_good == UNVOICED_CLAS ) + { + for( i=0; iGainAttn *= 0.95f; + } + else if( st->nbLostCmpt > 1 ) + { + for( i=0; iGainAttn *= 0.5f; + } + else + { + for( i=0; iGainAttn *= 0.85f; + } + + GainFrame = st->GainAttn * st->GainFrame_prevfrm; + } + else + { + for( i=0; icummulative_damping * st->GainShape_Delay[4+i]; + } + } + + if( tilt_swb_fec > 8 ) + { + if( st->nbLostCmpt == 1 ) + { + GainFrame = 0.6* st->cummulative_damping * st->GainFrame_prevfrm; + } + else if( st->nbLostCmpt == 2 ) + { + GainFrame = 0.35* st->cummulative_damping * st->GainFrame_prevfrm; + } + else + { + GainFrame = 0.2* st->cummulative_damping * st->GainFrame_prevfrm; + } + } + else + { + GainFrame = st->GainFrame_prevfrm; /* gain locking */ + } + } + + if( st->total_brate == ACELP_24k40 || st->total_brate == ACELP_32k ) + { + if( st->codec_mode == MODE1 ) + { + scale = st->prev1_shb_ener_sf/sqrt((st->prev2_shb_ener_sf * st->prev3_shb_ener_sf) +0.0001); + scale = st->prev_res_shb_gshape * min(scale, 1.0f); + if(st->prev2_shb_ener_sf > 2.0f * st->prev1_shb_ener_sf || st->prev3_shb_ener_sf > 2.0f * st->prev2_shb_ener_sf) + { + shb_ener_sf = 0.5f * scale * st->prev1_shb_ener_sf; + if(st->nbLostCmpt > 1) + { + shb_ener_sf *= 0.5f; + } + } + else + { + shb_ener_sf = scale * scale * st->prev1_shb_ener_sf; + } + } + else + { + if( st->prev2_shb_ener_sf > 2.0f * st->prev1_shb_ener_sf || st->prev3_shb_ener_sf > 2.0f * st->prev2_shb_ener_sf ) + { + shb_ener_sf = 0.5f* st->cummulative_damping * st->prev1_shb_ener_sf; + } + else + { + shb_ener_sf = st->cummulative_damping * st->prev1_shb_ener_sf; + } + } + } + + shb_ener_sf = max(shb_ener_sf, 1.0f); + mixFactors = st->prev_mixFactors; + + if( st->codec_mode == MODE2 ) + { + set_f( shb_res_gshape, 1.0f, NB_SUBFR16k ); + } + else + { + set_f( shb_res_gshape, 0.2f, NB_SUBFR16k ); + } + } + } + + /* get the gainshape delay */ + mvr2r( &st->GainShape_Delay[4], &st->GainShape_Delay[0], NUM_SHB_SUBFR/4 ); + for( i = 0; iGainShape_Delay[i+4] = GainShape[i*4]; + } + + mvr2r( voice_factors, vf_modified, NB_SUBFR16k ); + if( coder_type == VOICED || mean(voice_factors, 4) > 0.4f ) + { + for( i = 1; i < NB_SUBFR; i++ ) + { + vf_modified[i] = 0.8f * voice_factors[i] + 0.2f * voice_factors[i-1]; + } + + if(st->L_frame != L_FRAME ) + { + vf_modified[4] = 0.8f * voice_factors[4] + 0.2f * voice_factors[3]; + } + + } + + if(st->use_partial_copy && st->nelp_mode_dec) + { + set_f( vf_modified, 0.0f, NB_SUBFR16k ); + } + + /* SHB LSF from current frame; and convert to LSP for interpolation */ + lsf2lsp( lsf_shb, lsp_shb_2, LPC_SHB_ORDER, 1.0f ); + + if( st->last_extl == SWB_TBE || st->last_extl == FB_TBE ) + { + /* SHB LSP values from prev. frame for interpolation */ + mvr2r( st->swb_lsp_prev_interp, lsp_shb_1, LPC_SHB_ORDER ); + } + else + { + /* Use current frame's LSPs; in effect no interpolation */ + mvr2r( lsp_shb_2, lsp_shb_1, LPC_SHB_ORDER ); + } + if( st->bws_cnt == 0 && st->bws_cnt1 == 0 && st->prev_use_partial_copy == 0 && st->use_partial_copy == 0) + { + lsf_diff[0] = lsf_diff[LPC_SHB_ORDER-1] = 0.5f; + for(i=1; i<(LPC_SHB_ORDER-1); i++) + { + lsf_diff[i] = lsf_shb[i] - lsf_shb[i-1]; + } + + a2rc (st->cur_sub_Aq+1, refl, (short) M); + tilt_para = 6.6956f * (1.0f + refl[0]) * (1.0f + refl[0]) - 3.8714f * (1.0f + refl[0]) + 1.3041f; + if( st->last_extl != SWB_TBE && st->last_extl != FB_TBE ) + { + for( i=1; iprev_lsf_diff[i-1] = 0.5f*lsf_diff[i]; + } + } + + if( st->total_brate <= ACELP_16k40 ) + { + if(!(st->prev_tilt_para > 5.0f && (coder_type == TRANSITION || tilt_para < 1.0f)) && !(((st->prev_tilt_para < 3.0f && st->prev_coder_type >= VOICED)) && tilt_para > 5.0f)) + { + for( i = 1; i < (LPC_SHB_ORDER-1); i++ ) + { + if( lsf_diff[i] < 0 || st->prev_lsf_diff[i-1] <= 0 ) /* safety check in case of bit errors */ + { + w[i] = 0; + st->BER_detect = 1; + } + else + { + w[i] = (lsf_diff[i] < st->prev_lsf_diff[i-1]) ? min(max(0.8f*lsf_diff[i]/st->prev_lsf_diff[i-1], 0.5f), 1.0f) : min(max(0.8f*st->prev_lsf_diff[i-1]/lsf_diff[i], 0.5f), 1.0f); + } + } + w[0] = w[1]; + w[LPC_SHB_ORDER-1] = w[LPC_SHB_ORDER-2]; + + for( i = 0; i < LPC_SHB_ORDER; i++ ) + { + lsp_temp[i] = lsp_shb_1[i]*(1.0f-w[i]) + lsp_shb_2[i]*w[i]; + } + } + else + { + mvr2r( lsp_shb_2, lsp_temp, LPC_SHB_ORDER ); + } + + /* convert from lsp to lsf */ + lsp2lsf( lsp_temp, lsf_shb, LPC_SHB_ORDER, 1.0f ); + } + mvr2r( lsf_diff+1, st->prev_lsf_diff, LPC_SHB_ORDER-2 ); + st->prev_tilt_para = tilt_para; + } + else + { + mvr2r(lsp_shb_2, lsp_temp, LPC_SHB_ORDER); + } + + if( st->total_brate == ACELP_24k40 || st->total_brate == ACELP_32k ) + { + /* SHB LSP interpolation */ + ptr_lsp_interp_coef = interpol_frac_shb; + for( j = 0; j < 4; j++ ) + { + for( i = 0; i < LPC_SHB_ORDER; i++ ) + { + lsp_temp[i] = lsp_shb_1[i]*(*ptr_lsp_interp_coef) + lsp_shb_2[i]*(*(ptr_lsp_interp_coef+1)); + } + ptr_lsp_interp_coef += 2; + + /* convert from lsp to lsf */ + lsp2lsf( lsp_temp, lsp_temp, LPC_SHB_ORDER, 1.0f ); + + /* convert lsf to lpc for SHB synthesis */ + lsp2a( lpc_shb_sf+j*(LPC_SHB_ORDER+1), lsp_temp, LPC_SHB_ORDER ); + lpc_shb_sf[j*(LPC_SHB_ORDER+1)] = 1.0f; + } + } + + /* Save the SWB LSP values from current frame for interpolation */ + mvr2r( lsp_shb_2, st->swb_lsp_prev_interp, LPC_SHB_ORDER ); + + /* save the shb_ener and mixFactor values */ + st->prev3_shb_ener_sf = st->prev2_shb_ener_sf; + st->prev2_shb_ener_sf = st->prev1_shb_ener_sf; + st->prev1_shb_ener_sf = shb_ener_sf; + st->prev_res_shb_gshape = shb_res_gshape[4]; + st->prev_mixFactors = mixFactors; + + /* SWB CNG/DTX - update memories */ + mvr2r( st->lsp_shb_prev, st->lsp_shb_prev_prev, LPC_SHB_ORDER ); + mvr2r( lsf_shb, st->lsp_shb_prev, LPC_SHB_ORDER ); + + /* convert LSPs back into LP coeffs */ + lsp2a( lpc_shb, lsf_shb, LPC_SHB_ORDER ); + lpc_shb[0] = 1.0; + vind = (short)(mixFactors*8.0f); + + /* Determine formant PF strength */ + formant_fac = swb_formant_fac( lpc_shb[1], &st->tilt_mem ); + if(st->total_brate > ACELP_32k) + { + for( j = 0; j < 4; j++ ) + { + mvr2r(lpc_shb, &lpc_shb_sf[j*(LPC_SHB_ORDER+1)], LPC_SHB_ORDER+1); + } + } + + /* From low band excitation, generate highband excitation */ + mvr2r( st->state_syn_shbexc, shaped_shb_excitation, L_SHB_LAHEAD); + GenShapedSHBExcitation( shaped_shb_excitation + L_SHB_LAHEAD, lpc_shb, White_exc16k, st->mem_csfilt, st->mem_genSHBexc_filt_down_shb, st->state_lpc_syn, + coder_type, bwe_exc_extended, st->bwe_seed, vf_modified, st->extl, &(st->tbe_demph), &(st->tbe_premph), lpc_shb_sf, + &shb_ener_sf, shb_res_gshape, shb_res_dummy, &vind, formant_fac, st->fb_state_lpc_syn, &(st->fb_tbe_demph), st->total_brate , st->prev_bfi); + + for( i=0; imem_stp_swb, + st->ptr_mem_stp_swb, &(st->gain_prec_swb), st->mem_zero_swb, formant_fac ); + } + + mvr2r( shaped_shb_excitationTemp, &shaped_shb_excitation[L_SHB_LAHEAD], L_FRAME16k ); + prev_pow = sum2_f( shaped_shb_excitation, L_SHB_LAHEAD + 10 ); + curr_pow = sum2_f( shaped_shb_excitation + L_SHB_LAHEAD + 10, L_SHB_LAHEAD + 10 ); + + if( voice_factors[0] > 0.75f ) + { + curr_pow *= 0.25; + } + + if( prev_pow == 0 ) + { + scale = 0; + } + else + { + scale = sqrt(curr_pow/prev_pow); + } + for( i=0; istate_syn_shbexc, L_SHB_LAHEAD ); + l_subframe = L_FRAME16k/NUM_SHB_SUBGAINS; + ener = EPSILON; + for(i=0; ibws_cnt > 0 ) + { + ener *= 0.35f; + + if( st->tilt_swb > 8 ) + { + st->prev_fractive = 1; + } + + if( is_fractive == 0 ) + { + if( st->tilt_wb > 1.0 ) + { + st->tilt_wb = 1.0f; + } + else if( st->tilt_wb < 0.5 ) + { + st->tilt_wb = 0.5f; + } + + if( st->prev_fractive == 1 && st->tilt_wb > 0.5 ) + { + st->tilt_wb = 0.5f; + } + } + else + { + if ( st->tilt_wb > 4) + { + if ( st->prev_fractive == 0) + { + st->tilt_wb = 4; + } + else + { + st->tilt_wb = 8; + } + } + else + { + st->tilt_wb *= 2; + } + } + + if( ener != 0 ) + { + if( ener*st->tilt_wb > st->enerLH ) + { + st->tilt_wb = 0.5f*st->enerLH/ener; + } + else if( ener*st->tilt_wb < 0.05f*st->enerLH && is_fractive == 1 ) + { + st->tilt_wb = 0.25f*st->enerLH/ener; + } + + GainFrame_prevfrm = st->prev_ener_shb/ener; + } + else + { + GainFrame_prevfrm = 0; + } + + if ( is_fractive == 1) + { + GainFrame = 8.0f*st->tilt_wb; + } + else + { + GainFrame = 2.0f*st->tilt_wb; + } + + if ( (is_fractive & st->prev_fractive) == 1 && GainFrame > GainFrame_prevfrm ) + { + GainFrame = 0.2f*GainFrame + 0.8f*GainFrame_prevfrm; + } + else + { + if ( (st->prev_enerLH < 2.0f*st->enerLH && st->prev_enerLH > 0.5f*st->enerLH ) + && (st->prev_enerLL < 2.0f*st->enerLL && st->prev_enerLL > 0.5f*st->enerLL) + && (is_fractive ^ st->prev_fractive) == 0) + { + GainFrame = 0.5f*GainFrame + 0.5f*GainFrame_prevfrm; + } + else + { + if ( is_fractive == 0 && st->prev_fractive == 1 ) + { + GainFrame = (1.0f-0.1f*GainFrame)*GainFrame + 0.1f*GainFrame*GainFrame_prevfrm; + } + else + { + GainFrame = 0.5f*GainFrame + 0.5f*GainFrame_prevfrm; + } + } + } + + GainFrame *= ((float)N_WS2N_FRAMES - (float)st->bws_cnt) / (float)N_WS2N_FRAMES; + } + else + { + if( st->bws_cnt1 > 0 ) + { + GainFrame *= (float)st->bws_cnt1 / (float)N_WS2N_FRAMES; + } + + if( st->nbLostCmpt == 1 ) + { + prev_ener_ratio = st->prev_ener_shb/ener; + + if( st->clas_dec != UNVOICED_CLAS && st->clas_dec != UNVOICED_TRANSITION && st->tilt_swb_fec < 8.0 && + ((st->enerLL > 0.5f*st->prev_enerLL && st->enerLL < 2.0f*st->prev_enerLL)|| (st->enerLH > 0.5f*st->prev_enerLH && st->enerLH < 2.0f*st->prev_enerLH))) + { + if( prev_ener_ratio > 4.0f * GainFrame ) + { + GainFrame = 0.4f * prev_ener_ratio + 0.6f * GainFrame; + } + else if( prev_ener_ratio > 2.0f * GainFrame ) + { + GainFrame = 0.8f * prev_ener_ratio + 0.2f * GainFrame; + } + else + { + GainFrame = 0.2f * prev_ener_ratio + 0.8f * GainFrame; + } + + if( tilt_swb_fec > st->tilt_swb_fec ) + { + GainFrame *= st->tilt_swb_fec > 0 ? (min(5.0f,tilt_swb_fec/st->tilt_swb_fec)) : 1.0f; + } + + } + else if( (st->clas_dec != UNVOICED_CLAS || st->tilt_swb_fec > 8.0) && prev_ener_ratio > 4.0f * GainFrame && + (st->enerLL > 0.5f*st->prev_enerLL || st->enerLH > 0.5f*st->prev_enerLH) ) + { + GainFrame = 0.2f * prev_ener_ratio + 0.8f * GainFrame; + } + } + else if( st->nbLostCmpt > 1 ) + { + prev_ener_ratio = st->prev_ener_shb/ener; + if((prev_ener_ratio > 4.0 * GainFrame) && ((st->codec_mode == MODE1 && st->enerLL > st->prev_enerLL && st->enerLH > st->prev_enerLH) || st->codec_mode == MODE2)) + { + if( tilt_swb_fec > 10.0f && st->tilt_swb_fec >10.0f ) + { + GainFrame = min((prev_ener_ratio *0.8f + GainFrame * 0.2f),4.0f * GainFrame); + } + else + { + GainFrame = min((prev_ener_ratio *0.5f + GainFrame * 0.5f),4.0f * GainFrame); + } + } + else if((prev_ener_ratio > GainFrame) &&((st->codec_mode == MODE1 && st->enerLL > st->prev_enerLL && st->enerLH > st->prev_enerLH) || st->codec_mode == MODE2)) + { + if( tilt_swb_fec > 10.0f && st->tilt_swb_fec >10.0f ) + { + GainFrame = 0.5f * prev_ener_ratio + 0.5f * GainFrame; + } + else + { + GainFrame = 0.2f * prev_ener_ratio + 0.8f * GainFrame; + } + } + } + } + + st->prev_fractive = is_fractive; + + /* Adjust the subframe and frame gain of the synthesized shb signal */ + /* Scale the shaped excitation */ + if( st->L_frame == L_FRAME ) + { + pitch = 0.25f*sum_f(pitch_buf, 4); + } + else + { + pitch = 0.2f*sum_f(pitch_buf, 5); + } + + if( ((st->total_brate >= ACELP_24k40 && st->prev_coder_type == coder_type && coder_type != UNVOICED) + || (st->total_brate <= ACELP_16k40 && (st->prev_coder_type == coder_type || (st->prev_coder_type == VOICED && coder_type == GENERIC) || (st->prev_coder_type == GENERIC && coder_type == VOICED)))) + && pitch > 70 && st->extl < FB_TBE) + { + for( i=0; i st->prev_ener*st->prev_GainShape ) + { + GainShape_tmp[i] = 0.5f*(st->prev_ener*st->prev_GainShape/ener_tmp[i] + GainShape_tmp[i]); + } + st->prev_ener = ener_tmp[i]; + st->prev_GainShape = GainShape_tmp[i]; + } + for( i=0; isyn_overlap,GainShape,GainFrame,window_shb,subwin_shb ); + + curr_frame_pow = sum2_f( shaped_shb_excitation, L_FRAME16k ) + 0.001f; + curr_frame_pow = min( curr_frame_pow, FLT_MAX ); + + if( !st->bfi && (st->prev_bfi || st->prev_use_partial_copy ) ) + { + + if( ( curr_frame_pow > 2.0f * st->prev_swb_bwe_frame_pow ) && + ( curr_frame_pow < 30.0f * st->prev_swb_bwe_frame_pow ) && + st->prev_coder_type == UNVOICED ) + { + scale = sqrt( st->prev_swb_bwe_frame_pow/curr_frame_pow ); + if ((curr_frame_pow) == 0) + { + scale = 0; + } + + temp = (float)pow( scale, 0.125f ); + } + else + { + scale = 1.0f; + temp = 1.0f; + } + + for( j=0; j<8; j++ ) + { + GainShape[2*j] *= scale; + GainShape[2*j+1] *= scale; + for( i=0; ibfi ) + { + scale = 1.0f; + temp = 1.0f; + if( st->nbLostCmpt == 1 ) + { + if( curr_frame_pow > st->prev_swb_bwe_frame_pow && + st->prev_coder_type != UNVOICED && + st->last_good != UNVOICED_CLAS ) + { + scale = sqrt( st->prev_swb_bwe_frame_pow/curr_frame_pow ); + if ((curr_frame_pow) == 0) + { + scale = 0; + } + temp = (float) pow( scale, 0.125f ); + } + else if( curr_frame_pow < 0.5f *st->prev_swb_bwe_frame_pow && st->nbLostCmpt == 1 && + (st->enerLL > 0.5 * st->prev_enerLL || st->enerLH > 0.5 *st->prev_enerLH) && + (st->prev_coder_type == UNVOICED || st->last_good == UNVOICED_CLAS || st->tilt_swb_fec > 5.0f) ) + { + scale = sqrt(st->prev_swb_bwe_frame_pow / curr_frame_pow); + if ((curr_frame_pow) == 0) + { + scale = 0; + } + temp = (float) pow(scale, 0.125f); + } + } + else if ( st->nbLostCmpt > 1 ) + { + if( curr_frame_pow > st->prev_swb_bwe_frame_pow ) + { + scale = sqrt( st->prev_swb_bwe_frame_pow / curr_frame_pow ); + if ((curr_frame_pow) == 0) + { + scale = 0; + } + temp = (float) pow( scale, 0.125f ); + } + else if( curr_frame_pow < 0.5f *st->prev_swb_bwe_frame_pow && + (st->enerLL > 0.5 * st->prev_enerLL || st->enerLH > 0.5 *st->prev_enerLH) && + (st->prev_coder_type == UNVOICED || st->last_good == UNVOICED_CLAS || st->tilt_swb_fec > 5.0f) ) + { + scale = min(2.0f,sqrt(st->prev_swb_bwe_frame_pow/curr_frame_pow)); + if ((curr_frame_pow) == 0) + { + scale = 0; + } + temp = (float) pow(scale, 0.125f); + } + } + + for( j=0; j<8; j++ ) + { + GainShape[2 * j] *= scale; + GainShape[2 * j + 1] *= scale; + for( i=0; iprev_swb_bwe_frame_pow = curr_frame_pow; + + st->prev_ener_shb = EPSILON; + for( i=0; iprev_ener_shb += shaped_shb_excitation[i] * shaped_shb_excitation[i]; + } + st->prev_ener_shb = (float)sqrt(st->prev_ener_shb/L_FRAME16k); + + for(i=0; iprev_SWB_fenv[i] = (float)sqrt(curr_frame_pow/L_FRAME16k); + } + + /* generate 32kHz SHB synthesis from 12.8(16)kHz signal */ + GenSHBSynth( shaped_shb_excitation, error, st->genSHBsynth_Hilbert_Mem, + st->genSHBsynth_state_lsyn_filt_shb_local, st->L_frame, &(st->syn_dm_phase) ); + + mvr2r( error + L_FRAME32k - L_SHB_TRANSITION_LENGTH, st->old_tbe_synth, L_SHB_TRANSITION_LENGTH ); + + /* resample SHB synthesis (if needed) and scale down */ + synth_scale = (st->codec_mode == MODE1) ? 0.9f : 1.f; + + if( st->output_Fs == 48000 ) + { + if ( st->extl == FB_TBE) + { + for( i=0; iint_3_over_2_tbemem_dec, allpass_poles_3_ov_2 ); + } + + else if( st->output_Fs == 32000 ) + { + for( i=0; ioutput_Fs == 16000 ) + { + for( i=0; imem_resamp_HB_32k, L_FRAME32k, synth ); + } + + /* Update previous frame parameters for FEC */ + mvr2r( lsf_shb, st->lsp_prevfrm, LPC_SHB_ORDER ); + if( st->codec_mode == MODE1 ) + { + st->GainFrame_prevfrm = GainFrame; + st->tilt_swb_fec = tilt_swb_fec; + + if( !st->bfi ) + { + st->GainAttn = 1.0f; + } + } + else + { + if( !st->bfi ) + { + st->tilt_swb_fec = tilt_swb_fec; + st->GainFrame_prevfrm = GainFrame; /* gain locking on lost frame */ + st->GainAttn = 1.0f; + } + } + st->prev_ener = ener_tmp[NUM_SHB_SUBGAINS-1]; + st->prev_GainShape = GainShape[NUM_SHB_SUBFR-1]; + + return; +} + +/*-------------------------------------------------------------------* + * Dequant_lower_LSF() + * + * Dequantized the lower LSFs + *-------------------------------------------------------------------*/ + +static void Dequant_lower_LSF( + const short lsf_idx[], /* i : LSF indices */ + float lsf_q[] /* o : Quantized LSFs */ +) +{ + short i; + + lsf_q[0] = lsf_q_cb[0][lsf_idx[0]]; + for (i = 1; i < NUM_Q_LSF; i++) + { + lsf_q[i] = lsf_q_cb[i][lsf_idx[i]] + lsf_q[i-1]; + } + + return; +} + +/*-------------------------------------------------------------------* + * Map_higher_LSF() + * + * Map the higher LSFs from the lower LSFs + *-------------------------------------------------------------------*/ + +static void Map_higher_LSF( + float lsf_q[], /* i/o : Quantized lower LSFs */ + const float m, /* i : Mirroring point */ + const float grid_in[] /* i : Input LSF smoohthing grid */ +) +{ + float lsf_map[NUM_MAP_LSF]; + float grid[NUM_MAP_LSF]; + float last_q_lsf; + float lsf_smooth[NUM_MAP_LSF]; + float offset; + short i; + float scale; + + for (i = 0; i < NUM_MAP_LSF; i++) + { + lsf_map[i] = 2*m - lsf_q[NUM_MAP_LSF - 1 - i]; + } + + if (m > MAX_LSF/2) + { + offset = lsf_map[0]; + scale = (MAX_LSF - m)/m; + for (i = 0; i < NUM_MAP_LSF; i++) + { + lsf_map[i] = (lsf_map[i] - offset)*scale + offset; + } + } + + last_q_lsf = lsf_q[NUM_Q_LSF - 1]; + scale = MAX_LSF - last_q_lsf; + + for (i = 0; i < NUM_MAP_LSF; i++) + { + grid[i] = grid_in[i]*scale + last_q_lsf; + } + + for (i = 0; i < NUM_MAP_LSF; i++) + { + lsf_smooth[i] = (1 - grid_smoothing[i])*lsf_map[i] + grid_smoothing[i]*grid[i]; + } + + for (i = 0; i < NUM_MAP_LSF; i++) + { + lsf_q[NUM_Q_LSF + i] = lsf_smooth[i]; + } + + return; +} + +/*-------------------------------------------------------------------* + * Map_higher_LSF() + * + * Map the higher LSFs from the lower LSFs + *-------------------------------------------------------------------*/ + +static void Dequant_mirror_point( + const float lsf_q[], /* i/o : Quantized lower LSFs */ + const short m_idx, /* i : Mirror point index */ + float *m /* i : Mirroring point */ +) +{ + *m = mirror_point_q_cb[m_idx] + lsf_q[NUM_Q_LSF - 1]; + + return; +} + +/*-------------------------------------------------------------------* + * dequantizeSHBparams() + * + * Dequantize super highband spectral envolope, temporal gains and frame gain + *-------------------------------------------------------------------*/ + +static void dequantizeSHBparams( + Decoder_State *st, /* i/o: decoder state structure */ + const short extl, /* i : extension layer */ + long extl_brate, /* i : extensiuon layer bitrate */ + float *Q_lsf, /* o : SHB LSF from de-quantization */ + float *Q_subgain, /* o : SHB subframe gains from de-quantization */ + float *Q_framegrain, /* o : SHB frame gain from de-quantization */ + short *uv_flag, /* o : unvoiced flag */ + float *Q_shb_ener_sf, + float *Q_shb_res_gshape, + float *Q_mixFactors +) +{ + short i, j, idxLSF, idxSubGain, idxFrameGain; + float Q_combined_gains[NUM_SHB_SUBFR/4]; + float lsf_q[LPC_SHB_ORDER]; + short lsf_idx[NUM_Q_LSF]; + short m_idx, grid_idx; + float m; + short idx_shb_fr_gain, idx_res_gs[5], idx_mixFac; + + /* LSFs */ + if( extl == WB_TBE ) + { + if ( extl_brate == WB_TBE_0k35 ) + { + idxFrameGain = st->gFrame_WB; + idxLSF = st->lsf_WB; + + mvr2r( lbr_wb_bwe_lsfvq_cbook_2bit + idxLSF*LPC_SHB_ORDER_LBR_WB, Q_lsf, LPC_SHB_ORDER_LBR_WB ); + set_f( Q_subgain, RECIP_ROOT_EIGHT, NUM_SHB_SUBFR/2 ); + mvr2r( SHBCB_FrameGain16 + idxFrameGain, Q_framegrain, 1 ); + } + else + { + /* read the information about UNVOICED frame */ + *uv_flag = (short)get_next_indice( st, 1 ); + + idxSubGain = (short)get_next_indice( st, NUM_BITS_SHB_SUBGAINS ); + idxFrameGain = (short)get_next_indice( st, NUM_BITS_SHB_FrameGain ); + idxLSF = (short)get_next_indice( st, NUM_BITS_WB_LSF ); + + mvr2r( wb_bwe_lsfvq_cbook_8bit + idxLSF*LPC_SHB_ORDER_WB, Q_lsf, LPC_SHB_ORDER_WB ); + mvr2r( HBCB_SubGain5bit + idxSubGain * NUM_SHB_SUBFR/4, Q_combined_gains, NUM_SHB_SUBFR/4 ); + + for( i=0; icodec_mode == MODE2 ) + { + idxSubGain = st->idxSubGains; + idxFrameGain = st->idxFrameGain; + } + else + { + idxSubGain = (short)get_next_indice( st, NUM_BITS_SHB_SUBGAINS ); + idxFrameGain = (short)get_next_indice( st, NUM_BITS_SHB_FRAMEGAIN ); + } + + if( st->total_brate == ACELP_24k40 || st->total_brate == ACELP_32k ) + { + if( st->codec_mode == MODE2 ) + { + idx_shb_fr_gain = st->idx_shb_fr_gain; + } + else + { + idx_shb_fr_gain = (short)get_next_indice( st, NUM_BITS_SHB_ENER_SF ); + } + *Q_shb_ener_sf = usdequant(idx_shb_fr_gain, 0, 0.042f); + *Q_shb_ener_sf = (float)pow(10.0, *Q_shb_ener_sf ); + + for( i=0; i<5; i++ ) + { + if( st->codec_mode == MODE2 ) + { + idx_res_gs[i] = st->idx_res_gs[i]; + } + else + { + idx_res_gs[i] = (short)get_next_indice( st, NUM_BITS_SHB_RES_GS ); + } + Q_shb_res_gshape[i] = usdequant(idx_res_gs[i], 0.125f, 0.125f); + } + + if( st->codec_mode == MODE2 ) + { + idx_mixFac = st->idx_mixFac; + } + else + { + idx_mixFac = (short)get_next_indice( st, NUM_BITS_SHB_VF ); + } + *Q_mixFactors = usdequant(idx_mixFac, 0.125f, 0.125f); + } + else + { + *Q_shb_ener_sf = 0; + *Q_mixFactors = 0; + set_f(Q_shb_res_gshape, 0, 5); + } + + + if( st->rf_flag == 0 && !((st->total_brate == ACELP_9k60) || ( (st->total_brate == 0) && ((st->last_total_brate == ACELP_9k60) || (st->last_total_brate == ACELP_13k20 && st->rf_flag_last)) )) ) + { + /* LSFs */ + if( extl_brate == SWB_TBE_1k6 || extl_brate == FB_TBE_1k8 || extl_brate == SWB_TBE_2k8 || extl_brate == FB_TBE_3k0 ) + { + for( i = 0; i < NUM_Q_LSF; i++ ) + { + if( st->codec_mode == MODE2 ) + { + lsf_idx[i] = st->lsf_idx[i]; + } + else + { + lsf_idx[i] = (short)get_next_indice(st, lsf_q_num_bits[i]); + } + } + } + Dequant_lower_LSF( lsf_idx, lsf_q ); + if( st->codec_mode == MODE2 ) + { + m_idx = st->m_idx; + grid_idx = st->grid_idx; + } + else + { + m_idx = (short)get_next_indice( st, MIRROR_POINT_BITS ); + grid_idx = (short)get_next_indice( st, NUM_LSF_GRID_BITS ); + } + + Dequant_mirror_point(lsf_q, m_idx, &m); + + /* safety check in case of bit errors */ + if( m > MAX_LSF ) + { + st->BER_detect = 1; + m = MAX_LSF; + } + + Map_higher_LSF(lsf_q, m, lsf_grid[grid_idx]); + + for( i = 0; i < LPC_SHB_ORDER; i++ ) + { + /* safety check in case of bit errors */ + if ( lsf_q[LPC_SHB_ORDER - 1 - i] > MAX_LSF ) + { + st->BER_detect = 1; + lsf_q[LPC_SHB_ORDER - 1 - i] = MAX_LSF; + } + Q_lsf[i] = 0.5f - lsf_q[LPC_SHB_ORDER - 1 - i]; + } + } + else + { + set_s(lsf_idx, 0, 5); + mvs2s(st->lsf_idx, lsf_idx, 5); + grid_idx = 0; + m_idx = 0; + mvr2r( swb_tbe_lsfvq_cbook_8b + lsf_idx[0]*LPC_SHB_ORDER, Q_lsf, LPC_SHB_ORDER ); + } + space_lsfs( Q_lsf, LPC_SHB_ORDER ); + + /* Dequantize subgain indices */ + j = idxSubGain*NUM_SHB_SUBGAINS; + for ( i = 0; i < NUM_SHB_SUBGAINS; i++) + { + Q_subgain[i] = (float) pow(10.0, SHBCB_SubGain5bit[j++]); + } + + for (i=NUM_SHB_SUBFR-1; i>=0; i--) + { + Q_subgain[i] = Q_subgain[i*NUM_SHB_SUBGAINS/NUM_SHB_SUBFR]; + } + + /* Frame gain */ + *Q_framegrain = usdequant(idxFrameGain, SHB_GAIN_QLOW, SHB_GAIN_QDELTA); + *Q_framegrain = (float) pow(10.0, *Q_framegrain); + } + + return; +} +/*-------------------------------------------------------------------* + * fb_tbe_dec() + * + * FB TBE decoder, 14(resp. 15.5) - 20 kHz band decoding module + *-------------------------------------------------------------------*/ +void fb_tbe_dec( + Decoder_State *st, /* i/o: encoder state structure */ + const float fb_exc[], /* i : FB excitation from the SWB part */ + float *hb_synth /* o : high-band synthesis */ +) + +{ + short i; + float ratio = 0, fb_exc_energy = 0; + float fb_synth[L_FRAME48k]; + + /* decode FB slope information */ + if ( st->extl == FB_TBE && !st->bfi ) + { + if( st->codec_mode == MODE2 ) + { + i = st->idxGain; + } + else + { + i = (short)get_next_indice( st, 4 ); + } + ratio = (float)(1 << i); + } + else if ( st->extl == FB_TBE && st->bfi ) + { + ratio = st->prev_fbbwe_ratio; + } + + fb_exc_energy = sum2_f(fb_exc,L_FRAME16k); + + /* FB TBE synthesis */ + synthesise_fb_high_band( fb_exc,fb_synth,fb_exc_energy,ratio, st->L_frame, st->bfi, &(st->prev_fbbwe_ratio), st->fbbwe_hpf_mem ); + + /* add the fb_synth component to the hb_synth component */ + v_add( hb_synth, fb_synth, hb_synth, L_FRAME48k ); + + return; +} + + +/*---------------------------------------------------------------------* + * tbe_read_bitstream() + * + * Read TBE bitstream and populate the parameters for TD-BWE decoder. + *---------------------------------------------------------------------*/ +void tbe_read_bitstream( + Decoder_State *st +) +{ + short i; + + if ( (st->rf_flag || st->total_brate == ACELP_9k60) && st->bwidth == WB) + { + /* WB LSF */ + st->lsf_WB = get_next_indice(st, NUM_BITS_LBR_WB_LSF); + + /* WB frame gain */ + st->gFrame_WB = get_next_indice(st, NUM_BITS_SHB_FrameGain_LBR_WB); + } + else if( st->total_brate >= ACELP_9k60 && st->total_brate <= ACELP_32k && (st->bwidth == SWB || st->bwidth == FB) ) + { + if(st->rf_flag == 0 && st->total_brate > ACELP_9k60) + { + for (i=0; ilsf_idx[i] = get_next_indice(st, lsf_q_num_bits[i]); + } + st->m_idx = get_next_indice(st, MIRROR_POINT_BITS); + st->grid_idx = get_next_indice(st, NUM_LSF_GRID_BITS); + } + else + { + st->lsf_idx[0] = get_next_indice(st, 8); + st->m_idx = 0; + st->grid_idx = 0; + } + /* shape gains */ + st->idxSubGains = get_next_indice(st, NUM_BITS_SHB_SUBGAINS); + + /* frame gain */ + st->idxFrameGain = get_next_indice(st, NUM_BITS_SHB_FRAMEGAIN); + + if( st->total_brate >= ACELP_24k40 ) + { + /* sub frame energy*/ + st->idx_shb_fr_gain = get_next_indice(st, NUM_BITS_SHB_ENER_SF); + + /* gain shapes residual */ + for (i = 0; i < NB_SUBFR16k; i++) + { + st->idx_res_gs[i] = get_next_indice(st, NUM_BITS_SHB_RES_GS); + } + + /* voicing factor */ + st->idx_mixFac = get_next_indice(st, NUM_BITS_SHB_VF); + } + + if( st->tec_tfa == 1 ) + { + st->tec_flag = get_next_indice(st, BITS_TEC); + st->tfa_flag = get_next_indice(st, BITS_TFA); + if( st->tfa_flag && st->tec_flag ) + { + st->tec_flag = 2; + st->tfa_flag = 0; + } + + + } + else + { + st->tec_flag = 0; + st->tfa_flag = 0; + } + } + + if( st->bwidth == FB ) + { + st->idxGain = get_next_indice(st, 4); + } + + return; +} + + +/*---------------------------------------------------------------------* + * 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( + const float *input, /* i : gain shape overlap buffer */ + const float *old_hb_synth, /* i : synthesized HB from previous frame */ + short length, /* i : targeted length of transition signal */ + float *output, /* o : synthesized transitions signal */ + float Hilbert_Mem[], /* i/o: memory */ + float state_lsyn_filt_shb_local[], /* i/o: memory */ + float mem_resamp_HB_32k[], /* i/o: memory */ + short *syn_dm_phase, + int output_Fs, + float *up_mem, + int rf_flag + , int bitrate +) +{ + short i; + float syn_overlap_32k[L_FRAME32k]; + + /* upsample overlap snippet */ + Interpolate_allpass_steep( input, state_lsyn_filt_shb_local, SHB_OVERLAP_LEN, syn_overlap_32k ); + + /* perform spectral flip and downmix with overlap snippet to match HB synth */ + if (rf_flag || bitrate == ACELP_9k60) + { + flip_and_downmix_generic( 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 < 2*SHB_OVERLAP_LEN; i++) + { + syn_overlap_32k[i] = ((i%2)==0)?(-syn_overlap_32k[i]):(syn_overlap_32k[i]); + } + } + + /* cross fade of overlap snippet and mirrored HB synth from previous frame */ + for (i=0; i<2*L_SHB_LAHEAD; i++) + { + output[i] = window_shb_32k[i]*old_hb_synth[L_SHB_TRANSITION_LENGTH-1-i] + window_shb_32k[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( output_Fs == 48000 ) + { + interpolate_3_over_2_allpass( output, length, output, up_mem, allpass_poles_3_ov_2 ); + } + else if( output_Fs == 16000 ) + { + Decimate_allpass_steep( output, mem_resamp_HB_32k, L_FRAME32k, output ); + } + + return; +} + + +void GenTransition_WB( + const float *input, /* i : gain shape overlap buffer */ + const float *old_hb_synth, /* i : synthesized HB from previous frame */ + short length, /* i : targeted length of transition signal */ + float *output, /* o : synthesized transitions signal */ + float state_lsyn_filt_shb1[], + float state_lsyn_filt_shb2[], + int output_Fs, + float *up_mem +) +{ + short i; + float speech_buf_16k1[L_FRAME16k], speech_buf_16k2[L_FRAME16k]; + float upsampled_synth[L_FRAME48k]; + + /* upsample overlap snippet */ + Interpolate_allpass_steep( input, state_lsyn_filt_shb1, SHB_OVERLAP_LEN/2, speech_buf_16k1); + Interpolate_allpass_steep( 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++) + { + speech_buf_16k2[i] = ((i%2)==0)?(-speech_buf_16k2[i]):(speech_buf_16k2[i]); + } + + /* cross fade of overlap snippet and mirrored HB synth from previous frame */ + for (i=0; ilast_core != ACELP_CORE ) + { + set_f( st->old_bwe_exc, 0.0f, PIT16k_MAX * 2 ); + st->bwe_non_lin_prev_scale = 0.f; + } + if( bandwidth == WB ) + { + wb_tbe_extras_reset( st->mem_genSHBexc_filt_down_wb2, st->mem_genSHBexc_filt_down_wb3 ); + wb_tbe_extras_reset_synth( st->state_lsyn_filt_shb, st->state_lsyn_filt_dwn_shb, st->mem_resamp_HB ); + set_f( st->mem_genSHBexc_filt_down_shb, 0, 7 ); + set_f( st->state_lpc_syn, 0, 10 ); + set_f( st->state_syn_shbexc, 0, L_SHB_LAHEAD/4 ); + set_f( st->syn_overlap, 0, L_SHB_LAHEAD ); + set_f( st->mem_csfilt, 0, 2 ); + } + else if( bandwidth == SWB || bandwidth == FB ) + { + swb_tbe_reset( st->mem_csfilt, st->mem_genSHBexc_filt_down_shb, st->state_lpc_syn, + st->syn_overlap, st->state_syn_shbexc, &(st->tbe_demph), &(st->tbe_premph), + st->mem_stp_swb, &(st->gain_prec_swb) ); + + set_f( st->GainShape_Delay, 0, NUM_SHB_SUBFR/2 ); + set_f( st->int_3_over_2_tbemem_dec, 0.f, INTERP_3_2_MEM_LEN ); + set_f( st->mem_resamp_HB_32k, 0, 2*ALLPASSSECTIONS_STEEP+1 ); + + swb_tbe_reset_synth( st->genSHBsynth_Hilbert_Mem, st->genSHBsynth_state_lsyn_filt_shb_local ); + + if ( bandwidth == FB ) + { + st->prev_fb_ener_adjust = 0.0f; + set_f(st->fb_state_lpc_syn, 0, LPC_SHB_ORDER); + st->fb_tbe_demph = 0; + fb_tbe_reset_synth( st->fbbwe_hpf_mem, &st->prev_fbbwe_ratio ); + } + } + + return; +} diff --git a/lib_dec/syn_outp.c b/lib_dec/syn_outp.c new file mode 100644 index 000000000..272cbfad3 --- /dev/null +++ b/lib_dec/syn_outp.c @@ -0,0 +1,106 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------* + * syn_output() + * + * Output synthesis signal with compensation for saturation + * returns number of clipped samples + *-------------------------------------------------------------------*/ + +unsigned int syn_output( /* o : number of clipped samples */ + float *synth, /* i/o: float synthesis signal */ + const short output_frame, /* i : output frame length */ + short *synth_out /* o : integer 16 bits synthesis signal */ +) +{ + /*-----------------------------------------------------------------* + * float to integer conversion with saturation control + *-----------------------------------------------------------------*/ + + /* integer conversion */ + return mvr2s( synth, synth_out, output_frame ); +} + + +/*-------------------------------------------------------------------* + * AGC_dec() + * + * In-place saturation control (Automatic Gain Control) + *-------------------------------------------------------------------*/ + +void AGC_dec( + float x[], /* i/o: input/output vector */ + float mem[], /* i/o: mem[2] should be init to [0,0] */ + const short n /* i : vector size */ +) +{ + short i; + float fac, prev, tmp, frame_fac, max; + + /*-----------------------------------------------------------------* + * calculate AGC factor to avoid saturation + *-----------------------------------------------------------------*/ + + max = 0.0f; + + for (i=0; i max) + { + max = tmp; + } + } + + frame_fac = 0.0f; + if ( max > 30000.0f ) + { + frame_fac = 0.5f - (15000.0f/max); + } + + fac = mem[0]; + prev = mem[1]; + + /*-----------------------------------------------------------------* + * AGC + *-----------------------------------------------------------------*/ + + for (i=0; i 32767.0f) + { + tmp = 32767.0f; + } + else if (tmp < -32768.0f) + { + tmp = -32768.0f; + } + + x[i] = (short)floor(tmp + 0.5f); + + } + + mem[0] = fac; + mem[1] = prev; + + return ; +} diff --git a/lib_dec/tcq_core_dec.c b/lib_dec/tcq_core_dec.c new file mode 100644 index 000000000..6fbc36cdb --- /dev/null +++ b/lib_dec/tcq_core_dec.c @@ -0,0 +1,451 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" +#include "basop_util.h" +#include "basop_proto_func.h" + +/*---------------------------------------------------------------------* + * tcq_core_LR_enc() + * + * Main Generic Audio Decoder Routine for LR-MDCT + *---------------------------------------------------------------------*/ + +void tcq_core_LR_dec( + Decoder_State *st, + int *inp_vector, + const short bit_budget, + const short BANDS, + const short *band_start, + const short *band_width, + Word32 *Rk_fx, + int *npulses, + short *k_sort, + const short *p2a_flags, + const short p2a_bands, + const short *last_bitalloc, + const short input_frame, + const short adjustFlag, + const short *is_transient +) +{ + short i, j, k; + float Rk_sort[NB_SFM]; + short flag_wbnb = 0; + short USQ_TCQ[NB_SFM]; /* TCQ is selected by default*/ + short nb_bytes, pulsesnum, nz; + int positions[L_FRAME32k]; + short k_num[2]; + ARCODEC ardec, *pardec; + BITSTREAM bs, *pbs; + + int nzbands = 0; + int lsbtcq_bits = TCQ_AMP; + int tcq_arbits = 2; + + /* LSB TCQ variables*/ + short dpath[280]; + short bcount = 0; + float mbuffer[560]; + + Word32 leftbits = 0; + Word32 sepbits = 0; + Word32 divider = 0; + + /*Word32 Rk_fx[NB_SFM];*/ /* Q16 */ + Word32 Rk_sort_fx[NB_SFM]; /* Q16 */ + Word32 bsub_fx = 0; + + Word16 nzb = 0; + Word32 delta_fx; + Word32 surplus_fx; + Word32 bit_surplus_fx[2]; + + /* initialization */ + set_s(dpath, 0, 280); + set_f(mbuffer, 0.f, 560); + set_f( Rk_sort, 0.f, NB_SFM ); + set_s( USQ_TCQ, 0, NB_SFM ); + set_i( positions, 0, L_FRAME32k ); + + if( input_frame <= L_FRAME16k && adjustFlag == 0 && *is_transient == 0 ) + { + flag_wbnb = 1; + lsbtcq_bits = 0; + tcq_arbits = 0; + } + + pardec = &ardec; + pbs = &bs; + pbs->curPos = 7; + pbs->numbits = 0; + pbs->numByte = 0; + + /* Bits distribution analysis*/ + for( i = 0; i < BANDS; i++ ) + { + if( L_sub( ar_div(Rk_fx[i], band_width[i]), 49152) >= 0) + { + /* USQ used for high importance bands*/ + USQ_TCQ[i] = 1; + } + else + { + /* TCQ used for usual bands*/ + USQ_TCQ[i] = 0; + } + if( Rk_fx[i] > 0.0f ) + { + nzbands++; + } + } + + for( j = 0; j < BANDS; j++ ) + { + if( Rk_fx[j] > 0.0f ) + { + nzb++; + } + } + +#define WMC_TOOL_SKIP + 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] = 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); +#undef WMC_TOOL_SKIP + + /*read the bits*/ + nb_bytes = bit_budget >> 3; + k = bit_budget - (nb_bytes << 3); + for( i = 0; i < nb_bytes; i++ ) + { + pbs->buf[i] = (unsigned char)get_next_indice(st, 8); + } + + if( k > 0 ) + { + pbs->buf[nb_bytes] = (unsigned char)get_next_indice(st, (short)k); + pbs->buf[nb_bytes] <<= (8 - k); + i++; + nb_bytes++; + } + /* set two more bytes, which are used to flush the arithmetic coder, to 0 + -> this avoids reading of uninitialized memory */ + nb_bytes = min(nb_bytes + 2, MAX_SIZEBUF_PBITSTREAM); + for( ; i < nb_bytes; i++ ) + { + pbs->buf[i] = 0; + } + + pbs->maxBytes = nb_bytes; + + ar_decoder_start( pardec, pbs ); + + delta_fx = 0; + surplus_fx = 0; + + if( input_frame <= L_FRAME16k && adjustFlag == 0 && *is_transient == 0 ) + { + surplus_fx = -131072; + + 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; + for ( j = 0; j < BANDS; j++ ) + { + if ( sub(j, k_num[0]) == 0 || sub(j, k_num[1]) == 0) + { + 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++ ) + { + if( k != k_num[0] && k != k_num[1]) + { + if (Rk_fx[k_sort[k]] > 0 && USQ_TCQ[k_sort[k]] == 0) + { +#define WMC_TOOL_SKIP + /* 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; + for( i = 0; i < band_width[k_sort[k]]; i++ ) + { + inp_vector[band_start[k_sort[k]] + i] = 0; + } + if( surplus_fx != 0 ) + { + surplus_fx = L_add( Rk_fx[k_sort[k]], surplus_fx); + surplus_fx = L_add( delta_fx, surplus_fx); + } + } + else + { +#undef WMC_TOOL_SKIP + /*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, band_width[k_sort[k]], pulsesnum, &nz, &positions[band_start[k_sort[k]]] ); + decode_mangitude_tcq_fx( pardec, band_width[k_sort[k]], pulsesnum, nz, &positions[band_start[k_sort[k]]], &inp_vector[band_start[k_sort[k]]], &surplus_fx ); + decode_signs_fx( pardec, band_width[k_sort[k]], &inp_vector[band_start[k_sort[k]]] ); + + } + nzbands--; + } + else if (Rk_fx[k_sort[k]] > 0 && USQ_TCQ[k_sort[k]] == 1) + { +#define WMC_TOOL_SKIP + /* 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; + for( i = 0; i < band_width[k_sort[k]]; i++ ) + { + inp_vector[band_start[k_sort[k]] + i] = 0; + } + if( surplus_fx != 0 ) + { + surplus_fx = L_add( Rk_fx[k_sort[k]], surplus_fx); + surplus_fx = L_add( delta_fx, surplus_fx); + } + } + else + { +#undef WMC_TOOL_SKIP + + 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, band_width[k_sort[k]], pulsesnum, &nz, &positions[band_start[k_sort[k]]] ); + decode_magnitude_usq_fx( pardec, band_width[k_sort[k]], pulsesnum, nz, &positions[band_start[k_sort[k]]], &inp_vector[band_start[k_sort[k]]] ); + decode_signs_fx( pardec, band_width[k_sort[k]], &inp_vector[band_start[k_sort[k]]] ); + + } + nzbands--; + } + else + { + pulsesnum = 0; + for( i = 0; i < band_width[k_sort[k]]; i++ ) + { + inp_vector[band_start[k_sort[k]] + i] = 0; + } + } + + npulses[k_sort[k]] = pulsesnum; + +#define WMC_TOOL_SKIP + 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); + } + else + { + delta_fx = 0; + } +#undef WMC_TOOL_SKIP + } + } + +#define WMC_TOOL_SKIP + if (( L_sub(surplus_fx,524288) > 0 && sub(input_frame,L_FRAME8k) == 0 ) || ( L_sub(surplus_fx,786432) > 0 && sub(input_frame,L_FRAME16k) == 0 )) + { + 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; + bit_surplus_fx[1] = 0; + } +#undef WMC_TOOL_SKIP + + for( k = 0; k < BANDS; k++ ) + { + for( j = 0; j < 2; j++ ) + { + if( k == k_num[j] ) + { +#define WMC_TOOL_SKIP + Rk_fx[k_sort[k]] = L_add(Rk_fx[k_sort[k]],bit_surplus_fx[j]); + 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, band_width[k_sort[k]], pulsesnum, &nz, &positions[band_start[k_sort[k]]] ); + /* decode tcq magniitude and update the surplus bits. */ + decode_mangitude_tcq_fx( pardec, band_width[k_sort[k]], pulsesnum, nz, &positions[band_start[k_sort[k]]], &inp_vector[band_start[k_sort[k]]], &surplus_fx ); + decode_signs_fx( pardec, band_width[k_sort[k]], &inp_vector[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, band_width[k_sort[k]], pulsesnum, &nz, &positions[band_start[k_sort[k]]] ); + /* decode usq magnitude and don't need to update surplus bits */ + decode_magnitude_usq_fx( pardec, band_width[k_sort[k]], pulsesnum, nz, &positions[band_start[k_sort[k]]], &inp_vector[band_start[k_sort[k]]] ); + decode_signs_fx( pardec, band_width[k_sort[k]], &inp_vector[band_start[k_sort[k]]] ); + } + else + { + pulsesnum = 0; + for ( i = 0; i < band_width[k_sort[k]]; i++ ) + { + inp_vector[band_start[k_sort[k]] + i] = 0; + } + } +#undef WMC_TOOL_SKIP + npulses[k_sort[k]] = pulsesnum; + } + } + } + } + else + { + for( k = 0; k < BANDS; k++ ) + { +#define WMC_TOOL_SKIP + 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, band_width[k_sort[k]], pulsesnum, &nz, &positions[band_start[k_sort[k]]] ); + + /*decode usq magnitude and don't need to update surplus bits*/ + decode_magnitude_usq_fx( pardec, band_width[k_sort[k]], pulsesnum, nz, &positions[band_start[k_sort[k]]], &inp_vector[band_start[k_sort[k]]] ); + decode_signs_fx( pardec, band_width[k_sort[k]], &inp_vector[band_start[k_sort[k]]] ); + + nzbands = sub(nzbands, 1); + } + else + { + pulsesnum = 0; + for( i = 0; i < band_width[k_sort[k]]; i++ ) + { + inp_vector[band_start[k_sort[k]] + i] = 0; + } + } + + npulses[k_sort[k]] = pulsesnum; + + /* surplus distribution */ + if ( surplus_fx > 0 && nzbands > 0 ) + { + delta_fx = ar_div(surplus_fx, nzbands); + surplus_fx = L_sub(surplus_fx, delta_fx); + } +#undef WMC_TOOL_SKIP + } + } + /* Load TCQ path from bitstream */ + LoadTCQdata( pardec, dpath, lsbtcq_bits); + + TCQLSBdec( dpath, mbuffer, 2*lsbtcq_bits ); + + ar_decoder_done( pardec ); + + /* Restore TCQ */ + if( !flag_wbnb ) + { + for( k = 0; k < BANDS; k++) + { + if( Rk_fx[k_sort[k]] > 0 ) + { + RestoreTCQdec( &inp_vector[ band_start[ k_sort[ k]]], band_width[k_sort[k]], &bcount, mbuffer ); + } + } + } + else + { + for( k = 0; k < BANDS; k++) + { + if( Rk_fx[k_sort[k]] > 0 && k != k_num[0] && k != k_num[1] ) + { + RestoreTCQdec( &inp_vector[ band_start[ k_sort[ k]]], band_width[k_sort[k]], &bcount, mbuffer ); + } + } + for( k = 0; k < BANDS; k++) + { + if( Rk_fx[k_sort[k]] > 0 && (k == k_num[0] || k == k_num[1]) ) + { + RestoreTCQdec( &inp_vector[ band_start[ k_sort[ k]]], band_width[k_sort[k]], &bcount, mbuffer ); + } + } + } + + + + return; +} diff --git a/lib_dec/tcx_utils_dec.c b/lib_dec/tcx_utils_dec.c new file mode 100644 index 000000000..aee82f563 --- /dev/null +++ b/lib_dec/tcx_utils_dec.c @@ -0,0 +1,251 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "cnst.h" +#include "wmc_auto.h" +#include +#include +#include +#include +#include "options.h" +#include "prot.h" +#include "rom_com.h" + + + +void tcx_decoder_memory_update( + float *xn_buf, /* i/o: mdct output buffer used also as temporary buffer */ + float *synthout, /* o: synth */ + int L_frame_glob, /* i: global frame length */ + float *A, /* i: Quantized LPC coefficients */ + Decoder_State *st, /* i/o : decoder memory state */ + float *syn /* o: st->syn */ +) +{ + float tmp; + float *synth; + float buf[1+M+L_FRAME_PLUS]; + float preemph_f = st->preemph_fac; + + /*TCX must be aligned with ACELP*/ + assert(st->tcx_cfg.lfacNext<=0); + + /* Output synth */ + mvr2r(xn_buf, synthout, L_frame_glob); + + /* Update synth */ + synth = buf + 1 + M; + mvr2r(syn, buf, 1+M); + mvr2r(xn_buf, synth, L_frame_glob); + mvr2r(synth+L_frame_glob-M-1, syn, 1+M); + + /* Emphasis of synth -> synth_pe */ + tmp = synth[-M-1]; + preemph(synth-M, preemph_f, M+L_frame_glob, &tmp); + + mvr2r(synth+L_frame_glob-M, st->mem_syn2, M); + mvr2r( synth+L_frame_glob-L_SYN_MEM, st->mem_syn_r, L_SYN_MEM); + + if ( !st->tcxonly || L_frame_glob == L_FRAME16k) + { + /* Update excitation */ + assert(L_frame_glob < L_EXC_MEM_DEC); + mvr2r(st->old_exc+(L_frame_glob), st->old_exc, L_EXC_MEM_DEC-(L_frame_glob) ); + residu(A, M, synth, st->old_exc+L_EXC_MEM_DEC-(L_frame_glob), (L_frame_glob)); + } + + /* Update old_Aq */ + mvr2r(A, st->old_Aq_12_8, M+1); +} + +/*--------------------------------------------------------------- + * Residual Quantization + *--------------------------------------------------------------*/ + +/* Returns: number of bits used (including "bits") */ +int tcx_ari_res_invQ_spec( + float x_Q[], /* i/o: quantized spectrum */ + int L_frame, /* i: number of lines */ + const int prm[], /* i: bit-stream */ + int target_bits, /* i: number of bits available */ + int bits, /* i: number of bits used so far */ + float deadzone, /* i: quantizer deadzone */ + const float x_fac[] /* i: spectrum post-quantization factors */ +) +{ + int i, j, num_zeros; + int zeros[L_FRAME_PLUS]; + float fac_m, fac_p, sign; + + + /* Limit the number of residual bits */ + target_bits = min(target_bits, NPRM_RESQ); + + + /* Requantize the spectrum line-by-line */ + fac_m = deadzone * 0.5f; + num_zeros = 0; + for (i=0; i= target_bits) + { + /* no bits left */ + break; + } + if (x_Q[i] != 0) + { + if (x_Q[i] > 0) + { + sign = x_fac[i]; + } + else + { + sign = -x_fac[i]; + } + + x_Q[i] += sign*(prm[bits++] * 0.5f - fac_m); + } + else + { + zeros[num_zeros++] = i; + } + } + + /* Requantize zeroed-lines of the spectrum */ + fac_p = (1.0f - deadzone)*0.33f*2.0f; + --target_bits; /* reserve 1 bit for the check below */ + for (j=0; j= target_bits) + { + /* 1 or 0 bits left */ + break; + } + + i = zeros[j]; + + if (prm[bits++] != 0) + { + x_Q[i] = (2*prm[bits++]-1) * fac_p * x_fac[i]; + } + } + + + return bits; +} + +int tcx_res_invQ_gain( + float *gain_tcx, + const int *prm, + int resQBits +) +{ + int bits; + + + /*Refine the gain quantization*/ + for(bits=0; bits 0.0f) ? fac_m : fac_p; + } + else + { + x[i] += (x[i] > 0.0f) ? fac_p : fac_m; + } + } + } + resQBits--; /* Quantize zeroed lines of the spectrum */ + for (i = 0; (i < L_frame) && (bits < resQBits); i++) + { + if (x[i] == 0.0f) + { + if (prm[bits++] != 0) + { + x[i] = (prm[bits++] * 2.64f - 1.32f) * fac_p; + } + } + } + + return bits; + } + for(i=0; i=resQBits) + { + break; + } + if(x[i]!=0.f && lf_deemph_factors[i] > 0.5f) + { + if(prm[bits++]==0) + { + x[i]-=(x[i]>0)? fac_m*lf_deemph_factors[i]: fac_p*lf_deemph_factors[i]; + } + else + { + x[i]+=(x[i]>0)? fac_p*lf_deemph_factors[i]: fac_m*lf_deemph_factors[i]; + } + } + } + + /*Quantize zeroed-line of the spectrum*/ + for(i=0; i=(resQBits-1)) /*need at least two bits*/ + { + break; + } + if(x[i]==0.f && lf_deemph_factors[i] > 0.5f) + { + if(prm[bits++]==1) + { + thres=(1-sq_round)*0.66f*lf_deemph_factors[i]; + x[i]=(prm[bits++]*2.f-1.f)*thres; + } + } + } + + return bits; +} diff --git a/lib_dec/tns_base_dec.c b/lib_dec/tns_base_dec.c new file mode 100644 index 000000000..7b2af93c8 --- /dev/null +++ b/lib_dec/tns_base_dec.c @@ -0,0 +1,72 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "cnst.h" +#include "wmc_auto.h" +#include "rom_com.h" +#include "prot.h" +#include +#include +#include + +#define WMC_TOOL_SKIP + + +/** 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 float (* TLinearPredictionFilter)(int order, float const parCoeff[], float * state, float x); + +/********************************/ +/* Interface functions */ +/********************************/ + +TNS_ERROR ReadTnsData(STnsConfig const * pTnsConfig, Decoder_State * st, int * pnBits, int * stream, int * pnSize) +{ + int start_bit_pos; + start_bit_pos = st->next_bit_pos; + if (pTnsConfig->nMaxFilters > 1) + { + if (pTnsConfig->iFilterBorders[0] < 512) + { + ReadFromBitstream(&tnsEnabledSWBTCX10BitMap, 1, st, &stream, pnSize); + } + else + { + ReadFromBitstream(&tnsEnabledSWBTCX20BitMap, 1, st, &stream, pnSize); + } + } + else + { + ReadFromBitstream(&tnsEnabledWBTCX20BitMap, 1, st, &stream, pnSize); + } + + *pnBits = st->next_bit_pos - start_bit_pos; + return TNS_NO_ERROR; +} + +int DecodeTnsData(STnsConfig const * pTnsConfig, int const * stream, int * pnSize, STnsData * pTnsData) +{ + ResetTnsData(pTnsData); + if (pTnsConfig->nMaxFilters > 1) + { + if (pTnsConfig->iFilterBorders[0] < 512) + { + SetParameters(&tnsEnabledSWBTCX10BitMap, 1, pTnsData, &stream, pnSize); + } + else + { + SetParameters(&tnsEnabledSWBTCX20BitMap, 1, pTnsData, &stream, pnSize); + } + } + else + { + SetParameters(&tnsEnabledWBTCX20BitMap, 1, pTnsData, &stream, pnSize); + } + return (pTnsData->nFilters > 0) ? TRUE : FALSE; +} diff --git a/lib_dec/tonalMDCTconcealment.c b/lib_dec/tonalMDCTconcealment.c new file mode 100644 index 000000000..253c4ed0c --- /dev/null +++ b/lib_dec/tonalMDCTconcealment.c @@ -0,0 +1,706 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#define _USE_MATH_DEFINES +#include "wmc_auto.h" + +#include +#include +#include +#include "options.h" +#include "prot.h" + + +#define WMC_TOOL_SKIP + + +/************************************************************************************/ +/* forward declarations for local functions, see implementation at end of this file */ +/************************************************************************************/ + +static void CalcMDXT(TonalMDCTConcealPtr const self, + char const type, + float const * const timeSignal, + float * const mdxtOutput); + +static void CalcPowerSpec(float const * mdctSpec, + float const * mdstSpec, + unsigned int nSamples, + float floorPowerSpectrum, + float * powerSpec); + +static void CalcPowerSpecAndDetectTonalComponents(TonalMDCTConcealPtr const self, + float secondLastMDST[], + float secondLastMDCT[], + float const pitchLag); + +static void FindPhases(TonalMDCTConcealPtr const self, + float const secondLastMDCT[], + float const secondLastMDST[]); + +static void FindPhaseDifferences(TonalMDCTConcealPtr const self, + float powerSpectrum[]); + +/*******************************************************/ +/*-------------- public functions -------------------- */ +/*******************************************************/ + +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_Init( TonalMDCTConcealPtr self, + unsigned int nSamples, + unsigned int nSamplesCore, + unsigned int nScaleFactors, + TCX_config * tcx_cfg + ) +{ + if (nSamples > L_FRAME_MAX || 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]; + self->secondLastBlockData.spectralData = self->spectralDataBuffers[1]; + self->secondLastPowerSpectrum = self->secondLastBlockData.spectralData; + self->lastBlockData.scaleFactors = self->scaleFactorsBuffers[0]; + self->secondLastBlockData.scaleFactors = self->scaleFactorsBuffers[1]; + self->lastBlockData.blockIsValid = 0; + self->secondLastBlockData.blockIsValid = 0; + self->nSamples = 0; + self->nScaleFactors = 0; + + self->lastBlockData.blockIsConcealed = 0; + self->secondLastBlockData.blockIsConcealed = 0; + self->pTCI = (TonalComponentsInfo *)self->timeDataBuffer; + + self->lastPitchLag = 0; + + if (self->nSamples != nSamples) + { + self->secondLastBlockData.blockIsValid = 0; + self->lastBlockData.blockIsValid = 0; + } + self->nSamples = nSamples; + self->nSamplesCore = nSamplesCore; + self->nScaleFactors = nScaleFactors; + + /* Offset the pointer to the end of buffer, so that pTCI is not destroyed when + new time samples are stored in lastPcmOut */ + /* just the second half of the second last pcm output is needed */ + self->secondLastPcmOut = &self->timeDataBuffer[(3*L_FRAME_MAX)/2-(3*min(L_FRAME_MAX, nSamples))/2]; + self->lastPcmOut = &self->timeDataBuffer[(3*L_FRAME_MAX)/2-min(L_FRAME_MAX, nSamples)]; + + /* If the second last frame was lost and concealed with tonal PLC, 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, + float const *mdctSpectrum, + unsigned int nNewSamples, + unsigned int nNewSamplesCore, + float const *scaleFactors + ) +{ + float * temp; + int nOldSamples; + + 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 */ + if (!self->lastBlockData.tonalConcealmentActive || (self->lastBlockData.nSamples != nNewSamples)) + { + if (nNewSamples <= L_FRAME_MAX) + { + /* Shift the buffers */ + temp = self->secondLastBlockData.spectralData; /* Save the pointer */ + self->secondLastBlockData.spectralData = self->lastBlockData.spectralData; + self->lastBlockData.spectralData = temp; + temp = self->secondLastBlockData.scaleFactors; + self->secondLastBlockData.scaleFactors = self->lastBlockData.scaleFactors; + self->lastBlockData.scaleFactors = temp; + } + else + { + /* Order the buffers so that even transition frame can fit in if written into the first buffer */ + self->lastBlockData.spectralData = self->spectralDataBuffers[0]; + self->secondLastBlockData.spectralData = self->spectralDataBuffers[1]; + self->lastBlockData.scaleFactors = self->scaleFactorsBuffers[0]; + self->secondLastBlockData.scaleFactors = self->scaleFactorsBuffers[1]; + } + nOldSamples = self->lastBlockData.nSamples; + self->lastBlockData.nSamples = nNewSamples; + self->secondLastBlockData.nSamples = nOldSamples; + nOldSamples = self->lastBlockData.nSamplesCore; + self->lastBlockData.nSamplesCore = nNewSamplesCore; + self->secondLastBlockData.nSamplesCore = nOldSamples; + } + if ((nNewSamples > 0) && (nNewSamples <= 2*L_FRAME_MAX)) + { + /* Store new data */ + mvr2r(mdctSpectrum, self->lastBlockData.spectralData, nNewSamples); + mvr2r(scaleFactors, self->lastBlockData.scaleFactors, self->nScaleFactors); + } + return TONALMDCTCONCEAL_OK; +} + + +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_UpdateState(TonalMDCTConcealPtr self, + int nNewSamples, + float pitchLag, + int badBlock, + int tonalConcealmentActive + ) +{ + int newBlockIsValid; + + + assert(!(!badBlock && tonalConcealmentActive)); + + if (badBlock) + { + newBlockIsValid = self->lastBlockData.blockIsValid; + } + else + { + newBlockIsValid = (nNewSamples <= 2*L_FRAME_MAX) && (nNewSamples > 0); + } + + /* Shift old state */ + self->secondLastBlockData.blockIsConcealed = self->lastBlockData.blockIsConcealed; + self->secondLastBlockData.blockIsValid = self->lastBlockData.blockIsValid; + self->secondLastBlockData.tonalConcealmentActive = self->lastBlockData.tonalConcealmentActive; + + /* Store new state */ + self->lastBlockData.blockIsConcealed = badBlock; + self->lastBlockData.blockIsValid = newBlockIsValid; + self->lastBlockData.tonalConcealmentActive = tonalConcealmentActive; + self->lastPitchLag = pitchLag; + + return TONALMDCTCONCEAL_OK; +} + + +static void FindPhases(TonalMDCTConcealPtr const self, float const secondLastMDCT[], float const secondLastMDST[]) +{ + unsigned int i; + int l; + float * 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++) + { + *pCurrentPhase++ = (float)atan2(secondLastMDST[l], secondLastMDCT[l]); + } + } + + return; +} + + +static void FindPhaseDifferences(TonalMDCTConcealPtr const self, float powerSpectrum[]) +{ + static float const bandwidth = 7.0f; + float const m = (float)cos(EVS_PI/bandwidth); + float const s = (float)cos((3*EVS_PI)/bandwidth); + float const n = (float)sin(EVS_PI/bandwidth); + float const j = (float)sin((3*EVS_PI)/bandwidth); + static float const G = (float)(1.0/(2*1.36)); + static float const maxRatio = 44.8f; /* Maximum ratio |ODFT[k-1]|/|ODFT[k+1]| is 16.5 dB, that is maximum ratio (for fractional = 0) is (cos(EVS_PI/bandwidth)/cos(3PI/bandwidth))^1.36 */ + + unsigned int i, k; + float odft_left, odft_right; + float * phaseDiff; + float fractional; + float Q, a; + + phaseDiff = self->pTCI->phaseDiff; + for (i = 0; i < self->pTCI->numIndexes; i++) + { + k = self->pTCI->indexOfTonalPeak[i]; + odft_left = powerSpectrum[k-1]; + odft_right = powerSpectrum[k+1]; + if (odft_left >= maxRatio*odft_right) + { + a = (float)tan(0.0f*EVS_PI/bandwidth); + } + else + { + if (odft_right >= maxRatio*odft_left) + { + a = (float)tan(2.0f*EVS_PI/bandwidth); + } + else + { + Q = (float)pow(odft_left/odft_right, G); + a = (m - Q * s) / (n + Q * j); + } + } + fractional = (float)atan(a) * (bandwidth/2.0f); + assert((fractional >= 0) && (fractional <= EVS_PI + 1.192092896e-07F)); + phaseDiff[i] = fractional + EVS_PI*(k%4); + } + + return; +} + + +static void CalcPowerSpecAndDetectTonalComponents(TonalMDCTConcealPtr const self, + float secondLastMDST[], + float secondLastMDCT[], + float const pitchLag) +{ + unsigned int nSamples; + unsigned int i; + float floorPowerSpectrum; /* Minimum significant value of a spectral line in the power spectrum */ + float powerSpectrum[L_FRAME_MAX]; /* 32 bits are required */ + float invScaleFactors[FDNS_NPTS]; + + nSamples = self->nNonZeroSamples; + + /* It is taken into account that the MDCT is not normalized. */ + floorPowerSpectrum = self->nSamples*self->nSamples/400.0f; + CalcPowerSpec(secondLastMDCT, secondLastMDST, nSamples, floorPowerSpectrum, powerSpectrum ); + + /* This setting to minimal level is required because the power spectrum is used in the threshold adaptation using the pitch up to self->nSamples. */ + set_f(powerSpectrum+nSamples, floorPowerSpectrum, 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 (self->nSamplesCore > self->nSamples) + { + set_zero(powerSpectrum+self->nSamples, self->nSamplesCore-self->nSamples); + } + DetectTonalComponents(self->pTCI->indexOfTonalPeak, + self->pTCI->lowerIndex, + self->pTCI->upperIndex, + &self->pTCI->numIndexes, + self->lastPitchLag, + pitchLag, + self->lastBlockData.spectralData, + self->lastBlockData.scaleFactors, + powerSpectrum, + nSamples, + self->nSamplesCore, + floorPowerSpectrum ); + FindPhases(self, secondLastMDCT, secondLastMDST); + FindPhaseDifferences(self, powerSpectrum); + if (self->pTCI->numIndexes > 0) + { + self->secondLastPowerSpectrum = self->secondLastBlockData.spectralData; + for ( i=0; inScaleFactors; i++) + { + invScaleFactors[i] = 1.0f/self->secondLastBlockData.scaleFactors[i]; + } + mdct_noiseShaping(powerSpectrum, self->nSamplesCore, invScaleFactors); + v_multc( powerSpectrum + self->nSamplesCore, invScaleFactors[FDNS_NPTS-1], powerSpectrum + self->nSamplesCore, self->nSamples - self->nSamplesCore); + mvr2r( powerSpectrum, self->secondLastPowerSpectrum, self->nSamples); /* 16 bits are now enough for storing the power spectrum */ + } + + return; +} + + +static void CalcMDXT(TonalMDCTConcealPtr const self, + char const type, + float const * const timeSignal, + float * const mdxtOutput) +{ + float windowedTimeSignal[L_FRAME_PLUS+2*L_MDCT_OVLP_MAX]; + int left_overlap, right_overlap, L_frame; + + L_frame = self->nSamples; + WindowSignal( self->tcx_cfg, self->tcx_cfg->tcx_offsetFB, FULL_OVERLAP, FULL_OVERLAP, + &left_overlap, &right_overlap, timeSignal, &L_frame, windowedTimeSignal, 1 ); + if (type == 'S') + { + TCX_MDST( windowedTimeSignal, mdxtOutput, left_overlap, L_frame - (left_overlap+right_overlap)/2, right_overlap ); + } + else + { + TCX_MDCT( windowedTimeSignal, mdxtOutput, left_overlap, L_frame - (left_overlap+right_overlap)/2, right_overlap ); + } + + return; +} + + +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_Detect( TonalMDCTConcealPtr const self, + float const pitchLag, + int * const numIndices) +{ + float secondLastMDST[L_FRAME_MAX]; /* 32 bits are required */ + float secondLastMDCT[L_FRAME_MAX]; /* 32 bits are required */ + float * powerSpectrum = secondLastMDST; + unsigned int nSamples; + unsigned int i; + + nSamples = self->nSamples; + if (self->lastBlockData.blockIsValid + && self->secondLastBlockData.blockIsValid + && (self->lastBlockData.nSamples == nSamples) + && (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) + { + if (!self->secondLastBlockData.tonalConcealmentActive) + { + CalcMDXT(self, 'S', self->secondLastPcmOut, secondLastMDST); + CalcMDXT(self, 'C', self->secondLastPcmOut, secondLastMDCT); + self->nNonZeroSamples = 0; + for (i = 0; i < self->nSamples; i++) + { + if (self->secondLastBlockData.spectralData[i] != 0) + { + self->nNonZeroSamples = i; + } + } + /* 23 is the maximum length of the MA filter in getEnvelope */ + self->nNonZeroSamples = min(self->nSamples, self->nNonZeroSamples+23); + CalcPowerSpecAndDetectTonalComponents(self, secondLastMDST, secondLastMDCT, 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; + mvr2r(self->secondLastPowerSpectrum, powerSpectrum, nSamples); /* Convert from 16 bits to 32 bits */ + mdct_noiseShaping(powerSpectrum, self->nSamplesCore, self->secondLastBlockData.scaleFactors); + v_multc(powerSpectrum + self->nSamplesCore, + self->secondLastBlockData.scaleFactors[FDNS_NPTS-1], + powerSpectrum + self->nSamplesCore, + nSamples - self->nSamplesCore); + v_mult(powerSpectrum, powerSpectrum, powerSpectrum, nSamples); + 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, + self->lastBlockData.scaleFactors, + powerSpectrum, + nSamples, + self->nSamplesCore, + self->nSamples*self->nSamples/400.0f /* floorPowerSpectrum */ ); + } + } + } + else + { + self->pTCI->numIndexes = 0; + } + *numIndices = self->pTCI->numIndexes; + + + return TONALMDCTCONCEAL_OK; +} + + +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_InsertNoise( TonalMDCTConcealPtr self, /*IN */ + float* mdctSpectrum, /*OUT*/ + int tonalConcealmentActive, + short* pSeed, + float tiltCompFactor, + float crossfadeGain, + int crossOverFreq) +{ + unsigned int i; + Word16 rnd; + float g, nrgNoiseInLastFrame, nrgWhiteNoise, tiltFactor, tilt; + + + g = 1.0f-crossfadeGain; + if (!self->lastBlockData.blockIsConcealed) + { + rnd = 1977; + } + else + { + rnd = *pSeed; + } + if (!self->lastBlockData.blockIsValid) + { + /* may just become active if the very first frame is lost */ + set_f( mdctSpectrum, 0.0f, self->nSamples); + } + else + { + /* based on what is done in tcx_noise_filling() */ + tiltFactor = (float)pow(max(0.375f, tiltCompFactor), 1.0f/self->lastBlockData.nSamples); + tilt = 1.0f; + nrgNoiseInLastFrame = nrgWhiteNoise = 0.0f; + if (!tonalConcealmentActive) + { + for (i = 0; i < (unsigned int)crossOverFreq; i++) + { + float const x = self->lastBlockData.spectralData[i]; + float y; + rnd = (Word16) (rnd * 31821L + 13849L); + y = tilt*rnd; + nrgNoiseInLastFrame += x*x; + nrgWhiteNoise += y*y; + mdctSpectrum[i] = y; + tilt *= tiltFactor; + } + if (nrgWhiteNoise > 0) + { + g *= (float)sqrt(nrgNoiseInLastFrame/nrgWhiteNoise); + } + for (i = 0; i < (unsigned int)crossOverFreq; i++) + { + float const x = self->lastBlockData.spectralData[i]; + float const y = mdctSpectrum[i]; + + if (y > 0) + { + mdctSpectrum[i] = g*y + crossfadeGain*x; + } + else + { + mdctSpectrum[i] = g*y - crossfadeGain*x; + } + } + + for (i = (unsigned int)crossOverFreq; i < self->lastBlockData.nSamples; i++) + { + mdctSpectrum[i] = self->lastBlockData.spectralData[i]; + } + } + else + { + unsigned int l; + assert(self->pTCI->numIndexes > 0); + for (l = 0; l < self->pTCI->lowerIndex[0]; l++) + { + float const x = self->lastBlockData.spectralData[l]; + float y; + rnd = (Word16) (rnd * 31821L + 13849L); + y = tilt*rnd; + nrgNoiseInLastFrame += x*x; + nrgWhiteNoise += y*y; + mdctSpectrum[l] = y; + 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); + for (l = self->pTCI->upperIndex[i-1]+1; l < self->pTCI->lowerIndex[i]; l++) + { + float const x = self->lastBlockData.spectralData[l]; + float y; + rnd = (Word16) (rnd * 31821L + 13849L); + y = tilt*rnd; + nrgNoiseInLastFrame += x*x; + nrgWhiteNoise += y*y; + mdctSpectrum[l] = y; + tilt *= tiltFactor; + } + } + tilt *= (float)pow(tiltFactor, self->pTCI->upperIndex[self->pTCI->numIndexes-1]-self->pTCI->lowerIndex[self->pTCI->numIndexes-1]+1); + + for (l = self->pTCI->upperIndex[self->pTCI->numIndexes-1]+1; l < (unsigned int)crossOverFreq; l++) + { + float const x = self->lastBlockData.spectralData[l]; + float y; + rnd = (Word16) (rnd * 31821L + 13849L); + y = tilt*rnd; + nrgNoiseInLastFrame += x*x; + nrgWhiteNoise += y*y; + mdctSpectrum[l] = y; + tilt *= tiltFactor; + } + if (nrgWhiteNoise > 0) + { + g *= (float)sqrt(nrgNoiseInLastFrame/nrgWhiteNoise); + } + for (l = 0; l < self->pTCI->lowerIndex[0]; l++) + { + float const x = self->lastBlockData.spectralData[l]; + float const y = mdctSpectrum[l]; + + if (y > 0) + { + mdctSpectrum[l] = g*y + crossfadeGain*x; + } + else + { + mdctSpectrum[l] = g*y - crossfadeGain*x; + } + } + for (i = 1; i < self->pTCI->numIndexes; i++) + { + for (l = self->pTCI->upperIndex[i-1]+1; l < self->pTCI->lowerIndex[i]; l++) + { + float const x = self->lastBlockData.spectralData[l]; + float const y = mdctSpectrum[l]; + + if (y > 0) + { + mdctSpectrum[l] = g*y + crossfadeGain*x; + } + else + { + mdctSpectrum[l] = g*y - crossfadeGain*x; + } + } + } + /* 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] = 0; + + } + } + for (l = self->pTCI->upperIndex[self->pTCI->numIndexes-1]+1; l < (unsigned int)crossOverFreq; l++) + { + float const x = self->lastBlockData.spectralData[l]; + float const y = mdctSpectrum[l]; + + if (y > 0) + { + mdctSpectrum[l] = g*y + crossfadeGain*x; + } + else + { + mdctSpectrum[l] = g*y - crossfadeGain*x; + } + } + for (l = (unsigned int)crossOverFreq; l < self->lastBlockData.nSamples; l++) + { + mdctSpectrum[l] = self->lastBlockData.spectralData[l]; + } + } + } + + *pSeed = rnd; + + return TONALMDCTCONCEAL_OK; +} + + +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_Apply(TonalMDCTConcealPtr self, /*IN */ + float *mdctSpectrum /*OUT */ + ) +{ + unsigned int i, l; + float * phaseDiff, * pCurrentPhase; + float phaseToAdd; + float powerSpectrum[L_FRAME_MAX]; + unsigned int nSamples; + + + if (self->lastBlockData.blockIsValid & self->secondLastBlockData.blockIsValid) + { + assert(self->pTCI->numIndexes > 0); + + nSamples = self->nNonZeroSamples; + assert(self->pTCI->upperIndex[self->pTCI->numIndexes-1] < nSamples); + mvr2r(self->secondLastPowerSpectrum, powerSpectrum, nSamples); /* Convert from 16 bits to 32 bits */ + mdct_noiseShaping(powerSpectrum, self->nSamplesCore, self->secondLastBlockData.scaleFactors); + v_multc( powerSpectrum + self->nSamplesCore, self->secondLastBlockData.scaleFactors[FDNS_NPTS-1], powerSpectrum + self->nSamplesCore, nSamples - self->nSamplesCore ); + phaseDiff = self->pTCI->phaseDiff; /* if multiple frame loss occurs use the phase from the last frame and continue rotating */ + pCurrentPhase = self->pTCI->phase_currentFramePredicted; + if (!self->lastBlockData.blockIsConcealed) + { + if (self->secondLastBlockData.tonalConcealmentActive) + { + self->nFramesLost += 1; + } + else + { + self->nFramesLost = 1.5; + } + } + /* for each index group */ + for (i = 0; i < self->pTCI->numIndexes; i++) + { + phaseToAdd = self->nFramesLost*phaseDiff[i]; + /* Move phaseToAdd to range -EVS_PI..EVS_PI */ + while (phaseToAdd > EVS_PI) + { + phaseToAdd -= 2*EVS_PI; + } + while (phaseToAdd < -EVS_PI) + { + /* should never occur in flt - kept for safety reasons */ + phaseToAdd += 2*EVS_PI; + } + for (l = self->pTCI->lowerIndex[i]; l <= self->pTCI->upperIndex[i]; l++) + { + float const currentPhase = (*pCurrentPhase++) + phaseToAdd; /* *pCurrentPhase and phaseToAdd are in range -EVS_PI..EVS_PI */ + mdctSpectrum[l] = (float)cos(currentPhase) * powerSpectrum[l]; + } + } + } + self->nFramesLost++; + + return TONALMDCTCONCEAL_OK; +} + + +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_SaveTimeSignal( TonalMDCTConcealPtr self, + float* timeSignal, + unsigned int nNewSamples + ) +{ + if (nNewSamples == self->nSamples) + { + assert(nNewSamples <= L_FRAME_MAX); + if (!self->secondLastBlockData.tonalConcealmentActive) + { + mvr2r(self->lastPcmOut + self->nSamples/2, self->secondLastPcmOut, self->nSamples/2); + } + mvr2r(timeSignal, self->lastPcmOut, self->nSamples); + } + return TONALMDCTCONCEAL_OK; +} + + +static void CalcPowerSpec(float const * mdctSpec, float const * mdstSpec, + unsigned int nSamples, float floorPowerSpectrum, + float * powerSpec) +{ + unsigned int k; + float x; + + for (k = 1; k <= nSamples-2; k++) + { + x = mdctSpec[k] * mdctSpec[k] + mdstSpec[k] * mdstSpec[k]; + powerSpec[k] = max(floorPowerSpectrum, x); + } + powerSpec[0] = 0.5f*powerSpec[1]; + powerSpec[nSamples-1] = 0.5f*powerSpec[nSamples-2]; + + + return; +} diff --git a/lib_dec/transition_dec.c b/lib_dec/transition_dec.c new file mode 100644 index 000000000..45f8a355c --- /dev/null +++ b/lib_dec/transition_dec.c @@ -0,0 +1,744 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*----------------------------------------------------------------------* + * Local functions + *----------------------------------------------------------------------*/ + +static void tc_dec( Decoder_State *st, const short L_frame, float exc[], short *T0, short *T0_frac, const short i_subfr, + const short tc_subfr, short *position, const long core_brate, float bwe_exc[] ); + +/*-------------------------------------------------------------------* + * transition_dec() + * + * Principal function for TC decoding + *-------------------------------------------------------------------*/ + +void transition_dec( + Decoder_State *st, /* i/o: decoder state structure */ + const long core_brate, /* i : core bitrate */ + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short L_frame, /* i : length of the frame */ + const short i_subfr, /* i : subframe index */ + const short coder_type, /* i : coder type */ + const short tc_subfr, /* i : TC subframe index */ + short *Jopt_flag, /* i : joint optimization flag */ + float *exc, /* o : excitation signal */ + short *T0, /* o : close loop integer pitch */ + short *T0_frac, /* o : close loop fractional part of the pitch */ + short *T0_min, /* i/o: delta search min for sf 2 & 4 */ + short *T0_max, /* i/o: delta search max for sf 2 & 4 */ + float **pt_pitch, /* o : floating pitch values */ + short *position, /* i/o: first glottal impulse position in frame */ + float *bwe_exc /* o : excitation for SWB TBE */ +) +{ + short i, pit_flag, pit_start, pit_limit, index, nBits; + short limit_flag; + short offset; + + /* 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( tc_subfr > i_subfr+TC_0_192 ) + { + set_f(&exc[i_subfr], 0, L_SUBFR); + + if( L_frame == L_FRAME ) + { + set_f(&bwe_exc[i_subfr*HIBND_ACB_L_FAC], 0, (short) (L_SUBFR*HIBND_ACB_L_FAC)); /* set past excitation buffer to 0 */ + } + else + { + set_f(&bwe_exc[i_subfr*2], 0, (short) (L_SUBFR*2)); /* set past excitation buffer to 0 */ + } + + *T0 = L_SUBFR; + *T0_frac = 0; + **pt_pitch = (float)L_SUBFR; + } + + /*---------------------------------------------------------------------* + * glottal shape codebook search + *---------------------------------------------------------------------*/ + + else if( (tc_subfr-i_subfr >= 0) && (tc_subfr-i_subfr <= TC_0_192) ) + { + set_f( exc-L_EXC_MEM, 0, L_EXC_MEM ); /* set past excitation buffer to 0 */ + + if( L_frame == L_FRAME ) + { + set_f( bwe_exc-PIT_MAX*HIBND_ACB_L_FAC, 0, PIT_MAX*HIBND_ACB_L_FAC); /* set past excitation buffer to 0 */ + } + else + { + set_f( bwe_exc-PIT16k_MAX*2, 0, PIT16k_MAX*2); /* set past excitation buffer to 0 */ + } + + /* glottal shape codebook contribution construction */ + tc_dec( st, L_frame, exc, T0, T0_frac, i_subfr, tc_subfr, position, core_brate, bwe_exc ); + + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; /* save subframe pitch values */ + *Jopt_flag = 1; + } + + /*---------------------------------------------------------------------* + * 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 (tc_subfr < i_subfr) + { + if( L_frame == L_FRAME ) + { + *Jopt_flag = 1; + + if( (i_subfr - tc_subfr >= L_SUBFR) && (i_subfr - tc_subfr <= L_SUBFR + TC_0_192) ) + { + pit_flag = 0; + } + else + { + pit_flag = L_SUBFR; + } + + if( tc_subfr == TC_0_0 ) + { + if( i_subfr == L_SUBFR ) + { + limit_T0( L_FRAME, 8, pit_flag, limit_flag, *T0, 0, T0_min, T0_max ); + } + + pit_flag = 1; + } + + /*-----------------------------------------------------------------* + * get number of bits for pitch decoding + *-----------------------------------------------------------------*/ + + nBits = ACB_bits_tbl[BIT_ALLOC_IDX(core_brate, TRANSITION, i_subfr, TC_SUBFR2IDX(tc_subfr))]; + + /*------------------------------------------------------------* + * first glottal impulse is in the 1st subframe + *------------------------------------------------------------*/ + + if( (i_subfr == L_SUBFR) && (tc_subfr >= TC_0_128) ) + { + /*--------------------------------------------------------* + * second glottal impulse is in the 3rd or 4th subframe + * - build exc[] in 2nd subframe + *--------------------------------------------------------*/ + + *T0 = 2*L_SUBFR; + *T0_frac = 0; + *Jopt_flag = 0; + + /* set adaptive part of exciation for curent subframe to 0 */ + set_f( &exc[i_subfr], 0, (short)(L_SUBFR+1) ); + + set_f( &bwe_exc[i_subfr*HIBND_ACB_L_FAC], 0, (short)(L_SUBFR*HIBND_ACB_L_FAC) ); + } + else if( (i_subfr == L_SUBFR) && (tc_subfr == TC_0_64) ) + { + /*--------------------------------------------------------* + * second glottal impulse is in the 2nd subframe, + * - build exc[] in 2nd subframe + *--------------------------------------------------------*/ + + if( PIT_MIN > (*position) ) + { + pit_start = L_SUBFR - (*position); + } + else + { + pit_start = PIT_MIN; + } + + if( pit_start < PIT_MIN ) + { + pit_start = PIT_MIN; + } + + pit_limit = 2*pit_start + (*position); + + /* 7 bit pitch DECODER */ + index = (short)get_next_indice( st, nBits ); + + *T0 = (short) (floor( pit_start + index/2 )); + *T0_frac = (index - (*T0 - pit_start)*2 ) * 2; + limit_T0( 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, inter4_2, L_INTERPOL2, PIT_UP_SAMP ); + + offset = tbe_celp_exc_offset(*T0, *T0_frac); + for (i=0; i (PIT_MAX<<2)+2 ) + { + *T0 = L_SUBFR; + *T0_frac = 0; + st->BER_detect = 1; + } + + /* Find the adaptive codebook vector. ACELP long-term prediction */ + pred_lt4( &exc[i_subfr], &exc[i_subfr], *T0, *T0_frac, L_SUBFR+1, inter4_2, L_INTERPOL2, PIT_UP_SAMP ); + + offset = tbe_celp_exc_offset(*T0, *T0_frac); + for (i=0; iBER_detect ); + + /* Find the adaptive codebook vector */ + pred_lt4( &exc[i_subfr], &exc[i_subfr], *T0, *T0_frac, L_SUBFR+1, inter4_2, L_INTERPOL2, PIT_UP_SAMP ); + + offset = tbe_celp_exc_offset(*T0, *T0_frac); + for (i=0; i= 2*L_SUBFR) && (i_subfr == 3*L_SUBFR) ) + { + (*pt_pitch) -= 3; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + } + else if( (tc_subfr == L_SUBFR) && (i_subfr == 2*L_SUBFR) ) + { + (*pt_pitch) -= 2; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + } + else if( (tc_subfr == TC_0_64) && (i_subfr == L_SUBFR) ) + { + (*pt_pitch) -= 1; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + } + else if( (tc_subfr == TC_0_128) && (i_subfr == 2*L_SUBFR) ) + { + (*pt_pitch) -= 2; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + } + else if( (tc_subfr == TC_0_192) && (i_subfr == 3*L_SUBFR) ) + { + (*pt_pitch) -= 3; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + } + + } + else /* L_frame == L_FRAME16k */ + { + if( i_subfr >= 2*L_SUBFR ) + { + limit_flag = 1; + } + + if( i_subfr - tc_subfr == L_SUBFR ) + { + limit_T0( L_FRAME16k, 8, 0, limit_flag, *T0, *T0_frac, T0_min, T0_max ); /* find T0_min and T0_max */ + } + + /*-----------------------------------------------------------------* + * get number of bits and index for pitch decoding + *-----------------------------------------------------------------*/ + + nBits = ACB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ(core_brate, coder_type, i_subfr, TC_SUBFR2IDX_16KHZ(tc_subfr))]; + + index = (short)get_next_indice( st, nBits ); + + /*-----------------------------------------------------------------* + * Find adaptive part of excitation, encode pitch period + *-----------------------------------------------------------------*/ + + if( nBits == 10 ) + { + pit16k_Q_dec( index, nBits, limit_flag, T0, T0_frac, T0_min, T0_max, &st->BER_detect ); + } + else if( 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( index < (PIT16k_FR2_TC0_2SUBFR-PIT16k_MIN)*4 ) + { + *T0 = PIT16k_MIN + (index/4); + *T0_frac = index - (*T0 - PIT16k_MIN)*4; + } + else + { + index -= (PIT16k_FR2_TC0_2SUBFR-PIT16k_MIN)*4; + *T0 = PIT16k_FR2_TC0_2SUBFR + (index/2); + *T0_frac = index - (*T0 - PIT16k_FR2_TC0_2SUBFR)*2; + (*T0_frac) *= 2; + } + + /* biterror detection mechanism */ + if( ((*T0<<2) + *T0_frac) > ((2*L_SUBFR)<<2) ) + { + *T0 = L_SUBFR; + *T0_frac = 0; + st->BER_detect = 1; + } + } + else if( nBits == 6 ) + { + delta_pit_dec( 4, index, T0, T0_frac, *T0_min ); + } + if( nBits == 6 ) + { + limit_T0( 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) + *-----------------------------------------------------------------*/ + + if( (i_subfr == L_SUBFR) && (*T0 == 2*L_SUBFR) ) + { + /* no adaptive excitation in the second subframe */ + set_f( &exc[i_subfr], 0, L_SUBFR+1 ); + + get_next_indice( st, 1 ); /* this bit is actually not needed */ + + set_f( &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, inter4_2, L_INTERPOL2, PIT_UP_SAMP); + + for (i=0; i= 0) && (i < L_SUBFR) ) + { + exc[i+i_subfr] = glottal_cdbk[(imp_shape)*L_IMPULSE+i-imp_pos+L_IMPULSE2]*gain_trans; + } + } + + /*--------------------------------------------------------------* + * adapt. search of the second impulse in the same subframe + * (when appears) + *--------------------------------------------------------------*/ + + pred_lt4_tc( exc, *T0, *T0_frac, inter4_2, imp_pos, i_subfr ); + + if( L_frame == L_FRAME ) + { + interp_code_5over2(&exc[i_subfr], &bwe_exc[i_subfr * HIBND_ACB_L_FAC], L_SUBFR); + } + else + { + interp_code_4over2(&exc[i_subfr], &bwe_exc[i_subfr * 2], L_SUBFR); + } + + *position = imp_pos + i_subfr; + + return; +} +/*-------------------------------------------------------------------* + * tc_classif() + * + * TC subframe classification decoding + *-------------------------------------------------------------------*/ + +short tc_classif( + Decoder_State *st, /* i/o: decoder state structure */ + const short L_frame /* i : length of the frame */ +) +{ + short tc_subfr, indice; + + if( L_frame == L_FRAME ) + { + if ( get_next_indice( st, 1 ) ) + { + tc_subfr = TC_0_0; + } + else + { + if ( get_next_indice( st, 1 ) ) + { + tc_subfr = 0; + + if ( get_next_indice( st, 1 ) ) + { + tc_subfr = TC_0_192; + } + else + { + if ( get_next_indice( st, 1 ) ) + { + tc_subfr = TC_0_64; + } + else + { + tc_subfr = TC_0_128; + } + } + } + else + { + if ( get_next_indice( st, 1 ) ) + { + tc_subfr = L_SUBFR; + } + else + { + if ( get_next_indice( st, 1 ) ) + { + tc_subfr = 2*L_SUBFR; + } + else + { + tc_subfr = 3*L_SUBFR; + } + } + } + } + } + else /* L_frame == L_FRAME16k */ + { + indice = (short) get_next_indice( st, 2 ); + + if( indice < 3 ) + { + tc_subfr = indice * L_SUBFR; + } + else + { + if( get_next_indice( st, 1 ) == 0 ) + { + tc_subfr = 3*L_SUBFR; + } + else + { + tc_subfr = 4*L_SUBFR; + } + } + } + + return( tc_subfr ); +} diff --git a/lib_dec/updt_dec.c b/lib_dec/updt_dec.c new file mode 100644 index 000000000..ab85b1331 --- /dev/null +++ b/lib_dec/updt_dec.c @@ -0,0 +1,586 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "prot.h" +#include "rom_com.h" +#include "cnst.h" + +/*-------------------------------------------------------------------* + * updt_dec() + * + * Common updates (all frame types) + *-------------------------------------------------------------------*/ + +void updt_dec( + Decoder_State *st, /* i/o: state structure */ + const short L_frame, /* i : length of the frame */ + const short coder_type, /* i : coding type */ + const float *old_exc, /* i : buffer of excitation */ + const float *pitch_buf, /* i : floating pitch values for each subframe */ + const float Es_pred, /* i : predicited scaled innovation energy */ + const float *Aq, /* i : A(z) quantized for all subframes */ + const float *lsf_new, /* i : current frame LSF vector */ + const float *lsp_new, /* i : current frame LSP vector */ + const float voice_factors[], /* i : voicing factors */ + const float *old_bwe_exc, /* i : buffer of excitation */ + const float *gain_buf +) +{ + short i; + short tmp_seed; + + /* update old excitation buffer */ + mvr2r( &old_exc[L_frame], st->old_exc, L_EXC_MEM_DEC); + if( !st->Opt_AMR_WB ) + { + mvr2r( &old_bwe_exc[L_FRAME32k], st->old_bwe_exc, PIT16k_MAX * 2 ); + } + + /* update old LSP and LSF vector */ + mvr2r( lsf_new, st->lsf_old, M ); + mvr2r( lsp_new, st->lsp_old, M ); + + /* update last coding type */ + st->last_coder_type = coder_type; + if ( coder_type == INACTIVE || (st->bpf_off == 1 && coder_type != AUDIO && coder_type != TRANSITION) ) + { + /* overwrite previous coding type to help FEC */ + st->last_coder_type = UNVOICED; + } + + if( (coder_type != AUDIO || st->Last_GSC_noisy_speech_flag != 0) && st->Last_GSC_pit_band_idx > 0 ) + { + st->Last_GSC_pit_band_idx = 0; /*The temporal contribution of the GSC is meaningless after 1 frame lost for inactive & unvoiced content */ + } + /* this ensures that st->last_coder_type is never set to INACTIVE in case of AVQ inactive because the FEC does not distinguish between GSC inactive and AVQ inactive */ + + if ( coder_type == INACTIVE && st->total_brate > ACELP_24k40 ) + { + st->last_coder_type = GENERIC; + } + + if( st->Opt_AMR_WB && coder_type == INACTIVE && st->core_brate != SID_1k75 && st->core_brate != FRAME_NO_DATA ) + { + /* overwrite previous coding type to help FEC */ + st->last_coder_type = UNVOICED; + st->last_voice_factor = voice_factors[NB_SUBFR-1]; + } + + if( !st->Opt_AMR_WB ) + { + /* update voicing factor of TBE to help FEC */ + if(st->L_frame == L_FRAME ) + { + st->last_voice_factor = voice_factors[NB_SUBFR-1]; + } + else /* L_frame == L_FRAME16k */ + { + st->last_voice_factor = voice_factors[NB_SUBFR16k-1]; + } + } + + if ( coder_type != AUDIO && coder_type != INACTIVE ) + { + st->noise_lev = NOISE_LEVEL_SP3; + set_f( st->old_y_gain, 0.0f, MBANDS_GN ); + + for( i = 0; i < L_FRAME; i++ ) + { + tmp_seed = st->seed_tcx; + st->Last_GSC_spectrum[i] = own_random( &tmp_seed ) / 32768.0f; + } + } + + /* update last GSC SWB speech flag for FEC */ + st->Last_GSC_noisy_speech_flag = st->GSC_noisy_speech; + + /* update counter for FEC pitch estimate */ + st->upd_cnt++; + if( st->upd_cnt > MAX_UPD_CNT ) + { + st->upd_cnt = MAX_UPD_CNT; + } + + mvr2r( &st->old_pitch_buf[L_frame/L_SUBFR], st->old_pitch_buf, L_frame/L_SUBFR ); + mvr2r( pitch_buf, &st->old_pitch_buf[L_frame/L_SUBFR], L_frame/L_SUBFR ); + mvr2r( &st->mem_pitch_gain[2], &st->mem_pitch_gain[L_frame/L_SUBFR+2], L_frame/L_SUBFR ); + + if( L_frame == L_FRAME ) + { + st->mem_pitch_gain[2] = gain_buf[3]; + st->mem_pitch_gain[3] = gain_buf[2]; + st->mem_pitch_gain[4] = gain_buf[1]; + st->mem_pitch_gain[5] = gain_buf[0]; + } + else + { + st->mem_pitch_gain[2] = gain_buf[4]; + st->mem_pitch_gain[3] = gain_buf[3]; + st->mem_pitch_gain[4] = gain_buf[2]; + st->mem_pitch_gain[5] = gain_buf[1]; + st->mem_pitch_gain[6] = gain_buf[0]; + } + + + /* FEC - update adaptive LSF mean vector */ + mvr2r( st->lsfoldbfi0, st->lsfoldbfi1, M ); + mvr2r( lsf_new, st->lsfoldbfi0, M ); + + /* update of pitch and voicing information for HQ FEC */ + if ( st->last_core != HQ_CORE ) + { + if( !st->Opt_AMR_WB && coder_type == UNVOICED ) + { + st->HqVoicing = 0; + } + else + { + st->HqVoicing = 1; + } + } + + /* SC-VBR */ + st->old_ppp_mode = st->last_ppp_mode_dec; + st->last_ppp_mode_dec = st->ppp_mode_dec; + st->last_nelp_mode_dec = st->nelp_mode_dec; + st->last_vbr_hw_BWE_disable_dec = st->vbr_hw_BWE_disable_dec; + + /* core switching updates */ + mvr2r( &Aq[(st->L_frame/L_SUBFR-1)*(M+1)], st->old_Aq_12_8, M+1 ); + st->old_Es_pred = Es_pred; + + return; +} + +/*-------------------------------------------------------------------* + * updt_IO_switch() + * + * Common updates for AMR-WB IO mode and EVS primary mode switching + *-------------------------------------------------------------------*/ + +void updt_IO_switch_dec( + const short output_frame, /* i : output frame length */ + Decoder_State *st /* i/o: state structure */ +) +{ + float xsp_tmp[M]; + + if( st->last_core == AMR_WB_CORE ) /* switching to EVS primary mode */ + { + /* AMR-WB IO mode uses ISF(ISP), but EVS primary mode LSF(LSP) */ + mvr2r( stable_LSP, xsp_tmp, M ); + isf2lsf( st->lsf_old, st->lsf_old, xsp_tmp, M, INT_FS_12k8 ); + mvr2r( stable_LSP, xsp_tmp, M ); + isp2lsp( st->lsp_old, st->lsp_old, xsp_tmp, M ); + + /* AMR-WB IO mode uses ISF(ISP), but EVS primary mode uses LSF(LSP) */ + mvr2r( stable_LSP, xsp_tmp, M ); + isp2lsp( st->lspCNG, st->lspCNG, xsp_tmp, M ); + st->old_enr_index = min( (short)((float)st->old_enr_index / STEP_AMR_WB_SID * STEP_SID), 127 ); + + /* reset TD BWE buffers */ + set_f( st->old_bwe_exc, 0.0f, PIT16k_MAX * 2 ); + set_f( st->old_bwe_exc_extended, 0.0f, NL_BUFF_OFFSET ); + st->bwe_non_lin_prev_scale = 0.0; + st->last_voice_factor = 0.0f; + + wb_tbe_extras_reset( st->mem_genSHBexc_filt_down_wb2, st->mem_genSHBexc_filt_down_wb3 ); + wb_tbe_extras_reset_synth( st->state_lsyn_filt_shb, st->state_lsyn_filt_dwn_shb, st->mem_resamp_HB ); + + if( output_frame >= L_FRAME32k ) + { + swb_tbe_reset( st->mem_csfilt, st->mem_genSHBexc_filt_down_shb, st->state_lpc_syn, + st->syn_overlap, st->state_syn_shbexc, &st->tbe_demph, &st->tbe_premph, st->mem_stp_swb,&(st->gain_prec_swb) ); + + /* reset GainShape delay for SWB TBE FEC */ + set_f( st->GainShape_Delay, 0, NUM_SHB_SUBFR/2 ); + + swb_tbe_reset_synth( st->genSHBsynth_Hilbert_Mem, st->genSHBsynth_state_lsyn_filt_shb_local ); + } + + if( output_frame == L_FRAME48k ) + { + st->prev_fb_ener_adjust = 0.0f; + set_f(st->fb_state_lpc_syn, 0, LPC_SHB_ORDER); + st->fb_tbe_demph = 0; + fb_tbe_reset_synth( st->fbbwe_hpf_mem, &st->prev_fbbwe_ratio ); + } + + /* reset FD BWE buffers */ + st->prev_mode = NORMAL; + st->prev_Energy = 0.0f; + st->prev_Energy_wb = 0.0f; + st->prev_L_swb_norm = 8; + st->prev_frica_flag = 0; + set_f( st->mem_imdct, 0, L_FRAME48k ); + st->prev_td_energy = 0.0f; + st->prev_weight = 0.2f; + set_f( st->old_wtda_swb, 0, L_FRAME48k ); + + /* HQ core buffers */ + set_f( st->delay_buf_out, 0, HQ_DELTA_MAX*HQ_DELAY_COMP ); + + /* reset the unvoiced/audio signal improvement memories */ + st->seed_tcx = 15687; + st->UV_cnt = 30; + st->LT_UV_cnt = 60.0f; + + st->use_acelp_preq = 0; + if (st->last_flag_filter_NB == 1) + { + st->cldfbSyn->bandsToZero = 0; + } + st->last_active_bandsToZero_bwdec = 0; + st->flag_NB_bwddec = 0; + st->perc_bwddec = 0.0f; + st->last_flag_filter_NB = 0; + st->active_frame_cnt_bwddec = 0; + set_s(st->flag_buffer, 0, 20); + } + else /* switching to AMR-WB IO mode */ + { + /* ISF Q memories */ + set_f(st->mem_MA, 0, M ); + + /* AMR-WB IO mode uses ISF(ISP), but EVS primary mode LSF(LSP) */ + mvr2r( stable_ISP, xsp_tmp, M ); + lsf2isf( st->lsf_old, st->lsf_old, xsp_tmp, M, INT_FS_12k8 ); + mvr2r( stable_ISP, xsp_tmp, M ); + lsp2isp( st->lsp_old, st->lsp_old, xsp_tmp, M ); + + /* AMR-WB IO mode uses ISF(ISP), but EVS primary mode LSF(LSP) */ + mvr2r( stable_ISP, xsp_tmp, M ); + lsp2isp( st->lspCNG, st->lspCNG, xsp_tmp, M ); + st->old_enr_index = min( (short)((float)st->old_enr_index / STEP_SID * STEP_AMR_WB_SID), 63 ); + + /* gain quantization memory */ + set_f(st->past_qua_en, -14.0f, GAIN_PRED_ORDER ); + + /* HF synthesis memories */ + st->ng_ener_ST = -51.0f; + + hf_synth_amr_wb_reset( &st->seed2, st->mem_syn_hf, st->mem_hp_interp, &st->prev_r, &st->fmerit_w_sm, st->delay_syn_hf, + &st->frame_count, &st->ne_min, &st->fmerit_m_sm, &st->voice_fac_amr_wb_hf, &st->unvoicing, + &st->unvoicing_sm, &st->unvoicing_flag, &st->voicing_flag, &st->start_band_old, &st->OptCrit_old ); + + /* reset the unvoiced/audio signal improvement memories */ + st->seed_tcx = 15687; + st->UV_cnt = 30; + st->LT_UV_cnt = 60.0f; + st->Last_ener = 0.0f; + st->lt_voice_fac = 0.0f; + + st->psf_lp_noise = st->lp_noise; + + /* reset VBR signalling */ + st->last_ppp_mode_dec = 0; + st->last_nelp_mode_dec = 0; + st->ppp_mode_dec = 0; + st->nelp_mode_dec = 0; + } + + /* CNG - reset */ + st->ho_hist_size = 0; + + /* ISF Q memories */ + mvr2r( UVWB_Ave, st->mem_AR, M ); + + /* FEC - update adaptive LSF mean vector */ + mvr2r( st->lsf_old, st->lsfoldbfi0, M ); + mvr2r( st->lsf_old, st->lsfoldbfi1, M ); + mvr2r( st->lsf_old, st->lsf_adaptive_mean, M ); + + return; +} + +/*-------------------------------------------------------------------* + * updt_bw_switching() + * + * Updates for BW switching + *-------------------------------------------------------------------*/ + +void updt_bw_switching( + Decoder_State *st, /* i/o: decoder state structure */ + const float *synth /* i : float synthesis signal */ +) +{ + if( st->output_Fs == 32000 && st->bwidth == SWB ) + { + calc_tilt_bwe( synth, &(st->tilt_swb), L_FRAME32k ); + } + + st->prev_enerLH = st->enerLH; + st->prev_enerLL = st->enerLL; + st->last_bwidth = st->bwidth; + + if( st->core == ACELP_CORE ) + { + if( st->bwidth == WB && st->bws_cnt == 0 ) + { + st->last_inner_frame = L_FRAME16k; + } + else + { + st->last_inner_frame = L_FRAME32k; + } + + if(st->prev_mode == HARMONIC) + { + st->prev_weight1 = 0.2f; + } + else + { + st->prev_weight1 = 0.5f; + } + } + else + { + if( st->last_inner_frame >= L_FRAME16k && inner_frame_tbl[st->bwidth] <= L_FRAME16k && st->bws_cnt > 0 && st->bws_cnt < N_WS2N_FRAMES ) + { + st->last_inner_frame = st->last_inner_frame; + } + else + { + st->last_inner_frame = inner_frame_tbl[st->bwidth]; + } + + if(inner_frame_tbl[st->bwidth] >= L_FRAME32k || st->core_brate <= HQ_16k40) + { + if(st->prev_hqswb_clas == HQ_HARMONIC || st->prev_hqswb_clas == HQ_HVQ) + { + st->prev_weight1 = 0.2f; + } + else + { + st->prev_weight1 = 0.5f; + } + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * updt_dec_common() + * + * Common updates for MODE1 and MODE2 + *-------------------------------------------------------------------*/ + +void updt_dec_common( + Decoder_State *st, /* i/o: decoder state structure */ + const short hq_core_type, /* i : HQ core type */ + const float *synth /* i : decoded synthesis */ +) +{ + + st->last_codec_mode = st->codec_mode; + st->last_extl = st->extl; + st->last_L_frame = st->L_frame; + + st->prev_old_bfi = st->prev_bfi; + st->prev_bfi = st->bfi; + st->old_bfi_cnt = st->nbLostCmpt; + st->last_con_tcx = st->con_tcx; + st->con_tcx = 0; + + st->prev_last_core = st->last_core; + + if( st->use_partial_copy ) + { + st->prev_rf_frame_type = st->rf_frame_type; + } + else + { + st->prev_rf_frame_type = INACTIVE; + } + + st->tcxConceal_recalc_exc = 0; + if( (st->rf_frame_type >= RF_TCXFD && st->rf_frame_type <= RF_TCXTD2 && st->use_partial_copy && st->bfi) || !st->bfi ) + { + if( st->bfi && st->last_good <= UNVOICED_TRANSITION && st->clas_dec > UNVOICED_TRANSITION && st->last_con_tcx ) + { + st->tcxConceal_recalc_exc = 1; + } + st->last_good = st->clas_dec; + } + + if ( st->m_frame_type == ACTIVE_FRAME && ( !st->bfi || st->use_partial_copy ) ) + { + st->rf_flag_last = st->rf_flag; + } + + if( st->codec_mode == MODE1 ) + { + if( !st->bfi && st->core_brate > SID_2k40 ) + { + st->last_active_brate = st->total_brate; + } + + st->last_core = st->core; + st->last_hq_core_type = hq_core_type; + } + else if( st->codec_mode == MODE2 ) + { + if( !st->bfi && st->last_is_cng == 0 ) + { + st->last_active_brate = st->total_brate; + } + + if( st->m_frame_type != ACTIVE_FRAME ) + { + st->last_is_cng = 1; + } + + if( !st->bfi ) + { + st->last_core = st->core; + } + st->last_core_bfi = st->core; /* also required for clean channel decoding */ + } + + st->last_core_brate = st->core_brate; + + /* save synthesis for core switching */ + mvr2r( synth + NS2SA(st->output_Fs, ACELP_LOOK_NS+DELAY_BWE_TOTAL_NS), st->old_synth_sw, NS2SA(st->output_Fs, FRAME_SIZE_NS-ACELP_LOOK_NS-DELAY_BWE_TOTAL_NS) ); + + if( (st->core_brate <= SID_2k40 && st->cng_type == FD_CNG) || (st->tcxonly && st->codec_mode == MODE2) ) + { + /* reset LP memories */ + set_zero( st->mem_MA, M ); + if(st->sr_core == 16000) + { + mvr2r( GEWB2_Ave, st->mem_AR, M ); + } + else + { + mvr2r( GEWB_Ave, st->mem_AR, M ); + } + } + + return; +} + +/*-------------------------------------------------------------------* +* update_decoder_LPD_cng() +* +* +*--------------------------------------------------------------------*/ + +void update_decoder_LPD_cng( + Decoder_State *st, + const short coder_type, + float *timeDomainBuffer, + float *A, + float *bpf_noise_buf +) +{ + short i; + float lsp[M], lsf[M], pitch[NB_SUBFR16k]; + float *synth, synth_buf[M+1+L_FRAME_MAX+L_FRAME_MAX/2]; + float tmp; + float buf_synth[OLD_SYNTH_SIZE_DEC+L_FRAME_MAX+M]; + int pf_pitch[NB_SUBFR16k]; + float pf_gain[NB_SUBFR16k]; + + /* LPC -> LSP/lsp */ + a2lsp_stab( A, lsp, st->lsp_old ); + + /* LSP/lsp -> LSF/lsf */ + if( st->L_frame == L_FRAME16k ) + { + lsp2lsf( lsp, lsf, M, INT_FS_16k ); + } + else + { + lsp2lsf( lsp, lsf, M, INT_FS_12k8 ); + } + + mvr2r( st->old_synth, buf_synth, st->old_synth_len ); + mvr2r( timeDomainBuffer, buf_synth+st->old_synth_len, st->L_frame ); + + /* Update synth memory */ + synth = synth_buf + (1+M); + mvr2r( st->syn, synth_buf, 1+M ); + mvr2r( timeDomainBuffer, synth, st->L_frame ); + mvr2r( synth+st->L_frame-(1+M), st->syn, 1+M ); + mvr2r( st->old_synth+st->L_frame, st->old_synth, st->old_synth_len-st->L_frame ); + mvr2r( synth, st->old_synth+st->old_synth_len-st->L_frame, st->L_frame ); + + mvr2r( synth+st->L_frame-(st->L_frame/2), st->old_syn_Overl, st->L_frame/2 ); + + st->tcxltp_last_gain_unmodified = 0.0f; + + /* Update pre-synth memory */ + tmp = synth[-(1+M)]; + preemph( synth-M, st->preemph_fac, M+st->L_frame, &tmp ); + mvr2r( synth+st->L_frame-M, st->mem_syn2, M ); + mvr2r( synth+st->L_frame-L_SYN_MEM, st->mem_syn_r, L_SYN_MEM ); + + /* Update excitation memory */ + assert(st->L_frame < L_EXC_MEM_DEC); + mvr2r( st->old_exc+st->L_frame, st->old_exc, L_EXC_MEM_DEC-st->L_frame ); + residu( A, M,synth, st->old_exc+L_EXC_MEM_DEC-st->L_frame, st->L_frame ); + + /* Update LPC-related memories */ + mvr2r( lsp, st->lsp_old, M ); + mvr2r( lsf, st->lsf_old, M ); + mvr2r( lsp, st->lspold_uw, M ); + mvr2r( lsf, st->lsfold_uw, M ); + + st->envWeighted = 0; + mvr2r( A, st->old_Aq_12_8, M+1 ); + st->old_Es_pred = 0; + + /* Reset acelp memories */ + set_zero( st->dispMem, 8 ); + st->tilt_code = TILT_CODE; + st->gc_threshold = 0.0f; + + /* Update ace/tcx mode */ + st->core = ACELP_CORE; + st->last_is_cng = 1; + + /* Reset TCX overlap */ + st->tcx_cfg.tcx_curr_overlap_mode = st->tcx_cfg.tcx_last_overlap_mode = ALDO_WINDOW; + + /* For BBWE and Postfilter */ + mvr2r( A, &(st->mem_Aq[0]), M+1 ); + mvr2r( A, &(st->mem_Aq[(M+1)]), M+1 ); + mvr2r( A, &(st->mem_Aq[2*(M+1)]), M+1 ); + mvr2r( A, &(st->mem_Aq[3*(M+1)]), M+1 ); + if( st->L_frame == L_FRAME16k ) + { + mvr2r( A, &(st->mem_Aq[4*(M+1)]), M+1 ); + } + + /* Update for concealment */ + st->nbLostCmpt = 0; + st->prev_old_bfi = 0; + + for (i=0; ilsf_adaptive_mean[i] = ( st->lsfoldbfi1[i]+ st->lsfoldbfi0[i] + lsf[i] )/3; + st->lsfoldbfi1[i] = st->lsfoldbfi0[i]; + st->lsfoldbfi0[i] = lsf[i]; + } + + set_f( pitch, (float)L_SUBFR, NB_SUBFR16k ); + + FEC_clas_estim( synth, pitch, st->L_frame, UNVOICED, st->codec_mode, st->mem_syn_clas_estim, &(st->clas_dec), + &st->lp_ener_bfi, st->core_brate, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1.0f, st->narrowBand, 0, + 0, st->preemph_fac, st->tcxonly, st->last_core_brate ); + + /* Postfiltering */ + 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.f; + st->bpf_gain_param = 0; + + 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 000000000..665f6c71c --- /dev/null +++ b/lib_dec/vlpc_1st_dec.c @@ -0,0 +1,38 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "prot.h" + +extern float const dico_lsf_abs_8b[]; + +/*------------------------------------------------------------------* +* vlpc_1st_dec() +* +* +*------------------------------------------------------------------*/ + +void vlpc_1st_dec( + int index, /* input: codebook index */ + float *lsfq, /* i/o: i:prediction o:quantized lsf */ + float sr_core +) +{ + short i; + const float *p_dico; + float scale = sr_core/INT_FS_12k8; + + assert(index < 256); + + p_dico = &dico_lsf_abs_8b[index * M]; + for (i = 0; i < M; i++) + { + lsfq[i] += scale **p_dico++; + } + + return; + +} diff --git a/lib_dec/vlpc_2st_dec.c b/lib_dec/vlpc_2st_dec.c new file mode 100644 index 000000000..bc396636f --- /dev/null +++ b/lib_dec/vlpc_2st_dec.c @@ -0,0 +1,43 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include "prot.h" + +/*------------------------------------------------------------------* +* vlpc_2st_dec() +* +* +*------------------------------------------------------------------*/ + +void vlpc_2st_dec( + float *lsfq, /* i/o: i:1st stage o:1st+2nd stage */ + int *indx, /* input: index[] (4 bits per words) */ + int mode, /* input: 0=abs, >0=rel */ + float sr_core +) +{ + short i; + float w[M]; + int xq[M]; + float scale = sr_core/INT_FS_12k8; + + /* weighting from the 1st stage */ + lsf_weight_2st( lsfq, w, mode, sr_core ); + + /* quantize */ + AVQ_dec_lpc( indx, xq, 2 ); + + /* quantized lsf */ + for( i=0; i +#include "wmc_auto.h" +#include +#include "prot.h" +#include "cnst.h" +#include "rom_com.h" + +/*-------------------------------------------------------------------* + * ppp_voiced_decoder() + * + * Voiced decoder for SC-VBR + *-------------------------------------------------------------------*/ + +void ppp_voiced_decoder( + Decoder_State *st, /* i/o: state structure */ + float *out, /* o : residual signal */ + const float *lpc2, /* i : current frame LPC */ + float *exc, /* i : previous frame excitation */ + float *pitch /* o : floating pitch values for each subframe */ + ,short bfi +) +{ +#define WMC_TOOL_SKIP + short k, delta_lag_D = 0; + float upper_cut_off_freq_of_interest = 0, upper_cut_off_freq = 0; + int pl, l; + float interp_delay[3], temp_l, temp_pl, diff; + + DTFS_STRUCTURE *TMPDTFS = DTFS_new(); + DTFS_STRUCTURE *CURRP_Q_D = DTFS_new(); +#undef WMC_TOOL_SKIP + DTFS_STRUCTURE *dtfs_temp = DTFS_new(); + + if ( st->bwidth == NB ) + { + upper_cut_off_freq_of_interest = 3300.0; + upper_cut_off_freq = 4000.0; + } + else if ( st->bwidth == WB ) + { + upper_cut_off_freq_of_interest = 4000.0; + upper_cut_off_freq = 6400.0; + } + + /* Initialization */ + if (st->firstTime_voiceddec) + { + st->firstTime_voiceddec=0; + + /* (st->PREV_CW_D) = DTFS_new();*/ + st->dtfs_dec_lag = 0; + st->dtfs_dec_nH = 0; + st->dtfs_dec_nH_4kHz = 0; + st->dtfs_dec_upper_cut_off_freq_of_interest = 3300.0; + st->dtfs_dec_upper_cut_off_freq = 4000.0; + + for(k = 0; k < MAXLAG_WI; k++) + { + st->dtfs_dec_a[k] = 0.0; + st->dtfs_dec_b[k] = 0.0; + } + } + pl = (int)min(rint_new(st->old_pitch_buf[(2*NB_SUBFR)-1]),MAX_LAG_PIT); + delta_lag_D = (short) get_next_indice( st, 5 ); + + l = min(MAX_LAG_PIT,pl+delta_lag_D-11); + + temp_pl = (float) pl; + temp_l = (float) l; + + if (temp_pl != temp_l) + { + for(k=0; klast_coder_type == UNVOICED) + { + pl = l; /* if prev frame was sil/uv*/ + } + + if (pl > (int)anint(1.85*l)) + { + pl /= 2; + } + + if (pl*2 <= PIT_MAX && pl <= (int)anint(0.54*l)) + { + pl *= 2; + } + + /* Restoring PPP memories when the last frame is non-PPP or full-rate PPP */ + if (st->last_ppp_mode_dec != 1) + { + DTFS_to_fs(exc-pl, pl, dtfs_temp, st->bwidth == WB ? (short)16000 : (short)8000 ,0); + + st->ph_offset_D = 0.0 ; + + /* Copy over PREV_CW_D into TMPDTFS */ + DTFS_copy(TMPDTFS, *dtfs_temp); + + DTFS_car2pol(TMPDTFS); + + st->lastLgainD = (float) log10(TMPDTFS->lag*DTFS_setEngyHarm(92.0,1104.5,0.0,1104.5,1.0,TMPDTFS)); + st->lastHgainD = (float) log10(TMPDTFS->lag*DTFS_setEngyHarm(1104.5,upper_cut_off_freq_of_interest,1104.5,upper_cut_off_freq,1.0,TMPDTFS)); + + DTFS_to_erb(*TMPDTFS,st->lasterbD); + } + else + { + /* Copy DTFS related parameters from 'st' to 'dtfs_temp' structure */ + dtfs_temp->lag = st->dtfs_dec_lag; + dtfs_temp->nH = st->dtfs_dec_nH; + dtfs_temp->nH_4kHz = st->dtfs_dec_nH_4kHz; + dtfs_temp->upper_cut_off_freq_of_interest = st->dtfs_dec_upper_cut_off_freq_of_interest; + dtfs_temp->upper_cut_off_freq = st->dtfs_dec_upper_cut_off_freq; + + mvr2r(st->dtfs_dec_a, dtfs_temp->a, MAXLAG_WI); + mvr2r(st->dtfs_dec_b, dtfs_temp->b, MAXLAG_WI); + } + + CURRP_Q_D->lag = l; + + /* safety check in case of bit errors */ + if( CURRP_Q_D->lag <= 0 ) + { + CURRP_Q_D->lag = 1; + st->BER_detect = 1; + } + + /* compute nH for lag */ + CURRP_Q_D->nH = (int)floor(upper_cut_off_freq/(((float)INT_FS_12k8)/CURRP_Q_D->lag)); + diff = ((float)INT_FS_12k8) / CURRP_Q_D->lag ; + + if (upper_cut_off_freq-(diff*CURRP_Q_D->nH)>=diff) + { + CURRP_Q_D->nH++; + } + + CURRP_Q_D->nH_4kHz = (int)floor(4000.0/(INT_FS_12k8/CURRP_Q_D->lag)); + + if (4000.0 - (diff*CURRP_Q_D->nH_4kHz) >= diff) + { + CURRP_Q_D->nH_4kHz++; + } + + CURRP_Q_D->upper_cut_off_freq = dtfs_temp->upper_cut_off_freq; + CURRP_Q_D->upper_cut_off_freq_of_interest = dtfs_temp->upper_cut_off_freq_of_interest; + + if ( bfi == 0 ) + { + ppp_quarter_decoder( st, CURRP_Q_D, dtfs_temp->lag, &(st->lastLgainD), &(st->lastHgainD), + &(st->lasterbD[0]), + bfi, + *dtfs_temp ); + } + + WIsyn(*dtfs_temp, CURRP_Q_D, lpc2, &(st->ph_offset_D), out, (short) L_FRAME ,0 ); + + DTFS_copy(dtfs_temp, *CURRP_Q_D); + + /* Copy DTFS related parameters from 'dtfs_temp' to 'st' structure */ + st->dtfs_dec_lag = dtfs_temp->lag; + st->dtfs_dec_nH = dtfs_temp->nH; + st->dtfs_dec_nH_4kHz = dtfs_temp->nH_4kHz; + st->dtfs_dec_upper_cut_off_freq_of_interest = dtfs_temp->upper_cut_off_freq_of_interest; + st->dtfs_dec_upper_cut_off_freq = dtfs_temp->upper_cut_off_freq; + + mvr2r(dtfs_temp->a, st->dtfs_dec_a, MAXLAG_WI); + mvr2r(dtfs_temp->b, st->dtfs_dec_b, MAXLAG_WI); + + free(TMPDTFS); + free(CURRP_Q_D); + free(dtfs_temp); + + return; +} diff --git a/lib_dec/voip_client.c b/lib_dec/voip_client.c new file mode 100644 index 000000000..c4c45b798 --- /dev/null +++ b/lib_dec/voip_client.c @@ -0,0 +1,365 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include +#include "options.h" +#include "prot.h" +#include "cnst.h" +#include "rom_com.h" +#include "EvsRXlib.h" +#include "g192.h" +#include "evs_rtp_payload.h" + +#define WMC_TOOL_SKIP + +/*------------------------------------------------------------------------------------------* + * Global variables + *------------------------------------------------------------------------------------------*/ +extern long frame; /* Counter of frames */ + +/*------------------------------------------------------------------------------------------* + * Local constants + *------------------------------------------------------------------------------------------*/ + +#define PCMBUFSIZE 1920 + +/*------------------------------------------------------------------------------------------* + * decodeVoip() + * + * Main function for EVS decoder with VOIP mode + *------------------------------------------------------------------------------------------*/ + +int decodeVoip( + Decoder_State *st, + FILE *f_stream, + FILE *f_synth, +#ifdef SUPPORT_JBM_TRACEFILE + const char *jbmTraceFileName, +#endif + const char *jbmFECoffsetFileName, /* : Output file for Optimum FEC offset */ + const short quietMode +) +{ + /* input/output */ + G192_HANDLE g192 = NULL; + G192_ERROR g192err; + EVS_RTPDUMP_DEPACKER rtpdumpDepacker; + EVS_RTPDUMP_DEPACKER_ERROR rtpdumpDepackerError = EVS_RTPDUMP_DEPACKER_NO_ERROR; + + short optimum_offset,FEC_hi; + FILE *f_offset = NULL; + + /* main loop */ + unsigned int nextPacketRcvTime_ms = 0; + unsigned int 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] */ + short dec_delay, zero_pad; + + unsigned char au[2560]; + short auSize; + unsigned char *auPtr = NULL; + bool isAMRWB_IOmode; + uint16_t frameTypeIndex; + bool qBit; + unsigned short rtpSequenceNumber; + unsigned int rtpTimeStamp; + + Word16 pcmBuf[3 * L_FRAME48k] = {0}; + unsigned int pcmBufSize = 3 * L_FRAME48k; + + rtpdumpDepacker.rtpdump = NULL; + if( st->bitstreamformat == VOIP_RTPDUMP ) + { + rtpdumpDepackerError = EVS_RTPDUMP_DEPACKER_open(&rtpdumpDepacker, f_stream, st->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->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 (wraps decoder) */ + rxerr = EVS_RX_Open(&hRX, st, 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 name: %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(st->output_Fs, get_delay(DEC, st->output_Fs) + 0.5f); + zero_pad = dec_delay; + + + /* read first packet */ + + if (st->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, &rtpSequenceNumber, &rtpTimeStamp, + &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( ; ; ) + { + unsigned int nSamples = 0; + /* read all packets with a receive time smaller than the system time */ + while( 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->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, &rtpSequenceNumber, &rtpTimeStamp, + &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 = (unsigned int) -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 == (unsigned int)(-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->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; + } + + if ( dec_delay == 0 ) + { + fwrite( pcmBuf, sizeof(Word16), nSamples, f_synth ); + } + else + { + if ( dec_delay <= (short)nSamples ) + { + fwrite( pcmBuf + dec_delay, sizeof(Word16), nSamples - dec_delay, f_synth ); + dec_delay = 0; + } + else + { + 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 */ + set_s( 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 ); + } + fprintf( stdout, "\n\n" ); + + /* free memory etc. */ + G192_Reader_Close(&g192); + EVS_RTPDUMP_DEPACKER_close(&rtpdumpDepacker); + EVS_RX_Close(&hRX); + return 0; +} +#undef WMC_TOOL_SKIP diff --git a/lib_dec/waveadjust_fec_dec.c b/lib_dec/waveadjust_fec_dec.c new file mode 100644 index 000000000..4de5805ae --- /dev/null +++ b/lib_dec/waveadjust_fec_dec.c @@ -0,0 +1,785 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include +#include +#include +#include +#include +#include "prot.h" + +#define WMC_TOOL_SKIP + + +static void LpFilter2(float *x, float *y, int N, float *mem); +static float harmo(float *X, int n, float f); +static int Is_Periodic(float cov_max, int zp, float ener, float ener_mean,int pitch, int Framesize, float *mdctdata); +static float sig_tilt(float *s, int FrameSize); +static int zero_pass(float *s, int N); +static float dot(float *a, float *b, int N); +static int array_max_indx(float *s, int N); + +/* Decoder side */ +static void LpFilter2(float *x, float *y, int N, float *mem) +{ + int i; + y[0] = 0.18f * mem[0] + 0.64f * mem[1] + 0.18f * x[0]; + y[1] = 0.18f * mem[1] + 0.64f * y[0] + 0.18f * x[1]; + for (i = 2; i < N; i++) + { + y[i] = 0.18f * y[i-2] + 0.64f * y[i-1] + 0.18f * x[i]; + } +} + +static float harmo(float *X, int n, float f) +{ + int h, k, m = 8; + float ener = 0, ener_harmo = 0; + for (k = 1; k < m+1; k++) + { + h = (int)(k*f - 0.5f); + if (k*f - h > 0.5f) + { + ener_harmo += X[h]*X[h] + X[h+1]*X[h+1]; + } + else + { + ener_harmo += X[h]*X[h]; + } + } + for (k = 0; k < n; k++) + { + ener += X[k]*X[k]; + } + return ener_harmo/(ener+EPSILON); +} + +static int Is_Periodic(float cov_max, int zp, float ener, float ener_mean,int pitch, int Framesize, float *mdctdata) +{ + int flag =0; + float f = 2.0f*Framesize/pitch; + float harm; + harm = harmo(mdctdata /*X*/, Framesize, f); + if (ener < 50 || (ener < ener_mean - 8.0f && cov_max < 0.9f)) + { + flag = 0; + } + else if (cov_max > 0.8f) + { + flag = 1; + } + else if (zp > 100) + { + flag = 0; + } + else if (ener < ener_mean - 6) + { + flag = 0; + } + else if (ener > ener_mean + 1 && cov_max > 0.6f) + { + flag = 1; + } + else if (harm < 0.7f) + { + flag = 0; + } + else + { + flag = 1; + } + return flag; +} + +static int zero_pass(float *s, int N) +{ + int zp = 0, i; + for (i = 1; i < N; i++) + { + if (s[i-1] * s[i] <= 0) + { + zp++; + } + } + return zp; +} + +static float dot(float *a, float *b, int N) +{ + float sum = 0; + int i; + for (i = 0; i < N; i++) + { + sum += (float)(a[i] * b[i]); + } + return sum; +} + +static int array_max_indx(float *s, int N) +{ + int i, indx = 0; + for (i = 0; i < N; i++) + { + if (s[i] > s[indx]) + { + indx = i; + } + } + return indx; +} + +static float sig_tilt(float *s, int FrameSize) +{ + float tilt, enr1, enr2; + int subFrameSize, shift = 2; + float *p1, *p2; + subFrameSize = FrameSize>>2; + p1 = s+subFrameSize; + p2 = s+subFrameSize-shift; + enr1 = dot(p1, p2, FrameSize-subFrameSize); + enr2 = dot(p1, p1, FrameSize-subFrameSize); + tilt = enr1 / (enr2+EPSILON); + return tilt; +} + +static int pitch_search(float *s, /* lastPcmOut */ + float *outx_new, + int Framesize, + float *voicing, + int *zp, + float *ener, + float ener_mean, + float *mdct_data, + int curr_mode + ) +{ + int pitch = 0, t, i; + float cov_max = 0, temp = 0, tmp, tilt, mdct_ener = 0, low_freq_rate; + float s_LP[L_FRAME_MAX] = {0}; + float mem[2]= {0}; + short start_pos, end_pos; + int cov_size; + int flag = 0, zp_current; + int curr_frmsize = Framesize/curr_mode; + float tmp_last = 0; /* not needed, just to avoid compiler warning */ + float cov_max_tmp = 0; + zp_current = zero_pass(outx_new, curr_frmsize); + + if (curr_mode==2) + { + zp_current = zp_current << 1; + } + if (Framesize <= 256) + { + if (zp_current > 70) + { + return 0; + } + } + else + { + if (zp_current > 105) + { + return 0; + } + } + if (curr_mode == 2) + { + mdct_data = mdct_data + (Framesize>>1); + } + + for (i = 0; i < 30/curr_mode; i++) + { + mdct_ener += mdct_data[i]*mdct_data[i]; + } + low_freq_rate = mdct_ener; + for (i = 30/curr_mode; i < Framesize/curr_mode; i++) + { + mdct_ener += mdct_data[i]*mdct_data[i]; + } + low_freq_rate /= (mdct_ener+EPSILON); + if (curr_mode == 2) + { + mdct_data = mdct_data - (Framesize>>1); + } + if(low_freq_rate < 0.02f) + { + return 0; + } + + LpFilter2(s, s_LP, Framesize, mem); + tilt = sig_tilt(s_LP, Framesize); + if (Framesize <= 320) + { + if (tilt < 0.5f) + { + return 0; + } + } + else + { + if (tilt < 0.7f) + { + return 0; + } + } + if (Framesize <= 320) + { + start_pos = (int)(Framesize * 34/256.0 + 0.5f); + end_pos = (int)(Framesize * 3/4.0 + 0.5f); + for (t = start_pos; t < end_pos; t++) + { + cov_size = Framesize-t; + tmp = dot(s_LP, s_LP+t, cov_size)/cov_size; + if (t > start_pos) /* don't use the first value */ + { + if ( tmp > tmp_last) /* store the current cov, if it is larger than the last one */ + { + cov_max_tmp = tmp; + } + else if (cov_max < cov_max_tmp) /* otherwise */ + { + cov_max = cov_max_tmp; /* use the last value cov, being a max */ + pitch = t-1; /* and the last index as pitch */ + } + } + tmp_last = tmp; + } + temp = (float)(sqrt(dot(s_LP+pitch, s_LP+pitch, Framesize-pitch)) * + sqrt(dot(s_LP,s_LP,Framesize-pitch))); + *voicing = cov_max * (Framesize - pitch) / (temp + EPSILON); + { + float temp2, voicing2; + temp2 = (float)(sqrt(dot(s_LP+(pitch>>1), s_LP+(pitch>>1), Framesize-(pitch>>1))) * + sqrt(dot(s_LP,s_LP,Framesize-(pitch>>1)))); + voicing2 = dot(s_LP+(pitch>>1),s_LP,Framesize-(pitch>>1))/temp2; + if (voicing2 > *voicing) + { + pitch = pitch>>1; + *voicing = voicing2; + } + } + } + else + { + float s_tmp[L_FRAME_MAX]; + int Framesize_tmp = Framesize>>1; + int pitch_tmp[3]; + for (i = 0; i < Framesize_tmp; i++) + { + s_tmp[i] = s_LP[2*i]; + } + start_pos = (int)((34.0f*Framesize_tmp)/256 + 0.5f); + end_pos = (int)((Framesize_tmp>>1)*1.5f + 0.5f); + cov_max = 0; + pitch = 0; + for (t = start_pos; t < end_pos; t++) + { + cov_size = Framesize_tmp-t; + tmp = dot(s_tmp, s_tmp+t, cov_size)/cov_size; + if (t > start_pos) /* don't use the first value */ + { + if ( tmp > tmp_last) /* store the current cov, if it is larger than the last one */ + { + cov_max_tmp = tmp; + } + else if (cov_max < cov_max_tmp) /* otherwise */ + { + cov_max = cov_max_tmp; /* use the last value cov, being a max */ + pitch = t-1; /* and the last index as pitch */ + } + } + tmp_last = tmp; + } + + if (pitch > 0) + { + pitch_tmp[0] = max(2*pitch - 1,0); + pitch_tmp[1] = 2*pitch; + pitch_tmp[2] = 2*pitch + 1; + cov_max = 0; + pitch = 0; + for (i = 0; i < 3; i++) + { + cov_size = Framesize - pitch_tmp[i]; + temp = (float)(sqrt(dot(s_LP+pitch_tmp[i], s_LP+pitch_tmp[i], cov_size)) * + sqrt(dot(s_LP,s_LP,cov_size))); + tmp = dot(s_LP, s_LP + pitch_tmp[i], cov_size)/(temp+EPSILON); + if (tmp > cov_max) + { + cov_max = tmp; + pitch = pitch_tmp[i]; + } + } + *voicing = cov_max; + } + } + if (pitch > 0) + { + flag = Is_Periodic(*voicing, *zp, *ener, ener_mean, pitch, Framesize, mdct_data); + } + if (flag == 0 ) + { + pitch = 0; + } + return pitch; +} + +static int OverlapAdd(float *pitch125_data, float *sbuf, int n, int pitch, int Bufsize) +{ + int pitch125 = (int)floor(0.5f+(1.25f*(float)pitch)); + int Loverlap = pitch125 - pitch; + int n1 = min(Loverlap, Bufsize-n); + int n2 = min(pitch125, Bufsize-n); + int i; + float tmp, dat; + for (i = 0; i < n1; i++) + { + tmp = (float)i/(float)Loverlap; + dat = sbuf[n+i]; + sbuf[n+i] = (float)((1.0 - tmp)*dat + tmp*pitch125_data[i]); + } + for (i = n1; i < n2; i++) + { + sbuf[n+i] = pitch125_data[i]; + } + return (n+pitch); +} + +static void add_noise (float * const sbuf, + float * const outx_new_n1, + float const* const noise_seg, + int const Len, + float * const gain, + float const* const gain_n, + int const firstFrame) +{ + int i; + + if (!firstFrame) + { + sbuf[0] += *gain * (noise_seg[0] - 0.68f*(*outx_new_n1)); + *gain = 0.99f*(*gain) + 0.01f*(*gain_n); + } + for (i = 1; i < Len; i++) + { + sbuf[i] += *gain * (noise_seg[i] - 0.68f*noise_seg[i-1]); + *gain = 0.99f*(*gain) + 0.01f*(*gain_n); + } + *outx_new_n1 = noise_seg[i-1]; + +} + +static +int waveform_adj( + float *overlapbuf, + float *outdata2, + float *outx_new, + float *data_noise, + float *outx_new_n1, + float *nsapp_gain, + float *nsapp_gain_n, + int Framesize, + int T_bfi, + float voicing, + int curr_mode, + int pitch) +{ + int i, zp1, zp2; + float sbuf[L_FRAME_MAX] = {0}; + + zp1 = zero_pass(outdata2, Framesize>>1); + zp2 = zero_pass(outdata2+(Framesize>>1), Framesize>>1); + + /* judge if the pitch is usable */ + if( 4*max(zp1,1) < zp2 ) + { + return 0; + } + + /* adjust the pitch value */ + if (T_bfi && pitch <= Framesize>>1 && Framesize > 256 && curr_mode == 1) + { + int i1 = 0, i2 = 0; + i1 = 1 + array_max_indx(outx_new, pitch); + i2 = 1 + array_max_indx(outx_new+pitch, pitch); + if ((float)(i2+pitch-i1)<(1.25f*pitch) && (1.25f*(i2+pitch-i1))>(float)pitch && (float)(i2+pitch-i1)<(float)(Framesize>>1)) + { + pitch = i2+pitch-i1; + } + } + + { + int pitch125 = 0, Loverlap = 0, n = 0; + float pitch125_data[L_FRAME_MAX] = {0}; + + pitch125 = (int)floor(0.5f+(1.25f*(float)pitch)); + Loverlap = pitch125 - pitch; + memcpy(pitch125_data, outdata2+Framesize-pitch, sizeof(float)*pitch); + memcpy(pitch125_data+pitch, outx_new, sizeof(float)*Loverlap); + memcpy(sbuf, outx_new, sizeof(float)*Framesize); + { + float tmp_buf[L_FRAME_MAX]= {0}, *p_tmp = tmp_buf+1; + memcpy(p_tmp, pitch125_data, sizeof(float)*pitch125); + p_tmp[-1] = outdata2[Framesize-pitch-1]; + p_tmp[pitch125] = outx_new[Loverlap]; + for (i = 0; i < pitch125; i++) + { + pitch125_data[i] = 0.18f*p_tmp[i-1]+0.64f*p_tmp[i]+0.18f*p_tmp[i+1]; + } + } + while (n < Framesize) /* periodical extension */ + { + n = OverlapAdd(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 */ + mvr2r(&sbuf[Framesize/4], pitch125_data, (3*Framesize)/4); + + *nsapp_gain = 0.0; + *nsapp_gain_n = 1.0f - voicing/2; + { + int size = Framesize; + /* use last good signal for noise generation */ + add_noise(sbuf, outx_new_n1, outdata2, size, nsapp_gain, nsapp_gain_n, 1); + /* save current (noisy) output from IMDCT */ + mvr2r(outx_new, data_noise, size); + } + /* overlapbuf can now be filled with sbuf, needed for subsequently lost frames */ + mvr2r(pitch125_data, &overlapbuf[Framesize/4], (3*Framesize)/4); + } + for (i = 0; i < Framesize; i++) + { + outx_new[i] = sbuf[i]; + } + + return pitch; +} + +void waveform_adj2(float *overlapbuf, + float *outx_new, + float *data_noise, + float *outx_new_n1, + float *nsapp_gain, + float *nsapp_gain_n, + float *recovery_gain, + float step_concealgain, + int pitch, + int Framesize, + int delay, + int bfi_cnt, + int bfi) +{ + int i, n=0; + float ratio; + float sbuf[L_FRAME_MAX]; + if (pitch > 0) + { + while (n < Framesize) + { + /* periodical extension */ + for (i = 0; i < min(pitch, Framesize-n); i++) + { + sbuf[n+i] = overlapbuf[Framesize-pitch+i]; + } + n += pitch; + } + for (i = 0; i < Framesize; i++) + { + overlapbuf[i] = sbuf[i]; + } + { + int size = Framesize; + float* 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); + if (bfi) + { + /* save current (noisy) output from IMDCT */ + mvr2r(outx_new, noise_ptr, size); + } + } + if (bfi_cnt == 4 || bfi == 0) + { + if (bfi == 0) + { + int gain_zero_start = 10000; + /* overlap-and-add */ + if (step_concealgain > EPSILON) + { + gain_zero_start = (int)min((float)L_FRAME48k, (*recovery_gain/step_concealgain)) + 1; + } + + if (delay > 0) + { + Framesize -= delay; + } + for (i = 0; i < min(gain_zero_start, Framesize); i++) + { + ratio = (float)i/(float)Framesize; + outx_new[i] = (1-ratio)*sbuf[i]**recovery_gain+ratio*outx_new[i]; + *recovery_gain -= step_concealgain; + } + for (i = gain_zero_start; i < Framesize; i++) + { + ratio = (float)i/(float)Framesize; + outx_new[i] = ratio*outx_new[i]; + } + if (*recovery_gain < 0.0f) + { + *recovery_gain = 0.0f; + } + } + else + { + /* overlap-and-add */ + for (i = 0; i < Framesize; i++) + { + ratio = (float)i/(float)Framesize; + outx_new[i] = (1-ratio)*sbuf[i]+ratio*outx_new[i]; + } + } + } + else + { + for (i = 0; i < Framesize; i++) + { + outx_new[i] = sbuf[i]; + } + } + } + return; +} + +void set_state(int *state, int num, int N) +{ + int i; + for (i = 0; i < N-1; i++) + { + state[i] = state[i+1]; + } + state[N-1] = num; + return; +} + +void concealment_init(int N, void *_plcInfo) +{ + T_PLCInfo *plcInfo = (T_PLCInfo*)_plcInfo; + int i; + + plcInfo->FrameSize = N; + plcInfo->Pitch = 0; + plcInfo->T_bfi = 0; + plcInfo->outx_new_n1 = 0.0f; + plcInfo->nsapp_gain = 0.0f; + plcInfo->nsapp_gain_n = 0.0f; + plcInfo->ener_mean = 59.4260f; + plcInfo->ener = 0.0f; + plcInfo->zp = N; + plcInfo->recovery_gain = 0.0f; + plcInfo->step_concealgain = 0.0f; + plcInfo->concealment_method = TCX_NONTONAL; + plcInfo->subframe = 0; + plcInfo->nbLostCmpt = 0; + plcInfo->seed = 21845; + + for (i = 0; i < TCX_TONALITY_INIT_CNT; i++) + { + plcInfo->TCX_Tonality[i] = 1; + } + for (i = TCX_TONALITY_INIT_CNT; i < DEC_STATE_LEN; i++) + { + plcInfo->TCX_Tonality[i] = 0; + } + for (i = 0; i < MAX_POST_LEN; i++) + { + plcInfo->Transient[i] = 1; + } + + for (i = 0; i < L_FRAME_MAX; i++) + { + plcInfo->data_reci2[i] = 0; + } + return; +} + +void concealment_decode(int curr_mode, float *invkoef, void *_plcInfo) +{ + T_PLCInfo *plcInfo = (T_PLCInfo*)_plcInfo; + int i; + int N = plcInfo->FrameSize; + short *seed = &(plcInfo->seed); + short sign; + if (plcInfo->concealment_method == TCX_NONTONAL) + { + if (curr_mode == 1) + { + /* copy the data of the last frame */ + mvr2r(plcInfo->data_reci2, invkoef, N); + /* sign randomization */ + for (i = 0; i < N; i++) + { + sign = ((own_random(seed)>>15)<<1)+1; + invkoef[i] *= sign; + } + } + } + return; +} + +void concealment_update(int bfi, int curr_mode, int tonality, float *invkoef, void *_plcInfo) +{ + T_PLCInfo *plcInfo = (T_PLCInfo*)_plcInfo; + float *data_reci2 = plcInfo->data_reci2; + int *tcx_tonality = plcInfo->TCX_Tonality; + int FrameSize = plcInfo->FrameSize; + int subframe = plcInfo->subframe; + int i; + if (curr_mode == 1) + { + set_state(plcInfo->Transient, curr_mode, MAX_POST_LEN); + for (i = 0; i < FrameSize; i++) + { + data_reci2[i] = invkoef[i]; + } + if (!bfi) + { + set_state(tcx_tonality, tonality, DEC_STATE_LEN); + } + } + else + { + if (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(), low_freq_rate is derived on the last good + TCX-10 spectrum */ + if (!bfi || subframe == 0) + { + float *ptr = data_reci2+subframe; + for (i = 0; i < FrameSize>>1; i++) + { + ptr[i] = invkoef[i]; + } + } + } + return; +} + +void concealment_update2(float *outx_new, void *_plcInfo, int FrameSize) +{ + T_PLCInfo *plcInfo = (T_PLCInfo*)_plcInfo; + plcInfo->zp = zero_pass(outx_new, FrameSize); + plcInfo->ener = dot(outx_new, outx_new, FrameSize)/FrameSize; + plcInfo->ener = 10 * (float)log10(plcInfo->ener+EPSILON); + if (plcInfo->zp < 100 && plcInfo->ener > 50) + { + plcInfo->ener_mean = 0.98f*plcInfo->ener_mean + 0.02f*plcInfo->ener; + } + return; +} + +void concealment_signal_tuning(int bfi, int curr_mode, float *outx_new, void *_plcInfo, int nbLostCmpt, int pre_bfi, + float *OverlapBuf, int past_core_mode, float *outdata2, Decoder_State *st) +{ + T_PLCInfo *plcInfo = (T_PLCInfo*)_plcInfo; + int FrameSize = plcInfo->FrameSize; + float *data_reci2 = plcInfo->data_reci2; + int Pitch = plcInfo->Pitch; + float voicing = 0; + if (bfi) + { + + if (st->enablePlcWaveadjust && plcInfo->concealment_method == TCX_NONTONAL) + { + if (nbLostCmpt == 1) + { + plcInfo->Pitch = pitch_search(outdata2, + outx_new, + FrameSize, + &voicing, + &plcInfo->zp, + &plcInfo->ener, + plcInfo->ener_mean, + data_reci2, + curr_mode + ); + if (plcInfo->Pitch) /* waveform adjustment for the first lost frame */ + { + plcInfo->Pitch = waveform_adj(OverlapBuf, + outdata2, + outx_new, + plcInfo->data_noise, + &plcInfo->outx_new_n1, + &plcInfo->nsapp_gain, + &plcInfo->nsapp_gain_n, + FrameSize, + plcInfo->T_bfi, + voicing, + curr_mode, + plcInfo->Pitch); + } + } + else if (nbLostCmpt < 5) /* waveform adjustment for the 2nd~4th lost frame */ + { + waveform_adj2(OverlapBuf, + outx_new, + plcInfo->data_noise, + &plcInfo->outx_new_n1, + &plcInfo->nsapp_gain, + &plcInfo->nsapp_gain_n, + &plcInfo->recovery_gain, + plcInfo->step_concealgain, + Pitch, + FrameSize, + 0, + nbLostCmpt, + bfi); + } + } + plcInfo->T_bfi = 1; + } + else + { + if (pre_bfi && + past_core_mode != 0 && + st->last_total_brate >= HQ_48k && + st->last_codec_mode == MODE2) + { + if (plcInfo->concealment_method == TCX_NONTONAL) + { + if (plcInfo->nbLostCmpt < 4) /* smoothing of the concealed signal with the good signal */ + { + waveform_adj2(OverlapBuf, + outx_new, + plcInfo->data_noise, + &plcInfo->outx_new_n1, + &plcInfo->nsapp_gain, + &plcInfo->nsapp_gain_n, + &plcInfo->recovery_gain, + plcInfo->step_concealgain, + Pitch, + FrameSize, + 0, + plcInfo->nbLostCmpt + 1, + bfi); + } + } + } + else + { + plcInfo->T_bfi = 0; + } + } + return; +} diff --git a/lib_enc/ACcontextMapping_enc.c b/lib_enc/ACcontextMapping_enc.c new file mode 100644 index 000000000..ce1a9d4f9 --- /dev/null +++ b/lib_enc/ACcontextMapping_enc.c @@ -0,0 +1,637 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + + +/*-------------------------------------------------------------------* +* ACcontextMapping_encode2_no_mem_s17_LC() +* +* Arithmetic encoder +*-------------------------------------------------------------------*/ + +void ACcontextMapping_encode2_no_mem_s17_LC( + Encoder_State *st, + int *x, + int nt, + int lastnz, + int nbbits, + int resQMaxBits, + CONTEXT_HM_CONFIG *hm_cfg) +{ + int ptr[BITBUFSIZE]; + Tastat as, as_overflow; + int bp, bp_overflow; + int a1, b1, a1_i, b1_i, k; + int t, pki, lev1; + int rateFlag; + int value; + int nbbits_ntuples, nbbits_lsbs, nbbits_signs,nbbits_signs_overflow, nbbits_lsbs_overflow, flag_overflow; + int *lsbs_bits; + int nt_half; + int c[2], *ctx; + int p1, p2; + int ii[2], idx1, idx2, idx; + int numPeakIndicesOrig, numHoleIndices; + int signs[N_MAX]; + int nbbits_m2; + + a1 = 0; /* to avoid compilation warnings */ + b1 = 0; /* to avoid compilation warnings */ + + /* Rate flag */ + if (nbbits > 400) + { + rateFlag = 2 << NBITS_CONTEXT; + } + else + { + rateFlag = 0; + } + + /* Init */ + nt_half = nt >> 1; + c[0] = c[1] = 0; + + /* Bits for encoding the number of encoded tuples */ + nbbits_ntuples = 0; + k = 1; + + while (knumPeakIndices; + hm_cfg->numPeakIndices = min(hm_cfg->numPeakIndices, lastnz); + numHoleIndices = lastnz - hm_cfg->numPeakIndices; + + /* Mark hole indices beyond lastnz as pruned */ + for (k=numHoleIndices; knumHoleIndices; ++k) + { + hm_cfg->holeIndices[k] = hm_cfg->holeIndices[k] + nt; + } + + ii[0] = numPeakIndicesOrig; + ii[1] = 0; + + p1 = p2 = 0; /* to avoid compilation warnings */ + } + else + { + /* unmapped domain */ + ii[0] = 0; + + p1 = p2 = 0; + + /* Find last non-zero tuple */ + /* ensure termination of while loop by dummy value */ + a1 = x[0]; + x[0] = 1; + + while (x[lastnz-1] == 0 && x[lastnz-2] == 0) + { + lastnz -= 2; + } + x[0] = a1; + } + + lsbs_bits=ptr+nbbits-1; + + /*Start Encoding*/ + ari_start_encoding_14bits(&as); + + /*Main Loop through the 2-tuples*/ + b1_i = -1; + + for (k=0; k= idx) ? 0 : (1 << NBITS_CONTEXT); + + /* Init current 2-tuple encoding */ + + if (flag_overflow != 0) + { + x[a1_i] = 0; + x[b1_i] = 0; + } + + a1 = abs(x[a1_i]); + b1 = abs(x[b1_i]); + + lev1 = -1; + + /*Copy states*/ + ari_copy_states(&as, &as_overflow); + bp_overflow = bp; + nbbits_signs_overflow = nbbits_signs; + nbbits_lsbs_overflow = nbbits_lsbs; + + /*Signs encoding*/ + + if (a1 > 0) + { + signs[nbbits_signs++] = ((unsigned int)x[a1_i] >> (sizeof(unsigned int)*8-1)); + } + + if (b1 > 0) + { + signs[nbbits_signs++] = ((unsigned int)x[b1_i] >> (sizeof(unsigned int)*8-1)); + } + + /* MSBs coding */ + while (max(a1, b1) >= A_THRES) + { + pki = ari_lookup_s17_LC[t + ((lev1+1) << (NBITS_CONTEXT + NBITS_RATEQ))]; + bp = ari_encode_14bits_ext(ptr,bp,&as,VAL_ESC,ari_pk_s17_LC_ext[pki]); + + *lsbs_bits-- = a1 & 1; + *lsbs_bits-- = b1 & 1; + + /* LSBs bit counting */ + nbbits_lsbs += 2; + + a1 >>= 1; + b1 >>= 1; + + lev1 = min(lev1+1, 2); + } + + pki = ari_lookup_s17_LC[t + ((lev1+1) << (NBITS_CONTEXT + NBITS_RATEQ))]; + bp = ari_encode_14bits_ext(ptr,bp,&as,a1+A_THRES*b1,ari_pk_s17_LC_ext[pki]); + + + /* Check bit budget */ + if (bp+as.vobf+nbbits_signs+nbbits_lsbs > nbbits_m2) + { + ari_copy_states(&as_overflow, &as); + bp = bp_overflow; + + if (!flag_overflow) + { + nbbits_signs = nbbits_signs_overflow; + nbbits_lsbs = nbbits_lsbs_overflow; + + if (hm_cfg) + { + flag_overflow = 1; + + /* Code from now only zeros */ + x[a1_i] = 0; + x[b1_i] = 0; + lev1 = -1; + + pki = ari_lookup_s17_LC[t]; + bp = ari_encode_14bits_ext(ptr,bp,&as,0,ari_pk_s17_LC_ext[pki]); + + if (bp+as.vobf+nbbits_signs+nbbits_lsbs>nbbits_m2) + { + ari_copy_states(&as_overflow, &as); + bp = bp_overflow; + break; + } + } + else + { + break; + } + } + else + { + break; + } + } + + /* Update context for next 2-tuple */ + if (p1 == p2) + { + /* peak-peak or hole-hole context */ + + if (lev1 <= 0) + { + t = 1 + (a1 + b1)*(lev1+2); + } + else + { + t = 13 + lev1; + } + + *ctx = (*ctx & 0xf) * 16 + t; + } + else + { + /* mixed context */ + + if (idx1 & 1) + { + /* update first context */ + c[p1] = update_mixed_context(c[p1], abs(x[a1_i])); + } + + if (idx2 & 1) + { + /* update second context */ + c[p2] = update_mixed_context(c[p2], abs(x[b1_i])); + } + } + } /*end of the 2-tuples loop*/ + + + /* End arithmetic coder, overflow management */ + bp = ari_done_encoding_14bits(ptr,bp,&as); + + /*Overflow is detected*/ + + if (k!=lastnz) + { + + if (hm_cfg) + { + /*Fill with zero to be sure that decoder finish at the same position the MSB decoding*/ + + for(; bp>1)-1; + push_next_indice(st, value, nbbits_ntuples); + + /* Push arithmetic coded bits */ + push_next_bits(st, &ptr[nbbits_ntuples], bp - nbbits_ntuples); + + /* Push sign bits */ + push_next_bits(st, signs, nbbits_signs); + bp += nbbits_signs; + + /*write residual Quantization bits*/ + + for(k=0; kindexBuffer; + + for (i=length; i >= 4; i-=2) + { + + if (x[tmp[i-2]] != 0 || x[tmp[i-1]] != 0) + { + last_nz = i; + break; + } + } + } + else + { + /* unmapped kernel */ + + for (i=length; i >= 4; i-=2) + { + + if (x[i-2] != 0 || x[i-1] != 0) + { + last_nz = i; + break; + } + } + } + + return last_nz; +} + + + +/*-------------------------------------------------------------------* +* ACcontextMapping_encode2_estimate_no_mem_s17_LC() +* +* +*-------------------------------------------------------------------*/ + +int ACcontextMapping_encode2_estimate_no_mem_s17_LC( + const int *x, + int nt, + int *lastnz_out, + int *nEncoded, + int target, + int *stop, + CONTEXT_HM_CONFIG *hm_cfg +) +{ + int a1, b1, a1_i, b1_i; + int k, t, pki, lev1; + int lastnz, lastnz2; + int rateFlag; + int nbits_old, nbits; + int stop2; + int proba; + short nlz; + const unsigned short *cum_freq; + long symbol; + const unsigned char *lookup; + int nt_half; + int c[2], *ctx; + int p1, p2; + int ii[2], idx1, idx2, idx; + int numPeakIndicesOrig = 0, numHoleIndices = 0; /* only to avoid compiler warning */ + + /* Rate flag */ + if (target > 400) + { + rateFlag = 2 << NBITS_CONTEXT; + } + else + { + rateFlag = 0; + } + + /* 2 bits = arithmetic coder initialization interval = 1 bits for rounding last proba + 1 bit?*/ + nbits = 2; + /*proba coded on 14bits -> proba=1*/ + proba = 16384; + + /* Init */ + nt_half = nt >> 1; + stop2 = 0; + c[0] = c[1] = 0; + + /* bits to encode lastnz */ + k = 1; + + while (knumPeakIndices; + hm_cfg->numPeakIndices = min(hm_cfg->numPeakIndices, lastnz); + numHoleIndices = lastnz - hm_cfg->numPeakIndices; + + /* Mark hole indices beyond lastnz as pruned */ + for (k=numHoleIndices; knumHoleIndices; ++k) + { + hm_cfg->holeIndices[k] = hm_cfg->holeIndices[k] + nt; + } + + ii[0] = numPeakIndicesOrig; + ii[1] = 0; + + p1 = p2 = 0; /* to avoid compilation warnings */ + } + else + { + /* unmapped domain */ + ii[0] = 0; + + p1 = p2 = 0; + } + + /* Main Loop through the 2-tuples */ + for (k=0; k= idx) ? 0 : (1 << NBITS_CONTEXT); + + /* Init current 2-tuple encoding */ + a1 = abs(x[a1_i]); + b1 = abs(x[b1_i]); + lev1 = -(1 << (NBITS_CONTEXT+NBITS_RATEQ)); + + /* Signs Bits */ + nbits += min(a1, 1); + nbits += min(b1, 1); + + /* pre-compute address of ari_pk_s17_LC_ext[0][Val_esc] to avoid doing it multiple times inside the loop */ + lookup = &ari_lookup_s17_LC[t] + (1 << (NBITS_CONTEXT+NBITS_RATEQ)); + + /* check while condition */ + /* MSBs coding */ + while (max(a1, b1) >= A_THRES) + { + pki = lookup[lev1]; + cum_freq = ari_pk_s17_LC_ext[pki] + VAL_ESC; + /*p1*p2=proba on 28 bits: p=0.5->power(2,27)*/ + proba *= *(cum_freq); + /*Number of leading zero computed in one cycle=norm_l() in BASOP*/ + nlz=2; + while(proba<134217728) /*power(2,27)*/ + { + nlz++; + proba=proba<<1; + } + nbits+=nlz; + /*addition added as shift not done in norm_l(): real shift = 14-nlz*/ + proba>>=14; /*proba is rounded down on 14 bits ->automatic over-estimation of bit consumption*/ + + (a1) >>= 1; + (b1) >>= 1; + + lev1 = min(lev1 + (1 << (NBITS_CONTEXT+NBITS_RATEQ)), 2 << (NBITS_CONTEXT+NBITS_RATEQ)); + /* check while condition */ + } + pki = lookup[lev1]; + symbol = a1 + A_THRES*b1; + cum_freq = ari_pk_s17_LC_ext[pki] + symbol; + /*p1*p2=proba on 28 bits: p=0.5->power(2,27)*/ + proba *= (cum_freq[0] - cum_freq[1]); + /*Number of leading zero computed in one cycle=norm_l() in BASOP*/ + nlz=0; + while(proba<134217728) /*power(2,27)*/ + { + nlz++; + proba=proba<<1; + } + + nbits+=nlz; + proba>>=14; /*proba is rounded down on 14 bits ->automatic over-estimation of bit consumption*/ + + /* Should we truncate? */ + if ( nbits>0 ) + { + stop2 = 1; + + if (*stop) + { + break; + } + } + else + { + if (hm_cfg || k==0 || x[a1_i] || x[b1_i]) + { + nbits_old = nbits+target; + lastnz2 = b1_i+1; + } + } + + /* Update context for next 2-tuple */ + if (p1 == p2) /* peak-peak or hole-hole context */ + { + lev1 >>= NBITS_CONTEXT+NBITS_RATEQ; + + if (lev1 <= 0) + { + t = 1 + (a1 + b1)*(lev1+2); + } + else + { + t = 13 + lev1; + } + + *ctx = (*ctx & 0xf) * 16 + t; + } + else + { + /* mixed context */ + + if (idx1 & 1) + { + /* update first context */ + c[p1] = update_mixed_context(c[p1], abs(x[a1_i])); + } + + if (idx2 & 1) + { + /* update second context */ + c[p2] = update_mixed_context(c[p2], abs(x[b1_i])); + } + } + } /*end of the 2-tuples loop*/ + + nbits += target; + + /* Output */ + + if (*stop) + { + nbits = nbits_old; + } + + if (stop2) + { + stop2 = nbits; + } + *nEncoded = lastnz2; + *stop = stop2; + *lastnz_out = lastnz; + + if (hm_cfg) + { + /* Restore hole indices beyond lastnz */ + for (k=numHoleIndices; knumHoleIndices; ++k) + { + hm_cfg->holeIndices[k] = hm_cfg->holeIndices[k] - nt; + } + hm_cfg->numPeakIndices = numPeakIndicesOrig; + } + + return nbits_old; +} diff --git a/lib_enc/FEC_enc.c b/lib_enc/FEC_enc.c new file mode 100644 index 000000000..72f6a1f15 --- /dev/null +++ b/lib_enc/FEC_enc.c @@ -0,0 +1,240 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*-------------------------------------------------------------------* + * FEC_encode() + * + * Encoder supplementary information for FEC + *-------------------------------------------------------------------*/ + +void FEC_encode( + Encoder_State *st, /* i/o: encoder state structure */ + const float *synth, /* i : pointer to synthesized speech for E computation */ + const short coder_type, /* i : type of coder */ + short clas, /* i : signal clas for current frame */ + const float *fpit, /* i : close loop fractional pitch buffer */ + const float *res, /* i : LP residual signal frame */ + short *last_pulse_pos, /* i/o: Position of the last pulse */ + const short L_frame, /* i : Frame length */ + const long total_brate, /* i : total codec bitrate */ + const long core_brate /* i : total codec bitrate */ +) +{ + short tmpS, index; + short maxi, sign = 0, tmp_FER_pitch; + float enr_q; + + tmpS = 0; + enr_q = 1.0f; + + if( coder_type > UNVOICED && coder_type < AUDIO && core_brate >= ACELP_11k60 ) + { + /*-----------------------------------------------------------------* + * encode signal class (not needed for VC mode since it is clearly voiced) (2 bits) + *-----------------------------------------------------------------*/ + + if ( coder_type != VOICED ) + { + /* encode signal clas with 2 bits */ + if( clas == UNVOICED_CLAS ) + { + index = 0; + } + else if( clas == VOICED_TRANSITION || clas == UNVOICED_TRANSITION ) + { + index = 1; + } + else if( clas == VOICED_CLAS ) + { + index = 2; + } + else + { + index = 3; + } + + push_indice( st, IND_FEC_CLAS, index, FEC_BITS_CLS); + } + + /*-----------------------------------------------------------------* + * Encode frame energy (5 bits) + *-----------------------------------------------------------------*/ + + if( total_brate >= ACELP_16k40 && 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) */ + fer_energy( L_frame, clas, synth, fpit[(L_frame>>6)-1], &enr_q, L_frame ); + + /* 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 ); + + if( tmpS > FEC_ENR_QLIMIT ) + { + tmpS = FEC_ENR_QLIMIT; + } + + if( tmpS < 0 ) + { + tmpS = 0; + } + + push_indice( st, IND_FEC_ENR, tmpS, FEC_BITS_ENR ); + } + + /*-----------------------------------------------------------------* + * Encode last glottal pulse position (8 bits) + *-----------------------------------------------------------------*/ + + if( total_brate >= ACELP_32k && 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 = (short)(fpit[0]); /* take the 1st subframe pitch, since it is easier to retieve it on decoder side */ + + + sign = 0; + maxi = *last_pulse_pos; + if ( maxi < 0 ) + { + sign = 1; + maxi = -maxi; + } + + if ( tmp_FER_pitch >= 128 ) + { + maxi /= 2; + } + + if ( 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; + } + + if( sign == 1 ) + { + maxi += 128; /* use 8 bits (MSB represents the sign of the pulse) */ + } + + push_indice( st, IND_FEC_POS, maxi, FEC_BITS_POS ); + } + + /* find the glottal pulse position of the current frame (could be sent as extra FEC info in the next frame) */ + maxi = 0; + if( clas >= VOICED_CLAS && total_brate >= ACELP_24k40 ) + { + maxi = findpulse( L_frame, res, (short)(fpit[(L_frame>>6)-1]), 0, &sign ); + if ( sign == 1 ) + { + maxi = -maxi; + } + } + + *last_pulse_pos = maxi; + } + else + { + *last_pulse_pos = 0; + } + + return; +} + + +/*-------------------------------------------------------------------* + * FEC_lsf_estim_enc() + * + * 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( + Encoder_State *st, /* i : Encoder static memory */ + const short L_frame, /* i : length of the frame */ + float *lsf /* o : estimated LSF vector */ +) +{ + short i; + float alpha, lsf_mean[M]; + + if( L_frame == L_FRAME ) + { + mvr2r( UVWB_Ave, lsf_mean, M ); + } + else + { + mvr2r( GEWB2_Ave, lsf_mean, M ); + } + + /*----------------------------------------------------------------------* + * Initialize the alpha factor + *----------------------------------------------------------------------*/ + + if( st->last_coder_type == UNVOICED ) + { + /* clearly unvoiced */ + alpha = ALPHA_UU; + } + else if( st->last_coder_type == AUDIO || st->clas == INACTIVE_CLAS ) + { + alpha = 0.995f; + } + else if( st->clas == 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; + } + else if( st->clas == UNVOICED_TRANSITION ) + { + alpha = ALPHA_UT; + } + else if( st->clas == VOICED_CLAS || st->clas == ONSET ) + { + /* clearly voiced - mild convergence to the CNG spectrum for the first three erased frames */ + alpha = ALPHA_V; + } + else if( st->clas == SIN_ONSET ) + { + alpha = ALPHA_S; + } + else + { + /* long erasures and onsets - rapid convergence to the CNG spectrum */ + alpha = ALPHA_VT; + } + + /*----------------------------------------------------------------------* + * Extrapolate LSF vector + *----------------------------------------------------------------------*/ + + /* extrapolate the old LSF vector */ + for (i=0; ilsf_adaptive_mean[i]; + + /* move old LSF vector towards the mean LSF vector */ + lsf[i] = alpha * st->lsf_old[i] + (1.0f - alpha) * lsf_mean[i]; + } + + /* check LSF stability through LSF ordering */ + if( L_frame == L_FRAME ) + { + reorder_lsf( lsf, MODE1_LSF_GAP, M, INT_FS_12k8 ); + } + else /* L_frame == L_FRAME16k */ + { + reorder_lsf( lsf, MODE1_LSF_GAP, M, INT_FS_16k ); + } + + return; +} diff --git a/lib_enc/SNR_calc.c b/lib_enc/SNR_calc.c new file mode 100644 index 000000000..cee0a2be1 --- /dev/null +++ b/lib_enc/SNR_calc.c @@ -0,0 +1,195 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "prot.h" +#include "rom_enc.h" + + + + + + +void SNR_calc(float frame_sb_energy[], /*(i) energy of sub-band divided non-uniformly*/ + float sb_bg_energy[], /*(i) sub-band background energy*/ + float t_bg_energy, /*(i) time background energy of several frames*/ + float *snr, /*(o) frequency domain SNR */ + float *tsnr, /*(o) time domain SNR */ + float frame_energy, /*(i) current frame energy */ + int bandwidth /*(i) band width*/ + ) +{ + int i; + float snr_tmp,tmp; + int SNR_sb_num; + SNR_sb_num = ENERGY_BAND_NUM[bandwidth-CLDFBVAD_NB_ID]; + + snr_tmp = 0; + for(i=0; i< SNR_sb_num; i++) + { + tmp = (frame_sb_energy[i]+0.0001f)/(sb_bg_energy[i]+0.0001f); + tmp = (float)log10(tmp); + if(tmp>-0.1) + { + if(bandwidth == CLDFBVAD_SWB_ID) + { + tmp = tmp*3.2f; + } + else if (bandwidth == CLDFBVAD_WB_ID) + { + tmp = tmp*3.31f; + } + else + { + tmp = tmp*3.0f; + } + snr_tmp += tmp; + } + } + if (snr_tmp<0) + { + snr_tmp = 0; + } + *snr = snr_tmp/SNR_sb_num; + tmp = (frame_energy+0.0001f)/(t_bg_energy+0.0001f); + tmp = (float)log10(tmp); + *tsnr = tmp*3.0f; + if(bandwidth == CLDFBVAD_SWB_ID) + { + tmp = (frame_energy)/(t_bg_energy+FLT_MIN); + tmp = (float)log10(tmp+FLT_MIN); + *tsnr = tmp*2.8f; + } + +} + +void calc_snr_flux(float tsnr, /*(i) time-domain SNR*/ + float pre_snr[], /*(io)time-domain SNR storage*/ + float *snr_flux /*(o) average tsnr*/ + ) +{ + int i; + float snr_sum = 0.0f; + + + if (tsnr < 2.6f&& tsnr>0) + pre_snr[0] = tsnr; + else if(tsnr<=0) + pre_snr[0] = 0; + else + pre_snr[0] = 2.6f; + + snr_sum =0; + for(i=0; i0; i--) + { + pre_snr[i] = pre_snr[i-1]; + } + +} + +void calc_lt_snr(float *lt_snr_org, /*(o) original long time SNR*/ + float *lt_snr, /*(o) long time SNR calculated by fg_energy and bg_energy*/ + float fg_energy, /*(i) foreground energy sum */ + int fg_energy_count, /*(i) number of the foreground energy frame */ + float bg_energy, /*(i) background energy sum */ + int bg_energy_count, /*(i) number of the background energy frame */ + int bw_index, /*(i) band width index*/ + float lt_noise_sp_center0 /*(i) long time noise spectral center by 0*/ + ) +{ + float tmp_lt_noise_sp_center; + float rtn_lt_snr; + + const float offset = -0.00156247615814208984375f; + + + tmp_lt_noise_sp_center = lt_noise_sp_center0-1.4f; + if(tmp_lt_noise_sp_center>0.8) + { + tmp_lt_noise_sp_center = 0.8f; + } + if(tmp_lt_noise_sp_center<0) + { + tmp_lt_noise_sp_center = 0.0f; + } + rtn_lt_snr = (float)log10((fg_energy*bg_energy_count+FLT_MIN)/(bg_energy*fg_energy_count+FLT_MIN)); + *lt_snr_org = rtn_lt_snr; + + if(bg_energy_count<56|| fg_energy_count<56) + { + rtn_lt_snr = 2.1f; + } + + if(bw_index == CLDFBVAD_NB_ID) + { + rtn_lt_snr = (rtn_lt_snr-1.5f)*0.5f; + } + else if(bw_index == CLDFBVAD_WB_ID) + { + rtn_lt_snr = (rtn_lt_snr-1.5f)*0.50f; + } + else + { + rtn_lt_snr = (rtn_lt_snr-1.5f)*0.46f; + + } + rtn_lt_snr = rtn_lt_snr + (rtn_lt_snr*0.4f+offset)*tmp_lt_noise_sp_center*0.4f; + if(rtn_lt_snr<0) + { + rtn_lt_snr = 0.0f; + } + + if(rtn_lt_snr>2.0) + { + rtn_lt_snr = 2.0f; + } + + *lt_snr = rtn_lt_snr; + + +} + +void calc_lf_snr(float *lf_snr_smooth, /*(o) smoothed lf_snr*/ + float *lf_snr, /*(o) long time frequency domain + SNR calculated by l_speech_snr and l_silence_snr*/ + float l_speech_snr, /*(i) sum of active frames snr */ + int l_speech_snr_count, /*(i) number of the active frame */ + float l_silence_snr, /*(i) sum of the nonactive frames snr*/ + int l_silence_snr_count, /*(i) number of the nonactive frame */ + int fg_energy_count, /*(i) number of the foreground energy frame */ + int bg_energy_count, /*(i) number of the background energy frame */ + int bw_index /*(i) band width index*/ + ) +{ + float l_snr; + l_snr = l_speech_snr/l_speech_snr_count - l_silence_snr/l_silence_snr_count; + *lf_snr_smooth = *lf_snr_smooth*0.9f + 0.1f*l_snr; + + if(bg_energy_count<56|| fg_energy_count<56) + { + l_snr = 4.8f; + } + + + l_snr = (l_snr - 3.0f)*0.12f; + + if(l_snr<0) + { + l_snr = 0; + } + + if(l_snr>MAX_LF_SNR_TAB[bw_index]) + { + l_snr = MAX_LF_SNR_TAB[bw_index]; + } + + *lf_snr = l_snr; +} diff --git a/lib_enc/acelp_core_enc.c b/lib_enc/acelp_core_enc.c new file mode 100644 index 000000000..5ad5726cf --- /dev/null +++ b/lib_enc/acelp_core_enc.c @@ -0,0 +1,587 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_enc.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * acelp_core_enc() + * + * ACELP core encoder + *--------------------------------------------------------------------*/ + +void acelp_core_enc( + Encoder_State *st, /* i/o: encoder state structure */ + LPD_state *mem, /* i/o: acelp memories */ + const float inp[], /* i : input signal of the current frame */ + const short vad_flag, + const float ener, /* i : residual energy from Levinson-Durbin*/ + const short pitch[3], /* i : open-loop pitch values for quantiz. */ + const float voicing[3], /* i : Open-loop pitch gains */ + float A[NB_SUBFR16k*(M+1)], /* i : A(z) unquantized for the 4 subframes*/ + float Aw[NB_SUBFR16k*(M+1)], /* i : weighted A(z) unquant. for subframes*/ + const float epsP[M+1], /* i : LP prediction errors */ + float lsp_new[M], /* i : LSPs at the end of the frame */ + float lsp_mid[M], /* i : LSPs in the middle of the frame */ + short coder_type, /* i : coding type */ + const short sharpFlag, /* i : formant sharpening flag */ + short vad_hover_flag, + const short attack_flag, /* i : flag signalling attack encoded by AC mode (GSC) */ + float bwe_exc_extended[], /* i/o: bandwidth extended excitation */ + float *voice_factors, /* o : voicing factors */ + float old_syn_12k8_16k[], /* o : intermediate ACELP synthesis at 12.8kHz or 16kHz to be used by SWB BWE */ + float pitch_buf[NB_SUBFR16k], /* o : floating pitch for each subframe */ + short *unbits /* o : number of unused bits */ +) +{ + short nBits; /* reserved bits */ + short i; + float old_exc[L_EXC], *exc; /* excitation signal buffer */ + float lsf_new[M]; /* ISFs at the end of the frame */ + float Aq[NB_SUBFR16k*(M+1)]; /* A(z) quantized for the 4 subframes */ + float syn[L_FRAME16k]; /* synthesis signal buffer */ + float res[L_FRAME16k]; /* Residual signal for FER protection */ + float exc2[L_FRAME16k]; /* enhanced excitation */ + float Es_pred; /* predicited scaled innovation energy */ + float tmp_noise; /* NB post-filter long-term noise energy*/ + short tc_subfr; /* TC sub-frame indication */ + float old_bwe_exc[(PIT16k_MAX + (L_FRAME16k + 1) + L_SUBFR16k) * 2]; /* excitation buffer */ + float *bwe_exc; /* excitation for SWB TBE */ + short allow_cn_step; + float int_fs; + float att; + float lim; + short T_op[3]; + short nb_bits; /* parameters handling */ + int indice; + + /* SC-VBR - back-up memories for LSF quantizer and synthesis filter */ + short mCb1, pstreaklen; + float mem_MA[M], mem_AR[M], Bin_E[L_FFT], Bin_E_old[L_FFT/2], lsp_new_bck[M], lsp_mid_bck[M], mem_syn_bck[M]; + float clip_var, mem_w0_bck, streaklimit; + + float q_env[NUM_ENV_CNG]; + short sid_bw = -1; + float exc3[L_FRAME16k]; + float syn1[L_FRAME16k]; + float enr; + float enr_index; + + float tilt_code_bck; + float gc_threshold_bck; + float clip_var_bck[6]; + short next_force_sf_bck; + + + + /*------------------------------------------------------------------* + * Initialization + *------------------------------------------------------------------*/ + + Es_pred = 0; + + mvs2s( pitch, T_op, 3 ); + + /* convert pitch values to 16kHz domain */ + if ( st->L_frame == L_FRAME16k ) + { + T_op[0] = (short)(T_op[0] * 1.25f + 0.5f); + T_op[1] = (short)(T_op[1] * 1.25f + 0.5f); + T_op[2] = T_op[1]; + } + + exc = old_exc + L_EXC_MEM; /* pointer to excitation signal in the current frame */ + mvr2r( mem->old_exc, old_exc, L_EXC_MEM ); + + bwe_exc = old_bwe_exc + PIT16k_MAX * 2; /* pointer to BWE excitation signal in the current frame */ + mvr2r( st->old_bwe_exc, old_bwe_exc, PIT16k_MAX * 2 ); + + st->bpf_off = 0; + if( st->last_core == HQ_CORE || st->last_codec_mode == MODE2 ) + { + /* in case of HQ->ACELP switching, do not apply BPF */ + st->bpf_off = 1; + /* reset the GSC pre echo energy threshold in case of switching */ + st->Last_frame_ener = (float)MAX_32; + } + + /* force safety-net LSFQ in the first frames after CNG segment */ + if( st->last_core_brate <= SID_2k40 ) + { + st->Nb_ACELP_frames = 0; + } + st->Nb_ACELP_frames++; + + if( st->L_frame == L_FRAME ) + { + int_fs = INT_FS_12k8; + } + else + { + int_fs = INT_FS_16k; + } + + tmp_noise = 0; + tc_subfr = 0; + + /* SC-VBR temporary variables */ + mCb1 = 0; + pstreaklen = 0; + clip_var = 0; + mem_w0_bck = 0; + streaklimit = 0; + + /* channel-aware mode */ + reset_rf_indices(st); + + /*-----------------------------------------------------------------* + * ACELP@12k8 / ACELP@16k switching + *-----------------------------------------------------------------*/ + + if( st->last_L_frame != st->L_frame && st->last_core != HQ_CORE ) + { + /* in case of switching, do not apply BPF (flag employed also in updt_enc()) */ + st->bpf_off = 1; + + /* force safety-net LSFQ in the first frames after ACELP@12k8/ACELP@16k switching */ + st->Nb_ACELP_frames = 1; + + /* convert old quantized LSP vector */ + if( st->L_frame == L_FRAME ) + { + st->rate_switching_reset = lsp_convert_poly( st->lsp_old, st->L_frame, 0 ); + } + else + { + st->rate_switching_reset = st->rate_switching_reset_16kHz; + mvr2r( st->lsp_old16k, st->lsp_old, M ); + } + + /* convert old quantized LSF vector */ + lsp2lsf( st->lsp_old, st->lsf_old, M, int_fs ); + + /* interpolation of unquantized ISPs */ + if( st->rate_switching_reset ) + { + /*extrapolation in case of unstable LSP*/ + int_lsp4( st->L_frame, lsp_mid, lsp_mid, lsp_new, A, M, 0 ); + } + else + { + int_lsp4( st->L_frame, st->lsp_old, lsp_mid, lsp_new, A, M, 0 ); + } + + /* Reset LPC mem */ + mvr2r( GEWB_Ave, st->mem_AR, M ); + set_zero( st->mem_MA, M ); + + /* update synthesis filter memories */ + synth_mem_updt2( st->L_frame, st->last_L_frame, mem->old_exc, mem->mem_syn_r, mem->mem_syn2, mem->mem_syn, ENC ); + mvr2r( mem->old_exc, old_exc, L_EXC_MEM ); + mvr2r( mem->mem_syn2, st->mem_syn1, M ); + mvr2r( mem->mem_syn2, mem->mem_syn3, M ); + + /* update Aw[] coefficients */ + weight_a_subfr( st->L_frame/L_SUBFR, A, Aw, st->gamma, M ); + } + + if( st->last_bwidth == NB && st->bwidth != NB && st->ini_frame != 0 ) + { + st->rate_switching_reset = 1; + } + + /*----------------------------------------------------------------* + * Encoding of CNG frames + *----------------------------------------------------------------*/ + + if( st->core_brate == SID_2k40 || st->core_brate == FRAME_NO_DATA ) + { + if( st->cng_type == LP_CNG ) + { + /* Run CNG post parameter update */ + cng_params_postupd( st->ho_circ_ptr, &st->cng_buf_cnt, st->cng_exc2_buf, + st->cng_brate_buf, st->ho_env_circ); + /* encode CNG parameters */ + CNG_enc( st, st->L_frame, Aq, inp, ener, lsp_new, lsf_new , &allow_cn_step, st->burst_ho_cnt, q_env, &sid_bw, st->exc_mem2 ); + /* comfort noise generation */ + CNG_exc( st->core_brate, st->L_frame, &st->Enew, &st->cng_seed, exc, exc2, &st->lp_ener, + st->last_core_brate, &st->first_CNG, &st->cng_ener_seed, bwe_exc, allow_cn_step, &st->last_allow_cn_step, st->num_ho, + q_env, st->lp_env, st->old_env, st->exc_mem, st->exc_mem1, &sid_bw, &st->cng_ener_seed1, exc3, st->Opt_AMR_WB ); + } + else + { + if( st->core_brate == SID_2k40 ) + { + FdCng_encodeSID( st->hFdCngEnc, st, st->preemph_fac ); + st->last_CNG_L_frame = st->L_frame; + } + + generate_comfort_noise_enc( st ); + + FdCng_exc( st->hFdCngEnc->hFdCngCom, &st->CNG_mode, st->L_frame, st->lsp_old, st->first_CNG, st->lspCNG, Aq, lsp_new,lsf_new, exc, exc2, bwe_exc); + mvr2r( exc2, exc3, st->L_frame ); + if( st->core_brate == SID_2k40 ) + { + enr = dotp( exc, exc, st->L_frame ) / st->L_frame; + enr = (float)log10( enr + 0.1f ) / (float)log10( 2.0f ); + + /* decrease the energy in case of WB input */ + if( st->bwidth != NB ) + { + if( st->bwidth == WB ) + { + if( st->CNG_mode >= 0 ) + { + /* Bitrate adapted attenuation */ + att = ENR_ATT[st->CNG_mode]; + } + else + { + /* Use least attenuation for higher bitrates */ + att = ENR_ATT[4]; + } + } + else + { + att = 1.5f; + } + + enr -= att; + } + + enr_index = (short)( (enr + 2.0f) * STEP_SID ); + if( enr_index > 127 ) + { + enr_index = 127; + } + + if( enr_index < 0 ) + { + enr_index = 0; + } + st->old_enr_index = enr_index; + } + } + + st->burst_ho_cnt = 0; + + /* synthesis at 12.8kHz sampling rate */ + syn_12k8( st->L_frame, Aq, exc3, syn1, mem->mem_syn3, 1 ); + + /* reset the encoder */ + CNG_reset_enc( st, mem, pitch_buf, voice_factors, 0 ); + + /* update st->mem_syn1 for ACELP core switching */ + mvr2r( mem->mem_syn3, st->mem_syn1, M ); + + /* update ACELP core synthesis filter memory */ + mvr2r( mem->mem_syn3, mem->mem_syn, M ); + + /* update old synthesis buffer - needed for ACELP internal sampling rate switching */ + mvr2r( syn1 + st->L_frame - L_SYN_MEM, mem->mem_syn_r, L_SYN_MEM ); + + + /* save and delay synthesis to be used by SWB BWE */ + save_old_syn( st->L_frame, syn1, old_syn_12k8_16k, st->old_syn_12k8_16k, st->preemph_fac, &st->mem_deemph_old_syn ); + + /*Update MODE2 core switching memory*/ + deemph( syn1, st->preemph_fac, st->L_frame, &(st->LPDmem.syn[M]) ); + mvr2r( syn1+st->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 + *-----------------------------------------------------------------*/ + + if ( st->last_core_brate == FRAME_NO_DATA || st->last_core_brate == SID_2k40 ) + { + mvr2r( st->lspCNG, st->lsp_old, M ); + + lsp2lsf( st->lspCNG, st->lsf_old, M, int_fs ); + } + + /*-----------------------------------------------------------------* + * Reset higher ACELP pre-quantizer in case of switching + *-----------------------------------------------------------------*/ + + if( !st->use_acelp_preq ) + { + st->mem_deemp_preQ = 0.0f; + st->mem_preemp_preQ = 0.0f; + st->last_nq_preQ = 0; + } + st->use_acelp_preq = 0; + + /*-----------------------------------------------------------------* + * LSF Quantization + * A[z] calculation + *-----------------------------------------------------------------*/ + + /* SC-VBR & channel-aware mode - back-up memories for LSF quantizer and synthesis filter */ + lsf_syn_mem_backup( st, mem, &tilt_code_bck, &gc_threshold_bck, clip_var_bck, &next_force_sf_bck, lsp_new, lsp_mid, &clip_var, + mem_AR, mem_MA, lsp_new_bck, lsp_mid_bck, &mCb1, Bin_E, Bin_E_old, mem_syn_bck, &mem_w0_bck, &streaklimit, &pstreaklen ); + + lsf_enc( st, st->L_frame, coder_type, lsf_new, lsp_new, lsp_mid, Aq, &st->stab_fac, st->Nb_ACELP_frames ); + + /*---------------------------------------------------------------* + * Calculation of LP residual (filtering through A[z] filter) + *---------------------------------------------------------------*/ + + calc_residu( inp, res, Aq, st->L_frame ); + + /* smoothing in case of CNG */ + if( st->Opt_DTX_ON && vad_hover_flag ) + { + st->burst_ho_cnt++; + if(st->burst_ho_cnt > HO_HIST_SIZE) + { + st->burst_ho_cnt = HO_HIST_SIZE; + } + if( st->bwidth != NB ) + { + if( st->bwidth == WB && st->CNG_mode >= 0 ) + { + lim = HO_ATT[st->CNG_mode]; + } + else + { + lim = 0.6f; + } + + att = lim/6.0f; + att = 1.0f/(1 + att * st->burst_ho_cnt); + + if ( att < lim ) + { + att = lim; + } + + for( i = 0; i < st->L_frame; i++ ) + { + res[i] *= att; + } + } + } + else if ( st->Opt_DTX_ON && vad_flag ) + { + st->burst_ho_cnt = 0; + } + + /*---------------------------------------------------------------* + * Calculation of prediction for scaled innovation energy + * (for memory-less gain quantizer) + *---------------------------------------------------------------*/ + + if( ( coder_type != UNVOICED && coder_type != AUDIO && coder_type != INACTIVE && !(st->core_brate <= ACELP_8k00 && coder_type != TRANSITION) ) + || (coder_type == INACTIVE && st->total_brate >= ACELP_32k) ) + { + nb_bits = Es_pred_bits_tbl[BIT_ALLOC_IDX(st->core_brate, coder_type, -1, -1)]; + Es_pred_enc( &Es_pred, &indice, st->L_frame, L_SUBFR, res, voicing, nb_bits, 0 ); + + push_indice( st, IND_ES_PRED, indice, nb_bits ); + } + + /*------------------------------------------------------------* + * Encode excitation according to coding type + *------------------------------------------------------------*/ + + if( st->nelp_mode ) + { + /* SC-VBR - NELP frames */ + encod_nelp( st, mem, inp, Aw, Aq, res, syn, &tmp_noise, exc, exc2, pitch_buf, voice_factors, bwe_exc ); + } + else if( coder_type == UNVOICED ) + { + /* UNVOICED frames (Gauss. excitation) */ + encod_unvoiced( st, mem, inp, Aw, Aq, vad_flag, res, syn, &tmp_noise, exc, pitch_buf, voice_factors, bwe_exc ); + } + else if( coder_type == TRANSITION ) + { + tc_subfr = encod_tran( st, mem, st->L_frame, inp, Aw, Aq, coder_type, Es_pred, T_op, voicing, res, syn, + exc, exc2, pitch_buf, voice_factors, bwe_exc, attack_flag, unbits, sharpFlag ); + } + else if( st->ppp_mode ) + { + /* SC-VBR - PPP frames */ + encod_ppp( st, mem, inp, Aw, Aq, &coder_type, sharpFlag, T_op, voicing, res, syn, exc, exc2, pitch_buf, voice_factors, bwe_exc ); + + if( st->bump_up ) /* PPP failed, bump up */ + { + /* restore memories of LSF quantizer and synthesis filter */ + lsf_syn_mem_restore( st, mem, tilt_code_bck, + gc_threshold_bck, + clip_var_bck, next_force_sf_bck, + lsp_new, lsp_mid, clip_var, mem_AR, mem_MA, lsp_new_bck, lsp_mid_bck, mCb1, Bin_E,Bin_E_old,mem_syn_bck, mem_w0_bck, streaklimit, pstreaklen ); + + /* redo LSF quantization */ + lsf_enc( st, st->L_frame, coder_type, lsf_new, lsp_new, lsp_mid, Aq, &st->stab_fac, st->Nb_ACELP_frames ); + + /* recalculation of LP residual (filtering through A[z] filter) */ + calc_residu( inp, res, Aq, st->L_frame ); + st->burst_ho_cnt = 0; + + /* VOICED frames in SC-VBR */ + encod_gen_voic( st, mem, st->L_frame, sharpFlag, inp, Aw, Aq, coder_type, Es_pred, T_op, voicing, res, syn, + exc, exc2, pitch_buf, voice_factors, bwe_exc, unbits ); + } + } + else if( coder_type == AUDIO || ( coder_type == INACTIVE && st->core_brate <= ACELP_24k40 ) ) + { + /* AUDIO and INACTIVE frames (coded by GSC technology) */ + encod_audio( st, mem, inp, Aw, Aq, T_op, voicing, res, syn, exc, pitch_buf, voice_factors, bwe_exc, attack_flag, coder_type, lsf_new, &tmp_noise ); + } + else + { + /* GENERIC, VOICED and INACTIVE frames (coded by AVQ technology) */ + encod_gen_voic( st, mem, st->L_frame, sharpFlag, inp, Aw, Aq, coder_type, Es_pred, T_op, voicing, res, syn, + exc, exc2, pitch_buf, voice_factors, bwe_exc, unbits ); + } + + + /* update st->mem_syn1 for ACELP core switching */ + mvr2r( mem->mem_syn, st->mem_syn1, M ); + + /* update old synthesis buffer - needed for ACELP internal sampling rate switching */ + mvr2r( syn + st->L_frame - L_SYN_MEM, mem->mem_syn_r, L_SYN_MEM ); + + /* save and delay synthesis to be used by SWB BWE */ + save_old_syn( st->L_frame, syn, old_syn_12k8_16k, st->old_syn_12k8_16k, st->preemph_fac, &st->mem_deemph_old_syn ); + + /*Update MODE2 core switching memory*/ + mvr2r( syn, syn1, st->L_frame ); + deemph( syn1, st->preemph_fac, st->L_frame, &(st->LPDmem.syn[M]) ); + mvr2r( syn1+st->L_frame-M-1, st->LPDmem.syn, M+1 ); + + + /*--------------------------------------------------------------------------------------* + * Modify the excitation signal when the noise is stationary + *--------------------------------------------------------------------------------------*/ + + if ( st->nelp_mode != 1 ) + { + /* exc2 buffer is needed only for updating of Aq[] which is needed for core switching */ + mvr2r( exc, exc2, st->L_frame); + stat_noise_uv_enc( st, coder_type, epsP, lsp_new, lsp_mid, Aq, exc2 ); + } + + /*-----------------------------------------------------------------* + * Encode supplementary information for Frame Error Concealment + *-----------------------------------------------------------------*/ + + FEC_encode( st, syn, coder_type, st->clas, pitch_buf, res, &st->Last_pulse_pos, st->L_frame, st->total_brate, st->core_brate ); + + if( st->L_frame == L_FRAME ) + { + mvr2r( Aq+2*(M+1), st->cur_sub_Aq, (M+1) ); + } + else + { + mvr2r( Aq+3*(M+1), st->cur_sub_Aq, (M+1) ); + } + + + } /* end of active inp coding */ + + + /*-----------------------------------------------------------------* + * Write ACELP unused bits + *-----------------------------------------------------------------*/ + + if ( st->core_brate != SID_2k40 && st->core_brate != FRAME_NO_DATA && st->core_brate != PPP_NELP_2k80 ) + { + /* unused bits */ + if ( coder_type == AUDIO || ( coder_type == INACTIVE && st->core_brate <= ACELP_24k40 ) ) + { + nBits = 0; + } + else if(st->L_frame == L_FRAME ) + { + nBits = reserved_bits_tbl[BIT_ALLOC_IDX(st->core_brate, coder_type, -1, TC_SUBFR2IDX(tc_subfr))]; + } + else + { + nBits = 0; + } + + while( nBits > 0 ) + { + i = min(nBits, 16); + push_indice( st, IND_UNUSED, 0, i ); + nBits -= i; + } + } + + /*-----------------------------------------------------------------* + * Apply non linearity in case of SWB TBE + *-----------------------------------------------------------------*/ + + if( (st->last_Opt_SC_VBR == 1 && st->Opt_SC_VBR == 0) || ((st->extl == SWB_TBE || st->extl == WB_TBE || st->extl == FB_TBE) && st->last_extl != SWB_TBE && st->last_extl != WB_TBE && st->last_extl != FB_TBE) ) + { + st->bwe_non_lin_prev_scale = 0.0f; + set_f( st->old_bwe_exc_extended, 0.0f, NL_BUFF_OFFSET ); + } + + if( !st->Opt_SC_VBR ) + { + /* Apply a non linearity to the SHB excitation */ + non_linearity( bwe_exc, bwe_exc_extended, st->old_bwe_exc_extended, L_FRAME32k, &st->bwe_non_lin_prev_scale, coder_type, voice_factors, st->L_frame ); + } + + if ( st->core_brate == SID_2k40 || st->core_brate == FRAME_NO_DATA ) + { + st->bwe_non_lin_prev_scale = 0.0f; + } + + /*-----------------------------------------------------------------* + * Updates + *-----------------------------------------------------------------*/ + + updt_enc( st, st->L_frame, coder_type, old_exc, pitch_buf, Es_pred, Aq, lsf_new, lsp_new, old_bwe_exc ); + + if( st->Opt_DTX_ON && st->core_brate > SID_2k40 ) + { + /* update CNG parameters in active frames */ + cng_params_upd( lsp_new, exc, st->L_frame, &st->ho_circ_ptr, st->ho_ener_circ, + &st->ho_circ_size, st->ho_lsp_circ, ENC, st->ho_env_circ, + &st->cng_buf_cnt, st->cng_exc2_buf, st->cng_brate_buf, st->last_active_brate ); + + if( st->L_frame == L_FRAME ) + { + /* store LSPs@16k, potentially to be used in CNG@16k */ + mvr2r( st->lsp_old16k, &(st->ho_lsp_circ2[(st->ho_circ_ptr)*M]), M ); + } + + /* set LSP@16k flag for the first buffer */ + st->ho_16k_lsp[st->ho_circ_ptr] = (st->L_frame == L_FRAME ? 0 : 1 ); + + /* efficient DTX hangover control */ + if ( st->burst_ho_cnt > 1 ) + { + dtx_hangover_control( st, lsp_new ); + } + } + + /* SC-VBR update of average data rate */ + if ( vad_flag == 1 ) + { + update_average_rate( st ); + + } + + + + return; +} diff --git a/lib_enc/acelp_core_switch_enc.c b/lib_enc/acelp_core_switch_enc.c new file mode 100644 index 000000000..cd9f65339 --- /dev/null +++ b/lib_enc/acelp_core_switch_enc.c @@ -0,0 +1,431 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_enc.h" +#include "rom_com.h" +#include "prot.h" +#include "prot.h" + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ + +static void encod_gen_voic_core_switch( Encoder_State *st, LPD_state *mem,const short L_frame, const float inp[], + const float Aq[], const float A[], const short coder_type, const short T_op[], + const float voicing[], float *exc, const long core_bitrate ); + +static void bwe_switch_enc( Encoder_State *st, const float *old_input ); + +/*-------------------------------------------------------------------* + * acelp_core_switch_enc() + * + * ACELP core encoder in the ACELP->HQ switching frame + *--------------------------------------------------------------------*/ + +void acelp_core_switch_enc( + Encoder_State *st, /* i/o: encoder state structure */ + LPD_state *mem, /* i/o: encoder memories */ + const float inp12k8[], /* i : input signal @12.8 kHz */ + const float inp16k[], /* i : input signal @16 kHz */ + const short T_op_orig[2], /* i : open-loop pitch values for quantiz. */ + const float voicing[3], /* i : Open-loop pitch gains */ + const float A[NB_SUBFR16k*(M+1)] /* i : A(z) unquantized for the 4 subframes*/ +) +{ + short i, T_op[2]; + float old_exc[L_EXC], *exc; /* excitation signal buffer */ + const float *inp; + long cbrate; + float Aq[2*(M+1)]; + + /* initializations */ + exc = old_exc + L_EXC_MEM; /* pointer to excitation signal in the current frame */ + mvr2r( mem->old_exc, old_exc, L_EXC_MEM ); + + mvr2r( st->old_Aq_12_8, Aq, M+1 ); + mvr2r( st->old_Aq_12_8, Aq + (M+1), M+1 ); + + T_op[0] = T_op_orig[0]; + T_op[1] = T_op_orig[1]; + + /*----------------------------------------------------------------* + * set switching frame bit-rate + *----------------------------------------------------------------*/ + + if( st->last_L_frame == L_FRAME ) /* ACELP@12k8 core */ + { + inp = inp12k8; + + if( st->core_brate > ACELP_24k40 ) + { + cbrate = ACELP_24k40; + } + else + { + cbrate = st->core_brate; + } + } + else /* ACELP@16k core */ + { + inp = inp16k; + + if( st->core_brate <= ACELP_8k00 ) + { + cbrate = ACELP_8k00; + } + else if( st->core_brate <= ACELP_14k80 ) + { + cbrate = ACELP_14k80; + } + else + { + cbrate = min( st->core_brate, ACELP_22k60 ); + } + } + + if (st->last_L_frame != L_FRAME) /* ACELP@16k core */ + { + T_op[0] = (short)(1.25f * T_op[0] + 0.5f); + T_op[1] = (short)(1.25f * T_op[1] + 0.5f); + } + + /*----------------------------------------------------------------* + * Excitation encoding + *----------------------------------------------------------------*/ + + encod_gen_voic_core_switch( st, mem, st->last_L_frame, inp, Aq, A, GENERIC, T_op, voicing, exc, cbrate ); + + + /*----------------------------------------------------------------* + * Manipulate ACELP subframe indices (move them to their proper place) + *----------------------------------------------------------------*/ + + for( i=0; i<20; i++ ) + { + st->ind_list[IND_CORE_SWITCHING_CELP_SUBFRAME+i].value = st->ind_list[TAG_ACELP_SUBFR_LOOP_START+i].value; + st->ind_list[IND_CORE_SWITCHING_CELP_SUBFRAME+i].nb_bits = st->ind_list[TAG_ACELP_SUBFR_LOOP_START+i].nb_bits; + st->ind_list[TAG_ACELP_SUBFR_LOOP_START+i].nb_bits = -1; + } + + /*----------------------------------------------------------------* + * BWE encoding + *----------------------------------------------------------------*/ + + if( !( (st->last_L_frame == L_FRAME16k && inner_frame_tbl[st->bwidth]==L_FRAME16k ) || inner_frame_tbl[st->bwidth] == L_FRAME8k ) ) + { + bwe_switch_enc( st, (const float *)st->old_input_signal ); + } + + return; +} + + +/*-------------------------------------------------------------------* + * encod_gen_voic_core_switch() + * + * Encode excitation signal in ACELP->HQ switching frame + *-------------------------------------------------------------------*/ + +static void encod_gen_voic_core_switch( + Encoder_State *st, /* i/o: state structure */ + LPD_state *mem, /* i/o: encoder memories */ + const short L_frame, /* i : length of the frame */ + const float inp[], /* i : input signal */ + const float Aq[], /* i : LP coefficients */ + const float A[], /* i : unquantized A(z) filter */ + const short coder_type, /* i : coding type */ + const short T_op[], /* i : open loop pitch */ + const float voicing[], /* i : voicing */ + float *exc, /* i/o: current non-enhanced excitation */ + const long core_bitrate /* i : switching frame bit-rate */ +) +{ + float res[L_SUBFR]; /* residual signal */ + float Ap[M+1]; /* A(z) with spectral expansion */ + float xn[L_SUBFR]; /* Target vector for pitch search */ + float xn2[L_SUBFR]; /* Target vector for codebook search */ + float cn[L_SUBFR]; /* Target vector in residual domain */ + float h1[L_SUBFR+(M+1)]; /* Impulse response vector */ + float code[L_SUBFR]; /* Fixed codebook excitation */ + float y1[L_SUBFR]; /* Filtered adaptive excitation */ + float y2[L_SUBFR]; /* Filtered algebraic excitation */ + float gain_pit ; /* Pitch gain */ + float voice_fac; /* Voicing factor */ + float gain_code; /* Gain of code */ + float gain_inov; /* inovation gain */ + short i; /* tmp variables */ + short T0, T0_frac; /* close loop integer pitch and fractional part */ + short T0_min, T0_max; /* pitch variables */ + float pitch; /* floating pitch value */ + float g_corr[6]; /* ACELP correl, values + gain pitch */ + short clip_gain; /* ISF clip gain */ + short unbits; /* number of unused bits for EVS_PI */ + float norm_gain_code; + short pitch_limit_flag; + float tmpF; + short lp_select, lp_flag; + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + + unbits = 0; + + if( L_frame == L_FRAME ) + { + T0_max = PIT_MAX; + T0_min = PIT_MIN; + } + else /* L_frame == L_FRAME16k */ + { + T0_max = PIT16k_MAX; + T0_min = PIT16k_MIN; + } + + /*------------------------------------------------------------------* + * Calculation of LP residual (filtering through A[z] filter) + *------------------------------------------------------------------*/ + + residu( Aq, M, inp, res, L_SUBFR ); + + /*------------------------------------------------------------------* + * ACELP subframe loop + *------------------------------------------------------------------*/ + + mvr2r( res, exc, L_SUBFR ); + + if( L_frame == L_FRAME16k ) + { + weight_a( A, Ap, GAMMA16k, M ); /* Bandwidth expansion of A(z) filter coefficients */ + find_targets( inp, mem->mem_syn, 0, &mem->mem_w0, Aq, res, L_SUBFR, Ap, PREEMPH_FAC_16k, xn, cn, h1 ); + } + else + { + weight_a( A, Ap, GAMMA1, M ); /* Bandwidth expansion of A(z) filter coefficients */ + find_targets( inp, mem->mem_syn, 0, &mem->mem_w0, Aq, res, L_SUBFR, Ap, PREEMPH_FAC, xn, cn, h1 ); + } + + + /*----------------------------------------------------------------* + * Close-loop pitch search and quantization + * Adaptive exc. construction + *----------------------------------------------------------------*/ + + pitch = pit_encode( st, 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, exc, T0, T0_frac, L_SUBFR+1, 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( core_bitrate, voicing, 0, coder_type, xn, st->clip_var ); + + /*-----------------------------------------------------------------* + * LP filtering of the adaptive excitation, codebook target computation + *-----------------------------------------------------------------*/ + + lp_select = lp_filt_exc_enc( 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( lp_flag == NORMAL_OPERATION ) + { + push_indice( st, IND_LP_FILT_SELECT, lp_select, 1 ); + } + + /*-----------------------------------------------------------------* + * Innovation encoding + *-----------------------------------------------------------------*/ + + inov_encode( st, core_bitrate, 0, L_frame, L_frame, coder_type, st->bwidth, 0, 0, -1, Aq, gain_pit, cn, exc, + h1, mem->tilt_code, pitch, xn2, code, y2, &unbits ); + + /*-----------------------------------------------------------------* + * Gain encoding + *-----------------------------------------------------------------*/ + + if (L_frame == L_FRAME) + { + gain_enc_mless( st, core_bitrate, L_frame, TRANSITION, 0, -1, xn, y1, y2, code, st->old_Es_pred, + &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, clip_gain ); + } + else + { + gain_enc_mless( st, core_bitrate, L_frame, coder_type, 0, -1, xn, y1, y2, code, st->old_Es_pred, + &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, clip_gain ); + } + + gp_clip_test_gain_pit( core_bitrate, gain_pit, st->clip_var); + mem->tilt_code = est_tilt( exc, gain_pit, code, gain_code, &voice_fac, L_SUBFR, 0 ); + + /*-----------------------------------------------------------------* + * Construct adaptive part of the excitation + *-----------------------------------------------------------------*/ + + for( i = 0; i < L_SUBFR; i++ ) + { + tmpF = gain_pit * exc[i]; + exc[i] = tmpF + gain_code * code[i]; + } + + /* write reserved bits */ + if( unbits ) + { + push_indice( st, 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, inter4_2, L_INTERPOL2,PIT_UP_SAMP ); + + for( i = 0; i < L_SUBFR; i++ ) + { + exc[i+L_SUBFR] *= gain_pit; + } + + return; +} + + +/*-------------------------------------------------------------------* + * bwe_switch_enc() + * + * Encode BWE in ACELP->HQ switching frame + *-------------------------------------------------------------------*/ + +static void bwe_switch_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const float *new_speech /* i : original input signal */ +) +{ + short i, k, delta, Loverlapp, d1, d1m, maxd1, ind1, fdelay, gapsize; + float accA, accB, min_sq_cross, min_corr, E1, E2, gain; + float tmp_mem[2*L_FILT48k], tmp_mem2[2*L_FILT48k], hb_synth_tmp[NS2SA(48000, 10000000L)]; + const float *hp_filter; + float synth_subfr_bwe[SWITCH_MAX_GAP]; /* synthesized bwe for core switching */ + short n, L, input_frame; + + input_frame = st->input_Fs/50; + + L = NS2SA(st->input_Fs,FRAME_SIZE_NS); + n = ((float)L * N_ZERO_MDCT_NS/FRAME_SIZE_NS); + + /* set multiplication factor according to the sampling rate */ + hp_filter = hp16000_48000; + fdelay = 48; + if( st->input_Fs == 16000 ) + { + delta = 1; + if( st->last_L_frame == L_FRAME ) + { + hp_filter = hp12800_16000; + fdelay = 20; + } + } + else if( st->input_Fs == 32000 ) + { + delta = 2; + if( st->last_L_frame == L_FRAME ) + { + hp_filter = hp12800_32000; + fdelay = 40; + } + else + { + hp_filter = hp16000_32000; + fdelay = 32; + } + } + else + { + delta = 3; + if( st->last_L_frame == L_FRAME ) + { + hp_filter = hp12800_48000; + fdelay = 60; + } + } + + set_f( tmp_mem, 0, 2*L_FILT48k ); + set_f( tmp_mem2, 0, 2*L_FILT48k ); + + Loverlapp = delta*SWITCH_OVERLAP_8k*2; + gapsize = delta * (NS2SA(16000,SWITCH_GAP_LENGTH_NS)); + set_f( synth_subfr_bwe, 0, SWITCH_MAX_GAP ); + + for( i=0; i>1, fdelay, 1 ); + + + min_sq_cross = -1; + min_corr = 0; + d1m = 0; + + maxd1 = (short)(((input_frame>>1) - gapsize-fdelay)/delta); + + /* find delay */ + for( k = 0, d1 = 0; k < maxd1; d1 += delta, k++ ) + { + accA = accB = 0; + for( i = 0; i < gapsize; i += delta ) + { + accA += hb_synth_tmp[d1+i+fdelay] * hb_synth_tmp[d1+i+fdelay]; + accB += hb_synth_tmp[d1+i+fdelay] * synth_subfr_bwe[i]; + } + if( accB * accB * min_corr >= min_sq_cross *accA ) + { + d1m = k; + min_corr = accA; + min_sq_cross = accB * accB; + } + } + + push_indice( st, IND_CORE_SWITCHING_AUDIO_DELAY, d1m, AUDIODELAYBITS ); + + /* find gain */ + E1 = 0.0f; + E2 = 1.0f; /* to avoid /0 */ + + for( i=0; i +#include "wmc_auto.h" +#include +#include +#include "options.h" +#include "typedef.h" +#include "prot.h" +#include "cnst.h" +#include "rom_com.h" + + +/*-------------------------------------------------------------------* +* E_ACELP_toeplitz_mul() +* +* Multiplication of Toeplitz matrix with vector c, such that d = toeplitz(R)*c +*-------------------------------------------------------------------*/ + +void E_ACELP_toeplitz_mul( + float R[], + float c[], + float d[] +) +{ + short k, j; + float s; + + for (k=0; k +#include +#include "options.h" +#include "cnst.h" +#include "rom_enc.h" +#include "rom_com.h" +#include "prot.h" +#include "wmc_auto.h" + +/*-------------------------------------------------------------------* + * amr_wb_enc() + * + * AMR-WB encoder + *-------------------------------------------------------------------*/ + +void amr_wb_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const short *input_sp, /* i : input signal */ + const short n_samples /* i : number of input samples */ +) +{ + short i, delay, harm_flag; + float old_inp[L_INP_12k8], *new_inp, *inp; /* buffer of old input signal */ + float old_inp_16k[L_INP_12k8+L_SUBFR], *inp_16k, *new_inp_16k;/* buffer of old input signal @16kHz*/ + float old_exc[L_EXC], *exc; /* excitation signal buffer */ + float old_wsp[L_WSP], *wsp; /* weighted input signal buffer */ + short input_frame; /* frame length at input sampling freq. */ + float fr_bands[2*NB_BANDS]; /* energy in frequency bands */ + float lf_E[2*VOIC_BINS]; /* per bin spectrum energy in lf */ + float tmpN[NB_BANDS]; /* temporary noise update */ + float tmpE[NB_BANDS], PS[L_FFT/2]; /* temporary averaged energy of 2 sf. */ + float corr_shift; /* correlation shift */ + float relE; /* frame relative energy */ + float non_staX, cor_map_sum, sp_div; + short vad_flag; + short localVAD; + float Etot; /* total energy */ + float ener; /* residual energy from Levinson-Durbin */ + short pitch[3]; /* open-loop pitch values */ + float voicing[3]; /* open-loop pitch gains */ + float A[NB_SUBFR*(M+1)]; /* A(z) unquantized for the 4 subframes */ + float Aw[NB_SUBFR*(M+1)]; /* weigted A(z) unquant. for 4 subframes*/ + float epsP[M+1]; /* LP prediction errors */ + float isp_new[M]; /* ISPs at the end of the frame */ + float isf_new[M]; /* ISFs at the end of the frame */ + float isp_tmp[M]; + float Aq[NB_SUBFR*(M+1)]; /* A(z) quantized for the 4 subframes */ + float syn[L_FRAME]; /* synthesis vector */ + float res[L_FRAME]; /* residual signal for FER protection */ + float exc2[L_FRAME]; /* enhanced excitation */ + float pitch_buf[NB_SUBFR]; /* floating pitch for each subframe */ + float dummy_buf[L_FRAME32k]; /* dummy buffer - no usage */ + float snr_sum_he; + short allow_cn_step; + short localVAD_HE_SAD; + short tmps; + short vad_flag_dtx; + short vad_hover_flag; + short coder_type; + short hf_gain[NB_SUBFR]; + short high_lpn_flag; + float lp_bckr, hp_bckr; + float q_env[NUM_ENV_CNG]; + short sid_bw = 0; + float exc3[L_FRAME]; + float fft_buff[2*L_FFT]; + float sp_floor; + float tmp; + + push_wmops("amr_wb_enc"); + + + /*------------------------------------------------------------------* + * Initialization + *------------------------------------------------------------------*/ + + st->L_frame = L_FRAME; + st->gamma = GAMMA1; + st->core = AMR_WB_CORE; + st->core_brate = st->total_brate; + st->input_bwidth = st->last_input_bwidth; + st->bwidth = st->last_bwidth; + st->extl = -1; + coder_type = GENERIC; + input_frame = (short)(st->input_Fs / 50); /* frame length of the input signal */ + st->encoderPastSamples_enc = (L_FRAME*9)/16; + st->encoderLookahead_enc = L_LOOK_12k8; + + st->bpf_off = 0; + if( st->last_core == HQ_CORE || st->last_codec_mode == MODE2 ) + { + st->bpf_off = 1; + } + + st->igf = 0; + + /* Updates in case of EVS primary mode -> AMR-WB IO mode switching */ + if( st->last_core != AMR_WB_CORE ) + { + updt_IO_switch_enc( st, input_frame ); + } + + /* Updates in case of HQ -> AMR-WB IO switching */ + core_switching_pre_enc( st, &(st->LPDmem), NULL, NULL ); + + set_s( hf_gain, 0, NB_SUBFR ); + + set_f( old_inp, 0.0f, L_INP_12k8 ); + exc = old_exc + L_EXC_MEM; /* pointer to excitation signal in the current frame */ + mvr2r( 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 */ + + mvr2r( st->old_inp_12k8, old_inp, L_INP_MEM ); + mvr2r( st->old_wsp, 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 */ + mvr2r( st->old_inp_16k, old_inp_16k, L_INP_MEM ); + + /* in case of switching, reset AMR-WB BWE memories */ + if( st->total_brate == ACELP_23k85 && st->last_core_brate != ACELP_23k85 ) + { + hf_cod_init( st->mem_hp400_enc, st->mem_hf_enc, st->mem_syn_hf_enc, st->mem_hf2_enc, &st->gain_alpha ); + } + + /*----------------------------------------------------------------* + * set input samples buffer + *----------------------------------------------------------------*/ + + /* get delay to synchronize ACELP and MDCT frame */ + delay = NS2SA(st->input_Fs, DELAY_FIR_RESAMPL_NS); + + mvr2r( st->input - delay, st->old_input_signal, input_frame+delay ); + + /*----------------------------------------------------------------* + * Buffering of input signal + * (convert 'short' input data to 'float') + * HP filtering + *----------------------------------------------------------------*/ + + mvs2r( input_sp, st->input, n_samples ); + + for( i = n_samples; i < input_frame; i++ ) + { + st->input[i] = 0; + } + + hp20( st->input, input_frame, st->mem_hp20_in, st->input_Fs ); + + /*-----------------------------------------------------------------* + * switching from ACELP@16k core to AMR-WB IO mode + *-----------------------------------------------------------------*/ + + st->rate_switching_reset = 0; + + if( st->last_core != AMR_WB_CORE && st->last_L_frame == L_FRAME16k && st->last_core != HQ_CORE) + { + /* in case of switching, do not apply BPF */ + st->bpf_off = 1; + /* convert old quantized LSP vector */ + st->rate_switching_reset = lsp_convert_poly( st->lsp_old, L_FRAME, 1 ); + + /* convert old quantized LSF vector */ + lsp2lsf( st->lsp_old, st->lsf_old, M, INT_FS_12k8 ); + + /* Reset LPC mem */ + mvr2r( GEWB_Ave, st->mem_AR, M ); + set_zero( st->mem_MA, M ); + + /* update synthesis filter memories */ + synth_mem_updt2( L_FRAME, st->last_L_frame, st->LPDmem.old_exc, st->LPDmem.mem_syn_r, st->mem_syn1, st->LPDmem.mem_syn, ENC ); + mvr2r( st->LPDmem.old_exc, old_exc, L_EXC_MEM ); + mvr2r( st->mem_syn1, st->LPDmem.mem_syn2, M ); + mvr2r( st->LPDmem.mem_syn2, st->LPDmem.mem_syn3, M ); + + /* lsp -> isp */ + mvr2r( stable_ISP, isp_tmp, M ); + lsp2isp( st->lsp_old, st->lsp_old, isp_tmp, M ); + + } + + /* update buffer of old subframe pitch values */ + if( st->last_L_frame != L_FRAME ) + { + if( st->last_L_frame == L_FRAME32k ) + { + tmp = (float)12800/(float)32000; + } + else if( st->last_L_frame == 512 ) + { + tmp = (float)12800/(float)25600; + } + else /* st->last_L_frame == L_FRAME16k */ + { + tmp = (float)12800/(float)16000; + } + + for( i=NB_SUBFR16k-NB_SUBFR; iold_pitch_buf[i-1] = tmp * st->old_pitch_buf[i]; + } + + for( i=2*NB_SUBFR16k-NB_SUBFR; i<2*NB_SUBFR16k; i++ ) + { + st->old_pitch_buf[i-2] = tmp * st->old_pitch_buf[i]; + } + } + if( st->last_bwidth == NB && st->ini_frame != 0 ) + { + st->rate_switching_reset = 1; + } + + /*----------------------------------------------------------------* + * Change the sampling frequency to 12.8 kHz + *----------------------------------------------------------------*/ + + modify_Fs( st->input, input_frame, st->input_Fs, new_inp, 12800, st->mem_decim, 0 ); + + /* update signal buffer */ + mvr2r( new_inp, st->buf_speech_enc+L_FRAME, L_FRAME ); + + /*------------------------------------------------------------------* + * Perform fixed preemphasis through 1 - g*z^-1 + *-----------------------------------------------------------------*/ + + preemph( new_inp, PREEMPH_FAC, L_FRAME, &st->mem_preemph); + + /*----------------------------------------------------------------* + * Compute spectrum, find energy per critical frequency band + * Track energy and signal dynamics + * Detect NB spectrum in a 16kHz-sampled input + *----------------------------------------------------------------*/ + + analy_sp( inp, st->Bin_E, st->Bin_E_old, fr_bands, lf_E, &Etot, st->min_band, st->max_band, dummy_buf, PS, fft_buff ); + + noise_est_pre( Etot, st->ini_frame, &st->Etot_l, &st->Etot_h, &st->Etot_l_lp, &st->Etot_last, &st->Etot_v_h2, &st->sign_dyn_lp, st->harm_cor_cnt, &st->Etot_lp ); + + /*----------------------------------------------------------------* + * VAD + *----------------------------------------------------------------*/ + + vad_flag = wb_vad( st, fr_bands, &localVAD, &tmps, &tmps, &tmps, &snr_sum_he, &localVAD_HE_SAD, &st->flag_noisy_speech_snr ); + + if( vad_flag == 0 ) + { + coder_type = INACTIVE; + } + + /* apply DTX hangover for CNG analysis */ + vad_flag_dtx = dtx_hangover_addition( st, localVAD, vad_flag, st->lp_speech-st->lp_noise, 0, &vad_hover_flag ); + + + /*-----------------------------------------------------------------* + * Select SID or FRAME_NO_DATA frame if DTX enabled + *-----------------------------------------------------------------*/ + + if ( st->last_core != AMR_WB_CORE ) + { + st->fd_cng_reset_flag = 1; + } + else if ( st->fd_cng_reset_flag > 0 && st->fd_cng_reset_flag < 10 ) + { + st->fd_cng_reset_flag++; + } + else + { + st->fd_cng_reset_flag = 0; + } + + dtx( st, vad_flag_dtx, inp ); + + /*----------------------------------------------------------------* + * 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( fr_bands, st->bckr, tmpN, tmpE, st->min_band, st->max_band, &st->totalNoise, Etot, &st->Etot_last, &st->Etot_v_h2 ); + + high_lpn_flag = 0; + long_enr( st, Etot, localVAD_HE_SAD, high_lpn_flag ); + relE = Etot - st->lp_speech; + + if( st->bwidth != NB ) + { + lp_bckr = mean( st->bckr, 10 ); + } + else + { + lp_bckr = mean( st->bckr+1, 9 ); + } + hp_bckr = 0.5f * (st->bckr[st->max_band-1] + st->bckr[st->max_band]); + st->bckr_tilt_lt = 0.9f * st->bckr_tilt_lt + 0.1f * lp_bckr / hp_bckr; + + corr_shift = correlation_shift(st->totalNoise); + + /*----------------------------------------------------------------* + * WB, SWB and FB bandwidth detector + *----------------------------------------------------------------*/ + + bw_detect( st, st->input, localVAD, NULL ); + + /* in AMR_WB IO, limit the maximum band-width to WB */ + if( st->bwidth > WB ) + { + st->bwidth = WB; + } + + /*----------------------------------------------------------------* + * 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( &st->old_thres, &st->old_pitch, &st->delta_pit, &st->old_corr ) ; + } + + /* LP analysis */ + analy_lp_AMR_WB( inp, &ener, A, epsP, isp_new, st->lsp_old1, isf_new, st->old_pitch_la, st->old_voicing_la ); + + /* compute weighted input */ + find_wsp( L_FRAME, L_SUBFR, NB_SUBFR, A, Aw, inp, TILT_FAC, wsp, &st->mem_wsp, GAMMA1, L_LOOK_12k8 ); + + /* open-loop pitch analysis */ + pitch_ol( pitch,voicing, &st->old_pitch, &st->old_corr, corr_shift, &st->old_thres, + &st->delta_pit, st->old_wsp2, wsp, st->mem_decim2, relE, L_LOOK_12k8, 0, st->bwidth, 0 ); + + st->old_pitch_la = pitch[2]; + st->old_voicing_la = voicing[2]; + + vad_param_updt( st, pitch, voicing, st->pitO, corr_shift, A ); + + /*------------------------------------------------------------------* + * Update estimated noise energy and voicing cut-off frequency + *-----------------------------------------------------------------*/ + + noise_est( st, tmpN, pitch, voicing, epsP, Etot, relE, corr_shift, tmpE, fr_bands, &cor_map_sum, + &sp_div, &non_staX, &harm_flag, lf_E, &st->harm_cor_cnt, st->Etot_l_lp, &sp_floor ); + + /*----------------------------------------------------------------* + * Change the sampling frequency to 16 kHz, + * input@16kHz needed for AMR-WB IO BWE @23.85kbps + *----------------------------------------------------------------*/ + + if ( st->input_Fs == 16000 ) + { + /* no resampling needed, only delay adjustement to account for the FIR resampling delay */ + tmps = NS2SA(16000, DELAY_FIR_RESAMPL_NS); + mvr2r( st->mem_decim16k + tmps, new_inp_16k, tmps ); + mvr2r( st->input, new_inp_16k + tmps, input_frame - tmps ); + mvr2r( st->input + input_frame - 2*tmps, st->mem_decim16k, 2*tmps ); + } + else if( st->input_Fs == 32000 || st->input_Fs == 48000 ) + { + modify_Fs( st->input, input_frame, st->input_Fs, new_inp_16k, 16000, st->mem_decim16k, 0 ); + } + + /*----------------------------------------------------------------* + * Encoding of SID frames + *----------------------------------------------------------------*/ + + if ( st->core_brate == SID_1k75 || st->core_brate == FRAME_NO_DATA ) + { + /* encode CNG parameters */ + CNG_enc( st, L_FRAME, Aq, inp, ener, isp_new, isf_new , &allow_cn_step, st->burst_ho_cnt, q_env, &sid_bw, st->exc_mem2 ); + + /* comfort noise generation */ + CNG_exc( st->core_brate, L_FRAME, &st->Enew, &st->cng_seed, exc, exc2, &st->lp_ener, + st->last_core_brate, &st->first_CNG, &st->cng_ener_seed, dummy_buf, allow_cn_step, &st->last_allow_cn_step, st->num_ho, + q_env, st->lp_env, st->old_env, st->exc_mem, st->exc_mem1, &sid_bw, &st->cng_ener_seed1, exc3, st->Opt_AMR_WB ); + + if ( st->first_CNG == 0 ) + { + st->first_CNG = 1; + } + /* synthesis */ + syn_12k8( L_FRAME, Aq, exc2, dummy_buf, st->LPDmem.mem_syn3, 1 ); /* dummy_buf = temporary buffer to handle syn1[] */ + + /* reset the encoder */ + CNG_reset_enc( st, &(st->LPDmem), pitch_buf, dummy_buf+L_FRAME, 0 ); + + /* update st->mem_syn1 for ACELP core switching */ + mvr2r( st->LPDmem.mem_syn3, st->mem_syn1, M ); + + /* update ACELP core synthesis filter memory */ + mvr2r( st->LPDmem.mem_syn3, st->LPDmem.mem_syn, M ); + + /* update old synthesis buffer - needed for ACELP internal sampling rate switching */ + mvr2r( dummy_buf + L_FRAME - L_SYN_MEM, st->LPDmem.mem_syn_r, L_SYN_MEM ); + + /* Update MODE2 core switching memory */ + deemph( dummy_buf, PREEMPH_FAC, L_FRAME, &(st->LPDmem.syn[M]) ); + mvr2r( 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 + *-----------------------------------------------------------------*/ + + if( st->last_core_brate == FRAME_NO_DATA || st->last_core_brate == SID_1k75 ) + { + mvr2r( st->lspCNG, st->lsp_old, M ); + isp2isf( st->lspCNG, st->lsf_old, M, INT_FS_12k8 ); + set_f( old_exc, 0, L_EXC_MEM ); + } + + /*-----------------------------------------------------------------* + * ISF Quantization and interpolation + *-----------------------------------------------------------------*/ + + isf_enc_amr_wb( st, isf_new, isp_new, Aq, &st->stab_fac ); + + /*---------------------------------------------------------------* + * Calculation of LP residual (filtering through A[z] filter) + *---------------------------------------------------------------*/ + + calc_residu( inp, res, Aq, L_FRAME ); + st->burst_ho_cnt = 0; + + /*------------------------------------------------------------* + * Encode excitation + *------------------------------------------------------------*/ + + encod_amr_wb( st, &(st->LPDmem), inp, Aw, Aq, pitch, voicing, res, syn, exc, exc2, pitch_buf, hf_gain, inp_16k ); + + + /* update st->mem_syn1 for ACELP core switching */ + mvr2r( st->LPDmem.mem_syn, st->mem_syn1, M ); + + /* update old synthesis buffer - needed for ACELP internal sampling rate switching */ + mvr2r( syn + L_FRAME - L_SYN_MEM, st->LPDmem.mem_syn_r, L_SYN_MEM ); + + /* Update MODE2 core switching memory */ + mvr2r( syn, dummy_buf, L_FRAME ); + deemph( dummy_buf, PREEMPH_FAC, L_FRAME, &(st->LPDmem.syn[M]) ); + mvr2r( dummy_buf+L_FRAME-M-1, st->LPDmem.syn, M+1 ); + + /*--------------------------------------------------------------------------------------* + * Write VAD information into the bitstream in AMR-WB IO mode + *--------------------------------------------------------------------------------------*/ + + push_indice( st, IND_VAD_FLAG, vad_flag, 1 ); + + } + + + /*-----------------------------------------------------------------* + * Updates + *-----------------------------------------------------------------*/ + + /* update old weighted speech buffer - for OL pitch analysis */ + mvr2r( &old_wsp[L_FRAME], st->old_wsp, L_WSP_MEM ); + + /* update old input signal buffer */ + mvr2r( &old_inp[L_FRAME], st->old_inp_12k8, L_INP_MEM ); + + /* update old input signal @16kHz buffer */ + if( st->input_Fs > 8000 ) + { + mvr2r( &old_inp_16k[L_FRAME16k], st->old_inp_16k, L_INP_MEM ); + } + + /* update of old per-band energy spectrum */ + mvr2r( fr_bands + NB_BANDS, st->enrO, NB_BANDS ); + + /* update the last bandwidth */ + st->last_input_bwidth = st->input_bwidth; + st->last_bwidth = st->bwidth; + + /* update signal buffers */ + mvr2r( new_inp, st->buf_speech_enc_pe+L_FRAME, L_FRAME ); + mvr2r( wsp, st->buf_wspeech_enc+L_FRAME+L_SUBFR, L_FRAME + L_LOOK_12k8 ); + + updt_enc( 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 = -1; + st->last_core = st->core; + st->last_L_frame = L_FRAME; + st->last_core_brate = st->core_brate; + st->last_total_brate = st->total_brate; + st->Etot_last = Etot; + st->last_coder_type_raw = st->coder_type_raw; + st->last_codec_mode = st->codec_mode; + + /* Increase the counter of initialization frames */ + if( st->ini_frame < MAX_FRAME_COUNTER ) + { + (st->ini_frame)++; + } + + if( st->core_brate > SID_1k75 ) + { + st->last_active_brate = st->total_brate; + } + + if ( st->core_brate > SID_1k75 && st->first_CNG ) + { + if( st->act_cnt >= BUF_DEC_RATE ) + { + st->act_cnt = 0; + } + + st->act_cnt++; + + if( st->act_cnt == BUF_DEC_RATE && st->ho_hist_size > 0 ) + { + st->ho_hist_size--; + } + + if( ++(st->act_cnt2) >= MIN_ACT_CNG_UPD ) + { + st->act_cnt2 = MIN_ACT_CNG_UPD; + } + } + + + pop_wmops(); + + return; +} diff --git a/lib_enc/analy_lp.c b/lib_enc/analy_lp.c new file mode 100644 index 000000000..fe648ce25 --- /dev/null +++ b/lib_enc/analy_lp.c @@ -0,0 +1,143 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.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( + const float speech[], /* i : pointer to the speech frame */ + const short L_frame, /* i : length of the frame */ + const short L_look, /* i : look-ahead */ + float *ener, /* o : residual energy from Levinson-Durbin */ + float A[], /* o : A(z) filter coefficients */ + float epsP[], /* o : LP analysis residual energies for each iteration */ + float lsp_new[], /* o : current frame LSPs */ + float lsp_mid[], /* o : current mid-frame LSPs */ + float lsp_old[], /* i/o: previous frame unquantized LSPs */ + const short Top[2], /* i : open loop pitch lag */ + const float Tnc[2], /* i : open loop pitch gain */ + const float sr_core /* i : internal sampling rate */ +) +{ + short i_subfr, wind_length, half_frame; + float r[M+1], *lsp; + const float *wind, *pt; + short half_frame_idx; + + if( L_frame == L_FRAME ) + { + wind_length = L_LP; + wind = LP_assym_window; + } + else /* L_frame == L_FRAME16k */ + { + wind_length = L_LP_16k; + wind = LP_assym_window_16k; + } + lsp = lsp_mid; + half_frame = L_frame>>1; + + half_frame_idx = 0; + + for( i_subfr = half_frame; i_subfr <= L_frame; i_subfr = i_subfr + half_frame ) + { + pt = speech + i_subfr + L_look - wind_length; + + /* Autocorrelations */ + autocorr( pt, r, M, wind_length, wind, 0, 0, 0 ); + + /* Lag windowing */ + adapt_lag_wind( r, M, Top[half_frame_idx], Tnc[half_frame_idx], sr_core ); + ++half_frame_idx; + + /* Levinson-Durbin */ + lev_dur( A, r, M, epsP ); + + /* Conversion of A(z) to LSPs */ + a2lsp_stab( A, lsp, lsp_old ); + + lsp = lsp_new; + } + + /* LSP interpolation */ + int_lsp4( L_frame, lsp_old, lsp_mid, lsp_new, A, M, 0 ); + + /* updates */ + mvr2r( lsp_new, lsp_old, M ); + + *ener = epsP[M]; + + 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( + const float speech[], /* i : pointer to the speech frame */ + float *ener, /* o : residual energy from Levinson-Durbin */ + float A[], /* o : A(z) filter coefficients */ + float epsP[], /* o : LP analysis residual energies for each iteration */ + float isp_new[], /* o : current frame ISPs */ + float isp_old[], /* i/o: previous frame unquantized ISPs */ + float isf_new[], /* o : current frame ISFs */ + const int Top, /* i : open loop pitch lag */ + const float Tnc /* i : open loop pitch gain */ +) +{ + short wind_length; + float r[M+1]; + const float *wind; + + /* Initialization */ + wind_length = L_LP_AMR_WB; + wind = hamcos_window; + + /* Autocorrelations */ + autocorr( speech - L_SUBFR, r, M, wind_length, wind, 0, 0, 0 ); + + /* Lag windowing */ + adapt_lag_wind( r, M, Top, Tnc, 12800 ); + + /* Levinson-Durbin */ + lev_dur( A, r, M, epsP ); + + a2isf( A, isf_new, stable_ISF, M); + isf2isp( isf_new, isp_new, M, INT_FS_12k8 ); + + /* ISP interpolation */ + int_lsp( L_FRAME, isp_old, isp_new, A, M, interpol_isp_amr_wb, 1 ); + + *ener = epsP[M]; + + /* updates */ + mvr2r( 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 000000000..ff2ef1cb9 --- /dev/null +++ b/lib_enc/analy_sp.c @@ -0,0 +1,210 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_enc.h" +#include "rom_com.h" +#include "prot.h" + + +static void find_enr( const float data[], float band[], float *ptE, float *Etot, const short min_band, + const short max_band, float *Bin_E, const short bin_freq, float *band_ener ); + +/*-------------------------------------------------------------------* + * analy_sp() + * + * Spectral analysis + *-------------------------------------------------------------------*/ + +void analy_sp( + float *speech, /* i : speech buffer */ + float *Bin_E, /* o : per bin log energy spectrum */ + float *Bin_E_old, /* o : per bin log energy spectrum for mid-frame */ + float *fr_bands, /* o : per band energy spectrum (2 analyses) */ + float lf_E[], /* o : per bin E for first VOIC_BINS bins (without DC) */ + float *Etot, /* o : total input energy */ + const short min_band, /* i : minimum critical band */ + const short max_band, /* i : maximum critical band */ + float *band_ener, /* o: energy in critical frequency bands without minimum noise floor E_MIN */ + float *PS /* o : Per bin energy spectrum */ + ,float *fft_buff /* o : FFT coefficients */ +) +{ + short i_subfr, i; + float *pt_bands, *pt_fft, *pt; + const float *pt1; + /*-----------------------------------------------------------------* + * Perform two spectral analyses + * Find energy per critical frequency band and total energy in dB + *-----------------------------------------------------------------*/ + + pt_bands = fr_bands; + pt_fft = fft_buff; + *Etot = 0.0f; + + for( i_subfr = 0; i_subfr <= 1; i_subfr++ ) + { + /* set pointer to the beginning of the signal for spectral analysis */ + if (i_subfr == 0) + { + /* set the pointer for first analysis window */ + pt = speech + 3*(L_SUBFR/2) - L_FFT/2; + } + else + { + /* set the pointer for second analysis window */ + pt = speech + 7*(L_SUBFR/2) - L_FFT/2; + } + + /* 1st half of the window */ + pt1 = sqrt_han_window; + for( i=0; i +#include "wmc_auto.h" +#include +#include "cnst.h" +#include "prot.h" +#include "stat_com.h" +#include "assert.h" +#include "basop_util.h" + + + + +/** + * \brief Copy state + * + * \param[i] source + * \param[o] dest + * + * \return none + */ +void ari_copy_states(Tastat *source, Tastat *dest) +{ + dest->low = source->low; + dest->high = source->high; + dest->vobf = source->vobf; +} + +/*--------------------------------------------------------------- + Ari encoder 14 bits routines + -------------------------------------------------------------*/ + +/** + * \brief Start ArCo encoding + * + * \param[o] s + * + * \return none + */ +void ari_start_encoding_14bits(Tastat *s) +{ + /* : addressing is made with walking pointer s */ + s->low = 0; + s->high = ari_q4new; + s->vobf = 0; +} + +/** + * \brief Finish ArCo encoding + * + * \param[o] ptr + * \param[i] bp + * \param[i] s + * + * \return bit consumption + */ +long ari_done_encoding_14bits(int *ptr,long bp,Tastat *s) +{ + long low; + long bits_to_follow; + + + + + /* not needed, s points to s->low */ + low = s->low; + bits_to_follow = s->vobf+1; + + if ( low < ari_q1new ) + { + ptr[bp++] = 0; /*send a zero*/ + for(; bits_to_follow>0; bits_to_follow--) + { + ptr[bp++] = 1; /*send a one*/ + } + } + else + { + ptr[bp++] = 1; /*send a one*/ + for(; bits_to_follow>0; bits_to_follow--) + { + ptr[bp++] = 0; /*send a zero*/ + } + } + + /*It is done so no need to save values-> no counting*/ + /*s->low = low; + s->vobf = bits_to_follow;*/ + + + return bp; +} + + +/** + * \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 + */ +long ari_encode_14bits_ext(int *ptr,long bp,Tastat *s,long symbol,const unsigned short *cum_freq) +{ + long low, high, range; + long bits_to_follow; + + + + /*for all operation using bit_ptr=&ptr[bp] */ + /* for reading s->high,low,vobf sequentially */ + high=s->high; + low =s->low; + range = high-low+1; + + high = low + mul_sbc_14bits(range,cum_freq[symbol]) - 1; + low += mul_sbc_14bits(range,cum_freq[symbol+1]); + + bits_to_follow = s->vobf; + + for (;;) + { + if ( high0; bits_to_follow--) + { + ptr[bp++] = 1; /*send a one*/ + } + } + else + { + if ( low>=ari_q2new ) + { + ptr[bp++] = 1; /*send a one*/ + for(; bits_to_follow>0; bits_to_follow--) + { + ptr[bp++] = 0; /*send a zero*/ + } + low -= ari_q2new; + high -= ari_q2new; /* Subtract offset to top. */ + } + else + { + /* Output an opposite bit */ + if ( low>=ari_q1new && highlow = low; + s->high = high; + s->vobf = bits_to_follow; + + + return bp; +} + +/*------------------------------------------------------------------------ + * Function: ari_encode_14bits_range + * + * Encode an cumulative frequency interval. + *-------------------------------------------------------------------------*/ + +long ari_encode_14bits_range(int *ptr, long bp, long bits, Tastat *s, unsigned short cum_freq_low, unsigned short cum_freq_high) +{ + long low, high, range; + long bits_to_follow; + + + + /* not needed, s points to s->low */ + high = s->high; + high++; + low = s->low; + range = high - low; + + high = low + mul_sbc_14bits(range, cum_freq_high); + low += mul_sbc_14bits(range, cum_freq_low); + + bits_to_follow = s->vobf; + + /* while there are more than 16 bits left */ + for (; bp + 16 + bits_to_follow - bits < 0;) + { + if (high <= ari_q2new) + { + ptr[bp++] = 0; /*send a zero*/ + for (; bits_to_follow > 0; bits_to_follow--) + { + ptr[bp++] = 1; /*send a one*/ + } + } + else if (low >= ari_q2new) + { + /* to reach this branch */ + ptr[bp++] = 1; /*send a one*/ + for (; bits_to_follow > 0; bits_to_follow--) + { + ptr[bp++] = 0; /*send a zero*/ + } + low -= ari_q2new; + high -= ari_q2new; /* Subtract offset to top. */ + } + else if (low >= ari_q1new && high <= ari_q3new) + { + /* to reach this branch */ + /* Output an opposite bit */ + /* later if in middle half. */ + bits_to_follow += 1; + low -= ari_q1new; /* Subtract offset to middle*/ + high -= ari_q1new; + } + else + { + /* to reach this branch */ + break; /* Otherwise exit loop. */ + } + + low += low; + high += high; /* Scale up code range. */ + } + /* if there are <= 16 bits left */ + if (bp + 16 + bits_to_follow - bits >= 0) + { + /* No need to do anyhing, but let's keep a place for a breakpoint */ + s->vobf = -1; + } + + s->low = low; + s->high = high - 1; + s->vobf = bits_to_follow; + + return bp; +} + +/*------------------------------------------------------------------------ + * Function: ari_encode_14bits_sign + * + * Encode a sign with equal probabilities. + *-------------------------------------------------------------------------*/ +long ari_encode_14bits_sign(int *ptr, long bp, long bits, Tastat *s, long sign) +{ + long low, high, range; + long bits_to_follow; + + + + /* not needed, s points to s->low */ + high = s->high; + high++; + low = s->low; + range = high - low; + + if (sign) + { + high = low + (range >> 1); + } + else + { + low += range >> 1; + } + + bits_to_follow = s->vobf; + + /* while there are more than 16 bits left */ + for (; bp + 16 + bits_to_follow - bits < 0;) + { + if (high <= ari_q2new) + { + ptr[bp++] = 0; /*send a zero*/ + for (; bits_to_follow > 0; bits_to_follow--) + { + ptr[bp++] = 1; /*send a one*/ + } + } + else if (low >= ari_q2new) + { + /* to reach this branch */ + ptr[bp++] = 1; /*send a one*/ + for (; bits_to_follow > 0; bits_to_follow--) + { + ptr[bp++] = 0; /*send a zero*/ + } + low -= ari_q2new; + high -= ari_q2new; /* Subtract offset to top. */ + } + else if (low >= ari_q1new && high <= ari_q3new) + { + /* to reach this branch */ + /* Output an opposite bit */ + /* later if in middle half. */ + bits_to_follow += 1; + low -= ari_q1new; /* Subtract offset to middle*/ + high -= ari_q1new; + } + else + { + /* to reach this branch */ + break; /* Otherwise exit loop. */ + } + + low += low; + high += high; /* Scale up code range. */ + } + + s->low = low; + s->high = high - 1; + s->vobf = bits_to_follow; + + return bp; +} + +/*------------------------------------------------------------------------ + * Function: ari_done_cbr_encoding_14bits + * + * Finish up encoding in CBR mode. + *-------------------------------------------------------------------------*/ +long ari_done_cbr_encoding_14bits(int *ptr, long bp, long bits, Tastat *s) +{ + + long high; + long bits_to_follow; + int k; + + + while (bits - bp - 16 - s->vobf > 0) + { + bp = ari_encode_14bits_sign(ptr, bp, bits, s, 0); + } + + /* not needed, s points to s->low */ + high = s->high; + bits_to_follow = s->vobf; + + if (bits_to_follow) + { + /* If in upper half, then output a one, bits_to_follow zeros, and the remaining bits, except the first one */ + if (high < 0x8000) + { + ptr[bp++] = 0; /*send a zero*/ + for (; bits_to_follow > 0; bits_to_follow--) + { + ptr[bp++] = 1; /*send a one*/ + } + } + else + { + ptr[bp++] = 1; /*send a one*/ + for (; bits_to_follow > 0; bits_to_follow--) + { + ptr[bp++] = 0; /*send a zero*/ + } + } + /* write remaining bits */ + for (k = 0x4000; k > 0; k >>= 1) + { + if (k & high) + { + ptr[bp++] = 1; /*send a one*/ + } + else + { + ptr[bp++] = 0; /*send a zero*/ + } + if (bp >= bits) + { + break; + } + } + + } + else + { + /* no carry-bits, just write all bits */ + for (k = 0x8000; k > 0; k >>= 1) + { + if (k & high) + { + ptr[bp++] = 1; /*send a one*/ + } + else + { + ptr[bp++] = 0; /*send a zero*/ + } + if (bp >= bits) + { + break; + } + } + + } + + + return bp; +} diff --git a/lib_enc/ari_hm_enc.c b/lib_enc/ari_hm_enc.c new file mode 100644 index 000000000..45feabd5d --- /dev/null +++ b/lib_enc/ari_hm_enc.c @@ -0,0 +1,590 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "cnst.h" +#include "wmc_auto.h" +#include "rom_enc.h" +#include "stl.h" +#include "basop_util.h" +#include +#include +#include "prot.h" +#include "rom_com.h" + + +/*-------------------------------------------------------------------* + * EncodeIndex() + * + * + *-------------------------------------------------------------------*/ + +int EncodeIndex( + int Bandwidth, + int PeriodicityIndex, + Encoder_State *st +) +{ + + if (PeriodicityIndex & kLtpHmFlag) + { + int LtpPitchIndex = PeriodicityIndex >> 9; + assert(0 <= LtpPitchIndex && LtpPitchIndex <= 16); + --PeriodicityIndex; + assert((PeriodicityIndex & 0xff) < (1 << NumRatioBits[Bandwidth][LtpPitchIndex])); + + push_next_indice(st, PeriodicityIndex & 0xff, NumRatioBits[Bandwidth][LtpPitchIndex]); + return NumRatioBits[Bandwidth][LtpPitchIndex]; + } + else + { + push_next_indice(st, PeriodicityIndex, 8); + return 8; + } +} + + +/*-------------------------------------------------------------------* + * GetWeight() + * + * + *-------------------------------------------------------------------*/ + +static float GetWeight(int i) +{ + i = 3 * i - 2; + + return (float)(pow(i, 0.3) / pow(256 - 1, 0.3)); +} + + +/*-------------------------------------------------------------------* + * SearchPeriodicityIndex_Single() + * + * + *-------------------------------------------------------------------*/ + +static float SearchPeriodicityIndex_Single( + const float AbsMdct3[], + int NumToConsider, + int Lag, + int FractionalResolution +) +{ + int HighestMultiplier; + float AbsMeanCurrent3; /* Mean for BucketWidth == 3 */ + int Limit; + int OldIndex, i; + + Limit = (NumToConsider - 1) << FractionalResolution; + AbsMeanCurrent3 = 0; + HighestMultiplier = 1; + + for (i=Lag; i> FractionalResolution; + AbsMeanCurrent3 += AbsMdct3[OldIndex] * GetWeight(HighestMultiplier); + ++HighestMultiplier; + } + + return AbsMeanCurrent3 / (HighestMultiplier - 1 + 0.00001f); +} + + +/*-------------------------------------------------------------------* + * SearchPeriodicityIndex_Range() + * + * + *-------------------------------------------------------------------*/ + +static void SearchPeriodicityIndex_Range( + const float AbsMdct3[], + int NumToConsider, + int Lo, + int Hi, + int FractionalResolution, + int Adj, + int Spacing, + int *PeriodicityIndex, + float *Score +) +{ + int Index, BestIndex; + float CurrentScore, BestScore; + int B; + + BestScore = -1e30f; + BestIndex = 0; + + for (Index = Lo; Index < Hi; Index += Spacing) + { + CurrentScore = SearchPeriodicityIndex_Single( AbsMdct3, NumToConsider, Index + Adj, FractionalResolution ); + + if (CurrentScore > BestScore) + { + BestScore = CurrentScore; + BestIndex = Index; + } + } + + if (BestScore > *Score) + { + *Score = BestScore; + *PeriodicityIndex = BestIndex; + } + + + B = BestIndex - (Spacing >> 1); + B = max(Lo, B); + + for (Index = B; Index < BestIndex; ++Index) + { + CurrentScore = SearchPeriodicityIndex_Single( AbsMdct3, NumToConsider, Index + Adj, FractionalResolution ); + + if (CurrentScore > *Score) + { + *Score = CurrentScore; + *PeriodicityIndex = Index; + } + } + + B = BestIndex + (Spacing >> 1); + + for (Index = BestIndex + 1; Index <= B; ++Index) + { + CurrentScore = SearchPeriodicityIndex_Single( AbsMdct3, NumToConsider, Index + Adj, FractionalResolution ); + + if (CurrentScore > *Score) + { + *Score = CurrentScore; + *PeriodicityIndex = Index; + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * UnmapIndex() + * + * + *-------------------------------------------------------------------*/ + +/* Returns: PeriodicityIndex */ +int SearchPeriodicityIndex( + const float Mdct[], /* (I) Coefficients, Mdct[0..NumCoeffs-1] */ + const float UnfilteredMdct[], /* (I) Unfiltered coefficients, UnfilteredMdct[0..NumCoeffs-1] */ + int NumCoeffs, /* (I) Number of coefficients */ + int TargetBits, /* (I) Target bit budget (excl. Done flag) */ + short LtpPitchLag, + float LtpGain, /* (I) LTP gain */ + float *RelativeScore /* (O) Energy concentration factor */ +) +{ + float AbsMdct3[MAX_LENGTH], A, B, C=0.f; + int i; + int MaxAt; + float Score; + int PeriodicityIndex = 0; + int NumToConsider = NumCoeffs; + float AbsTotal; + + + Score = -1e30f; + + A = (float)fabs(Mdct[0]); + B = (float)fabs(Mdct[1]); + + for (i = 1; i < NumToConsider - 3; i += 3) + { + C = (float)fabs(Mdct[i + 1]); + AbsMdct3[i] = A + B + C; + + A = (float)fabs(Mdct[i + 2]); + AbsMdct3[i + 1] = A + B + C; + + B = (float)fabs(Mdct[i + 3]); + AbsMdct3[i + 2] = A + B + C; + } + + if (i < NumToConsider - 1) + { + C = (float)fabs(Mdct[i + 1]); + AbsMdct3[i] = A + B + C; + } + + + if (i + 1 < NumToConsider - 1) + { + A = (float)fabs(Mdct[i + 2]); + AbsMdct3[i + 1] = A + B + C; + } + + AbsTotal = 0.0f; + + if (UnfilteredMdct != NULL) + { + for (i = 0; i < NumToConsider; ++i) + { + AbsTotal += (float)fabs(UnfilteredMdct[i]); + } + } + else + { + for (i = 1; i < NumToConsider - 1; i += 3) + { + AbsTotal += AbsMdct3[i]; + } + } + + + if ((LtpPitchLag > 0) && (LtpGain > kLtpHmGainThr)) + { + int FractionalResolution = kLtpHmFractionalResolution; + int Multiplier; + int LtpPitchIndex; + int Bandwidth; + + Bandwidth = NumCoeffs >= 256; + LtpPitchIndex = ((LtpPitchLag + (1 << (kLtpHmFractionalResolution - 1))) >> kLtpHmFractionalResolution) - 2; + assert(0 <= LtpPitchIndex && LtpPitchIndex <= 16); + + for (Multiplier = 1; Multiplier <= (1 << NumRatioBits[Bandwidth][LtpPitchIndex]); ++Multiplier) + { + float CurrentScore; + int Lag; + + Lag = (LtpPitchLag * (int)(4 * Ratios[Bandwidth][LtpPitchIndex][Multiplier-1])) >> 2; + + if (Lag >= (4 << FractionalResolution) && (Lag <= ((NumToConsider-2) << FractionalResolution))) + { + CurrentScore = SearchPeriodicityIndex_Single( AbsMdct3, NumToConsider, Lag, FractionalResolution ); + + if (CurrentScore > Score) + { + Score = CurrentScore; + PeriodicityIndex = Multiplier | kLtpHmFlag; + } + } + } + PeriodicityIndex |= LtpPitchIndex << 9; + } + else + { + if (UnfilteredMdct != NULL) + { + MaxAt = 1; + A = AbsMdct3[1]; + + for (i = 4; i < NumToConsider - 1; i += 3) + { + + if (AbsMdct3[i] > AbsMdct3[MaxAt]) + { + MaxAt = i; + } + A += AbsMdct3[i]; + } + + if (AbsMdct3[MaxAt] > A * 0.7f) + { + NumToConsider = min(NumToConsider, MaxAt + 4); + } + } + + SearchPeriodicityIndex_Range( AbsMdct3, NumToConsider, 0, 16, 3, GET_ADJ2(0, 6, 3), 4, &PeriodicityIndex, &Score ); + + SearchPeriodicityIndex_Range( AbsMdct3, NumToConsider, 16, 80, 4, GET_ADJ2(16, 8, 4), 4, &PeriodicityIndex, &Score ); + + SearchPeriodicityIndex_Range( AbsMdct3, NumToConsider, 80, 208, 3, GET_ADJ2(80, 12, 3), 4, &PeriodicityIndex, &Score ); + + if (NumToConsider <= 128) + { + /* no long lags for band-limited MDCTs */ + + SearchPeriodicityIndex_Range( AbsMdct3, NumToConsider, 208, 88 + NumToConsider, 0, GET_ADJ2(224, 188, 0), 1, &PeriodicityIndex, &Score ); + } + else + { + + if (TargetBits > kSmallerLagsTargetBitsThreshold && NumCoeffs >= 256) + { + SearchPeriodicityIndex_Range( AbsMdct3, NumToConsider, 208, 224, 1, GET_ADJ2(208, 28, 1), 1, &PeriodicityIndex, &Score ); + + SearchPeriodicityIndex_Range( AbsMdct3, NumToConsider, 224, 256, 0, GET_ADJ2(224, 188, 0 ), 1, &PeriodicityIndex, &Score ); + } + else + { + SearchPeriodicityIndex_Range( AbsMdct3, NumToConsider, 208, 256, 1, GET_ADJ2(208, 28, 1), 1, &PeriodicityIndex, &Score ); + } + } + } + + if (AbsTotal > 0) + { + *RelativeScore = Score/AbsTotal*(float)NumCoeffs; + } + else + { + *RelativeScore = 0; + } + + + return PeriodicityIndex; +} + + +/*-------------------------------------------------------------------* + * PeakFilter() + * + * + *-------------------------------------------------------------------*/ + +#define kPeakElevationThreshold 1.0f + +static void PeakFilter( + const float x[], /* (I) absolute spectrum */ + float y[], /* (O) filtered absolute spectrum, must not alias x[] */ + int L_frame /* (I) number of spectral lines */ +) +{ + int flen, i; + float a, m; + + flen = (L_frame >> 4); + m = kPeakElevationThreshold / (float)(2*flen + 1); + + a = 0.0f; + for (i=0; i= 256, LtpPitchLag, (targetBits - *hm_bits <= kSmallerLagsTargetBitsThreshold) || (L_frame < 256), &fract_res, &lag ); + + /* Render harmonic model */ + tcx_hm_render( lag, fract_res, LtpGain, p ); + + /* Calculate and quantize gain */ + gain = 0; + + tcx_hm_quantize_gain( abs_spectrum, env, lag, fract_res, p, L_frame, coder_type, RelativeScore, &prm_hm[2], &gain ); + + /* Decision */ + if (gain > 0) + { + prm_hm[0] = 1; /* flag: on */ + + *hm_bits += CountIndexBits( L_frame >= 256, prm_hm[1] ); + + if (coder_type == VOICED) + { + *hm_bits += kTcxHmNumGainBits; + } + + tcx_hm_modify_envelope( gain, lag, fract_res, p, env, L_frame ); + } + else + { + prm_hm[0] = 0; /* flag: off */ + prm_hm[1] = -1; /* pitch index */ + prm_hm[2] = 0; /* gain index */ + } + + return; +} diff --git a/lib_enc/arith_coder_enc.c b/lib_enc/arith_coder_enc.c new file mode 100644 index 000000000..552698882 --- /dev/null +++ b/lib_enc/arith_coder_enc.c @@ -0,0 +1,627 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include "basop_util.h" +#include "basop_proto_func.h" + +#define WMC_TOOL_SKIP + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define LOG2_E 1.44269504089f + +#define kMaxNumHeapElems 10 + +typedef struct HeapElem +{ + float mScore; /* Sort key */ + int mIndex; /* Original index */ +} HeapElem; + +typedef struct Heap +{ + HeapElem mElem[2*kMaxNumHeapElems+1]; + int mSize; +} Heap; + + +/*-------------------------------------------------------------------* + * tcx_arith_estimate_scale() + * + * + *-------------------------------------------------------------------*/ + +static float tcx_arith_estimate_scale( /* o: estimated SQ scale */ + const float abs_spectrum[], /* i: absolute MDCT coefficients */ + int L_frame, /* i: number of spectral lines */ + const Word16 envelope[], /* i: scaled envelope (Q15-e) */ + Word16 envelope_e /* i: scaled envelope exponent (Q0) */ +) +{ + float scale, tmp; + int k; + + /* compute normalised standard deviation and determine approximate scale */ + scale = 0.01f; + for (k = 0; k < L_frame; k++) + { + tmp = abs_spectrum[k] * envelope[k]; + scale += tmp * tmp; + } + tmp = (float)(1 << (15-envelope_e)); + scale = (float)sqrt((L_frame * tmp*tmp*4.0f) / scale); + + + return scale; +} + + +/*-------------------------------------------------------------------* + * MinHeapify_i() + * + * + *-------------------------------------------------------------------*/ + +static void MinHeapify_i(Heap *H, int i) +{ + int left, right, largest; + HeapElem T; + + left = 2*i + 1; + right = left + 1; + largest = i; + + if (H->mElem[left].mScore < H->mElem[largest].mScore) + { + largest = left; + } + if (H->mElem[right].mScore < H->mElem[largest].mScore) + { + largest = right; + } + while (largest != i) + { + T.mIndex = H->mElem[i].mIndex; + T.mScore = H->mElem[i].mScore; + + H->mElem[i].mIndex = H->mElem[largest].mIndex; + H->mElem[i].mScore = H->mElem[largest].mScore; + + H->mElem[largest].mIndex = T.mIndex; + H->mElem[largest].mScore = T.mScore; + + i = largest; + + left = 2*i + 1; + right = left + 1; + + if (H->mElem[left].mScore < H->mElem[largest].mScore) + { + largest = left; + } + if (H->mElem[right].mScore < H->mElem[largest].mScore) + { + largest = right; + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * tcx_arith_find_max_scale() + * + * + *-------------------------------------------------------------------*/ + +static float tcx_arith_find_max_scale( + const float abs_spectrum[], /* i: absolute MDCT coefficients */ + int L_frame, /* i: number of spectral lines */ + const Word16 envelope[], /* i: scaled envelope (Q15-e) */ + Word16 envelope_e, /* i: scaled envelope exponent (Q0) */ + const Word16 exps[], /* i: expfp(-(int)envelope[]/2) */ + float deadzone /* i: deadzone (0.5f = no deadzone) */ +) +{ + int i, k, q; + float p, scale; + Heap heap; + Word16 tmpi1, tmpi2; + float envelope_scale; + const float limit = -9.70406052784f; /* = ln(1/16384): log of smallest allowed probability */ + + /* Find the top most offending lines according to probability estimates */ + heap.mSize = kMaxNumHeapElems; + heap.mElem[0].mScore = 0; /* mal: just to silnce the compiler */ + + for (i=0; i heap.mElem[0].mScore) + { + heap.mElem[0].mScore = p; + heap.mElem[0].mIndex = k; + 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); + envelope_scale = -(float)pow(2, envelope_e-16); + for (i=0; i= 2) + { + /* q may be too low */ + powfp_odd2(exps[k], q+1, &tmpi1, &tmpi2); + while (tmpi1 - tmpi2 >= 2) + { + ++q; + powfp_odd2(exps[k], q+1, &tmpi1, &tmpi2); + } + } + else + { + /* q is too high */ + --q; + powfp_odd2(exps[k], q, &tmpi1, &tmpi2); + while (tmpi1 - tmpi2 < 2) + { + --q; + 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); + assert((int)(abs_spectrum[k] * p + deadzone) <= q); + scale = min(scale, p); + } + + + return scale; +} + + +/*-------------------------------------------------------------------* + * tcx_arith_find_kMax() + * + * + *-------------------------------------------------------------------*/ + +static int tcx_arith_find_kMax( /* o: index of highest freq. nonzero line (-1 if all zeros) */ + const float abs_spectrum[], /* i: absolute MDCT coefficients */ + int L_frame, /* i: number of spectral lines */ + float scale, /* i: scalar quantizer scale */ + float deadzone, /* i: deadzone (0.5f = no deadzone) */ + const int deadzone_flags[] /* i: line-wise deadzone control */ +) +{ + int kMax; + + + kMax = L_frame - 1; + while ((kMax >= 0) && (abs_spectrum[kMax] * scale < (1.0f - deadzone) + deadzone * deadzone_flags[kMax])) + { + kMax--; + } + + return kMax; +} + + +/*-------------------------------------------------------------------* + * tcx_arith_rateloop() + * + * + *-------------------------------------------------------------------*/ + +static float tcx_arith_rateloop( /* o: best scale */ + const float abs_spectrum[], /* i: absolute MDCT coefficients */ + int L_frame, /* i: number of spectral lines */ + const Word16 envelope[], /* i: scaled envelope (Q15-e) */ + Word16 envelope_e, /* i: scaled envelope exponent (Q0) */ + const Word16 exps[], /* i: expfp(-(int)envelope[]/2) */ + int target_bits, /* i: target bit budget */ + float deadzone, /* i: deadzone (0.5f = no deadzone) */ + const int deadzone_flags[], /* i: line-wise deadzone control */ + float *target_bits_fac /* i/o: scale estimator compensation */ +) +{ + int k, kMax, q; + float s, adjust; + float fixed_bits[2][N_MAX_ARI]; + float estimator_undershoot; + float max_complexity; + int iter; /* rate loop iteration counter */ + float scale; /* SQ scale factor to try next */ + float scale_best; /* best SQ scale factor */ + float scale_max; /* maximum allowable scale factor */ + float lob; /* lower bound of SQ scale factor */ + float hib; /* upper bound of SQ scale factor */ + int flag; /* 1:bit surplus, -1:bit deficit, 0:unknown */ + float complexity; /* cumulative rate loop complexity */ + float bits; /* number of bits (approximate) */ + float envelope_scale; + + + scale = tcx_arith_estimate_scale(abs_spectrum, L_frame, envelope, envelope_e); + scale *= *target_bits_fac; + + scale_max = tcx_arith_find_max_scale(abs_spectrum, L_frame, envelope, envelope_e, exps, deadzone); + if (scale > scale_max) scale = scale_max; + + scale_best = scale; + lob = 0.0f; + hib = 0.0f; + flag = 0; + complexity = 0; + bits = 0; + max_complexity = 96.0f * L_frame; + iter = 0; + envelope_scale = (float)pow(2, envelope_e-15); + + estimator_undershoot = 0; + /* Precalculate fixed bit costs */ + for (k=0; k 1.25f) *target_bits_fac = 1.25f; + if (*target_bits_fac < 0.75f) *target_bits_fac = 0.75f; + } + } + if (bits <= target_bits) + { + /* Bits leftover => scale is too small */ + if (flag <= 0 || scale >= scale_best) + { + scale_best = scale; + flag = 1; + } + + lob = scale; + if (hib > 0) + { + /* Bisection search */ + scale = (lob + hib)*0.5f; + } + else + { + /* Initial scale adaptation */ + adjust = 1.25f * target_bits / (float)bits; + if (adjust > 2.0f) adjust = 2.0f; + scale *= adjust; + if (scale > scale_max) scale = scale_max; + } + } + else + { + /* Ran out of bits => scale is too large */ + hib = scale; + if (lob > 0) + { + /* Bisection search */ + scale = (lob + hib)*0.5f; + } + else + { + /* Initial scale adaptation */ + adjust = 0.8f * target_bits / (float)bits; + if (adjust < 0.5f) adjust = 0.5f; + scale *= adjust; + } + if (flag <= 0) + { + scale_best = scale; + flag = 0; + } + } + ++iter; + } + + + return scale_best; +} + + +/*-------------------------------------------------------------------* + * tcx_arith_encode() + * + * + *-------------------------------------------------------------------*/ + +static int tcx_arith_encode( /* o: number of bits consumed */ + int q_abs_spectrum[], /* i/o: scalar quantized absolute spectrum */ + const int signs[], /* i: signs */ + int kMax, /* i: number of nonzero spectral lines to code */ + int L_frame, /* i: nominal number of spectral lines */ + const Word16 exps[], /* i: expfp(-(int)envelope[]/2) */ + int target_bits, /* i: target bit budget */ + int prm[] /* o: bit-stream */ +) +{ + Tastat as, as_lastgood; + int bp, bp_lastgood; + int k; + int kEncoded; + Word16 tmpi1, tmpi2; + + /* Final coding */ + ari_start_encoding_14bits(&as); + ari_copy_states(&as, &as_lastgood); + bp = bp_lastgood = 0; + kEncoded = kMax; + 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, exps[k]>>1, 16384); + } + else + { + /* q_abs_spectrum[k] != 0 */ + powfp_odd2(exps[k], q_abs_spectrum[k], &tmpi1, &tmpi2); + while (tmpi1 < tmpi2 + 2) + { + --q_abs_spectrum[k]; + powfp_odd2(exps[k], q_abs_spectrum[k], &tmpi1, &tmpi2); + } + bp = ari_encode_14bits_range(prm, bp, target_bits, &as, tmpi2>>1, tmpi1>>1); + bp = ari_encode_14bits_sign(prm, bp, target_bits, &as, signs[k]); + } + /* Check bit budget status */ + if (as.high <= as.low) + { + /* no bits left */ + /* printf("\noverflow at %d\n\n", k); */ + if (q_abs_spectrum[k] > 1) /* Lower magnitude is still > 0 */ + { + /* Restore state */ + ari_copy_states(&as_lastgood, &as); + bp = bp_lastgood; + + /* Quantize to lower magnitude */ + --q_abs_spectrum[k]; + + /* Retry encoding */ + powfp_odd2(exps[k], q_abs_spectrum[k], &tmpi1, &tmpi2); + bp = ari_encode_14bits_range(prm, bp, target_bits, &as, tmpi2>>1, tmpi1>>1); + bp = ari_encode_14bits_sign(prm, bp, target_bits, &as, signs[k]); + if (as.high > as.low) /* Success */ + { + ari_copy_states(&as, &as_lastgood); + bp_lastgood = bp; + kEncoded = k; + for (++k; k <= kMax; k++) + { + q_abs_spectrum[k] = 0; + } + break; + } + } + ari_copy_states(&as_lastgood, &as); + bp = bp_lastgood; + kEncoded = k-1; + for (; k <= kMax; k++) + { + q_abs_spectrum[k] = 0; + } + break; + } + else + { + ari_copy_states(&as, &as_lastgood); + bp_lastgood = bp; + } + } + + /* Send zeros until L_frame */ + for (k=kEncoded+1, kEncoded=L_frame-1; k= 2); + bp = ari_encode_14bits_range(prm, bp, target_bits, &as, exps[k]>>1, 16384); + /* Check bit budget status */ + if (as.high <= as.low) + { + /* no bits left */ + ari_copy_states(&as_lastgood, &as); + bp = bp_lastgood; + kEncoded = k-1; + break; + } + else + { + ari_copy_states(&as, &as_lastgood); + bp_lastgood = bp; + } + } + + if (kEncoded == L_frame-1) + { + /* RESQ bits possibly available */ + /* Limit target bits to actually needed bits */ + bp = ari_done_cbr_encoding_14bits(prm, bp, bp + 16 + as.vobf, &as); + } + else + { + bp = ari_done_cbr_encoding_14bits(prm, bp, target_bits, &as); + } + + return bp; +} + + +/*-------------------------------------------------------------------* + * tcx_arith_encode_envelope() + * + * + *-------------------------------------------------------------------*/ + +void tcx_arith_encode_envelope( + float spectrum[], /* i/o: MDCT coefficients */ + int signs[], /* o: signs (spectrum[.]<0) */ + int L_frame, /* i: frame or MDCT length */ + int L_spec, /* i: length w/o BW limitation */ + Encoder_State *st, /* i/o: coder state */ + const Word16 A_ind[], /* i: quantised LPC coefficients */ + int target_bits, /* i: number of available bits */ + int prm[], /* o: bitstream parameters */ + int use_hm, /* i: use HM in current frame? */ + int prm_hm[], /* o: HM parameter area */ + short tcxltp_pitch, /* i: TCX LTP pitch in FD, -1 if n/a*/ + int *arith_bits, /* o: bits used for ari. coding */ + int *signaling_bits, /* o: bits used for signaling */ + int low_complexity /* i: low-complexity flag */ +) +{ + Word16 tmp; + Word32 env[N_MAX_ARI]; /* unscaled envelope (Q16) */ + Word16 *envelope; /* scaled envelope (Q15-e) */ + Word16 envelope_e; + Word16 exponents[N_MAX_ARI]; /* Q15 */ + int L_spec_core; + int *q_spectrum; + TCX_config *tcx_cfg; + float scale; + int k, kMax; + float deadzone; + const int *deadzone_flags; + float gamma_w, gamma_uw; + int hm_bits; + + assert(L_spec<=N_MAX_ARI); + + tcx_cfg = &st->tcx_cfg; + deadzone = tcx_cfg->sq_rounding; + deadzone_flags = st->memQuantZeros; + *signaling_bits = 0; + assert(st->enableTcxLpc); + gamma_w = 1.0f; + gamma_uw = 1.0f/st->gamma; + tcx_arith_render_envelope( A_ind, L_frame, L_spec, FL2WORD16(tcx_cfg->preemph_fac), FL2WORD16(gamma_w), FL2WORD16(0.5f*gamma_uw), env ); + + for (k=0; kcoder_type, prm_hm, tcxltp_pitch, st->tcxltp_gain, &hm_bits ); + + target_bits -= hm_bits; + *signaling_bits += hm_bits; + } + else + { + prm_hm[0] = 0; /* just to be sure */ + hm_bits = 0; + } + + L_spec_core = L_spec; + if (st->igf) + { + L_spec_core = 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); + FOR (k = 0; k < L_spec; k++) + { + exponents[k] = expfp(negate(envelope[k]), tmp); + } + scale = tcx_arith_rateloop( spectrum, L_spec, envelope, envelope_e, exponents, target_bits, deadzone, deadzone_flags, &st->LPDmem.tcx_target_bits_fac ); + + /* Final quantization */ + kMax = tcx_arith_find_kMax( spectrum, L_spec, scale, deadzone, deadzone_flags ); + + q_spectrum = (int*)env; /* Reuse buffer */ + for (k=0; k<=kMax; ++k) + { + /* quantise using dead-zone */ + q_spectrum[k] = (int)(spectrum[k] * scale + deadzone); + } + + /* Final encoding */ + *arith_bits = tcx_arith_encode( q_spectrum, signs, kMax, L_spec, exponents, target_bits, prm ); + + /* Multiply back the signs */ + for (k=0; k<=kMax; ++k) + { + spectrum[k] = (float)(q_spectrum[k] * (1-2*signs[k])); + } + for (; k +#include "options.h" +#include "prot.h" +#include "rom_com.h" +#include "wmc_auto.h" + +/*-------------------------------------------------------------------* + * Function AVQ_cod() * + * * + * Split algebraic vector quantizer (AVQ) based on RE8 latice * + *-------------------------------------------------------------------*/ + +float AVQ_cod( /* o: comfort noise gain factor */ + const float xri[], /* i: vector to quantize */ + int xriq[], /* o: quantized normalized vector (assuming the bit budget is enough) */ + const short nb_bits, /* i: number of allocated bits */ + const short Nsv /* i: number of subvectors (lg=Nsv*8) */ +) +{ + short i, j, iter; + int c[8]; + float gain_inv, x1[8], ener, tmp, nbits, nbits_max, fac, offset; + float ebits[NSV_MAX]; + + /* find energy of each subvector in log domain (scaled for bits estimation) */ + for( i=0; i= 0 */ + for( j=0; j<8; j++ ) + { + x1[j] = xri[i*8+j]; + ener += x1[j]*x1[j]; + } + + /* estimated bit consumption when gain=1 */ + ebits[i] = 5.0f * FAC_LOG2 * (float)log10( ener*0.5f ); + } + + /* estimate gain according to number of bits allowed */ + fac = 128.0f; /* start at the middle (offset range = 0 to 255.75) */ + offset = 0.0f; + nbits_max = 0.95f * ((float)(nb_bits - Nsv)); + + /* tree search with 10 iterations : offset with step of 0.25 bits (0.3 dB) */ + for( iter=0; iter<10; iter++ ) + { + offset += fac; + /* calculate the required number of bits */ + nbits = 0.0; + for( i=0; i bits ) + { + bits = (short)t[j]; + pos = j; + } + } + sort_idx[i] = pos; + t[pos] = -1; + } + + /* compute multi-rate indices and avoid bit budget overflow */ + pos_max = 0; + bits = 0; + for( i=0; i 0 ) + { + j = pos_max; + if( pos > j ) + { + j = pos; + } + + /* compute (number of bits -1) to describe Q #nq */ + if( nq[pos] >= 2 ) + { + overflow = (short)(nq[pos]*5-1); + } + else + { + overflow = 0; + } + + /* check for overflow and compute number of bits-1 (n) */ + if( (bits+overflow+j) > *nb_bits ) + { + /* if budget overflow */ + for( j=pos*8; j<(pos*8)+8; j++ ) + { + xriq[j] = 0; + } + nq[pos] = 0; /* force Q0 */ + } + else + { + bits += overflow; + pos_max = j; /* update index of the last described subvector */ + } + } + } + + /* write indexes to the bitstream */ + /* ============================== */ + + bits = *nb_bits; + overflow = 0; + + for( i=0; i 8 ) + { + /* write the unary code for nq[i] */ + j = (short)(nq[i] - 1); + if ( nq[i] > 0 ) + { + /* write the unary code */ + while ( j > 16 ) + { + push_indice( st, nq_ind, 65535, 16 ); + bits -= 16; + j -= 16; + } + + if ( j > 0 ) + { + push_indice( st, nq_ind, (1< 4 ) + { + nk = (nq-3)>>1; + n = nq - nk*2; + } + + /* write n groups of 4-bit for base codebook index (I) */ + while( n-- > 0 ) + { + indx[pos++] = (I & 0x0F); + I >>= 4; + } + + /* write n groups of 4-bit for Voronoi index (k[]) */ + while( nk-- > 0 ) + { + ival = 0; + + for( i=0; i<8; i++ ) + { + ival <<= 1; + ival += (kv[i] & 0x01); + kv[i] >>= 1; + } + indx[pos++] = (ival & 0x0F); + ival >>= 4; + indx[pos++] = (ival & 0x0F); + } + } + + return; +} diff --git a/lib_enc/bass_psfilter_enc.c b/lib_enc/bass_psfilter_enc.c new file mode 100644 index 000000000..1173a8843 --- /dev/null +++ b/lib_enc/bass_psfilter_enc.c @@ -0,0 +1,225 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "options.h" + +#include "prot.h" +#include "rom_com.h" + + + +/*---------------------------------------------------------------------* + * bass_pf_enc() + * + * Low-frequency postfiltering, decoder parammeter estimation + *---------------------------------------------------------------------*/ + +float bass_pf_enc( + const float *orig, /* (i) : 12.8kHz original signal */ + const float *syn, /* (i) : 12.8kHz synthesis to postfilter */ + const float pitch_buf[], /* (i) : Pitch gain for all subframes (gainT_sf[16]) */ + const float gainT_sf[], /* (i) : Pitch gain for all subframes (gainT_sf[16]) */ + const short l_frame, /* (i) : frame length (should be multiple of l_subfr)*/ + const short l_subfr_in, /* (i) : sub-frame length (80/64) */ + float mem_bpf[], /* i/o : memory state [2*L_FILT16k] */ + float mem_error_bpf[], /* i/o : memory state [2*L_FILT16k] */ + int *gain_factor_param, /* (o) : quantized gain factor */ + const short mode, /* (i) : coding mode of adapt bpf */ + float *mem_deemph_err, /* o : Error deemphasis memory */ + float *lp_ener /* o : long_term error signal energy */ +) +{ + int i, j, sf, i_subfr, T, lg, l_subfr, l_filt; + float d,n, snr, nrg1,nrg2, gain,nrg,tmp; + float noise_buf[L_FILT16k+(2*L_SUBFR)], *noise, *noise_in; + float error_buf[L_FILT16k+(2*L_SUBFR)], *error, *error_in; + float cross_n_d, nrg_n; + const float *pFilt; + float ener2; + + + if ( l_frame!=L_FRAME16k ) + { + pFilt = filt_lp; + l_filt = L_FILT; + } + else + { + pFilt = filt_lp_16kHz; + l_filt = L_FILT16k; + } + + noise = noise_buf + l_filt; + noise_in = noise_buf + 2*l_filt; + error = error_buf + l_filt; + error_in = error_buf + 2*l_filt; + + sf = 0; + snr=0.f; + nrg_n=1e-6f; + cross_n_d = 0.f; + l_subfr = l_subfr_in; + for (i_subfr=0; i_subfr 1.0f) + { + gain = 1.0f; + } + if (gain < 0.0f) + { + gain = 0.0f; + } + + lg = l_frame - T - i_subfr; + if (lg < 0) + { + lg = 0; + } + if (lg > l_subfr) + { + lg = l_subfr; + } + + + if (gain > 0) + { + tmp = 0.01f; + nrg=0.01f; + for (i=0; i1.0f) + { + gain=1.0f; + } + else if(gain<0.f) + { + gain=0.f; + } + + ener2=0.01f; + for (i=0; i0.5f) + { + tmp=0.5f; + } + else if(tmp<0.f) + { + tmp=0.0f; + } + + for (i=0; i/ */ + if(mode==2) + { + *gain_factor_param = (int)(-2.f*(cross_n_d/nrg_n)+0.5f); + if(*gain_factor_param>3) + { + *gain_factor_param=3; + } + else if(*gain_factor_param<0) + { + *gain_factor_param=0; + } + /*If optimal gain negatif or zero but snr still positif->gain=0.5f*/ + if(snr>0.f && *gain_factor_param==0) + { + *gain_factor_param=1; + } + } + else + { + *gain_factor_param=2; + } + + + return(snr); + +} diff --git a/lib_enc/bw_detect.c b/lib_enc/bw_detect.c new file mode 100644 index 000000000..6e7911c19 --- /dev/null +++ b/lib_enc/bw_detect.c @@ -0,0 +1,506 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_enc.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define ALPHA_BWD 0.75f +#define BWD_LT_THRESH 0.6f + +#define BWD_COUNT_MAX 100 +#define BWD_COUNT_WIDER_BW 10 + +#define CLDFB_ENER_OFFSET 1.6f + +/*-------------------------------------------------------------------* + * bw_detect() + * + * bandwidth detector + *-------------------------------------------------------------------*/ + +void bw_detect( + Encoder_State *st, /* i/o: Encoder State */ + const float signal_in[], /* i : input signal */ + const short localVAD, + float *enerBuffer +) +{ + short i, j, k, bw_max, bin_width, n_bins; + float spect[BWD_TOTAL_WIDTH], in_win[BWD_TOTAL_WIDTH]; + float spect_bin[BWD_N_BINS_MAX]; + float cldfb_bin[9]; + const float *pt, *pt1; + float max_NB, max_WB, max_SWB, max_FB, mean_NB, mean_WB, mean_SWB, mean_FB; + short cldfb_bin_width = 4; + + if( st->input_Fs > 8000 ) + { + if( enerBuffer != NULL ) + { + float ScalFac = 1.0f; + + ScalFac = 1/ ( st->cldfbAnaEnc->scale * st->cldfbAnaEnc->scale * 8.f); + set_f( cldfb_bin, 0.001f, 9 ); + + /* NB: 1.2 - 2.8 kHz, 4 cldfb-bands*/ + cldfb_bin[0] += sum_f( &(enerBuffer[3]), cldfb_bin_width ); + + /* WB: 4.4 - 7.2 kHz, 8 cldfb-bands, mid band(14) counted twice */ + if( st->input_Fs >= 16000 ) + { + cldfb_bin[1] += sum_f( &(enerBuffer[11]), cldfb_bin_width ); + cldfb_bin[2] += sum_f( &(enerBuffer[14]), cldfb_bin_width ); + } + + /* SWB: 9.2 - 15.6 kHz, 16 cldfb-bands */ + if( st->input_Fs >= 32000 ) + { + cldfb_bin[3] += sum_f( &(enerBuffer[23]), cldfb_bin_width ); + cldfb_bin[4] += sum_f( &(enerBuffer[27]), cldfb_bin_width ); + cldfb_bin[5] += sum_f( &(enerBuffer[31]), cldfb_bin_width ); + cldfb_bin[6] += sum_f( &(enerBuffer[35]), cldfb_bin_width ); + } + + /* FB: 16.8 - 20.0 kHz, 8 cldfb-bands */ + if( st->input_Fs >= 48000 ) + { + cldfb_bin[7] += sum_f( &(enerBuffer[42]), cldfb_bin_width ); + cldfb_bin[8] += sum_f( &(enerBuffer[46]), cldfb_bin_width ); + } + + for (i=0; i<9; i++) + { + cldfb_bin[i] = (float)log10( cldfb_bin[i]* ScalFac ); /* see formula used in perform_noise_estimation_enc() for CNG */ + } + + } + else + { + + /* set width of a speactral bin (corresponds to 1.5kHz) */ + if( st->input_Fs == 16000 ) + { + bw_max = WB; + bin_width = 60; + n_bins = 5; /* spectrum to 7.5 kHz */ + } + else if( st->input_Fs == 32000 ) + { + bw_max = SWB; + bin_width = 30; + n_bins = 10; /* spectrum to 15 kHz */ + } + else /* st->input_Fs == 48000 */ + { + bw_max = FB; + bin_width = 20; + n_bins = BWD_N_BINS_MAX; /* spectrum to 19.5 kHz */ + } + + /*---------------------------------------------------------------------* + * windowing of the input signal + *---------------------------------------------------------------------*/ + + pt = signal_in; + pt1 = hann_window_320; + + /* 1st half of the window */ + for( i=0; iinput_Fs == 16000 ) + { + /* for 16kHz sampled inputs, do not check SWB & FB */ + mean_SWB = 0.0f; + max_SWB = 0.0f; + mean_FB = 0.0f; + max_FB = 0.0f; + } + else if( st->input_Fs == 32000 ) + { + /* for 32kHz sampled inputs, do not check FB */ + mean_FB = 0.0f; + max_FB = 0.0f; + mean_SWB = mean( cldfb_bin + 3, 4 ); /* SWB: 9.2 - 15.6 kHz, 16 cldfb-bands (4 bins) */ + maximum ( cldfb_bin + 3, 4 , &max_SWB ); + mean_SWB += CLDFB_ENER_OFFSET; + max_SWB += CLDFB_ENER_OFFSET; + } + else + { + mean_SWB = mean( cldfb_bin + 3, 4 ) ; /* SWB: 9.2 - 15.6 kHz, 16 cldfb-bands (4 bins) */ + maximum ( cldfb_bin + 3, 4 , &max_SWB ); + mean_FB = mean ( cldfb_bin + 7, 2 ); /* FB: 16.8 - 20.0 kHz, 8 cldfb-bands (2 bins) */ + maximum ( cldfb_bin + 7, 2 , &max_FB ); + + mean_SWB += CLDFB_ENER_OFFSET; + max_SWB += CLDFB_ENER_OFFSET; + mean_FB += CLDFB_ENER_OFFSET; + max_FB += CLDFB_ENER_OFFSET; + } + + } + else + { + mean_NB = mean( spect_bin + bwd_start_bin[0], bwd_end_bin[0]-bwd_start_bin[0]+1 ); /* NB: 1.5-3.0kHz (1 bin) */ + maximum ( spect_bin + bwd_start_bin[0], bwd_end_bin[0]-bwd_start_bin[0]+1, &max_NB ); + mean_WB = mean( spect_bin + bwd_start_bin[1], bwd_end_bin[1]-bwd_start_bin[1]+1 ); /* WB: 4.5-7.5kHz (2 bins) */ + maximum( spect_bin + bwd_start_bin[1], bwd_end_bin[1]-bwd_start_bin[1]+1, &max_WB ); + + if( st->input_Fs == 16000 ) + { + /* for 16kHz sampled inputs, do not check SWB & FB */ + mean_SWB = 0.0f; + max_SWB = 0.0f; + mean_FB = 0.0f; + max_FB = 0.0f; + } + else if( st->input_Fs == 32000 ) + { + mean_SWB = mean( spect_bin + bwd_start_bin[2], bwd_end_bin[2]-bwd_start_bin[2]+1 ); /* SWB: 9.0-15.0kHz (4 bins) */ + maximum( spect_bin + bwd_start_bin[2], bwd_end_bin[2]-bwd_start_bin[2]+1, &max_SWB ); + + /* for 32kHz sampled inputs, do not check FB */ + mean_FB = 0.0f; + max_FB = 0.0f; + } + else + { + mean_SWB = mean( spect_bin + bwd_start_bin[2], bwd_end_bin[2]-bwd_start_bin[2]+1 ); /* SWB: 9.0-15.0kHz (4 bins) */ + maximum( spect_bin + bwd_start_bin[2], bwd_end_bin[2]-bwd_start_bin[2]+1, &max_SWB ); + mean_FB = mean( spect_bin + bwd_start_bin[3], bwd_end_bin[3]-bwd_start_bin[3]+1 ); /* FB: 16.5-19.5kHz (2 bins) */ + maximum( spect_bin + bwd_start_bin[3], bwd_end_bin[3]-bwd_start_bin[3]+1, &max_FB ); + } + } + + /*---------------------------------------------------------------------* + * update LT counters and energies + *---------------------------------------------------------------------*/ + + if( localVAD || st->lp_noise > 30 ) + { + st->lt_mean_NB = ALPHA_BWD * st->lt_mean_NB + (1-ALPHA_BWD) * mean_NB; + st->lt_mean_WB = ALPHA_BWD * st->lt_mean_WB + (1-ALPHA_BWD) * mean_WB; + st->lt_mean_SWB = ALPHA_BWD * st->lt_mean_SWB + (1-ALPHA_BWD) * mean_SWB; + + if( enerBuffer != NULL ) + { + if( 0.9f * max_WB > BWD_LT_THRESH * st->lt_mean_NB ) + { + if( 2.5f * max_WB > max_NB ) + { + st->count_WB++; + } + } + else + { + if( 3.5f * mean_WB < mean_NB ) + { + st->count_WB--; + } + } + + if( 0.83f * max_SWB > BWD_LT_THRESH * st->lt_mean_WB && max_WB > BWD_LT_THRESH * st->lt_mean_NB ) + { + if( 2 * max_SWB > max_WB ) + { + st->count_SWB++; + } + } + else + { + if( 3 * mean_SWB < mean_WB ) + { + st->count_SWB--; + } + } + + if( max_FB > BWD_LT_THRESH * st->lt_mean_SWB && 0.83f * max_SWB > BWD_LT_THRESH * st->lt_mean_WB && max_WB > BWD_LT_THRESH * st->lt_mean_NB ) + { + if( 3 * max_FB > max_SWB ) + { + st->count_FB++; + } + } + else + { + if( 4.1f * mean_FB < mean_SWB ) + { + st->count_FB--; + } + } + + } + else + { + if( max_WB > BWD_LT_THRESH * st->lt_mean_NB ) + { + if( 2 * max_WB > max_NB ) + { + st->count_WB++; + } + } + else + { + if( 2.6f * mean_WB < mean_NB ) + { + st->count_WB--; + } + } + + if( max_SWB > BWD_LT_THRESH * st->lt_mean_WB && max_WB > BWD_LT_THRESH * st->lt_mean_NB ) + { + if( 2 * max_SWB > max_WB ) + { + st->count_SWB++; + } + } + else + { + if( 3 * mean_SWB < mean_WB ) + { + st->count_SWB--; + } + } + + if( max_FB > BWD_LT_THRESH * st->lt_mean_SWB && max_SWB > BWD_LT_THRESH * st->lt_mean_WB && max_WB > BWD_LT_THRESH * st->lt_mean_NB ) + { + if( 2 * max_FB > max_SWB ) + { + st->count_FB++; + } + } + else + { + if( 3 * mean_FB < mean_SWB ) + { + st->count_FB--; + } + } + } + + st->count_WB = min(st->count_WB,BWD_COUNT_MAX); + st->count_SWB = min(st->count_SWB,BWD_COUNT_MAX); + st->count_FB = min(st->count_FB,BWD_COUNT_MAX); + st->count_WB = max(st->count_WB,0); + st->count_SWB = max(st->count_SWB,0); + st->count_FB = max(st->count_FB,0); + + /*---------------------------------------------------------------------* + * check against thresholds + * detect a band-width change + *---------------------------------------------------------------------*/ + + /* switching to a higher BW */ + if( st->last_input_bwidth == NB ) + { + if( st->count_WB > BWD_COUNT_WIDER_BW ) + { + st->input_bwidth = WB; + st->count_WB = BWD_COUNT_MAX; + + if( st->count_SWB > BWD_COUNT_WIDER_BW ) + { + st->input_bwidth = SWB; + st->count_SWB = BWD_COUNT_MAX; + + if( st->count_FB > BWD_COUNT_WIDER_BW ) + { + st->input_bwidth = FB; + st->count_FB = BWD_COUNT_MAX; + } + } + } + } + + if( st->last_input_bwidth == WB && st->input_Fs > 16000 ) + { + if( st->count_SWB > BWD_COUNT_WIDER_BW ) + { + st->input_bwidth = SWB; + st->count_SWB = BWD_COUNT_MAX; + + if( st->count_FB > BWD_COUNT_WIDER_BW ) + { + st->input_bwidth = FB; + st->count_FB = BWD_COUNT_MAX; + } + } + } + + if( st->last_input_bwidth == SWB && st->input_Fs > 32000 ) + { + if( st->count_FB > BWD_COUNT_WIDER_BW ) + { + st->input_bwidth = FB; + st->count_FB = BWD_COUNT_MAX; + } + } + + /* switching to a lower BW */ + if( st->last_input_bwidth == FB ) + { + if( st->count_FB < 10 ) + { + st->input_bwidth = SWB; + st->count_FB = 0; + } + if( st->count_SWB < 10 ) + { + st->input_bwidth = WB; + st->count_SWB = 0; + st->count_FB = 0; + } + if( st->count_WB < 10 ) + { + st->input_bwidth = NB; + st->count_WB = 0; + st->count_SWB = 0; + st->count_FB = 0; + } + } + + if( st->last_input_bwidth == SWB ) + { + if( st->count_SWB < 10 ) + { + st->input_bwidth = WB; + st->count_SWB = 0; + st->count_FB = 0; + } + if( st->count_WB < 10 ) + { + st->input_bwidth = NB; + st->count_WB = 0; + st->count_SWB = 0; + st->count_FB = 0; + } + } + + if( st->last_input_bwidth == WB ) + { + if( st->count_WB < 10 ) + { + st->input_bwidth = NB; + st->count_WB = 0; + st->count_SWB = 0; + st->count_FB = 0; + } + } + } + } + + /* verify that maximum encoded bandwidth (specified on the command line) is not exceeded */ + if( st->input_bwidth > st->max_bwidth ) + { + st->input_bwidth = st->max_bwidth; + } + + + /* Set and limit the encoded bandwidth */ + if ( st->codec_mode == MODE1 ) + { + long total_brate; + + st->bwidth = st->input_bwidth; + total_brate = st->total_brate; + if ( total_brate <= ACELP_9k60 && st->bwidth != NB && st->bwidth != WB ) + { + st->bwidth = WB; + } + else if ( total_brate >= ACELP_13k20 && total_brate <= ACELP_16k40 && st->bwidth > SWB ) + { + st->bwidth = SWB; + } + else if ( total_brate >= ACELP_32k && st->bwidth < WB ) + { + st->bwidth = WB; + } + } + else + { + short n, bits_frame_nominal, tmpBandwidthMin; + + bits_frame_nominal = st->total_brate / 50; + for( n=0; nrf_mode ) + { + tmpBandwidthMin = WB; + } + + st->bwidth = max(min(st->input_bwidth, FrameSizeConfig[n].bandwidth_max), tmpBandwidthMin); + } + + return; +} diff --git a/lib_enc/cng_enc.c b/lib_enc/cng_enc.c new file mode 100644 index 000000000..d0a4af5a9 --- /dev/null +++ b/lib_enc/cng_enc.c @@ -0,0 +1,1005 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_enc.h" +#include "rom_com.h" +#include "prot.h" + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ + +#define MAX_DELTA_CNG 1 + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ + +static short shb_DTX( Encoder_State *st, const float *shb_speech, const float *syn_12k8_16k ); + +static void shb_CNG_encod( Encoder_State *st, const short update + ); + +/*---------------------------------------------------------------------* + * CNG_enc() + * + * Confort noise generation for the coder + *---------------------------------------------------------------------*/ + +void CNG_enc( + Encoder_State *st, /* i/o: State structure */ + const short L_frame, /* i : length of the frame */ + float Aq[], /* o : LP coefficients */ + const float *speech, /* i : pointer to current frame input speech buffer */ + float enr, /* i : residual energy from Levinson-Durbin */ + float *lsp_new, /* i/o: current frame ISPs */ + float *lsf_new, /* i/o: current frame ISFs */ + short *allow_cn_step, /* o : allow CN step */ + short burst_ho_cnt, /* i : hangover frames at end of speech burst */ + float *q_env, + short *sid_bw, + float *exc_mem2 +) +{ + short enr_index, i; + float step, res[L_FRAME16k]; + short maxl, num_bits; + short j, k, ptr; + short m1; + float weights; + float sp_enr; + short m = 0; + float tmp[HO_HIST_SIZE*M]; + short ll, s_ptr; + float att=1.0f; + float lsf_tmp[M]; + float C[M]; + float max[2]; + short max_idx[2]; + float ftmp; + float lsp_tmp[M]; + float dev; + float max_dev; + float dist; + short max_idx1[2]= {0,0}; + float fft_io[L_FRAME16k]; + float *ptR,*ptI; + float enr1=0; + float env[NUM_ENV_CNG]; + float min1; + short min1_idx; + float d; + float res1[L_FRAME16k]; + float tmp_env[HO_HIST_SIZE*NUM_ENV_CNG]; + short force_cn_step=0; + float st_lp_sp_enr; + + st_lp_sp_enr = st->lp_sp_enr; + + /* calculate input energy */ + sp_enr = (float) log10( sum2_f( speech, L_frame )/L_frame + 0.1f )/ (float)log10(2.0f); + + if (sp_enr < 0.0f) + { + sp_enr = 0.0f; + } + + if ( st->first_CNG == 0 || st->old_enr_index < 0 ) + { + st->lp_sp_enr = sp_enr; + } + else + { + if ( st->last_core_brate > SID_2k40 && (st->last_core == HQ_CORE || burst_ho_cnt > 0) && st->lp_sp_enr < 6.0f && (sp_enr - st->lp_sp_enr) > 4.0f && sp_enr > 6.0f ) + { + st->lp_sp_enr = sp_enr; + force_cn_step = 1; + } + else + { + st->lp_sp_enr = 0.1f * sp_enr + 0.9f * st->lp_sp_enr; + } + } + + /* update the pointer to circular buffer of old LSP vectors */ + if( ++(st->cng_hist_ptr) == DTX_HIST_SIZE ) + { + st->cng_hist_ptr = 0; + } + + /* update the circular buffer of old LSP vectors with the new LSP vector */ + mvr2r( lsp_new, &(st->cng_lsp_hist[(st->cng_hist_ptr)*M]), M ); + + /*-----------------------------------------------------------------* + * Find CNG spectral envelope + * Find LSP median + *-----------------------------------------------------------------*/ + + if( (st->core_brate == SID_2k40 || st->core_brate == SID_1k75) && st->cng_cnt >= (st->cng_hist_size-1) ) + { + set_f( max, 0.0f, 2 ); + set_s( max_idx, 0, 2 ); + + for( i=0; icng_hist_size; i++ ) + { + if (st->L_frame == L_FRAME ) + { + lsp2lsf( &st->cng_lsp_hist[i*M], lsf_tmp, M, INT_FS_12k8 ); + ftmp = 6400.0f / (M+1); + C[i] = (6400.0f - lsf_tmp[M-1] - ftmp) * (6400.0f - lsf_tmp[M-1] - ftmp); + } + else + { + lsp2lsf( &st->cng_lsp_hist[i*M], lsf_tmp, M, INT_FS_16k ); + ftmp = 8000.0f / (M+1); + C[i] = (8000.0f - lsf_tmp[M-1] - ftmp) * (8000.0f - lsf_tmp[M-1] - ftmp); + } + + C[i] += (lsf_tmp[0] - ftmp) * (lsf_tmp[0] - ftmp); + + for ( j=0; j max[0] ) + { + max[1] = max[0]; + max_idx[1] = max_idx[0]; + max[0] = C[i]; + max_idx[0] = i; + } + else if ( C[i] > max[1] ) + { + max[1] = C[i]; + max_idx[1] = i; + } + } + + for ( i=0; icng_hist_size; j++ ) + { + lsp_new[i] += st->cng_lsp_hist[j*M+i]; + } + + lsp_new[i] -= (st->cng_lsp_hist[max_idx[0]*M+i] + st->cng_lsp_hist[max_idx[1]*M+i]); + lsp_new[i] /= (float)(st->cng_hist_size - 2); + } + max_idx1[0] = max_idx[0]; + max_idx1[1] = max_idx[1]; + } + + /*-----------------------------------------------------------------* + * Quantize CNG spectral envelope (only in SID frame) + * Quantize the LSF vector + *-----------------------------------------------------------------*/ + + *allow_cn_step = ((st->cng_cnt == 0) && + (st->lp_sp_enr > 6.0f) && + ((st_lp_sp_enr + 4.0f) < sp_enr) && + (st->first_CNG != 0) && + (st->old_enr_index >= 0) && + (st->last_core_brate > SID_2k40)) || + force_cn_step; + + if( st->core_brate == SID_2k40 || st->core_brate == SID_1k75 ) + { + /* LSF quantization */ + if ( st->Opt_AMR_WB ) + { + isf_enc_amr_wb( st, lsf_new, lsp_new, 0, 0 ); + } + else + { + lsf_enc( st, L_frame, INACTIVE, lsf_new, lsp_new, 0, 0, 0, 100 ); + } + + /* Reset CNG history if CNG frame length is changed */ + if ( st->bwidth == WB && st->first_CNG && st->L_frame != st->last_CNG_L_frame ) + { + st->ho_hist_size = 0; + } + } + else + { + /* Use old LSP vector */ + mvr2r( st->lsp_old, lsp_new, M ); + mvr2r( st->lsf_old, lsf_new, M ); + } + + /* Initialize the CNG spectral envelope in case of the very first CNG frame */ + if( st->first_CNG == 0 ) + { + mvr2r( st->lsp_old, st->lspCNG, M ); + } + + /*---------------------------------------------------------------------* + * CNG spectral envelope update + * Find A(z) coefficients + *---------------------------------------------------------------------*/ + + if( st->last_core_brate == FRAME_NO_DATA || st->last_core_brate == SID_1k75 || st->last_core_brate == SID_2k40 ) + { + /* Reset hangover counter if not first SID period */ + if( st->core_brate > FRAME_NO_DATA ) + { + st->num_ho = 0; + } + /* Update LSPs if last SID energy not outlier or insufficient number of hangover frames */ + if( st->num_ho < 3 || st->Enew < 1.5f * st->lp_ener ) + { + for( i=0; ilspCNG[i] = CNG_ISF_FACT * st->lspCNG[i] + (1-CNG_ISF_FACT) * lsp_new[i]; + } + } + } + else + { + /* Update CNG_mode if allowed */ + if( ( st->Opt_AMR_WB || st->bwidth == WB ) && ( !st->first_CNG || st->act_cnt2 >= MIN_ACT_CNG_UPD ) ) + { + if( st->last_active_brate > ACELP_16k40 ) + { + st->CNG_mode = -1; + } + else if( st->last_active_brate > ACELP_13k20 ) + { + st->CNG_mode = 4; + } + else if( st->last_active_brate > ACELP_9k60 ) + { + st->CNG_mode = 3; + } + else if( st->last_active_brate > ACELP_8k00 ) + { + st->CNG_mode = 2; + } + else if( st->last_active_brate > ACELP_7k20 ) + { + st->CNG_mode = 1; + } + else + { + st->CNG_mode = 0; + } + } + + /* If first SID after active burst update LSF history from circ buffer */ + st->act_cnt = 0; + s_ptr = st->ho_circ_ptr-burst_ho_cnt+1; + if( s_ptr < 0 ) + { + s_ptr += st->ho_circ_size; + } + + for( ll = burst_ho_cnt; ll > 0; ll-- ) + { + if( ++(st->ho_hist_ptr) == HO_HIST_SIZE ) + { + st->ho_hist_ptr = 0; + } + /* Conversion between 12.8k and 16k LSPs */ + if( L_frame == L_FRAME && st->ho_16k_lsp[s_ptr] == 1 ) + { + /* Conversion from 16k LPSs to 12k8 */ + lsp_convert_poly( &(st->ho_lsp_circ[s_ptr*M]), L_frame, 0 ); + } + else if ( L_frame == L_FRAME16k && st->ho_16k_lsp[s_ptr] == 0 ) + { + /* 16k LSPs already converted and stored, just copy to the other buffer */ + mvr2r(&(st->ho_lsp_circ2[s_ptr*M]), &(st->ho_lsp_circ[s_ptr*M]), M ); + } + + /* update circular buffers */ + mvr2r(&(st->ho_lsp_circ[s_ptr*M]), &(st->ho_lsp_hist[st->ho_hist_ptr*M]), M ); + mvr2r(&(st->ho_ener_circ[s_ptr]), &(st->ho_ener_hist[st->ho_hist_ptr]), 1 ); + st->ho_sid_bw = ( st->ho_sid_bw & 0x3fffffffL ) << 1; + mvr2r(&(st->ho_env_circ[s_ptr*NUM_ENV_CNG]), &(st->ho_env_hist[st->ho_hist_ptr*NUM_ENV_CNG]), NUM_ENV_CNG ); + + st->ho_hist_size++; + if (st->ho_hist_size > HO_HIST_SIZE) + { + st->ho_hist_size = HO_HIST_SIZE; + } + + s_ptr++; + + if( s_ptr == st->ho_circ_size ) + { + s_ptr = 0; + } + } + if ( burst_ho_cnt > 0) + { + *allow_cn_step |= ( st->ho_ener_hist[st->ho_hist_ptr] > 4.0f * st->lp_ener ); + } + + if ( !*allow_cn_step && st->ho_hist_size > 0 ) + { + ptr = st->ho_hist_ptr; + mvr2r( &(st->ho_lsp_hist[ptr*M]), tmp, M ); + m1 = 0; + if( (st->ho_sid_bw & 0x1L) == 0 ) + { + mvr2r( &st->ho_env_hist[ptr*NUM_ENV_CNG], tmp_env, NUM_ENV_CNG ); + m1 = 1; + } + enr = W_DTX_HO[0] * st->ho_ener_hist[ptr]; + weights = W_DTX_HO[0]; + m = 1; + for( k=1; kho_hist_size; k++ ) + { + ptr--; + if( ptr < 0 ) + { + ptr = HO_HIST_SIZE - 1; + } + + if ( st->ho_ener_hist[ptr] < st->ho_ener_hist[st->ho_hist_ptr] * BUF_H_NRG && + st->ho_ener_hist[ptr] > st->ho_ener_hist[st->ho_hist_ptr] * BUF_L_NRG ) + { + enr += W_DTX_HO[k] * st->ho_ener_hist[ptr]; + weights += W_DTX_HO[k]; + mvr2r( &st->ho_lsp_hist[ptr*M], &tmp[m*M], M ); + if( (st->ho_sid_bw & (0x1L << k)) == 0 ) + { + mvr2r( &st->ho_env_hist[ptr*NUM_ENV_CNG], &tmp_env[m1*NUM_ENV_CNG], NUM_ENV_CNG ); + m1++; + } + m++; + } + } + + enr /= weights; + st->lp_ener = enr; + + set_f( max, 0.0f, 2 ); + set_s( max_idx, 0, 2 ); + + for( i=0; iL_frame == L_FRAME ) + { + lsp2lsf( &tmp[i*M], lsf_tmp, M, INT_FS_12k8 ); + ftmp = 6400.0f / (M+1); + C[i] = (6400.0f - lsf_tmp[M-1] - ftmp) * (6400.0f - lsf_tmp[M-1] - ftmp); + } + else + { + lsp2lsf( &tmp[i*M], lsf_tmp, M, INT_FS_16k ); + ftmp = 8000.0f / (M+1); + C[i] = (8000.0f - lsf_tmp[M-1] - ftmp) * (8000.0f - lsf_tmp[M-1] - ftmp); + } + + C[i] += (lsf_tmp[0] - ftmp) * (lsf_tmp[0] - ftmp); + + for ( j=0; j max[0] ) + { + max[1] = max[0]; + max_idx[1] = max_idx[0]; + max[0] = C[i]; + max_idx[0] = i; + } + else if ( C[i] > max[1] ) + { + max[1] = C[i]; + max_idx[1] = i; + } + } + + if ( m == 1 ) + { + mvr2r(tmp, lsp_tmp, M); + } + else if ( m < 4 ) + { + for ( i=0; i max_dev ) + { + max_dev = dev; + } + } + + if ( dist > 0.4f || max_dev > 0.1f ) + { + for( i=0; ilspCNG[i] = lsp_tmp[i]; + } + } + else + { + for( i=0; ilspCNG[i] = 0.8f * lsp_tmp[i] + (1-0.8f) * lsp_new[i]; + } + } + if( m1 > 0 ) + { + for ( i=0; ilp_ener; + } + mvr2r(env, st->lp_env, NUM_ENV_CNG); + } + } + else + { + mvr2r( lsp_new, st->lspCNG, M ); /* use newly analyzed parameters */ + } + } + + if ( st->Opt_AMR_WB ) + { + isp2a( st->lspCNG, Aq, M ); + } + else + { + lsp2a_stab( st->lspCNG, Aq, M ); + } + + for( i=1; ibwidth != NB ) + { + if( st->bwidth == WB && st->CNG_mode >= 0 ) + { + ftmp = HO_ATT[st->CNG_mode]; + } + else + { + ftmp = 0.6f; + } + + att = ftmp/6.0f; + att = 1.0f/(1 + att * 8); + + if ( att < ftmp ) + { + att = ftmp; + } + + for( i = 0; i < st->L_frame; i++ ) + { + res1[i] *= att; + } + } + + /* calculate the spectrum of residual signal */ + mvr2r(res1, fft_io, st->L_frame); + + if ( st->L_frame == L_FRAME16k ) + { + modify_Fs( fft_io, L_FRAME16k, 16000, fft_io, 12800, exc_mem2, 0 ); + } + + fft_rel(fft_io, L_FFT, LOG2_L_FFT); + ptR = &fft_io[1]; + ptI = &fft_io[L_FFT-1]; + for ( i=0; icng_res_env[(st->cng_hist_ptr)*NUM_ENV_CNG]), NUM_ENV_CNG ); + /* calculate the residual signal energy */ + enr = dotp( res, res, L_frame ) / L_frame; + + /* convert log2 of residual signal energy */ + enr = (float)log10( enr + 0.1f ) / (float)log10( 2.0f ); + + /* update the circular buffer of old energies */ + st->cng_ener_hist[st->cng_hist_ptr] = enr; + + /*-----------------------------------------------------------------* + * Quantize residual signal energy (only in SID frame) + *-----------------------------------------------------------------*/ + + if( st->core_brate == SID_2k40 || st->core_brate == SID_1k75 ) + { + if( st->cng_cnt >= st->cng_hist_size - 1 ) + { + /* average the envelope except outliers */ + for ( i=0; icng_hist_size; j++ ) + { + env[i] += st->cng_res_env[j*NUM_ENV_CNG+i]; + } + + env[i] -= (st->cng_res_env[max_idx1[0]*NUM_ENV_CNG+i] + st->cng_res_env[max_idx1[1]*NUM_ENV_CNG+i]); + env[i] /= (float)(st->cng_hist_size - 2); + } + /* compute average excitation energy */ + enr = 0; + weights = 0; + ptr = st->cng_hist_ptr; + + for( k=0; kcng_hist_size; k++ ) + { + enr += W_HIST[k] * st->cng_ener_hist[ptr--]; + if( ptr < 0 ) + { + ptr = DTX_HIST_SIZE - 1; + } + + weights += W_HIST[k]; + } + + /* normalize the average value */ + enr /= weights; + } + + /* decrease the energy in case of WB input */ + if( st->bwidth != NB ) + { + if( st->bwidth == WB ) + { + if( st->CNG_mode >= 0 ) + { + /* Bitrate adapted attenuation */ + att = ENR_ATT[st->CNG_mode]; + } + else + { + /* Use least attenuation for higher bitrates */ + att = ENR_ATT[4]; + } + } + else + { + att = 1.5f; + } + + enr -= att; + } + + /* intialize the energy quantization parameters */ + if( !st->Opt_AMR_WB ) + { + step = STEP_SID; + maxl = 127; + num_bits = 7; + } + else + { + step = STEP_AMR_WB_SID; + maxl = 63; + num_bits = 6; + } + + /* calculate the energy quantization index */ + enr_index = (short)( (enr + 2.0f) * step ); + + /* limit the energy quantization index */ + if( enr_index > maxl ) + { + enr_index = maxl; + } + + if( enr_index < 0 ) + { + enr_index = 0; + } + + /* allow only slow energy increase */ + if( st->first_CNG && enr_index > st->old_enr_index + MAX_DELTA_CNG ) + { + if( *allow_cn_step == 1 ) + { + enr_index = st->old_enr_index + (short) (0.85f*(enr_index - st->old_enr_index)) ; + } + else + { + enr_index = st->old_enr_index + MAX_DELTA_CNG; + } + } + st->old_enr_index = enr_index; + + push_indice( st, IND_ENERGY, enr_index, num_bits ); + if ( enr_index == 0 ) + { + enr_index = -5; + } + /* find the quatized energy */ + st->Enew = (float)enr_index / step - 2.0f; + st->Enew = (float)( pow( 2.0f, st->Enew ) ); + if ( st->core_brate == SID_2k40 ) + { + enr1 = (float)log10( st->Enew*L_frame + 0.1f ) / (float)log10( 2.0f ); + for ( i=0; iEnew; + + if ( env[i] < 0.0f ) + { + env[i] = 0.1f; + } + + env[i] = (float)log10( env[i] + 0.1f ) / (float)log10( 2.0f ); + env[i] -= att; + + if ( env[i] < 0 ) + { + env[i] = 0; + } + + env[i] = enr1 - env[i]; + } + + /* codebook search */ + min1 = 9999.0f; + min1_idx = 0; + + for ( i=0; i<64; i++ ) + { + d = 0.0f; + for ( j=0; jEnew < 1.5f * st->lp_ener) ) + { + /* update the pointer to circular buffer of old LSP vectors */ + if( ++(st->ho_hist_ptr) == HO_HIST_SIZE ) + { + st->ho_hist_ptr = 0; + } + + /* update the circular buffer of old LSP vectors with the new LSP vector */ + mvr2r( lsp_new, &(st->ho_lsp_hist[(st->ho_hist_ptr)*M]), M ); + + /* update the hangover energy buffer */ + st->ho_ener_hist[st->ho_hist_ptr] = st->Enew; + if ( st->core_brate == SID_2k40 ) + { + for ( i=0; iEnew; + } + mvr2r( env, &(st->ho_env_hist[(st->ho_hist_ptr)*NUM_ENV_CNG]), NUM_ENV_CNG ); + } + if(++(st->ho_hist_size) > HO_HIST_SIZE) + { + st->ho_hist_size = HO_HIST_SIZE; + } + } + } + + /* dithering bit for AMR-WB IO mode is always set to 0 */ + if( st->core_brate == SID_1k75 ) + { + push_indice( st, IND_DITHERING, 0, 1 ); + } + + if ( st->core_brate == SID_2k40 ) + { + push_indice( st, IND_ACELP_16KHZ, st->L_frame == L_FRAME16k ? 1 : 0, 1 ); + } + + if ( st->core_brate == SID_2k40 ) + { + /* transmit ho_cnt for use at decoder side as CNG synthesis assistance */ + if( st->burst_ho_cnt > (HO_HIST_SIZE-1) ) + { + push_indice( st, IND_CNG_HO, (HO_HIST_SIZE-1), 3 ); /* send max allowed value , limited to 7 */ + } + else + { + push_indice( st, IND_CNG_HO, st->burst_ho_cnt, 3 ); /* send actual value */ + } + st->num_ho = m; + push_indice( st, IND_SID_TYPE, 0, 1 ); + + if ( st->input_Fs < 32000 ) + { + push_indice( st, IND_SID_BW, 0, 1 ); + *sid_bw = 0; + } + } + + /*-----------------------------------------------------------------* + * Updates + *-----------------------------------------------------------------*/ + + /* update the SID frames counter */ + if( st->core_brate == SID_2k40 || st->core_brate == SID_1k75 ) + { + st->cng_cnt = 0; + st->cng_hist_ptr = -1; + + /* update frame length memory */ + st->last_CNG_L_frame = st->L_frame; + } + else + { + st->cng_cnt++; + } + + + + return; +} + +/*---------------------------------------------------------------------* + * swb_CNG_enc() + * + * SWB DTX/CNG encoding + *---------------------------------------------------------------------*/ + +void swb_CNG_enc( + Encoder_State *st, /* i/o: State structure */ + const float *shb_speech, /* i : SHB target signal (6-14kHz) at 16kHz */ + const float *syn_12k8_16k /* i : ACELP core synthesis at 12.8kHz or 16kHz */ +) +{ + short shb_SID_updt; + + if( st->core_brate == SID_2k40 || st->core_brate == FRAME_NO_DATA ) + { + if ( st->cng_type == LP_CNG ) + { + /* decide if SHB SID encoding or not */ + shb_SID_updt = shb_DTX( st, shb_speech, syn_12k8_16k ); + + /* SHB CNG encoding */ + shb_CNG_encod( st, shb_SID_updt ); + } + st->last_vad = 0; + } + else + { + st->last_vad = 1; + } + + return; +} + +/*---------------------------------------------------------------------* + * shb_CNG_encod() + * + * SID parameters encoding for SHB signal + *---------------------------------------------------------------------*/ + +static void shb_CNG_encod( + Encoder_State *st, /* i/o: State structure */ + const short update /* i : SID update flag */ +) +{ + short idx_ener = 0; + + if ( update == 1 ) + { + /* SHB energy quantization */ + idx_ener = (short)(0.9f * (0.1f*st->mov_shb_cng_ener/(float)log10(2.0f) + 6.0f) + 0.5f ); + if ( st->bwidth < SWB ) + { + idx_ener = 0; + } + + if ( idx_ener > 15 ) + { + idx_ener = 15; + } + else if ( idx_ener < 0 ) + { + idx_ener = 0; + } + + push_indice( st, IND_SHB_CNG_GAIN, idx_ener, 4 ); + push_indice( st, IND_SID_BW, 1, 1 ); + st->nb_bits_tot = st->nb_bits_tot - st->ind_list[IND_CNG_ENV1].nb_bits; + st->ind_list[IND_CNG_ENV1].nb_bits = -1; + push_indice( st, IND_UNUSED, 0, 2 ); + st->ho_sid_bw = ( st->ho_sid_bw & 0x3fffffffL ) << 1; + st->ho_sid_bw |= 0x1L; + } + else if ( st->core_brate == SID_2k40 ) + { + st->ho_sid_bw = ( st->ho_sid_bw & 0x3fffffffL ) << 1; + push_indice( st, IND_SID_BW, 0, 1 ); + } + + + return; +} + +/*---------------------------------------------------------------------* + * shb_DTX() + * + * Decide if encoding SHB SID or not + *---------------------------------------------------------------------*/ + +static short shb_DTX( + Encoder_State *st, /* i/o: State structure */ + const float *shb_speech, /* i : SHB target signal (6-14kHz) at 16kHz */ + const float *syn_12k8_16k /* i : ACELP core synthesis at 12.8kHz or 16kHz */ +) +{ + short i; + short update; + float shb_old_speech[(L_LOOK_12k8 + L_SUBFR + L_FRAME) * 5/4]; + float *shb_new_speech; + float wb_ener; + float shb_ener; + float log_wb_ener; + float log_shb_ener; + float ftmp; + short allow_cn_step=0; + + shb_new_speech = shb_old_speech + (L_LOOK_12k8 + L_SUBFR) * 5/4; + mvr2r( st->old_speech_shb, shb_old_speech, (L_LOOK_12k8 + L_SUBFR) * 5/4 ); + mvr2r( shb_speech, shb_new_speech, L_FRAME16k ); + mvr2r( shb_old_speech + L_FRAME16k, st->old_speech_shb, (L_LOOK_12k8 + L_SUBFR) * 5/4 ); + + shb_ener = FLT_MIN * L_FRAME16k; + for ( i=0; iL_frame) + 0.001f; + wb_ener = wb_ener/st->L_frame; + + log_wb_ener = 10 * (float)log10(wb_ener); + log_shb_ener = 10 * (float)log10(shb_ener) - 6.5f; + + if ( st->first_CNG == 0 ) + { + st->mov_wb_cng_ener = log_wb_ener; + st->mov_shb_cng_ener = log_shb_ener; + st->last_wb_cng_ener = log_wb_ener; + st->last_shb_cng_ener = log_shb_ener; + } + if ( fabs(log_wb_ener - st->mov_wb_cng_ener) > 12.0f ) + { + allow_cn_step = 1; + } + + if ( allow_cn_step == 1 ) + { + st->mov_wb_cng_ener = log_wb_ener; + st->mov_shb_cng_ener = log_shb_ener; + } + else + { + ftmp = log_wb_ener - st->mov_wb_cng_ener; + + st->mov_wb_cng_ener += 0.9f * ftmp; + + ftmp = log_shb_ener - st->mov_shb_cng_ener; + + st->mov_shb_cng_ener += 0.25f * ftmp; + } + st->shb_NO_DATA_cnt++; + + update = 0; + if ( st->core_brate == SID_2k40 ) + { + if ( st->first_CNG == 0 ) + { + update = 1; + } + else if ( st->shb_cng_ini_cnt > 0 ) + { + st->shb_cng_ini_cnt--; + update = 1; + } + else if ( st->last_vad == 1 ) + { + update = 1; + } + else if ( st->shb_NO_DATA_cnt >= 100 ) + { + update = 1; + } + else if ( fabs((st->mov_wb_cng_ener - st->mov_shb_cng_ener) - (st->last_wb_cng_ener - st->last_shb_cng_ener)) > 3.0f ) + { + update = 1; + } + else if ( (st->bwidth >=SWB && st->last_SID_bwidth < SWB) || (st->bwidth last_SID_bwidth >= SWB) ) + { + update = 1; + } + + st->last_SID_bwidth = st->bwidth; + } + + if ( update == 1 ) + { + st->last_wb_cng_ener = st->mov_wb_cng_ener; + st->last_shb_cng_ener = st->mov_shb_cng_ener; + st->shb_NO_DATA_cnt = 0; + } + + return (update); +} diff --git a/lib_enc/cod2t32.c b/lib_enc/cod2t32.c new file mode 100644 index 000000000..8f81fcb4d --- /dev/null +++ b/lib_enc/cod2t32.c @@ -0,0 +1,305 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.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( + Encoder_State *st, /* i/o: encoder state structure */ + const float dn[], /* i : corr. between target and h[]. */ + const float h[], /* i : impulse response of weighted synthesis filter */ + float code[], /* o : algebraic (fixed) codebook excitation */ + float y[] /* o : filtered fixed codebook excitation */ +) +{ + short i, j, k, i0, i1, ix, iy, pos, pos2, index; + float psk, ps1, ps2, alpk, alp1, alp2, sq; + float pol[L_SUBFR], dn_p[L_SUBFR], r0; + short ii,jj; + float s, cor, sign0, sign1; + float *p0, *p1, *p2; + const float *ptr_h1, *ptr_h2, *ptr_hf; + float rrixix[NB_TRACK_FCB_2T][NB_POS_FCB_2T]; + float rrixiy[MSIZE]; + + + /*----------------------------------------------------------------* + * Compute rrixix[][] needed for the codebook search. + *----------------------------------------------------------------*/ + + /* Init pointers to last position of rrixix[] */ + p0 = &rrixix[0][NB_POS_FCB_2T - 1]; + p1 = &rrixix[1][NB_POS_FCB_2T - 1]; + + ptr_h1 = h; + cor = 0.0f; + for (i = 0; i < NB_POS_FCB_2T; i++) + { + cor += *ptr_h1 **ptr_h1; + ptr_h1++; + *p1-- = cor; + cor += *ptr_h1 **ptr_h1; + ptr_h1++; + *p0-- = cor; + } + + p0 = rrixix[0]; + p1 = rrixix[1]; + + for (i = 0; i < NB_POS_FCB_2T; i++) + { + *p0 = 0.5f * (*p0); + p0++; + *p1 = 0.5f * (*p1); + p1++; + } + + /*------------------------------------------------------------* + * Compute rrixiy[][] needed for the codebook search. + *------------------------------------------------------------*/ + + pos = MSIZE - 1; + pos2 = MSIZE - 2; + ptr_hf = h + 1; + + for (k = 0; k < NB_POS_FCB_2T; k++) + { + /* Init pointers to last position of diagonals */ + p1 = &rrixiy[pos]; + p0 = &rrixiy[pos2]; + + cor = 0.0f; + ptr_h1 = h; + ptr_h2 = ptr_hf; + + for (i = k+1; i < NB_POS_FCB_2T; i++) + { + cor += *ptr_h1++ **ptr_h2++; + *p1 = cor; + + cor += *ptr_h1++ **ptr_h2++; + *p0 = cor; + + p1 -= (NB_POS_FCB_2T + 1); + p0 -= (NB_POS_FCB_2T + 1); + } + + cor += *ptr_h1++ **ptr_h2; + *p1 = cor; + + pos -= NB_POS_FCB_2T; + pos2--; + ptr_hf += STEP; + } + + /*----------------------------------------------------------------* + * computing reference vector and pre-selection of polarities + *----------------------------------------------------------------*/ + + for(i=0; i=0.0f) + { + pol[i]= 1.0f; + } + else + { + pol[i]=-1.0f; + } + + /* including polarities into dn[] */ + dn_p[i]=dn[i]*pol[i]; + } + + /*----------------------------------------------------------------* + * compute denominator ( multiplied by polarity ) + *----------------------------------------------------------------*/ + + k=0; + ii=0; + for(i=0; i 0) + { + psk = sq; + alpk = alp2; + pos = i1; + } + } + p1 -= NB_POS_FCB_2T; + if (pos >= 0) + { + ix = i0; + iy = pos; + } + } + + i0 = ix/STEP; + i1 = iy/STEP; + sign0 = pol[ix]; + sign1 = pol[iy]; + + + /*-------------------------------------------------------------------* + * Build the codeword, the filtered codeword and index of codevector. + *-------------------------------------------------------------------*/ + + set_f( code, 0.0f, L_SUBFR ); + + code[ix] = sign0; + code[iy] = sign1; + index = (i0<<6) + i1; + + if(sign0 < 0.0f) + { + index += 0x800; + } + + if(sign1 < 0.0f) + { + index += 0x20; + } + + set_f( y, 0.0f, L_SUBFR ); + for(i=ix; i 0 ) + { + index += L_SUBFR; + } + + push_indice( st, IND_ALG_CDBK_1T64, index, 7 ); + + return; +} diff --git a/lib_enc/cod4t64.c b/lib_enc/cod4t64.c new file mode 100644 index 000000000..13b4f2eee --- /dev/null +++ b/lib_enc/cod4t64.c @@ -0,0 +1,957 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_enc.h" +#include "prot.h" +#include "rom_com.h" + + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ + +static short quant_1p_N1( const short pos, const short N ); +static short quant_2p_2N1( const short pos1, const short pos2, const short N ); +static short quant_3p_3N1( const short pos1, const short pos2, const short pos3, const short N ); +static long quant_4p_4N( const short pos[], const short N ); +static long quant_5p_5N( const short pos[], const short N ); +static long quant_6p_6N_2( const short pos[], const short N ); +static int pre_process( const float v[], short pos_vector[], int pos_vector_num[], int *pulse_pos_num); +static int fcb_encode_position( short pos_vector[], int n, int pos_num, int flag ); +static int fcb_encode_class( int *buffer, int pulse_num, int pos_num ); +static int fcb_encode_PI( const float v[], int pulse_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. + *---------------------------------------------------------------------*/ + +short acelp_4t64( + Encoder_State *st, /* i/o: encoder state structure */ + float dn[], /* i : corr. between target and h[]. */ + const float cn[], /* i : residual after long term prediction */ + const float H[], /* i : impulse response of weighted synthesis filter */ + float R[], /* i : autocorrelation values */ + const short acelpautoc, /* i : autocorrealtion flag */ + float code[], /* o : algebraic (fixed) codebook excitation */ + float y[], /* o : filtered fixed codebook excitation */ + short nbbits, /* i : number of bits per codebook */ + const short cmpl_flag, /* i : coomplexity reduction flag */ + const short Opt_AMR_WB /* i : flag indicating AMR-WB IO mode */ +) +{ + short i, k, index, track; + long L_index; + + short ind[NPMAXPT*NB_TRACK_FCB_4T+32]; + short saved_bits = 0; + PulseConfig config; + int indexing_indices[6], wordcnt, bitcnt; + + + /*-----------------------------------------------------------------* + * Configuration + *-----------------------------------------------------------------*/ + + + switch (nbbits) + { + case 20: /* EVS/AMR-WB pulse indexing: 20 bits, 4 pulses, 4 tracks */ + config.nbiter = 4; /* 4x12x16=768 loop */ + config.alp = 2.0f; + config.nb_pulse = 4; + config.fixedpulses = 0; + config.nbpos[0] = 4; + config.nbpos[1] = 8; + break; + + case 28: /* EVS pulse indexing: 28 bits, 6 pulses, 4 tracks */ + config.nbiter = 4; /* 4x20x16=1280 loops */ + config.alp = 1.0f; /* coeff for sign setting */ + config.nb_pulse = 6; + config.fixedpulses = 0; + config.nbpos[0] = 6; + config.nbpos[1] = 6; + config.nbpos[2] = 8; + break; + + case 36: /* EVS/AMR-WB pulse indexing: 36 bits, 8 pulses, 4 tracks */ + config.nbiter = 4; /* 4x20x16=1280 loops */ + config.alp = 1.0f; /* coeff for sign setting */ + config.nb_pulse = 8; + config.fixedpulses = 2; + config.nbpos[0] = 4; + config.nbpos[1] = 8; + config.nbpos[2] = 8; + 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; /* 4x26x16=1664 loops */ + config.alp = 1.0f; + config.nb_pulse = 10; + config.fixedpulses = 2; + config.nbpos[0] = 4; + config.nbpos[1] = 6; + config.nbpos[2] = 8; + config.nbpos[3] = 8; + 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; /* 4x26x16=1664 loops */ + config.alp = 1.0f; + config.nb_pulse = 12; + config.fixedpulses = 4; + config.nbpos[0] = 4; + config.nbpos[1] = 6; + config.nbpos[2] = 8; + config.nbpos[3] = 8; + 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; /* 3x36x16=1728 loops */ + config.alp = 0.8F; + config.nb_pulse = 16; + config.fixedpulses = 4; + config.nbpos[0] = 4; + config.nbpos[1] = 4; + config.nbpos[2] = 6; + config.nbpos[3] = 6; + config.nbpos[4] = 8; + config.nbpos[5] = 8; + break; + + case 72: /* AMR-WB pulse indexing: 72 bits, 18 pulses, 4 tracks */ + config.nbiter = 3; /* 3x35x16=1680 loops */ + config.alp = 0.75F; + config.nb_pulse = 18; + config.fixedpulses = 4; + config.nbpos[0] = 2; + config.nbpos[1] = 3; + config.nbpos[2] = 4; + config.nbpos[3] = 5; + config.nbpos[4] = 6; + config.nbpos[5] = 7; + config.nbpos[6] = 8; + break; + + case 88: /* AMR-WB pulse indexing: 88 bits, 24 pulses, 4 tracks */ + config.nbiter = 2; /* 2x53x16=1696 loop */ + config.alp = 0.5f; + config.nb_pulse = 24; + config.fixedpulses = 4; + config.nbpos[0] = 2; + config.nbpos[1] = 2; + config.nbpos[2] = 3; + config.nbpos[3] = 4; + config.nbpos[4] = 5; + config.nbpos[5] = 6; + config.nbpos[6] = 7; + config.nbpos[7] = 8; + config.nbpos[8] = 8; + config.nbpos[9] = 8; + break; + + case 87: /* EVS pulse indexing: 87 bits, 26 pulses, 4 tracks */ + config.nbiter = 1; + config.alp = 0.5F; + config.nb_pulse = 26; + config.fixedpulses = 4; + config.nbpos[0] = 4; + config.nbpos[1] = 6; + config.nbpos[2] = 6; + config.nbpos[3] = 8; + config.nbpos[4] = 8; + config.nbpos[5] = 8; + config.nbpos[6] = 8; + config.nbpos[7] = 8; + config.nbpos[8] = 8; + config.nbpos[9] = 8; + config.nbpos[10] = 8; + break; + } + + /* reduce the number of iterations as a compromise between the performance and complexity */ + if( cmpl_flag > 0 ) + { + config.nbiter = cmpl_flag; + } + + config.codetrackpos = TRACKPOS_FIXED_FIRST; + config.bits = nbbits; + + /*-----------------------------------------------------------------* + * Search + *-----------------------------------------------------------------*/ + + if( acelpautoc ) + { + E_ACELP_4tsearchx( dn, cn, R, code, &config, ind ); + + /* Generate weighted code */ + set_f( y, 0.0f, L_SUBFR ); + for( i=0; i> 4; + bitcnt = nbbits & 15; + for ( i = 0; i < wordcnt; i++ ) + { + push_indice( st, IND_ALG_CDBK_4T64, indexing_indices[i], 16 ); + } + if ( bitcnt ) + { + push_indice( st, IND_ALG_CDBK_4T64, indexing_indices[i], bitcnt ); + } + + } + else + { + /* AMR-WB pulse indexing */ + + if (nbbits == 20) + { + for (track = 0; track < NB_TRACK_FCB_4T; track++) + { + k = track * NPMAXPT; + index = quant_1p_N1(ind[k], 4); + push_indice( st, IND_ALG_CDBK_4T64, index, 5 ); + } + } + else if (nbbits == 36) + { + for (track = 0; track < NB_TRACK_FCB_4T; track++) + { + k = track * NPMAXPT; + index = quant_2p_2N1(ind[k], ind[k+1], 4); + push_indice( st, IND_ALG_CDBK_4T64, index, 9 ); + } + } + else if (nbbits == 44) + { + for (track = 0; track < (NB_TRACK_FCB_4T - 2); track++) + { + k = track * NPMAXPT; + index = quant_3p_3N1(ind[k], ind[k+1], ind[k+2], 4); + push_indice( st, IND_ALG_CDBK_4T64, index, 13 ); + } + + for (track = 2; track < NB_TRACK_FCB_4T; track++) + { + k = track * NPMAXPT; + index = quant_2p_2N1(ind[k], ind[k+1], 4); + push_indice( st, IND_ALG_CDBK_4T64, index, 9 ); + } + } + else if (nbbits == 52) + { + for (track = 0; track < NB_TRACK_FCB_4T; track++) + { + k = track*NPMAXPT; + index = quant_3p_3N1(ind[k], ind[k+1], ind[k+2], 4); + push_indice( st, IND_ALG_CDBK_4T64, index, 13 ); + } + } + else if (nbbits == 64) + { + for (track = 0; track < NB_TRACK_FCB_4T; track++) + { + k = track * NPMAXPT; + L_index = quant_4p_4N(&ind[k], 4); + index = ((L_index >> 14) & 3); + push_indice( st, IND_ALG_CDBK_4T64_1, index, 2 ); + } + + for (track = 0; track < NB_TRACK_FCB_4T; track++) + { + k = track * NPMAXPT; + L_index = quant_4p_4N(&ind[k], 4); + index = (L_index & 0x3FFF); + push_indice( st, IND_ALG_CDBK_4T64_2, index, 14 ); + } + } + else if (nbbits == 72) + { + for (track=0; track< (NB_TRACK_FCB_4T - 2); track++) + { + k = track * NPMAXPT; + L_index = quant_5p_5N(&ind[k], 4); + index = ((L_index >> 10) & 0x03FF); + push_indice( st, IND_ALG_CDBK_4T64_1, index, 10 ); + } + + for (track = 2; track < NB_TRACK_FCB_4T; track++) + { + k = track * NPMAXPT; + L_index = quant_4p_4N(&ind[k], 4); + index = ((L_index >> 14) & 3); + push_indice( st, IND_ALG_CDBK_4T64_1, index, 2 ); + } + + for (track=0; track< (NB_TRACK_FCB_4T - 2); track++) + { + k = track * NPMAXPT; + L_index = quant_5p_5N(&ind[k], 4); + index = (L_index & 0x03FF); + push_indice( st, IND_ALG_CDBK_4T64_2, index, 10 ); + } + + for (track = 2; track < NB_TRACK_FCB_4T; track++) + { + k = track * NPMAXPT; + L_index = quant_4p_4N(&ind[k], 4); + index = (L_index & 0x3FFF); + push_indice( st, IND_ALG_CDBK_4T64_2, index, 14 ); + } + } + else if (nbbits == 88) + { + for (track = 0; track < NB_TRACK_FCB_4T; track++) + { + k = track * NPMAXPT; + L_index = quant_6p_6N_2(&ind[k], 4); + index = ((L_index >> 11) & 0x07FF); + push_indice( st, IND_ALG_CDBK_4T64_1, index, 11 ); + } + + for (track = 0; track < NB_TRACK_FCB_4T; track++) + { + k = track * NPMAXPT; + L_index = quant_6p_6N_2(&ind[k], 4); + index = (L_index & 0x07FF); + push_indice( st, IND_ALG_CDBK_4T64_2, index, 11 ); + } + } + } + + return saved_bits; +} + + +/*---------------------------------------------------------------------* + * Quantization of 1 pulse with N+1 bits: * + *---------------------------------------------------------------------*/ +static short quant_1p_N1( /* o: return N+1 bits */ + const short pos, /* i: position of the pulse */ + const short N /* i: number of bits for position */ +) +{ + short mask, index; + + mask = ((1<>2; + pos_vector_num[j] = fabs(v[k]); + if (v[k]>0) + sign = sign << 1; + else + sign = ( sign << 1 ) + 1; + j++; + } + } + *pulse_pos_num = j; + + return sign; +} + +/*---------------------------------------------------------------------* + *encode the position * + *---------------------------------------------------------------------*/ + +static int fcb_encode_position( /* o: return index of the positions which have pulse*/ + short pos_vector[], /* i: position of the pulse on a track */ + int n, + int pos_num, /* i: the number of position which have pulse */ + int flag +) +{ + int i; + int mmm1; + int temp2; + mmm1 = PI_select_table[n][pos_num] - 1; + temp2 = pos_num; + + if (flag) /* no decrease */ + { + for (i=0; i>2; + if (code[k]<0) + { + tmp += 16; + } + if (fabs(code[k])>1) + { + ind[j] = tmp; + ind[j+1] = tmp; + break; + } + else + { + ind[j] = tmp; + j++; + } + } + } + k = track * NPMAXPT; + ps[track] = quant_2p_2N1(ind[k], ind[k+1], 4); + p[track] = 2; + } + joint_index = ps[0]*5472 + ps[1]; + if (joint_index >= joint_offset) + { + joint_index += joint_offset; + } + else + { + saved_bits += 1; + } + + idxs[0] = ( ( ps[2] << 9 ) + ps[3] ) & 0xffff; + idxs[1] = ( ( joint_index << 2 ) + ( ps[2] >> 7 ) ) & 0xffff; + idxs[2] = 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 000000000..d1699a845 --- /dev/null +++ b/lib_enc/cod_ace.c @@ -0,0 +1,430 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "prot.h" +#include "options.h" +#include "rom_com.h" + +/*-------------------------------------------------------------------* + * coder_acelp() + * + * Encode ACELP frame + *-------------------------------------------------------------------*/ + +void coder_acelp( + ACELP_config *acelp_cfg, /* i/o: configuration of the ACELP */ + const short coder_type, /* i : coding type */ + const float A[], /* i : coefficients 4xAz[M+1] */ + const float Aq[], /* i : coefficients 4xAz_q[M+1] */ + const float speech[], /* i : speech[-M..lg] */ + float synth[], /* o : synthesis */ + LPD_state *LPDmem, /* i/o: ACELP memories */ + const float voicing[], /* input: open-loop LTP gain */ + const short T_op[], /* input: open-loop LTP lag */ + int *prm, /* output: acelp parameters */ + const float stab_fac, + Encoder_State *st, /* i/o : coder memory state */ + HANDLE_PLC_ENC_EVS hPlc_Ext, + const short target_bits, + float *gain_pitch_buf,/* o : gain pitch values */ + float *gain_code_buf, /* o : gain code values */ + float *pitch_buf, /* o : pitch values for each subfr.*/ + float *voice_factors, /* o : voicing factors */ + float *bwe_exc /* o : excitation for SWB TBE */ +) +{ + short i, i_subfr; + int T0, T0_min, T0_min_frac, T0_max, T0_max_frac, T0_res, T0_frac; + float tmp, Es_pred; + float gain_pit, gain_code, voice_fac; + ACELP_CbkCorr g_corr; + float g_corr2[6]; + const float *p_A, *p_Aq; + float h1[L_SUBFR]; /* weighted impulse response of LP */ + float code[L_SUBFR]; + float cn[L_SUBFR]; + float xn[L_SUBFR]; + float xn2[L_SUBFR]; + float y1[L_SUBFR]; /* Filtered adaptive excitation */ + float y2[L_SUBFR]; /* Filtered adaptive excitation */ + float res_save; + float exc_buf[L_EXC_MEM+L_FRAME16k+1], *exc; + float exc2[L_SUBFR]; + float *syn,syn_buf[M+L_FRAME16k+L_FRAME16k/2]; /*128 for the memory, L_FRAME for the current synth and 128 for the ZIR for next TCX*/ + float syn2[L_FRAME16k]; + float norm_gain_code, gain_inov; + short clip_gain; + float gain_code2; + float code2[L_SUBFR]; + float y22[L_SUBFR]; /* Filtered adaptive excitation */ + short lp_select; + float *pt_pitch, *pt_gain_pitch, *pt_gain_code; + int offset; + float error; + float gain_preQ; /* Gain of prequantizer excitation */ + float code_preQ[L_SUBFR]; /* Prequantizer excitation */ + + /* Configure ACELP */ + BITS_ALLOC_config_acelp( target_bits, coder_type, &(st->acelp_cfg), st->narrowBand, st->nb_subfr ); + + /*------------------------------------------------------------------------* + * Initialize buffers * + *------------------------------------------------------------------------*/ + + set_f( code_preQ, 0.f, L_SUBFR ); + gain_preQ = 0.0f; + + /* Reset phase dispersion */ + if( st->last_core > ACELP_CORE ) + { + set_zero( st->dispMem, 8 ); + } + + /* set excitation memory*/ + exc = exc_buf + L_EXC_MEM; + mvr2r( LPDmem->old_exc, exc_buf, L_EXC_MEM ); + *(exc+st->L_frame) = 0.f; /*to solve a warning*/ + + /* Init syn buffer */ + syn = syn_buf + M; + mvr2r( LPDmem->mem_syn, syn_buf, M ); + + pt_pitch = pitch_buf; + pt_gain_pitch = gain_pitch_buf; + pt_gain_code = gain_code_buf; + + T0 = 0; + T0_res = 0; + T0_frac = 0; + + error = 0.0f; + + /*---------------------------------------------------------------* + * Calculation of LP residual (filtering through A[z] filter) + *---------------------------------------------------------------*/ + + calc_residu( speech, exc, Aq, st->L_frame ); + + /*------------------------------------------------------------------------* + * Find and quantize mean_ener_code for gain quantizer * + *------------------------------------------------------------------------*/ + + if( acelp_cfg->nrg_mode > 0 ) + { + Es_pred_enc( &Es_pred, prm, st->L_frame, L_SUBFR, exc, voicing, acelp_cfg->nrg_bits, acelp_cfg->nrg_mode>1 ); + prm++; + } + else + { + Es_pred = 0.f; + } + + if( st->L_frame == L_FRAME ) + { + mvr2r( Aq+2*(M+1), st->cur_sub_Aq, (M+1) ); + } + else + { + mvr2r( Aq+3*(M+1), st->cur_sub_Aq, (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 * + *------------------------------------------------------------------------*/ + + p_A = A; + p_Aq = Aq; + + res_save = exc[0]; + + for( i_subfr = 0; i_subfr < st->L_frame; i_subfr += L_SUBFR ) + { + /* Restore exc[i_subfr] and save next exc[L_SUBFR+i_subfr] */ + exc[i_subfr] = res_save; + res_save = exc[L_SUBFR+i_subfr]; + + /*--------------------------------------------------------------------------* + * Find target for pitch search (xn[]), target for innovation search (cn[]) * + * and impulse response of the weighted synthesis filter (h1[]). * + *--------------------------------------------------------------------------*/ + + find_targets( speech, &syn[i_subfr-M], i_subfr, &LPDmem->mem_w0, p_Aq,exc, L_SUBFR, p_A, st->preemph_fac, xn, cn, h1 ); + + /*-----------------------------------------------------------------* + * Gain clipping test to avoid unstable synthesis on frame erasure + * or in case of floating point encoder & fixed p. decoder + *-----------------------------------------------------------------*/ + + clip_gain = gp_clip( st->core_brate, voicing, i_subfr, coder_type, xn, st->clip_var ); + + /*-----------------------------------------------------------------* + * - 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 ) + { + /* pitch lag coding */ + 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 ); + + /* find pitch excitation */ + if( st->pit_res_max == 6 ) + { + if ( T0_res == (st->pit_res_max>>1) ) + { + pred_lt4( &exc[i_subfr], &exc[i_subfr], T0, T0_frac<<1, L_SUBFR+1, inter6_2, PIT_L_INTERPOL6_2, PIT_UP_SAMP6); + } + else + { + pred_lt4( &exc[i_subfr], &exc[i_subfr], T0, T0_frac, L_SUBFR+1, inter6_2, PIT_L_INTERPOL6_2, PIT_UP_SAMP6); + } + } + else + { + if( T0_res == (st->pit_res_max>>1) ) + { + pred_lt4( &exc[i_subfr], &exc[i_subfr], T0, T0_frac<<1, L_SUBFR+1, inter4_2, L_INTERPOL2, PIT_UP_SAMP); + } + else + { + pred_lt4( &exc[i_subfr], &exc[i_subfr], T0, T0_frac, L_SUBFR+1, inter4_2, L_INTERPOL2, PIT_UP_SAMP); + } + } + + /* filter adaptive codebook */ + lp_select = lp_filt_exc_enc( MODE2, st->core_brate, 0, coder_type, i_subfr, exc, h1, xn, y1, xn2, L_SUBFR, + st->L_frame, g_corr2, clip_gain, &(gain_pit), &(acelp_cfg->ltf_mode) ); + + if( acelp_cfg->ltf_mode == NORMAL_OPERATION ) + { + *prm = lp_select; + prm++; + } + + g_corr.y1y1 = g_corr2[0]; + g_corr.xy1 = -0.5f*(g_corr2[1]-0.01f)+0.01f; + } + else + { + /* No adaptive codebook (UC) */ + gain_pit=0.f; + g_corr.xy1=0.f; + g_corr.y1y1=0.f; + set_zero( y1, L_SUBFR ); + set_zero( exc+i_subfr, L_SUBFR ); + T0 = L_SUBFR; + T0_frac = 0; + T0_res = 1; + } + + if( st->igf ) + { + if( st->sr_core == 12800 ) + { + 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; i < L_SUBFR * HIBND_ACB_L_FAC; i++) + { + bwe_exc[i + i_subfr * HIBND_ACB_L_FAC] = bwe_exc[i + i_subfr * HIBND_ACB_L_FAC - offset + (int) error]; + } + error += (float) offset - (float) T0 * HIBND_ACB_L_FAC - 0.25f * HIBND_ACB_L_FAC * (float) T0_frac; + } + else + { + offset = T0 * 2 + (int) ((float) T0_frac * 0.5f + 4 + 0.5f) - 4; + for (i=0; itilt_code, + acelp_cfg->fixed_cdk_index[i_subfr/L_SUBFR], + 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, + i_subfr, p_Aq, h1, xn, cn, y1, y2, + st->acelp_autocorr, &prm, code + ,st->L_frame, st->last_L_frame, st->total_brate + ); + + E_corr_xy2( xn, y1, y2, g_corr2, L_SUBFR ); + g_corr.y2y2 = 0.01F + g_corr2[2]; + g_corr.xy2 = 0.01F + -0.5f*g_corr2[3]; + g_corr.y1y2 = 0.01F + 0.5f*g_corr2[4]; + + g_corr.xx = 0.01F + dotp( xn, xn, L_SUBFR ); + + /*----------------------------------------------------------------------* + * Add Gaussian excitation * + *----------------------------------------------------------------------*/ + + if(acelp_cfg->gains_mode[i_subfr/L_SUBFR]==7) + { + gauss_L2( h1, code2, y2, y22, &gain_code2, g_corr2, gain_pit, + LPDmem->tilt_code, p_Aq, acelp_cfg->formant_enh_num, &(st->seed_acelp) ); + + g_corr.y1y1 = g_corr2[0]; + g_corr.y1y2 = g_corr2[4]; + } + else + { + gain_code2 = 0.f; + set_zero( code2, L_SUBFR ); + set_zero( y22, L_SUBFR ); + } + + /*----------------------------------------------------------* + * - Compute the fixed codebook gain * + * - quantize fixed codebook gain * + *----------------------------------------------------------*/ + + encode_acelp_gains( code, acelp_cfg->gains_mode[i_subfr/L_SUBFR], Es_pred, clip_gain, &g_corr, &gain_pit, &gain_code, + &prm, &norm_gain_code, &gain_inov, L_SUBFR, code2, &gain_code2, st->flag_noisy_speech_snr ); + + gp_clip_test_gain_pit( st->core_brate, gain_pit, st->clip_var); + + /*----------------------------------------------------------* + * - voice factor (for codebook tilt sharpening) * + *----------------------------------------------------------*/ + + LPDmem->tilt_code = est_tilt( exc+i_subfr, gain_pit, code, gain_code, &voice_fac, L_SUBFR, acelp_cfg->voice_tilt ); + + st->rf_tilt_buf[i_subfr/L_SUBFR] = LPDmem->tilt_code; + + + /*-----------------------------------------------------------------* + * Update memory of the weighting filter + *-----------------------------------------------------------------*/ + + LPDmem->mem_w0 = xn[L_SUBFR-1] - gain_pit * y1[L_SUBFR-1] - gain_code * y2[L_SUBFR-1] - gain_code2*y22[L_SUBFR-1]; + + /*-------------------------------------------------------* + * - Find the total excitation. * + *-------------------------------------------------------*/ + + for( i = 0; i < L_SUBFR; i++ ) + { + exc2[i] = gain_pit*exc[i+i_subfr]; + exc2[i] += gain_code2*code2[i]; + exc[i+i_subfr] = exc2[i] + gain_code*code[i]; + } + + /*-----------------------------------------------------------------* + * Prepare TBE excitation + *-----------------------------------------------------------------*/ + + prep_tbe_exc( st->L_frame, i_subfr, gain_pit, gain_code, code, voice_fac, &voice_factors[i_subfr/L_SUBFR], + bwe_exc, gain_preQ, code_preQ, T0, coder_type, st->core_brate ); + + /*---------------------------------------------------------* + * Enhance the excitation * + *---------------------------------------------------------*/ + + enhancer( MODE2, -1, acelp_cfg->fixed_cdk_index[i_subfr/L_SUBFR], 0, coder_type, st->L_frame, voice_fac, stab_fac, + norm_gain_code, gain_inov, &(LPDmem->gc_threshold), code, exc2, gain_pit, st->dispMem ); + + /*----------------------------------------------------------* + * - compute the synthesis speech * + *----------------------------------------------------------*/ + + syn_filt( p_Aq, M, exc2, &syn2[i_subfr], L_SUBFR, LPDmem->mem_syn2, 1 ); + + syn_filt( p_Aq, M, &exc[i_subfr], &syn[i_subfr], L_SUBFR, &syn[i_subfr-M], 0 ); + + /*----------------------------------------------------------* + * Save buffers for BPF * + *----------------------------------------------------------*/ + + *pt_pitch = ((float)T0+(float)T0_frac/(float)T0_res+0.5f); + *pt_gain_pitch = gain_pit; + *pt_gain_code = gain_code; + + /*----------------------------------------------------------* + * Update * + *----------------------------------------------------------*/ + + p_A += (M+1); + p_Aq += (M+1); + pt_pitch++; + pt_gain_pitch++; + pt_gain_code++; + + if( hPlc_Ext != NULL ) + { + hPlc_Ext->T0_4th = T0; + } + + } /* end of subframe loop */ + + p_A -= (M+1); + p_Aq -= (M+1); + + + /*----------------------------------------------------------* + * Update LPD memory * + *----------------------------------------------------------*/ + + mvr2r( exc + st->L_frame - L_EXC_MEM, LPDmem->old_exc, L_EXC_MEM ); + mvr2r( syn + st->L_frame - M, LPDmem->mem_syn, M ); + mvr2r( syn + st->L_frame - L_SYN_MEM, LPDmem->mem_syn_r, L_SYN_MEM ); + + if( hPlc_Ext != NULL ) + { + mvr2r( exc + st->L_frame - L_EXC_MEM - 8, hPlc_Ext->old_exc, 8 ); + } + + /*----------------------------------------------------------* + * ZIR at the end of the ACELP frame (for TCX) * + *----------------------------------------------------------*/ + + mvr2r( syn2, syn, st->L_frame ); + tmp = LPDmem->syn[M]; + deemph( syn, st->preemph_fac, st->L_frame, &tmp ); + mvr2r( syn + st->L_frame/2, LPDmem->Txnq, st->L_frame/2 ); + mvr2r( syn + st->L_frame - (M+1), LPDmem->syn, M+1 ); + mvr2r( syn, synth, st->L_frame ); + + + /*Update MODE1*/ + mvr2r( p_Aq, st->old_Aq_12_8, M+1 ); + st->old_Es_pred = Es_pred; + + return; +} diff --git a/lib_enc/cod_tcx.c b/lib_enc/cod_tcx.c new file mode 100644 index 000000000..d1b675ccd --- /dev/null +++ b/lib_enc/cod_tcx.c @@ -0,0 +1,1340 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "cnst.h" +#include "wmc_auto.h" +#include +#include +#include +#include +#include "prot.h" + + +/*-------------------------------------------------------------------* +* HBAutocorrelation() +* +* +*-------------------------------------------------------------------*/ + +void HBAutocorrelation( + TCX_config *tcx_cfg, /* input: configuration of TCX */ + int left_overlap_mode, /* input: overlap mode of left window half */ + int right_overlap_mode, /* input: overlap mode of right window half */ + float speech[], /* input: synthesis */ + int L_frame, /* input: frame length */ + float *r, /* output: autocorrelations vector */ + int m /* input : order of LP filter */ +) +{ + int i, j, left_overlap, right_overlap; + float s; + float xn_buf[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, xn_buf, 0 ); + + /*-----------------------------------------------------------* + * Autocorrelation * + *-----------------------------------------------------------*/ + + for (i = 0; i <= m; i++) + { + s = 0.0; + + for (j = 0; j < L_frame+(left_overlap+right_overlap)/2-i; j++) + { + s += xn_buf[j]*xn_buf[j+i]; + } + r[i] = s; + } + + if (r[0] < 100.0) + { + r[0] = 100.0; + } + + return; + +} + +/*-------------------------------------------------------------------* +* TNSAnalysis() +* +* +*-------------------------------------------------------------------*/ + +void TNSAnalysis( + TCX_config *tcx_cfg, /* input: configuration of TCX */ + int L_frame, /* input: frame length */ + int L_spec, + const short tcxMode, /* input: TCX mode for the frame/subframe - TCX20 | TCX10 | TCX 5 (meaning 2 x TCX 5) */ + int isAfterACELP, /* input: Flag indicating if the last frame was ACELP. For the second TCX subframe it should be 0 */ + float spectrum[], /* input: MDCT spectrum of the subframe */ + STnsData * pTnsData, /* output: Tns data */ + int * pfUseTns, /* output: Flag indicating if TNS is used */ + float* predictionGain +) +{ + float buff[8]; /* Buffer for the rearrangement of LF TCX5 */ + + /* Init TNS */ + *pfUseTns = 0; + + if (tcx_cfg->fIsTNSAllowed) + { + + tcx_cfg->pCurrentTnsConfig = &tcx_cfg->tnsConfig[tcxMode == TCX_20][isAfterACELP]; + L_spec = tcx_cfg->pCurrentTnsConfig->iFilterBorders[0]; + + /*-----------------------------------------------------------* + * Temporal Noise Shaping analysis * + *-----------------------------------------------------------*/ + + if (tcxMode == TCX_5) + { + /* rearrange LF sub-window lines prior to TNS analysis & filtering */ + if (L_spec < L_frame/2) + { + mvr2r(spectrum+8, spectrum+16, L_spec/2-8); + mvr2r(spectrum+L_frame/4, spectrum+8, 8); + mvr2r(spectrum+L_frame/4+8, spectrum+L_spec/2+8, L_spec/2-8); + } + else + { + mvr2r(spectrum+L_frame/4, buff, 8); + mvr2r(spectrum+8, spectrum+16, L_frame/4-8); + mvr2r(buff, spectrum+8, 8); + } + } + + *pfUseTns = DetectTnsFilt(tcx_cfg->pCurrentTnsConfig, spectrum, pTnsData, predictionGain); + + /* If TNS should be used then get the residual after applying it inplace in the spectrum */ + if (*pfUseTns) + { + ApplyTnsFilter(tcx_cfg->pCurrentTnsConfig, pTnsData, spectrum, 1); + + } + + if (tcxMode == TCX_5) + { + /* undo rearrangement of LF sub-window lines prior to TNS analysis */ + if (L_spec < L_frame/2) + { + mvr2r(spectrum+L_spec/2+8, spectrum+L_frame/4+8, L_spec/2-8); + mvr2r(spectrum+8, spectrum+L_frame/4, 8); + mvr2r(spectrum+16, spectrum+8, L_spec/2-8); + set_zero(spectrum+L_spec/2, L_frame/4-L_spec/2); + set_zero(spectrum+L_frame/4+L_spec/2, L_frame/4-L_spec/2); + } + else + { + mvr2r(spectrum+8, buff, 8); + mvr2r(spectrum+16, spectrum+8, L_frame/4-8); + mvr2r(buff, spectrum+L_frame/4, 8); + } + } + } + + return; +} + + +/*-------------------------------------------------------------------* +* ShapeSpectrum() +* +* +*-------------------------------------------------------------------*/ + +void ShapeSpectrum( + TCX_config *tcx_cfg,/*input: configuration of TCX */ + float A[], /* input: quantized coefficients NxAz_q[M+1] */ + float gainlpc[], /* output: MDCT gains for the previous frame */ + int L_frame_glob, /* input: frame length */ + int L_spec, + float spectrum[], /* i/o: MDCT spectrum */ + int fUseTns, /* output: Flag indicating if TNS is used */ + Encoder_State *st +) +{ + int L_frame; + int tcx_offset; + float Ap[M+2]; + float gamma1; + float max_low_pre = 0.f, max_high_pre = 0.f; + + /*-----------------------------------------------------------* + * Init * + *-----------------------------------------------------------*/ + + /* Init lengths */ + L_frame = L_frame_glob; + tcx_offset = tcx_cfg->tcx_offset; + gamma1 = st->gamma; + + if (st->enableTcxLpc) + { + gamma1 = 1.0f; + } + + /* if past frame is ACELP */ + + if (st->last_core == 0) + { + L_frame += tcx_offset; + L_spec += tcx_cfg->tcx_coded_lines >> 2; + if(tcx_cfg->lfacNext<0) + { + L_frame -= tcx_cfg->lfacNext; + } + } + + tcxGetNoiseFillingTilt( A, L_frame, (st->total_brate >= ACELP_13k20 && !st->rf_mode), &st->noiseTiltFactor ); + + /* Calculate Spectrum Flatness Measure for the TCX Concealment */ + if( st->enablePlcWaveadjust ) + { + tcx_cfg->SFM2 = SFM_Cal(spectrum, min(200, L_frame)); + } + + if( (st->total_brate == ACELP_9k60 && st->bwidth == SWB) || + (st->total_brate == ACELP_13k20 && st->bwidth == SWB) ) + { + int i; + + max_low_pre = 0.f; + for (i = 0; i < L_frame; i++) + { + float tmp = fabs(spectrum[i]); + if( tmp > max_low_pre ) + { + max_low_pre = tmp; + } + } + + max_high_pre = 0.f; + for (i = 0; i < L_spec - L_frame; i++) + { + float tmp = fabs(spectrum[L_frame + i]); + if( tmp > max_high_pre ) + { + max_high_pre = tmp; + } + } + } + + /*-----------------------------------------------------------* + * Pre-shaping in frequency domain using weighted LPC (Wz) * + *-----------------------------------------------------------*/ + weight_a(A, Ap, gamma1, M); + + lpc2mdct(Ap, M, gainlpc); + + mdct_preShaping(spectrum, L_frame, gainlpc); + + v_multc(spectrum+L_frame, 1.f/gainlpc[FDNS_NPTS-1], spectrum+L_frame, L_spec-L_frame); + + /* reduce the peaks in the IGF region, to make life of the core-coder easier... */ + if( (st->total_brate == ACELP_9k60 && st->bwidth == SWB) || + (st->total_brate == ACELP_13k20 && st->bwidth == SWB) ) + { + int i, sf_width; + int dist_low, dist_high; + float max_fac; + float max_low, max_low1, max_low2, max_high; + + if( st->tcx_lpc_shaped_ari ) + { + max_fac = 1.5f; + } + else + { + max_fac = 3.f; + } + + sf_width = L_frame / 2; + + max_low2 = 0.f; + dist_low = 0; + for (i = 0; i < sf_width; i++) + { + float tmp = fabs(spectrum[L_frame - 1 - i]); + if( tmp > max_low2 ) + { + max_low2 = tmp; + dist_low = i; + } + } + + max_low1 = 0.f; + for (i = 0; i < L_frame - sf_width; i++) + { + float tmp = fabs(spectrum[L_frame - sf_width - 1 - i]); + if( tmp > max_low1 ) + { + max_low1 = tmp; + } + if( tmp > max_low2 ) + { + dist_low = sf_width + i; + } + } + + max_low = max(max_low1, max_low2); + + max_high = 0.f; + dist_high = 0; + for (i = 0; i < L_spec - L_frame; i++) + { + float tmp = fabs(spectrum[L_frame + i]); + if( tmp > max_high) + { + max_high = tmp; + dist_high = i; + } + } + + if( (4.f * dist_high * max_high > dist_low * max_low) && (16.f * max_low_pre > max_high_pre) && (max_high > max_fac * max_low2) ) + { + float fac = max_fac * max_low2 / max_high; + v_multc(spectrum + L_frame, fac, spectrum + L_frame, L_spec - L_frame); + } + + } + + if (st->tcxonly && st->tcxltp && (st->tcxltp_gain > 0.0f) && !fUseTns ) + { + PsychAdaptLowFreqEmph(spectrum, gainlpc); + } + + return; +} + + +/*-------------------------------------------------------------------* +* QuantizeSpectrum() +* +* +*-------------------------------------------------------------------*/ + +void QuantizeSpectrum( + TCX_config *tcx_cfg,/*input: configuration of TCX*/ + float A[], /* input: quantized coefficients NxAz_q[M+1] */ + Word16 Aqind[], /* input: frame-independent quantized coefficients (M+1) */ + float gainlpc[], /* input: MDCT gains of the previous frame */ + float synth[], + int L_frame_glob, /* input: frame length */ + int L_frameTCX_glob, + int L_spec, + int nb_bits, /*input: bit budget*/ + int tcxonly, /*input: only TCX flag*/ + float spectrum[], /* i/o: MDCT spectrum, input is shaped MDCT spectrum */ + STnsData * pTnsData,/* input: Tns data */ + int fUseTns, /* input: Flag indicating if TNS is used */ + int tnsSize, /* input: number of tns parameters put into prm */ + LPD_state *LPDmem, /*i/o: memories*/ + int prm[], /* output: tcx parameters */ + int frame_cnt, /* input: frame counter in the super_frame */ + Encoder_State *st, + CONTEXT_HM_CONFIG *hm_cfg +) +{ + int i, sqTargetBits, L_frame, tcx_offset, stop; + int L_frameTCX; + float fac_ns, ener, gain_tcx, gain_tcx_opt; + float xn_buf[L_MDCT_OVLP_MAX+L_FRAME_PLUS+L_MDCT_OVLP_MAX]; + float x_orig[N_MAX]; + float sqGain = 1.0f; + int sqBits; + int sqBits_noStop; + int overlap; + int noiseFillingSize; + int noiseTransWidth = MIN_NOISE_FILLING_HOLE; + int nEncoded; + int *sqQ; + short LtpPitchLag; + int ctxHmBits; + int resQBits; + int resQTargetBits = 0; + short nf_seed = 0; + int PeriodicityIndex, NumIndexBits; + float *OriginalSpectrum; + int nEncodedCtxHm, stopCtxHm, sqBitsCtxHm, Selector; + int lastnz, lastnzCtxHm; + float RelativeScore; + int *signs; + int signaling_bits; + int *prm_ltp, *prm_tns, *prm_hm, *prm_lastnz, *prm_target; + float SFM; + float K, K2; + float Aq_old[M+1]; + short aldo; /* ALDO flag in current frame*/ + short nz; /* non-zero length in ALDO window*/ + int maxNfCalcBw; + + /*-----------------------------------------------------------* + * Init * + *-----------------------------------------------------------*/ + + /* Init lengths */ + L_frame = L_frame_glob; + L_frameTCX = L_frameTCX_glob; + overlap = tcx_cfg->tcx_mdct_window_length; + aldo=0; + nz=NS2SA(st->sr_core, N_ZERO_MDCT_NS); + + tcx_offset = tcx_cfg->tcx_offset; + + OriginalSpectrum = NULL; + signs = NULL; /* silence warning */ + NumIndexBits = 0; + sqBits = 0; + ctxHmBits = 0; + resQBits=0; + prm_ltp = &prm[1+NOISE_FILL_RANGES]; + prm_tns = prm_ltp + LTPSIZE; + prm_hm = prm_tns + tnsSize; + prm_lastnz = prm_hm + 2; + sqQ = prm_hm + NPRM_CTX_HM; + + /* if past frame is ACELP */ + + if (st->last_core == 0) + { + tcx_cfg->last_aldo=0; + + L_frame += tcx_offset; + L_frameTCX += tcx_cfg->tcx_offsetFB; + L_spec += tcx_cfg->tcx_coded_lines >> 2; + if(tcx_cfg->lfacNext<0) + { + L_frame -= tcx_cfg->lfacNext; + L_frameTCX -= tcx_cfg->lfacNextFB; + tcx_offset = tcx_cfg->lfacNext; + } + else + { + tcx_offset = 0; + } + st->noiseLevelMemory = 0; + } + + + lsp2a_stab( st->lsp_old, Aq_old, M ); + + /* target bitrate for SQ */ + sqTargetBits = nb_bits-7-NBITS_NOISE_FILL_LEVEL; + + /*Unquantized spectrum here*/ + if(st->enablePlcWaveadjust) + { + + SFM = SFM_Cal(spectrum, min(200, L_frame_glob)); + + if (L_frame_glob <= 256) + { + K = 0.4f; + K2 = 0.1f; + } + else if (L_frame_glob == 320 || L_frame_glob == 512) + { + K = 0.4f; + K2 = 0.1f; + } + else /*FrameSize_Core == 640*/ + { + K = 0.35f; + K2 = 0.04f; + } + + + if (SFM < K) + { + st->Tonal_SideInfo = 1; + } + else + { + st->Tonal_SideInfo = 0; + } + + if (tcx_cfg->SFM2 < K2) + { + st->Tonal_SideInfo = 1; + } + } + + /* Save pre-shaped spectrum*/ + mvr2r(spectrum, x_orig, L_spec); + + /*-----------------------------------------------------------* + * Bandwidth Limitation * + *-----------------------------------------------------------*/ + + noiseFillingSize = L_spec; + if (st->igf) + { + noiseFillingSize = (&st->hIGFEnc)->infoStartLine; + } + else + { + (&st->hIGFEnc)->infoStopLine = noiseFillingSize; + } + + for (i=(&st->hIGFEnc)->infoStopLine; i < max(L_frame, L_frameTCX); i++) + { + spectrum[i] = 0.0f; + } + + /*-----------------------------------------------------------* + * Quantization * + *-----------------------------------------------------------*/ + + if (!st->tcx_lpc_shaped_ari) + { + /* context based arithmetic coder */ + + /* Fast estimation of the scalar quantizer step size */ + if (tcx_cfg->ctx_hm && (st->last_core != 0) ) + { + + LtpPitchLag = ((!tcxonly) && (st->tcxltp_pitch_int < st->L_frame) + ? ((2 * st->L_frame * st->pit_res_max) << kLtpHmFractionalResolution) / (st->tcxltp_pitch_int * st->pit_res_max + st->tcxltp_pitch_fr): -1); + + ++ctxHmBits; /* ContextHM flag */ + --sqTargetBits; /* ContextHM flag */ + + OriginalSpectrum = spectrum; + + PeriodicityIndex = SearchPeriodicityIndex( OriginalSpectrum, NULL, L_spec, sqTargetBits, LtpPitchLag, + st->tcxltp ? st->tcxltp_gain : -1.0f, &RelativeScore ); + + ConfigureContextHm( L_spec, sqTargetBits, PeriodicityIndex, LtpPitchLag, hm_cfg ); + + NumIndexBits = CountIndexBits( L_spec >= 256, PeriodicityIndex ); + + /* Quantize original spectrum */ + sqGain = SQ_gain( OriginalSpectrum, (int)(LPDmem->tcx_target_bits_fac * (float)sqTargetBits), L_spec ); + + tcx_scalar_quantization( OriginalSpectrum, sqQ, L_spec, sqGain, tcx_cfg->sq_rounding, st->memQuantZeros, tcxonly ); + + /* Estimate original bitrate */ + stop = 0; + sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC( sqQ, L_spec, &lastnz, &nEncoded, sqTargetBits, &stop, NULL ); + + /* Estimate context mapped bitrate */ + stopCtxHm = 0; + + /* Context Mapping */ + sqBitsCtxHm = ACcontextMapping_encode2_estimate_no_mem_s17_LC( sqQ, L_spec, &lastnzCtxHm, &nEncodedCtxHm, + sqTargetBits - NumIndexBits, &stopCtxHm, hm_cfg ); + + /* Decide whether or not to use context mapping */ + + Selector = max(stop, sqBits) - (max(stopCtxHm, sqBitsCtxHm) + NumIndexBits); + + if (Selector > 2 || (abs(Selector) <= 2 && kCtxHmOlRSThr < RelativeScore)) + { + /* CtxHm is likely better */ + sqTargetBits -= NumIndexBits; + ctxHmBits += NumIndexBits; + prm_hm[0] = 1; + prm_hm[1] = PeriodicityIndex; + *prm_lastnz = lastnzCtxHm; + sqBits_noStop = sqBits = sqBitsCtxHm; + nEncoded = nEncodedCtxHm; + stop = stopCtxHm; + } + else + { + /* Original is better or not much difference */ + prm_hm[0] = 0; + prm_hm[1] = PeriodicityIndex; + *prm_lastnz = lastnz; + PeriodicityIndex = -1; + + sqBits_noStop = sqBits; + } + + if (stop != 0) + { + sqBits = stop; + } + } + else + { + /* no context hm*/ + PeriodicityIndex = -1; + + sqGain = SQ_gain(spectrum, (int)(LPDmem->tcx_target_bits_fac * (float)sqTargetBits), L_spec); + + /* Quantize spectrum */ + tcx_scalar_quantization( spectrum, sqQ, L_spec, sqGain, tcx_cfg->sq_rounding, st->memQuantZeros, tcxonly ); + + /* Estimate bitrate */ + stop = 0; + sqBits_noStop = sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC( sqQ, L_spec, prm_lastnz, &nEncoded, sqTargetBits, &stop, NULL); + + if(stop!=0) + { + sqBits=stop; + } + } /* end of if (ctx_hm) */ + + /* Adjust correction factor */ + if ((L_spec & (L_spec - 1)) == 0) + { + /* power-of-2 */ + LPDmem->tcx_target_bits_fac *= (float)sqTargetBits / (float)(sqBits + 1); + } + else + { + LPDmem->tcx_target_bits_fac *= (float)sqTargetBits / (float)sqBits; + } + + if (LPDmem->tcx_target_bits_fac>1.25) + { + LPDmem->tcx_target_bits_fac = 1.25; + } + if (LPDmem->tcx_target_bits_fac<0.75) + { + LPDmem->tcx_target_bits_fac = 0.75; + } + + /* Refine quantizer step size with a rate-control-loop (optional) */ + sqBits = tcx_scalar_quantization_rateloop( spectrum, sqQ, L_spec, &sqGain, tcx_cfg->sq_rounding, st->memQuantZeros, + prm_lastnz, /* lastnz */ sqTargetBits, &nEncoded, &stop, sqBits_noStop, sqBits, tcx_cfg->tcxRateLoopOpt, + tcxonly, PeriodicityIndex >= 0 ? hm_cfg : NULL ); + + if (ctxHmBits > 0) + { + /* Mapping tool is enabled */ + /* Truncate spectrum */ + for (i=nEncoded; i= 0) + { + /* Mapping is used */ + /* Estimate non-mapped bitrate */ + stopCtxHm = 1; + + sqBitsCtxHm = ACcontextMapping_encode2_estimate_no_mem_s17_LC(sqQ, L_spec, &lastnz, &nEncodedCtxHm, sqTargetBits, &stopCtxHm, NULL); + + /* Decide whether or not to revert mapping */ + Selector = sqBits - (sqBitsCtxHm + NumIndexBits); + + if (stopCtxHm == 0 && Selector > 0) + { + /* Non-mapped is better */ + sqTargetBits += NumIndexBits; + ctxHmBits -= NumIndexBits; + prm_hm[0] = 0; + *prm_lastnz = lastnz; + PeriodicityIndex = -1; + sqBits_noStop = sqBits = sqBitsCtxHm; + nEncoded = nEncodedCtxHm; + stop = stopCtxHm; + } + } + else + { + /* Mapping is not used */ + /* Estimate mapped bitrate */ + stopCtxHm = 1; + + sqBitsCtxHm = ACcontextMapping_encode2_estimate_no_mem_s17_LC( sqQ, L_spec, &lastnzCtxHm, &nEncodedCtxHm, + sqTargetBits - NumIndexBits, &stopCtxHm, hm_cfg ); + + /* Decide whether or not to use mapping */ + Selector = sqBits - (sqBitsCtxHm + NumIndexBits); + + if (stopCtxHm == 0 && Selector > 0) + { + /* Mapped is better */ + sqTargetBits -= NumIndexBits; + ctxHmBits += NumIndexBits; + prm_hm[0] = 1; + *prm_lastnz = lastnzCtxHm; + PeriodicityIndex = prm_hm[1]; + sqBits_noStop = sqBits = sqBitsCtxHm; + nEncoded = nEncodedCtxHm; + stop = stopCtxHm; + } + } + } + + /* Limit low sqGain for avoiding saturation of the gain quantizer*/ + if(sqGain < sqrt((float)NORM_MDCT_FACTOR / (float)L_spec)) + { + sqGain = (float)sqrt((float)NORM_MDCT_FACTOR / (float)L_spec); + + tcx_scalar_quantization( spectrum, sqQ, L_spec, sqGain, tcx_cfg->sq_rounding, st->memQuantZeros, tcxonly ); + + stop=1; + + sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC( sqQ, L_spec, prm_lastnz, &nEncoded, sqTargetBits, &stop, PeriodicityIndex >= 0 ? hm_cfg : NULL); + } + + /* Truncate spectrum (for CBR) */ + if ( stop ) + { + for (i=nEncoded; iindexBuffer; + + LtpPitchLag = ((st->tcxltp_pitch_int < st->L_frame) + ? ((2 * st->L_frame * st->pit_res_max) << kLtpHmFractionalResolution) / (st->tcxltp_pitch_int * st->pit_res_max + st->tcxltp_pitch_fr): -1); + + tcx_arith_encode_envelope( spectrum, signs, L_frame, L_spec, st, Aqind, sqTargetBits, sqQ, st->last_core != ACELP_CORE, + prm_hm, /* HM parameter area */ LtpPitchLag, &sqBits, &signaling_bits ,(st->bwidth > WB)? 1: 0 ); + + sqTargetBits -= signaling_bits; + *prm_target = sqTargetBits; + + /* Noise filling seed */ + for (i=0; itcx_lpc_shaped_ari, gainlpc, L_frame, xn_buf /* LF deemphasis factors */ ); + } + + gain_tcx_opt = get_gain(x_orig, spectrum, L_spec, &ener); + + if (gain_tcx_opt <= 0.0f) + { + gain_tcx_opt = sqGain; + } + gain_tcx = gain_tcx_opt; + + /*-----------------------------------------------------------* + * Quantize TCX gain * + *-----------------------------------------------------------*/ + + /* gain quantization here in case of VBR unvoiced coding; fixes problems of uninitialized global gain values */ + if (st->total_brate >= ACELP_13k20 && !st->rf_mode) + { + QuantizeGain(L_spec, &gain_tcx, &prm[0]); + } + + /*-----------------------------------------------------------* + * Residual Quantization * + *-----------------------------------------------------------*/ + + if (tcx_cfg->resq) + { + resQTargetBits = sqTargetBits-sqBits; + + if (st->tcx_lpc_shaped_ari) + { + /* envelope based arithmetic coder */ + int *prm_resq; + + prm_resq = sqQ + sqTargetBits - resQTargetBits; + + resQBits = tcx_ari_res_Q_spec( x_orig, signs, spectrum, L_spec, gain_tcx, prm_resq, resQTargetBits, + resQBits, tcx_cfg->sq_rounding, xn_buf /* LF deemphasis factors */ ); + + /* Transmit zeros when there bits remain after RESQ */ + for (i=resQBits; isq_rounding, tcxonly ? NULL : xn_buf /* LF deemphasis factors */ ); + } + + } + + /*-----------------------------------------------------------* + * ALFE tcx only bitrates * + *-----------------------------------------------------------*/ + + if (st->tcxonly) + { + if (st->tcxltp && (st->tcxltp_gain > 0.0f) && !fUseTns) + { + PsychAdaptLowFreqDeemph( spectrum, gainlpc, NULL ); + } + } + + /*-----------------------------------------------------------* + * TCX SNR for Analysis purposes * + *-----------------------------------------------------------*/ + + + + + maxNfCalcBw = min(noiseFillingSize, (int)(st->measuredBwRatio * (float)L_frame + 0.5f)); + + /*-----------------------------------------------------------* + * Estimate and quantize noise factor * + *-----------------------------------------------------------*/ + + if (st->total_brate >= HQ_96k) + { + fac_ns = 0.0f; + prm[1] = 0; + } + else + { + i = L_frame / ((st->total_brate >= ACELP_13k20 && !st->rf_mode) ? 6 : 8); /* noise filling start bin*/ + + if (tcxonly) + { + noiseTransWidth = HOLE_SIZE_FROM_LTP(max(st->tcxltp_gain,(tcx_cfg->ctx_hm && st->last_core != 0) ? 0.3125f*prm_hm[0] : 0)); + + if (L_frame == st->L_frame >> 1) + { + noiseTransWidth = 3; /* minimum transition for noise filling in TCX-10 */ + } + } + + tcx_noise_factor( x_orig, spectrum, i, maxNfCalcBw, noiseTransWidth, L_frame, + gain_tcx, st->noiseTiltFactor, &fac_ns, &prm[NOISE_FILL_RANGES] ); + + /* hysteresis for very tonal passages (more stationary noise filling level) */ + + if (prm[1] == 1) + { + st->noiseLevelMemory = 1 + abs(st->noiseLevelMemory); /* update counter */ + } + else + { + if ((prm[1] == 2) && (abs(st->noiseLevelMemory) > 5)) + { + prm[1] = 1; /* reduce noise filling level by one step */ + fac_ns = 0.75f / (1<noiseLevelMemory = (st->noiseLevelMemory < 0) ? 5 : -1 - st->noiseLevelMemory; + } + else + { + st->noiseLevelMemory = 0; /* reset memory since level is too different */ + } + } + } /* bitrate */ + + + /*-----------------------------------------------------------* + * Internal TCX decoder * + *-----------------------------------------------------------*/ + + /*-----------------------------------------------------------* + * Noise Filling. * + *-----------------------------------------------------------*/ + + /* Replication of ACELP formant enhancement for low rates */ + if ( st->total_brate < ACELP_13k20 || st->rf_mode ) + { + tcxFormantEnhancement(xn_buf, gainlpc, spectrum, L_frame); + } + + if (fac_ns > 0.0f) + { + i = tcxGetNoiseFillingTilt( A, L_frame, (st->total_brate >= ACELP_13k20 && !st->rf_mode), &st->noiseTiltFactor); + + tcx_noise_filling( spectrum, nf_seed, i, noiseFillingSize, noiseTransWidth, L_frame, st->noiseTiltFactor, fac_ns, NULL ); + } + + if (st->total_brate < ACELP_13k20 || st->rf_mode) + { + /* partially recompute global gain (energy part), taking noise filling and formant enhancement into account */ + gain_tcx_opt = 1e-6f; + for (i = 0; i < L_spec; i++) + { + gain_tcx_opt += spectrum[i] * spectrum[i]; + } + gain_tcx *= (float)sqrt(ener / gain_tcx_opt); + QuantizeGain(L_spec, &gain_tcx, &prm[0]); + } + + /*end of noise filling*/ + + /*-----------------------------------------------------------* + * Noise shaping in frequency domain (1/Wz) * + *-----------------------------------------------------------*/ + + /* LPC gains already available */ + mdct_noiseShaping( spectrum, L_frame, gainlpc ); + + /*-----------------------------------------------------------* + * Apply gain * + *-----------------------------------------------------------*/ + + if( st->tcx_cfg.coder_type == INACTIVE ) + { + + gain_tcx *= tcx_cfg->na_scale; + } + + v_multc( spectrum, gain_tcx, spectrum, L_spec); + + stop = tcx_cfg->tcx_last_overlap_mode; /* backup last TCX overlap mode */ + + + if ((L_frame == st->L_frame >> 1) && tcxonly) + { + int L = L_frame; + + if ((tcx_cfg->fIsTNSAllowed && fUseTns != 0) || (L_spec > L_frame)) + { + L = L_spec; + } + + tcxInvertWindowGrouping( tcx_cfg, xn_buf, spectrum, L, fUseTns, st->last_core, stop, frame_cnt, 0); + } + + /*-----------------------------------------------------------* + * Temporal Noise Shaping Synthesis * + *-----------------------------------------------------------*/ + + if (tcx_cfg->fIsTNSAllowed) + { + SetTnsConfig(tcx_cfg, L_frame_glob == st->L_frame, (st->last_core == 0) && (frame_cnt == 0)); + + /* Apply TNS to get the reconstructed signal */ + if (fUseTns != 0) + { + ApplyTnsFilter(tcx_cfg->pCurrentTnsConfig, pTnsData, spectrum, 0); + + if ((L_frame == st->L_frame >> 1) && (tcxonly)) + { + if ((tcx_cfg->tcx_last_overlap_mode != FULL_OVERLAP) || + ((tcx_cfg->tcx_curr_overlap_mode == FULL_OVERLAP) && (frame_cnt == 0) && (stop == 0)) + ) + { + const int L_win = L_spec >> 1; + + /* undo rearrangement of LF sub-window lines for TNS synthesis filter */ + if (L_frame > L_spec) + { + assert(0); + } + else + { + mvr2r(spectrum+8, xn_buf, L_win); + mvr2r(xn_buf, spectrum+L_win, 8); + mvr2r(xn_buf+8, spectrum+8, L_win-8); + } + } + } + } + } + + /*-----------------------------------------------------------* + * Compute inverse MDCT of spectrum[]. * + *-----------------------------------------------------------*/ + + if ((L_frame == st->L_frame >> 1) && (tcxonly)) + { + if (tcx_cfg->tcx_last_overlap_mode != FULL_OVERLAP) + { + /* minimum or half overlap, two transforms, grouping into one window */ + float win[(L_FRAME_PLUS+L_MDCT_OVLP_MAX)/2]; + const int L_win = L_frame >> 1; + const int L_spec_TCX5 = max(L_frame, L_spec) >> 1; + const int L_ola = (tcx_cfg->tcx_last_overlap_mode == MIN_OVERLAP) ? tcx_cfg->tcx_mdct_window_min_length : tcx_cfg->tcx_mdct_window_half_length; + int w; + + set_f( win, 0, (L_FRAME_PLUS+L_MDCT_OVLP_MAX)/2 ); + set_zero(xn_buf, tcx_offset+(L_ola>>1)); /* zero left end of buffer */ + + for (w = 0; w < 2; w++) + { + if (tcx_cfg->tcx_last_overlap_mode == MIN_OVERLAP) + { + TCX_MDCT_Inverse(spectrum+w*L_spec_TCX5, win, L_ola, L_win-L_ola, L_ola); + } + else + { + TCX_MDCT_Inverse(spectrum+w*L_spec_TCX5, win, L_ola, L_win-L_ola, L_ola); + } + + 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, w==0 && st->last_core==0, + (w > 0) || (w == 0 && stop == 2) ? MIN_OVERLAP : tcx_cfg->tcx_last_overlap_mode, LPDmem->acelp_zir, + st->LPDmem.Txnq, NULL, Aq_old, tcx_cfg->tcx_mdct_window_trans, L_win, + tcx_offset<0?-tcx_offset: 0, + (w > 0) ? 1 : st->last_core, 0, 0 ); + + if (w > 0) + { + tcx_windowing_synthesis_past_frame( xn_buf+tcx_offset-(L_ola>>1)+w*L_win, 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 */ + v_add(win, xn_buf+tcx_offset-(L_ola>>1)+w*L_win, xn_buf+tcx_offset-(L_ola>>1)+w*L_win, L_ola); + + /* copy new sub-window region not overlapping with previous window */ + mvr2r(win+L_ola, xn_buf+tcx_offset+(L_ola>>1)+w*L_win, L_win); + } + + /* To assure that no garbage values are copied to LPDmem->Txnq */ + set_zero(xn_buf+L_frame+tcx_offset+(L_ola>>1), overlap-tcx_offset-(L_ola>>1)); + } + else if ((frame_cnt == 0) && (tcx_cfg->tcx_curr_overlap_mode == FULL_OVERLAP)) + { + /* special overlap attempt, two transforms, grouping into one window */ + float win[(L_FRAME_PLUS+L_MDCT_OVLP_MAX)/2]; + const int L_win = L_frame >> 1; + const int L_spec_TCX5 = max(L_frame, L_spec) >> 1; + const int L_ola = tcx_cfg->tcx_mdct_window_min_length; + int w; + + set_f( 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, win+L_win, 0, L_win-(L_ola>>1), L_ola); + + /* copy new sub-window region not overlapping with previous window */ + mvr2r(win+L_win, xn_buf+(overlap>>1), L_win+(L_ola>>1)); + + /* 2nd TCX-5 window, regular MDCT with minimum overlap on both sides */ + TCX_MDCT_Inverse(spectrum+L_spec_TCX5, win, L_ola, L_win-L_ola, L_ola); + + 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, tcx_offset<0?-tcx_offset: 0, + 1, /* not st->last_core */ 0 ,0 ); + + tcx_windowing_synthesis_past_frame( xn_buf+(overlap>>1)+L_win-(L_ola>>1), 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 */ + v_add(win, xn_buf+(overlap>>1)+L_win-(L_ola>>1), xn_buf+(overlap>>1)+L_win-(L_ola>>1), L_ola); + + /* copy new sub-window region not overlapping with previous window */ + mvr2r(win+L_ola, xn_buf+(overlap>>1)+L_win+(L_ola>>1), L_win); + + /* extra folding-out on left side of win, for perfect reconstruction */ + for (w = (overlap>>1); w < overlap; w++) + { + xn_buf[overlap-1-w] = -1.0f * xn_buf[w]; + } + + tcx_windowing_synthesis_current_frame( xn_buf, 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 == ACELP_CORE, 0, /* left_mode */ LPDmem->acelp_zir, st->LPDmem.Txnq, NULL, + Aq_old, tcx_cfg->tcx_mdct_window_trans, L_win, tcx_offset<0?-tcx_offset: 0, + st->last_core, 0, 0 ); + } + else + { + /* default, i.e. maximum overlap, single transform, no grouping */ + TCX_MDCT_Inverse(spectrum, xn_buf, overlap, L_frame-overlap, overlap); + + tcx_windowing_synthesis_current_frame( xn_buf, 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 == ACELP_CORE, (frame_cnt > 0) && (stop == 0) && (st->last_core!=0) ? 2 : stop, LPDmem->acelp_zir, + st->LPDmem.Txnq, NULL, Aq_old, tcx_cfg->tcx_mdct_window_trans, L_frame_glob >> 1, + tcx_offset<0?-tcx_offset: 0, + st->last_core, 0, 0 ); + + } /* tcx_last_overlap_mode != FULL_OVERLAP */ + } + else + { + /* frame is TCX-20 or not TCX-only */ + + if (st->tcx_cfg.tcx_last_overlap_mode != TRANSITION_OVERLAP) + { + float tmp[L_FRAME_PLUS]; + + edct(spectrum, xn_buf+overlap/2+nz, L_frame); + v_multc( xn_buf+overlap/2+nz, (float)sqrt((float)L_frame / NORM_MDCT_FACTOR), tmp, L_frame); + + window_ola( tmp, xn_buf, st->old_out, L_frame, tcx_cfg->tcx_last_overlap_mode, tcx_cfg->tcx_curr_overlap_mode, 0, 0, NULL ); + aldo = 1; + } + else + { + TCX_MDCT_Inverse(spectrum, xn_buf, overlap, L_frame-overlap, overlap); + + /*-----------------------------------------------------------* + * Windowing, overlap and add * + *-----------------------------------------------------------*/ + + /* Window current frame */ + tcx_windowing_synthesis_current_frame( xn_buf, 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 == 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, L_frame_glob >> 1, tcx_offset<0?-tcx_offset: 0, + st->last_core, 0, 0 ); + } + } /* TCX-20/TCX-10 and TCX-only */ + + /* Window and overlap-add past frame if past frame is TCX */ + if ((st->last_core > 0) && (((L_frameTCX == st->L_frameTCX >> 1) && (st->tcxonly)) || (st->tcx_cfg.tcx_last_overlap_mode == TRANSITION_OVERLAP)) ) + { + if (tcx_cfg->last_aldo) + { + for (i=0; i < overlap - tcx_cfg->tcx_mdct_window_min_length; i++) + { + xn_buf[i] += st->old_out[i+nz]; + } + /* fade truncated ALDO window */ + for ( ; i < overlap; i++) + { + xn_buf[i] += st->old_out[i+nz] * tcx_cfg->tcx_mdct_window_minimum[overlap-1-i]; + } + } + else + { + if ((frame_cnt > 0) && (stop == 0) && (tcx_cfg->tcx_curr_overlap_mode == FULL_OVERLAP)&& (st->last_core!=0)) + { + stop = 2; /* use minimum overlap between the two TCX-10 windows */ + } + + 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, + (stop == 0 || tcx_cfg->tcx_last_overlap_mode == MIN_OVERLAP) ? tcx_cfg->tcx_last_overlap_mode : stop ); + + for (i=0; iTxnq[i]; + } + } + } + + if(!aldo && (((L_frameTCX == st->L_frameTCX >> 1)&& frame_cnt > 0) || L_frameTCX != (st->L_frameTCX >> 1))) + { + /*Compute windowed synthesis in case of switching to ALDO windows in next frame*/ + mvr2r(xn_buf+L_frame-nz, st->old_out, nz+overlap); + set_zero(st->old_out+nz+overlap, nz); + tcx_windowing_synthesis_past_frame( st->old_out+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(tcx_cfg->tcx_curr_overlap_mode==FULL_OVERLAP) + { + for (i=0; iold_out[nz+overlap+i]=xn_buf[L_frame-1-i]*tcx_cfg->tcx_aldo_window_1_trunc[-1-i]; + } + tcx_cfg->tcx_curr_overlap_mode=ALDO_WINDOW; + } + } + tcx_cfg->last_aldo=aldo; + + /* Update Txnq */ + if (!tcx_cfg->last_aldo) + { + mvr2r(xn_buf+L_frame, LPDmem->Txnq, overlap); + } + + /* Output */ + mvr2r( xn_buf+(overlap>>1)-tcx_offset, synth, L_frame_glob ); + + /* Update L_frame_past */ + st->L_frame_past = L_frame; + + return; +} + + +/*-------------------------------------------------------------------* +* coder_tcx() +* +* +*-------------------------------------------------------------------*/ + +void coder_tcx( + int n, + TCX_config *tcx_cfg, /*input: configuration of TCX*/ + float A[], /* input: quantized coefficients NxAz_q[M+1] */ + Word16 Aqind[], /* input: frame-independent quantized coefficients (M+1) */ + float synth[], + int L_frame_glob, /* input: frame length */ + int L_frameTCX_glob, + int L_spec, + int nb_bits, /*input: bit budget*/ + int tcxonly, /*input: only TCX flag*/ + float spectrum[], /* i/o: MDCT spectrum */ + LPD_state *LPDmem, /*i/o: memories*/ + int prm[], /* output: tcx parameters */ + Encoder_State *st, + CONTEXT_HM_CONFIG *hm_cfg +) +{ + int L_frame; + int left_overlap=-1, right_overlap=-1; + int tnsSize = 0; /* number of tns parameters put into prm */ + int tnsBits = 0; /* number of tns bits in the frame */ + int ltpBits = 0; + float gainlpc[FDNS_NPTS]; + float buf[N_MAX+L_MDCT_OVLP_MAX]; + float winMDST[N_MAX+L_MDCT_OVLP_MAX]; + float * win; + float * powerSpec; + + powerSpec = win = buf; /* Share memory for windowed TD signal and for the power spectrum */ + + L_frame = L_frameTCX_glob; + + /*-----------------------------------------------------------* + * Windowing * + *-----------------------------------------------------------*/ + if (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 for xn_buf[]. * + *-----------------------------------------------------------*/ + + TCX_MDCT( win, spectrum, left_overlap, L_frame-(left_overlap+right_overlap)/2, right_overlap ); + + } + else + { + wtda( st->new_speech_TCX, win, NULL, tcx_cfg->tcx_last_overlap_mode, tcx_cfg->tcx_curr_overlap_mode, L_frame); + + WindowSignal( tcx_cfg, tcx_cfg->tcx_offsetFB, tcx_cfg->tcx_last_overlap_mode == ALDO_WINDOW ? FULL_OVERLAP : tcx_cfg->tcx_last_overlap_mode, + tcx_cfg->tcx_curr_overlap_mode == ALDO_WINDOW ? FULL_OVERLAP : tcx_cfg->tcx_curr_overlap_mode, + &left_overlap, &right_overlap, st->speech_TCX, &L_frame, winMDST, 1 ); + + + edct( win, spectrum, L_frame ); + + v_multc(spectrum, (float)sqrt((float)NORM_MDCT_FACTOR / L_frame), spectrum, L_frame); + } + + /*-----------------------------------------------------------* + * Attenuate upper end of NB spectrum, * + * to simulate ACELP behavior * + *-----------------------------------------------------------*/ + + if( st->narrowBand ) + { + attenuateNbSpectrum(L_frame, spectrum); + } + + /*-----------------------------------------------------------* + * Compute noise-measure flags for spectrum filling * + * and quantization (0: tonal, 1: noise-like). * + * Detect low pass if present. * + *-----------------------------------------------------------*/ + + AnalyzePowerSpectrum( st, L_frame*st->L_frame/st->L_frameTCX, L_frame, left_overlap, right_overlap, spectrum, + (st->tcx_cfg.tcx_last_overlap_mode == TRANSITION_OVERLAP) ? win : winMDST, powerSpec ); + + if (tcx_cfg->fIsTNSAllowed) + { + SetTnsConfig(tcx_cfg, L_frame_glob == st->L_frame, st->last_core == 0); + TNSAnalysis(tcx_cfg, L_frame, L_spec, TCX_20, st->last_core == 0, spectrum, st->tnsData, st->fUseTns, &(&st->hIGFEnc)->tns_predictionGain ); + + } + else + { + st->fUseTns[0] = st->fUseTns[1] = 0; + } + + if(st->igf) + { + ProcessIGF(&st->hIGFEnc, st, spectrum, powerSpec, 1, st->fUseTns[0], (st->last_core == ACELP_CORE), 0); + } + + ShapeSpectrum( tcx_cfg, A, gainlpc, L_frame_glob, L_spec, spectrum, st->fUseTns[0], st ); + + if(st->igf) + { + nb_bits -= st->hIGFEnc.infoTotalBitsPerFrameWritten; + } + + if (tcx_cfg->fIsTNSAllowed) + { + EncodeTnsData(tcx_cfg->pCurrentTnsConfig, st->tnsData, prm+1+NOISE_FILL_RANGES+LTPSIZE, &tnsSize, &tnsBits); + } + + QuantizeSpectrum( tcx_cfg, A, Aqind, gainlpc, synth, L_frame_glob, L_frameTCX_glob, L_spec, + nb_bits-tnsBits-ltpBits, tcxonly, spectrum,st->tnsData, st->fUseTns[0], + tnsSize, LPDmem, prm, n, st, hm_cfg ); + + return; +} + +/*-------------------------------------------------------------------* +* coder_tcx_post() +* +* +*-------------------------------------------------------------------*/ + +void coder_tcx_post( + Encoder_State *st, + LPD_state *LPDmem, + TCX_config *tcx_cfg, + float *synth, + float *A, + const float *Ai, + float *wsig ) +{ + float xn_buf[L_FRAME_MAX]; + + /* TCX output */ + mvr2r( synth, xn_buf, st->L_frame ); + + + /*-----------------------------------------------------------* + * Memory update * + *-----------------------------------------------------------*/ + + /* Update LPDmem (Txnq,syn,syn_pe,old_exc,wsyn,Ai,Aq) */ + tcx_encoder_memory_update( wsig, xn_buf, st->L_frame, Ai, A, tcx_cfg->preemph_fac, LPDmem, st, M, synth ); + + return; +} diff --git a/lib_enc/cod_uv.c b/lib_enc/cod_uv.c new file mode 100644 index 000000000..f85a63b86 --- /dev/null +++ b/lib_enc/cod_uv.c @@ -0,0 +1,64 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "prot.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 float h[], /* i : weighted LP filter impulse response */ + float code[], /* o : gaussian excitation */ + float y2[], /* i : zero-memory filtered code. excitation */ + float y11[], /* o : zero-memory filtered gauss. excitation */ + float *gain, /* o : excitation gain */ + float g_corr[], /* i/o : correlation structure for gain coding */ + float gain_pit, /* i : unquantized gain of code */ + float tilt_code, /* i : tilt of code */ + const float *Aq, /* i : quantized LPCs */ + float formant_enh_num, /* i : formant enhancement factor */ + short *seed_acelp /*i/o : random seed */ +) +{ + short i; + assert(gain_pit==0.f); + (void)gain_pit; + + /*-----------------------------------------------------------------* + * 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 +#include "wmc_auto.h" +#include +#include +#include "prot.h" +#include "rom_enc.h" + + + +static int comvad_hangover( + float lt_snr_org, /*(i)original long time SNR*/ + float snr, /*(i) frequency domain SNR */ + float lf_snr, /*(i) long time frequency domain SNR calculated by l_speech_snr and l_silence_snr*/ + float snr_flux, /*(i) average tsnr*/ + int bw_index, /*(i) band width index*/ + int vad_flag, + int pre_res_hang_num, /*(i) residual number of previous hangover */ + int continuous_speech_num2, /*(i) number of continuous speech frames*/ + int noisy_type /*(i) noisy type*/ +); + + + +int comvad_decision(T_CldfbVadState *st, + float snr, /*(i) frequency domain SNR */ + float tsnr, /*(i) time domain SNR */ + float snr_flux, /*(i) average tsnr of several frames*/ + float lt_snr, /*(i)long time SNR calculated by fg_energy and bg_energy*/ + float lt_snr_org, /*(i)original long time SNR*/ + float lf_snr, /*(i) long time frequency domain + SNR calculated by l_speech_snr and l_silence_snr*/ + float frame_energy, /*(i) current frame energy */ + int music_backgound_f, /*(i) background music flag*/ + short *cldfb_addition, + short vada_flag + ) +{ + int speech_flag = st->speech_flag; + int fg_energy_count = st->fg_energy_count; + int bg_energy_count = st->bg_energy_count; + float fg_energy = st->fg_energy; + float bg_energy = st->bg_energy; + int l_speech_snr_count=st->l_speech_snr_count; + int vad_flag; + float snr_thresh = 0.2f; + float *ltd_stable_rate = st->ltd_stable_rate; + float *sp_center = st->sp_center; + int frameloop = st->frameloop; + int bw_index = st->bw_index; + int noisy_type = UNKNOWN_NOISE; + short vadb_flag = 0; + + /* + * ls_snr_org + * -------NB---------------WB----------------SWB--------- + * l16 [13.5 17] [13.5 16] [13.1 15.2] + * 126 [12 14] [10.7 12.7] [10.3 12.1] + * l36 [9.5 12] [8.5 10.5] [7.8 9.2] + * 15dB [3.5 4.5] + * 20dB [4.5 5.5] + */ + + /* + * lt_snr_org + * -------NB---------------WB----------------SWB--------- + * l16 [-- --] [-- --] [-- --] + * 126 [-- --] [-- -] [-- --] + * l36 [-- --] [-- --] [- --] + * 15dB [1.2 1.9] + * 20dB [2.1 2.7] [1.8 2.3] + */ + + if(st->lf_snr_smooth > LS_MIN_SELENCE_SNR[bw_index - CLDFBVAD_NB_ID] && lt_snr_org > LT_MIN_SILENCE_SNR[bw_index - CLDFBVAD_NB_ID]) + + { + noisy_type = SILENCE; + } + snr_thresh = construct_snr_thresh( sp_center, snr_flux, lt_snr, lf_snr, + st->continuous_speech_num, st->continuous_noise_num, st->fg_energy_est_start, bw_index); + + if(snr>(snr_thresh)) + { + vad_flag =1; + } + else + { + vad_flag =0; + } + if (bw_index == CLDFBVAD_WB_ID) + { + if (tsnr > 2.8) + { + vad_flag = 1; + } + } + else + { + if (tsnr > 2.6) + { + vad_flag = 1; + } + } + + + if(frameloop>25) + { + if(vad_flag == 1&& st->fg_energy_est_start==1) + { + if(fg_energy_count==512) + { + fg_energy = fg_energy*0.75f; + fg_energy_count = 384; + } + if((frame_energy*bg_energy_count)>6*bg_energy) + { + fg_energy = fg_energy + frame_energy; + fg_energy_count = fg_energy_count + 1; + } + } + } + if(music_backgound_f) + { + vad_flag =1; + } + if(vad_flag==1) + { + + if(snr > st->l_silence_snr/st->l_silence_snr_count + 1.5) + { + if(l_speech_snr_count==512) + { + st->l_speech_snr = st->l_speech_snr*0.75f; + l_speech_snr_count = 384; + + st->l_speech_snr += snr; + l_speech_snr_count++; + } + else + { + st->l_speech_snr += snr; + l_speech_snr_count++; + } + } + } + if(bw_index == CLDFBVAD_NB_ID) + { + if(snr_flux > 1.9+ lt_snr*0.28 ) + { + vad_flag = 1; + } + if((snr_flux > 1.5)&& sp_center[3]>1.6&& lt_snr_org<3.5) + { + vad_flag = 1; + } + if((snr_flux > 1.2)&& sp_center[3]>1.9&& lt_snr_org<3.5) + { + vad_flag = 1; + } + if((snr_flux > 1.00f)&& sp_center[3]>3.2&& lt_snr_org<3.5) + { + vad_flag = 1; + } + } + if(bw_index == CLDFBVAD_WB_ID) + { + if((snr_flux > 2.1+lt_snr*0.24) ) + { + vad_flag = 1; + } + if((snr_flux > 1.6)&& sp_center[3]>2.5&& lt_snr_org<3.5) + { + vad_flag = 1; + } + if((snr_flux > 1.2)&& sp_center[3]>2.8&& lt_snr_org<3.5) + { + vad_flag = 1; + } + if((snr_flux > 1.0)&& sp_center[3]>4.5&& lt_snr_org<3.5) + { + vad_flag = 1; + } + } + if(bw_index == CLDFBVAD_SWB_ID) + { + + if((snr_flux > 2.1+ lt_snr*0.32) ) + { + vad_flag = 1; + } + if((snr_flux > 1.68)&& sp_center[3]>2.76&& lt_snr_org<3.5) + { + vad_flag = 1; + } + if((snr_flux > 1.24)&& sp_center[3]>2.92&& lt_snr_org<3.5) + { + vad_flag = 1; + } + if((snr_flux > 1.10f)&& sp_center[3]>4.6&& lt_snr_org<3.5) + { + vad_flag = 1; + } + } + if(st->fg_energy_est_start==0) + { + if(ltd_stable_rate[0]>0.08 && vad_flag == 1 && frame_energy>50) + { + st->fg_energy_est_start=1; + } + } + + /************************************************************************/ + /* hangover */ + /************************************************************************/ + speech_flag = comvad_hangover(lt_snr_org, snr, lf_snr, snr_flux, bw_index, vad_flag, speech_flag, + st->continuous_speech_num2, noisy_type); + + if(vad_flag==0&& speech_flag>0) + { + speech_flag--; + vad_flag = 1; + } + + vadb_flag = vad_flag; + + if(bw_index == CLDFBVAD_SWB_ID) + { + + if(SILENCE == noisy_type && snr > 0.2 && vad_flag==0) + { + vad_flag = vada_flag; + } + else if(st->lf_snr_smooth < 10.5 || SILENCE!=noisy_type) + { + if((snr_flux > 1.8) + || (st->continuous_speech_num2 > 40 && (snr_flux > 1.6)) + || music_backgound_f == 1) + { + vad_flag = vada_flag | vadb_flag; + } + /*only use for silence*/ + else if(noisy_type == SILENCE) + { + vad_flag = vada_flag; + } + } + } + else if(bw_index == CLDFBVAD_WB_ID) + { + + if(SILENCE == noisy_type && snr > 0.2 && vad_flag==0) + { + vad_flag = vada_flag; + } + else + { + if(st->lf_snr_smooth < 10.5 || SILENCE!=noisy_type) + { + if(snr_flux > 2.2 + || (st->continuous_speech_num2 > 40 && (snr_flux > 1.6)) + || music_backgound_f == 1) + { + vad_flag = vada_flag|vadb_flag; + } + else if(SILENCE == noisy_type) + { + vad_flag = vada_flag; + } + + } + + } + + } + else + { + if(noisy_type == SILENCE ) + { + if(st->lf_snr_smooth > 12.5 && music_backgound_f == 0) + { + vad_flag = vada_flag; + } + } + else + { + if((snr_flux > 2.0) + || (st->continuous_speech_num2 > 30 && (snr_flux > 1.5)) + || music_backgound_f == 1) + { + vad_flag = vada_flag | vadb_flag; + } + } + } + if(vad_flag==0 ) + { + if(st->l_silence_snr_count==512) + { + st->l_silence_snr = st->l_silence_snr*0.75f; + st->l_silence_snr_count = 384; + + st->l_silence_snr += snr; + st->l_silence_snr_count++; + } + else if(snr<0.8) + { + st->l_silence_snr += snr; + st->l_silence_snr_count++; + } + } + if(vad_flag == 0) + { + if(bg_energy_count==512) + { + bg_energy = bg_energy*0.75f; + bg_energy_count = 384; + } + + if(tsnr<1.0) + { + bg_energy = bg_energy + frame_energy; + bg_energy_count = bg_energy_count +1; + } + } + + st->lt_snr_org = lt_snr_org; + st->speech_flag = speech_flag; + + st->fg_energy_count = fg_energy_count; + st->bg_energy_count = bg_energy_count; + st->fg_energy = fg_energy; + st->bg_energy = bg_energy; + st->l_speech_snr_count = l_speech_snr_count; + + + st->vad_flag_for_bk_update = vad_flag; + if(st->update_count < 12 && vadb_flag==1) + { + st->warm_hang_num = max(20, speech_flag); + } + + + if(vad_flag==0&& st->warm_hang_num>0) + { + st->warm_hang_num--; + vad_flag = 1; + } + + if(noisy_type == SILENCE + && bw_index != CLDFBVAD_NB_ID) + + { + *cldfb_addition = 2; + } + else + { + *cldfb_addition = 0; + + if(bw_index == CLDFBVAD_WB_ID) + { + *cldfb_addition = 3; + } + if(bw_index == CLDFBVAD_SWB_ID) + { + *cldfb_addition = 1; + } + if(st->bw_index == CLDFBVAD_NB_ID) + { + *cldfb_addition = 1; + } + } + + return vad_flag; +} + +float construct_snr_thresh(float sp_center[], /*(i) spectral center*/ + float snr_flux, /*(i) snr flux*/ + float lt_snr, /*(i) long time time domain snr*/ + float lf_snr, /*(i) long time frequency domain snr*/ + int continuous_speech_num, /*(i) number of continuous speech frames*/ + int continuous_noise_num, /*(i) number of continuous noise frames*/ + int fg_energy_est_start, /*(i) whether if estimated energy*/ + int bw_index /*(i) band width index*/ + ) +{ + float test_l_snr=0.f; + float snr_delta; + float snr_thresh; + float bw_snr; + + + snr_delta = COMVAD_INIT_SNR_DELTA[bw_index]; + bw_snr = lt_snr; + + if(bw_index == CLDFBVAD_SWB_ID) + { + + test_l_snr = lt_snr; + test_l_snr = test_l_snr*1.0f; + + if(sp_center[3]>2.80f) + { + snr_delta = snr_delta + 0.00f; + } + else if(sp_center[2]>2.6) + { + snr_delta = snr_delta + 0.03f; + } + else if(sp_center[2]>1.6) + { + snr_delta = snr_delta + 0.05f; + } + else if(sp_center[3]>1.4) + { + snr_delta = snr_delta + 0.10f; + } + else + { + snr_delta = snr_delta + 0.40f; + } + + if(continuous_speech_num > 8&& fg_energy_est_start==1) + { + snr_delta = snr_delta - 0.2f; + } + else if(continuous_noise_num > 12&&(snr_flux>0.6+lf_snr*0.1)) + { + snr_delta = snr_delta + 0.1f; + } + else if(continuous_noise_num > 24) + { + snr_delta = snr_delta + 0.2f; + } + else if((continuous_noise_num > 4)) + { + snr_delta = snr_delta + 0.1f; + } + + } + else if(bw_index == CLDFBVAD_WB_ID) + { + + test_l_snr = lt_snr; + if(sp_center[3]>2.80f) + { + snr_delta = snr_delta + 0.00f; + } + else if(sp_center[2]>2.6) + { + snr_delta = snr_delta + 0.03f; + } + else if(sp_center[2]>1.6) + { + snr_delta = snr_delta + 0.05f; + } + else if(sp_center[3]>1.4) + { + snr_delta = snr_delta + 0.10f; + } + else + { + snr_delta = snr_delta + 0.30f; + } + + if(continuous_speech_num > 8&& fg_energy_est_start==1) + { + snr_delta = snr_delta - 0.1f; + } + else if(continuous_noise_num > 12&&(snr_flux>0.6+bw_snr*0.1)) + { + snr_delta = snr_delta + 0.1f; + } + else if(continuous_noise_num > 24) + { + snr_delta = snr_delta + 0.2f; + } + else if((continuous_noise_num > 4)) + { + snr_delta = snr_delta + 0.1f; + } + } + else if(bw_index == CLDFBVAD_NB_ID) + { + + test_l_snr = lt_snr; + + if(sp_center[3]>3.0) + { + snr_delta = snr_delta + 0.00f; + } + else if(sp_center[2]>2.6) + { + snr_delta = snr_delta + 0.02f; + } + else if(sp_center[2]>1.6) + { + snr_delta = snr_delta + 0.04f; + } + else if(sp_center[2]>1.46) + { + snr_delta = snr_delta + 0.10f; + } + else + { + snr_delta = snr_delta + 0.18f; + } + + if(continuous_speech_num > 80&& fg_energy_est_start==1&&(sp_center[0]>1.4)) + { + snr_delta = snr_delta - 0.32f; + } + else if(continuous_speech_num > 8&& fg_energy_est_start==1&&(snr_flux>0.2+lf_snr*0.1)) + { + snr_delta = snr_delta - 0.1f; + } + else if(continuous_noise_num > 12&&(snr_flux>0.6+lf_snr*0.1)) + { + snr_delta = snr_delta + 0.1f; + } + else if(continuous_noise_num > 24) + { + + snr_delta = snr_delta + 0.2f; + } + } + else + { + snr_delta = 1.0f; + } + + snr_thresh = snr_delta + test_l_snr ; + + + return snr_thresh; +} + +static int comvad_hangover(float lt_snr_org, /*(i)original long time SNR*/ + float snr, /*(i) frequency domain SNR */ + float lf_snr, /*(i) long time frequency domain + SNR calculated by l_speech_snr and l_silence_snr*/ + float snr_flux, /*(i) average tsnr*/ + int bw_index, /*(i) band width index*/ + int vad_flag, + int pre_res_hang_num, /*(i) residual number of previous hangover */ + int continuous_speech_num2, /*(i) number of continuous speech frames*/ + int noisy_type /*(i) noisy type*/ + ) + +{ + int speech_flag = pre_res_hang_num; + + + if(bw_index == CLDFBVAD_SWB_ID) + { + if(vad_flag) + { + if(lt_snr_org > 3.5f) + speech_flag = 3; + else + speech_flag = 4; + if((continuous_speech_num2 < 8)&& (lt_snr_org < 4.0f)) + { + speech_flag = 8 - continuous_speech_num2; + } + else if((snr_flux > 0.8 )&&(continuous_speech_num2 > 24)) + { + if(lt_snr_org > 3.6f) + { + speech_flag = 3; + } + else if(lt_snr_org > 2.6f) + { + speech_flag = 3; + } + else if(lt_snr_org > 1.6f) + { + speech_flag = 4; + } + else + { + speech_flag = 5; + } + speech_flag = speech_flag - 1; + } + if(continuous_speech_num2 < 120) + { + if(snr>1.5) + { + speech_flag = 9; + } + else if(snr>1.0&& speech_flag<7) + { + speech_flag = 7; + } + else if(speech_flag<3) + { + speech_flag = 3; + } + if(speech_flag > 3) + { + speech_flag -= 2; + } + } + else + { + if(lt_snr_org > 3.6f) + { + speech_flag = 1; + } + else if(lt_snr_org > 3.0f) + { + speech_flag = 2; + } + else if(lt_snr_org > 2.5f) + { + speech_flag = 3; + } + else if(lt_snr_org > 2.0f) + { + speech_flag = 3; + } + else if(lt_snr_org > 1.5f) + { + speech_flag = 4; + } + else + { + speech_flag = 5; + } + } + if(noisy_type==SILENCE) + { + speech_flag = 6; + } + } + } + else if(bw_index == CLDFBVAD_WB_ID) + { + if(vad_flag) + { + if(lt_snr_org > 3.5f) + speech_flag = 1; + else + speech_flag = 2; + if((continuous_speech_num2 < 8)&& (lt_snr_org < 4.0f)) + { + speech_flag = 8 - continuous_speech_num2; + } + else if((snr_flux > 0.9 )&&(continuous_speech_num2 > 50)) + { + if(lt_snr_org > 3.6f) + { + speech_flag = 1; + } + else if(lt_snr_org > 2.6f) + { + speech_flag = 5; + } + else if(lt_snr_org > 1.6f) + { + speech_flag = 6; + } + else + { + speech_flag = 7; + } + if(speech_flag > 1) + { + speech_flag = speech_flag - 1; + } + + } + if(continuous_speech_num2 < 120) + { + if(snr>1.5) + { + speech_flag = 6; + } + else if(snr>1.0&& speech_flag<5) + { + speech_flag = 5; + } + else if(snr>0.8&& lt_snr_org < 2 && speech_flag<4) + { + speech_flag = 4; + } + else if(speech_flag<3) + { + speech_flag = 3; + } + } + else + { + if(lt_snr_org > 3.6f) + { + speech_flag = 1; + } + else if(lt_snr_org > 3.0f) + { + speech_flag = 2; + } + else if(lt_snr_org > 2.5f) + { + speech_flag = 2; + } + else if(lt_snr_org > 2.0f) + { + speech_flag = 3; + } + else + { + speech_flag = 3; + } + } + + if(noisy_type==SILENCE) + { + speech_flag = 6; + } + } + } + else + { + if(vad_flag) + { + if(lt_snr_org > 3.5f) + speech_flag = 3; + else + speech_flag = 4; + if((continuous_speech_num2 < 8)&& (lt_snr_org < 4.0f)) + { + speech_flag = 8 - continuous_speech_num2; + } + else if((snr_flux > 0.8 + lf_snr*0.1)&&(continuous_speech_num2 > 24)) + { + if(lt_snr_org > 3.6f) + { + speech_flag = 3; + } + else if(lt_snr_org > 2.6f) + { + speech_flag = 8; + } + else if(lt_snr_org > 1.2f) + { + speech_flag = 10; + } + else + { + speech_flag = 12; + } + if(speech_flag > 2) + { + speech_flag = speech_flag - 2; + } + + } + if(continuous_speech_num2 < 120) + { + if(snr>1.5) + { + speech_flag = 10; + } + else if(snr>1.0&& speech_flag<7) + { + speech_flag = 7; + } + else if(speech_flag<3&& continuous_speech_num2>12) + { + speech_flag = 3; + } + } + else + { + if(lt_snr_org > 3.6f) + { + speech_flag = 2; + } + else if(lt_snr_org > 3.0f) + { + speech_flag = 2; + } + else if(lt_snr_org > 2.5f) + { + speech_flag = 3; + } + else if(lt_snr_org > 2.0f) + { + speech_flag = 3; + } + else if(lt_snr_org > 1.5f) + { + speech_flag = 4; + } + else + { + speech_flag = 4; + } + } + if(noisy_type==SILENCE) + { + speech_flag = 2; + } + } + } + + if(vad_flag == 1) + { + if(noisy_type != SILENCE) + { + speech_flag--; + } + else + { + speech_flag = speech_flag - 3; + } + + if(speech_flag < 0) + { + speech_flag = 0; + } + } + + return speech_flag; +} diff --git a/lib_enc/cor_shif.c b/lib_enc/cor_shif.c new file mode 100644 index 000000000..001025055 --- /dev/null +++ b/lib_enc/cor_shif.c @@ -0,0 +1,37 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * Correlation_shift + * + * 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 + *-------------------------------------------------------------------*/ + +#define MAX_CORR_SHIFT 0.5f + +float correlation_shift( /* o : noise dependent voicing correction */ + const float totalNoise /* i : noise estimate over all critical bands */ +) +{ + float corr_shift; + + corr_shift = 0.0f; + if( totalNoise > 28.18225893613955f ) /* to make corr_shift > 0.0 */ + { + /* useful values range from 0 to 1 (can saturate at 1.0) */ + corr_shift = 2.4492e-4f * (float)exp( 0.1596f * totalNoise ) - 0.022f; + } + if( corr_shift > MAX_CORR_SHIFT ) + { + corr_shift = MAX_CORR_SHIFT; + } + return corr_shift; +} diff --git a/lib_enc/core_enc_2div.c b/lib_enc/core_enc_2div.c new file mode 100644 index 000000000..1219d9c17 --- /dev/null +++ b/lib_enc/core_enc_2div.c @@ -0,0 +1,229 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + + +/*-------------------------------------------------------------------* + * core_encode_twodiv() + * + * Two-div core encoder + *-------------------------------------------------------------------*/ + +void core_encode_twodiv( + const float new_samples[], /* i : new samples */ + Encoder_State *st, /* i/o : coder memory state */ + const short coder_type, /* i : coding type */ + const short pitch[3], /* i : open-loop pitch values for quantiz. */ + const float voicing[3], /* i : open-loop pitch gains */ + float Aw[NB_SUBFR16k*(M+1)] /* i : weighted A(z) unquant. for subframes*/ +) +{ + short n; + float lsp_new[M], lsp_mid[M]; + float lsf_q[M], lsp_q[M]; + float lspmid_q[M]; + float A_q[M+1]; + int param_lpc[NPRM_LPC_NEW]; + int nbits_lpc[2]; + int param_core[2*NPRM_DIV]; + int target_bits; + float gainlpc[2][FDNS_NPTS]; + int tnsSize[2]; /* number of tns parameters put into prm */ + int tnsBits[2]; /* number of tns bits in the frame */ + int ltpBits; + int bitsAvailable; + int indexBuffer[2*((N_MAX/2)+1)]; + CONTEXT_HM_CONFIG hm_cfg[2]; + short bits_param_lpc[10], no_param_lpc; + short i, T_op[3]; + + + hm_cfg[0].indexBuffer = &indexBuffer[0]; + hm_cfg[1].indexBuffer = &indexBuffer[N_MAX/2+1]; + + set_i( tnsSize, 0, 2 ); + set_i( tnsBits, 0, 2 ); + ltpBits = 0; + + for( i = 0; i < 3; i++ ) + { + T_op[i] = pitch[i]; + + /* check minimum pitch for quantization */ + if( T_op[i] < PIT_MIN_SHORTER ) + { + T_op[i] *= 2; + } + + /* convert pitch values to core sampling-rate */ + if ( st->L_frame != L_FRAME ) + { + T_op[i] = (short)(T_op[i] * (float)st->L_frame/(float)L_FRAME + 0.5f); + } + } + + + /*--------------------------------------------------------------* + * TCX20/TCX10 switching decision + *---------------------------------------------------------------*/ + + if ( st->tcxMode == TCX_10 ) + { + st->core = TCX_10_CORE; + } + else if ( st->tcxMode == TCX_20 ) + { + st->core = TCX_20_CORE; + } + + + /*--------------------------------------------------------------* + * Core Signal Analysis: MDCT, TNS, LPC analysis + *---------------------------------------------------------------*/ + + core_signal_analysis_high_bitrate( new_samples, T_op, voicing, pitch, lsp_new, lsp_mid, st, + tnsSize, tnsBits, param_core, <pBits, st->L_frame,st->L_frameTCX ); + + /*--------------------------------------------------------------* + * LPC Quantization + *---------------------------------------------------------------*/ + lpc_quantization( st, st->core, st->lpcQuantization, st->lsf_old, lsp_new, lsp_mid, lsp_q, lsf_q, + lspmid_q, st->mem_MA, st->mem_AR, st->narrowBand, coder_type, + 0, /*No acelp->no need to compute any mid-LPC*/ + param_lpc, nbits_lpc, &(st->seed_acelp), st->sr_core, st->Bin_E, st->Bin_E_old, + bits_param_lpc, &no_param_lpc ); + + /*--------------------------------------------------------------* + * Rate switching + *--------------------------------------------------------------*/ + + if( st->rate_switching_reset ) + { + mvr2r( lsp_q, st->lsp_old, M ); + mvr2r( lsf_q, st->lsf_old, M ); + } + + + + /*--------------------------------------------------------------* + * Run Two TCX10 + *---------------------------------------------------------------*/ + + if( st->core == TCX_10_CORE ) + { + const int last_ace_mode = st->last_core; + + for (n = 0; n < 2; n++) + { + if ( n == 0 ) + { + lsp2a_stab( lspmid_q, A_q, M ); + } + else + { + lsp2a_stab(lsp_q, A_q, M); + } + + /* Shape spectrum */ + ShapeSpectrum( &(st->tcx_cfg), A_q, gainlpc[n], st->L_frame/2, st->tcx_cfg.tcx_coded_lines/2, st->spectrum[n], st->fUseTns[n], st ); + + st->last_core = st->core; + } + st->last_core = last_ace_mode; + + /* Calculate target bits */ + bitsAvailable = 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 -= (st->tcx_cfg.tcx_curr_overlap_mode == HALF_OVERLAP || st->tcx_cfg.tcx_curr_overlap_mode == MIN_OVERLAP) ? 2 : 1; + bitsAvailable -= (&st->hIGFEnc)->infoTotalBitsWritten; + + st->measuredBwRatio = 1.f; + + for( n = 0; n < 2; n++ ) + { + target_bits = ((bitsAvailable + 1 - n)>>1) - tnsBits[n]; + + if( n == 0 ) + { + target_bits -= ltpBits; + } + + if(st->enablePlcWaveadjust && n) + { + target_bits -= 1; + } + + /* Run TCX10 encoder */ + QuantizeSpectrum( &(st->tcx_cfg), A_q, NULL, gainlpc[n], st->synth+n*st->L_frame/2, st->L_frame/2, st->L_frameTCX/2, st->tcx_cfg.tcx_coded_lines/2, + target_bits, st->tcxonly, st->spectrum[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 */ + if( (n > 0) || !st->tcxonly ) + { + 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 ); + } + + /*--------------------------------------------------------------* + * Run One TCX20 + *---------------------------------------------------------------*/ + + if( st->core == TCX_20_CORE ) + { + lsp2a_stab( lsp_q, A_q, M ); + + ShapeSpectrum( &(st->tcx_cfg), A_q, gainlpc[0], st->L_frame, st->tcx_cfg.tcx_coded_lines, st->spectrum_long, st->fUseTns[0], st ); + + st->measuredBwRatio = 1.f; + + /* Calculate target bits */ + target_bits = 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 -= (st->tcx_cfg.tcx_curr_overlap_mode == HALF_OVERLAP || st->tcx_cfg.tcx_curr_overlap_mode == MIN_OVERLAP) ? 2 : 1; + + target_bits -= st->hIGFEnc.infoTotalBitsPerFrameWritten; + + if( st->enablePlcWaveadjust ) + { + target_bits -= 1; + } + + QuantizeSpectrum( &(st->tcx_cfg), A_q, NULL, gainlpc[0],st->synth, st->L_frame, st->L_frameTCX,st->tcx_cfg.tcx_coded_lines, target_bits, + st->tcxonly, st->spectrum_long, st->tnsData, 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 ); + + } + + /* Update lsp/lsf memory */ + mvr2r( lsf_q, st->lsf_old, M ); + mvr2r( lsp_q, st->lsp_old, M ); + + + + /*--------------------------------------------------------------* + * Generate Bitstream + *---------------------------------------------------------------*/ + + enc_prm( coder_type, param_core, param_lpc, st, st->L_frame, hm_cfg, bits_param_lpc, no_param_lpc ); + + return; + +} diff --git a/lib_enc/core_enc_init.c b/lib_enc/core_enc_init.c new file mode 100644 index 000000000..39b05397a --- /dev/null +++ b/lib_enc/core_enc_init.c @@ -0,0 +1,721 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + + +/*-----------------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------------*/ + +static void init_tcx( Encoder_State *st, int L_frame_old ); +static void init_sig_buffers( Encoder_State *st, const int L_frame_old, const short L_subfr ); +static void init_core_sig_ana( Encoder_State *st ); +static void init_acelp( Encoder_State *st, int L_frame_old ); +static void init_modes( Encoder_State *st ); + + +/*-----------------------------------------------------------------------* + * init_coder_ace_plus() + * + * Initialization of state variables + *-----------------------------------------------------------------------*/ + +void init_coder_ace_plus( Encoder_State *st ) +{ + int L_frame_old; /*keep old frame size for switching */ + short L_subfr; + + /* Bitrate */ + st->tcxonly = getTcxonly(st->total_brate); + + /* Core Sampling Rate */ + st->sr_core = getCoreSamplerateMode2(st->total_brate, st->bwidth, st->rf_mode ); + st->fscale = sr2fscale(st->sr_core); + + /* Narrowband? */ + st->narrowBand = (st->bwidth == NB)? 1: 0; + + /* Core Framing */ + L_frame_old = st->last_L_frame; + st->L_frame = st->sr_core / 50; + st->L_frame_past = -1; + + st->L_frameTCX = st->input_Fs / 50; + + if( st->L_frame == L_FRAME16k && st->total_brate <= ACELP_32k ) + { + st->nb_subfr = NB_SUBFR16k; + } + else + { + st->nb_subfr = NB_SUBFR; + } + L_subfr = st->L_frame/st->nb_subfr; + + /* Core Lookahead */ + st->encoderLookahead_enc = NS2SA(st->sr_core, ACELP_LOOK_NS); + st->encoderLookahead_FB = NS2SA(st->input_Fs, ACELP_LOOK_NS); + + if( st->ini_frame == 0 ) + { + st->acelpFramesCount = 0; + st->prevTempFlatness = 1.0f; + } + + /* Initialize TBE */ + st->prev_coder_type = GENERIC; + set_f( st->prev_lsf_diff, 0.5f, LPC_SHB_ORDER-2 ); + st->prev_tilt_para = 0.0f; + set_zero( st->cur_sub_Aq, M+1 ); + + st->currEnergyHF = 0; + + /* Initialize LPC analysis/quantization */ + if( st->sr_core <= 16000 && st->tcxonly == 0 ) + { + st->lpcQuantization = 1; + } + else + { + st->lpcQuantization = 0; + } + + st->next_force_safety_net = 0; + if( (st->last_L_frame != st->L_frame) || (st->last_core == AMR_WB_CORE) || (st->last_core == HQ_CORE) ) + { + set_f( st->mem_MA, 0.0f, M ); + mvr2r( GEWB_Ave, st->mem_AR, M ); + } + + /* Initialize IGF */ + memset( &st->hIGFEnc, 0, sizeof(st->hIGFEnc) ); + st->hIGFEnc.infoStopFrequency = -1; + if( st->igf ) + { + IGFEncSetMode( &st->hIGFEnc, st->total_brate, st->bwidth, 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 ); + if( st->ini_frame == 0 ) + { + st->tec_tfa = 0; + } + if( st->tec_tfa == 0 ) + { + resetTecEnc( &(st->tecEnc), 0); + } + else + { + resetTecEnc( &(st->tecEnc), 1); + } + + if( st->bwidth == SWB && (st->total_brate == ACELP_16k40 || st->total_brate == ACELP_24k40) ) + { + st->tec_tfa = 1; + } + else + { + st->tec_tfa = 0; + } + + st->tec_flag = 0; + st->tfa_flag = 0; + + /* Initialize DTX */ + if( st->ini_frame == 0 ) + { + + vad_init(&st->vad_st); + } + + if( st->total_brate == ACELP_9k60 || st->total_brate == ACELP_16k40 || st->total_brate == ACELP_24k40 ) + { + st->glr = 1; + } + else + { + st->glr = 0; + } + + st->glr_reset = 0; + + /* Initialize ACELP/TCX Modes */ + init_modes( st ); + + /* Init I/O */ + + + /* Adaptive BPF */ + set_zero( st->mem_bpf, 2*L_FILT16k ); + set_zero( st->mem_error_bpf, 2*L_FILT16k ); + + if( st->total_brate >= HQ_48k ) + { + st->enablePlcWaveadjust = 1; + } + else + { + st->enablePlcWaveadjust = 0; + } + + open_PLC_ENC_EVS( &st->plcExt, st->sr_core ); + + st->glr_idx[0] = 0; + st->glr_idx[1] = 0; + st->mean_gc[0] = 0.0f; + st->mean_gc[1] = 0.0f; + st->prev_lsf4_mean = 0.0f; + st->last_stab_fac = 0.0f; + + return; +} + + +/*-----------------------------------------------------------------------* + * init_tcx() + * + * Initialization of TCX + *-----------------------------------------------------------------------*/ + +static void init_tcx( + Encoder_State *st, + int L_frame_old +) +{ + short mdctWindowLength; + short mdctWindowLengthFB; + + /* Share the memories for 2xTCX10/4xTCX5 and for TCX20 */ + st->spectrum[0] = st->spectrum_long; + st->spectrum[1] = st->spectrum_long + N_TCX10_MAX; + + st->tcx_cfg.tcx5Size = NS2SA(st->sr_core, FRAME_SIZE_NS/4); /* Always 5 ms */ + st->tcx_cfg.tcx5SizeFB = NS2SA(st->input_Fs, FRAME_SIZE_NS/4); /* Always 5 ms */ + + st->tcx_cfg.tcx_mdct_window_length_old = st->tcx_cfg.tcx_mdct_window_length; + mdctWindowLength = getMdctWindowLength(st->fscale); + mdctWindowLengthFB = mdctWindowLength * st->input_Fs / st->sr_core; + + /* Initialize the TCX MDCT window */ + /*Symmetric window = sinus LD window*/ + st->tcx_cfg.tcx_mdct_window_delay = mdctWindowLength; + st->tcx_cfg.tcx_mdct_window_delayFB = mdctWindowLengthFB; + st->tcx_cfg.tcx_mdct_window_length = mdctWindowLength; + st->tcx_cfg.tcx_mdct_window_lengthFB = mdctWindowLengthFB; + + mdct_window_sine( st->tcx_cfg.tcx_mdct_window, st->tcx_cfg.tcx_mdct_window_length ); + mdct_window_sine( st->tcx_cfg.tcx_mdct_windowFB, st->tcx_cfg.tcx_mdct_window_lengthFB ); + + mdct_window_sine( st->tcx_cfg.tcx_mdct_window_half, st->tcx_cfg.tcx_mdct_window_length/2 ); + mdct_window_sine( st->tcx_cfg.tcx_mdct_window_halfFB, st->tcx_cfg.tcx_mdct_window_lengthFB/2 ); + + /*ALDO windows for MODE2*/ + mdct_window_aldo(st->tcx_cfg.tcx_aldo_window_1, st->tcx_cfg.tcx_aldo_window_2, st->L_frame); + mdct_window_aldo(st->tcx_cfg.tcx_aldo_window_1_FB, st->tcx_cfg.tcx_aldo_window_2_FB, NS2SA(st->input_Fs, FRAME_SIZE_NS)); + st->tcx_cfg.tcx_aldo_window_1_trunc = st->tcx_cfg.tcx_aldo_window_1 + NS2SA(st->sr_core, N_ZERO_MDCT_NS); + st->tcx_cfg.tcx_aldo_window_1_FB_trunc = st->tcx_cfg.tcx_aldo_window_1_FB + NS2SA(st->input_Fs, N_ZERO_MDCT_NS); + + /*1.25ms transition window for ACELP->TCX*/ + st->tcx_cfg.tcx_mdct_window_trans_length = NS2SA(st->sr_core, ACELP_TCX_TRANS_NS); + mdct_window_sine( st->tcx_cfg.tcx_mdct_window_trans, st->tcx_cfg.tcx_mdct_window_trans_length ); + st->tcx_cfg.tcx_mdct_window_trans_lengthFB = NS2SA(st->input_Fs, ACELP_TCX_TRANS_NS); + mdct_window_sine( st->tcx_cfg.tcx_mdct_window_transFB, st->tcx_cfg.tcx_mdct_window_trans_lengthFB ); + + /*Mid-OLA*/ + /*compute minimum length for "half" window: lookahead - 5ms. It must be also multiple of 2*/ + st->tcx_cfg.tcx_mdct_window_half_length=2*((st->encoderLookahead_enc-(int)(0.005f*st->sr_core+0.5f))>>1); + st->tcx_cfg.tcx_mdct_window_half_lengthFB=2*((st->encoderLookahead_FB-(int)(0.005f*st->input_Fs+0.5f))>>1); + assert( (st->tcx_cfg.tcx_mdct_window_half_length>16) && "Half window can not be large enough!"); + + mdct_window_sine( st->tcx_cfg.tcx_mdct_window_half, st->tcx_cfg.tcx_mdct_window_half_length ); + mdct_window_sine( st->tcx_cfg.tcx_mdct_window_halfFB, st->tcx_cfg.tcx_mdct_window_half_lengthFB ); + + /* minimum overlap 1.25 ms */ + st->tcx_cfg.tcx_mdct_window_min_length = st->sr_core / 800; + st->tcx_cfg.tcx_mdct_window_min_lengthFB = st->input_Fs / 800; + mdct_window_sine(st->tcx_cfg.tcx_mdct_window_minimum, st->tcx_cfg.tcx_mdct_window_min_length); + mdct_window_sine(st->tcx_cfg.tcx_mdct_window_minimumFB, st->tcx_cfg.tcx_mdct_window_min_lengthFB); + + /* TCX Offset */ + st->tcx_cfg.tcx_offset = (st->tcx_cfg.tcx_mdct_window_delay>>1); + st->tcx_cfg.tcx_offsetFB = (st->tcx_cfg.tcx_mdct_window_delayFB>>1); + /*<0 rectangular transition with optimized window size = L_frame+L_frame/4*/ + st->tcx_cfg.lfacNext = st->tcx_cfg.tcx_offset - st->L_frame/4; + st->tcx_cfg.lfacNextFB = st->tcx_cfg.tcx_offsetFB - st->L_frameTCX/4; + + if( st->ini_frame == 0 ) + { + st->tcx_cfg.tcx_curr_overlap_mode = st->tcx_cfg.tcx_last_overlap_mode = ALDO_WINDOW; + } + /* Init TCX target bits correction factor */ + st->LPDmem.tcx_target_bits_fac = 1.0f; + + st->measuredBwRatio = 1.0f; + st->noiseTiltFactor = 0.5625f; + st->noiseLevelMemory = 0; + + /*SQ deadzone & memory quantization*/ + st->tcx_cfg.sq_rounding = 0.375f; /*deadzone of 1.25->rounding=1-1.25/2 (No deadzone=0.5)*/ + set_i( st->memQuantZeros, 0, L_FRAME_PLUS ); + + /* TCX rate loop */ + st->tcx_cfg.tcxRateLoopOpt = (st->tcxonly) ? 2 : 0; + + /* TCX bandwidth */ + st->tcx_cfg.bandwidth = getTcxBandwidth(st->bwidth); + + /* set number of coded lines */ + st->tcx_cfg.tcx_coded_lines = getNumTcxCodedLines(st->bwidth); + + /* TNS in TCX */ + st->tcx_cfg.pCurrentTnsConfig = NULL; + st->tcx_cfg.fIsTNSAllowed = getTnsAllowed( st->total_brate, st->igf ); + + if( st->tcx_cfg.fIsTNSAllowed ) + { + InitTnsConfigs( bwMode2fs[st->bwidth], st->tcx_cfg.tcx_coded_lines, st->tcx_cfg.tnsConfig, (&st->hIGFEnc)->infoStopFrequency, st->total_brate); + } + + /* TCX-LTP */ + st->tcxltp = getTcxLtp(st->sr_core); + + if( st->ini_frame == 0 ) + { + st->tcxltp_pitch_int_past = st->L_frame; + st->tcxltp_pitch_fr_past = 0; + st->tcxltp_gain_past = 0.f; + st->tcxltp_norm_corr_past = 0.f; + } + else if( st->L_frame!=L_frame_old && !((st->total_brate==ACELP_16k40|| st->total_brate==ACELP_24k40)&&(st->total_brate==st->last_total_brate)&&(st->last_bwidth==st->bwidth)) ) + { + int pitres, pitres_old; + float pit, pit_old; + + if ( L_frame_old%160==0 ) + { + pitres_old = 6; + } + else + { + pitres_old = 4; + } + pit_old = (float)st->tcxltp_pitch_int_past + (float)st->tcxltp_pitch_fr_past/(float)pitres_old; + if (st->L_frame%160==0 ) + { + pitres = 6; + } + else + { + pitres = 4; + } + pit = pit_old * (float)st->L_frame/(float)L_frame_old; + st->tcxltp_pitch_int_past = (int)pit; + st->tcxltp_pitch_fr_past = (int)( (pit-(float)st->tcxltp_pitch_int_past)*(float)pitres ); + } + + /* Context HM*/ + st->tcx_cfg.ctx_hm = getCtxHm( st->total_brate, st->rf_mode ); + + /* Residual Coding*/ + st->tcx_cfg.resq = getResq(st->total_brate); + st->tcx_cfg.tcxRateLoopOpt = (st->tcx_cfg.resq && !st->tcxonly) ? 1 : st->tcx_cfg.tcxRateLoopOpt; + + st->tcx_lpc_shaped_ari = getTcxLpcShapedAri( st->total_brate, st->bwidth, st->rf_mode ); + + return; + +} + +/*-----------------------------------------------------------------------* + * init_sig_buffers() + * + * Initialization of signal buffers + *-----------------------------------------------------------------------*/ + +static void init_sig_buffers( + Encoder_State *st, + const int L_frame_old, + const short L_subfr +) +{ + /* Encoder Past Samples at encoder-sampling-rate */ + st->encoderPastSamples_enc = (st->L_frame*9)/16; + + /* Initialize Signal Buffers and Pointers at encoder-sampling-rate */ + if ( st->ini_frame == 0 ) + { + set_zero(st->buf_speech_enc, L_PAST_MAX_32k+L_FRAME32k+L_NEXT_MAX_32k); + set_zero(st->buf_speech_enc_pe, L_PAST_MAX_32k+L_FRAME32k+L_NEXT_MAX_32k); + set_zero(st->buf_speech_ltp, L_PAST_MAX_32k+L_FRAME32k+L_NEXT_MAX_32k); + set_zero(st->buf_wspeech_enc, L_FRAME16k+L_SUBFR+L_FRAME16k+L_NEXT_MAX_16k); + } + else if ( st->L_frame!=L_frame_old && !((st->total_brate==16400|| st->total_brate==24400)&&(st->total_brate==st->last_total_brate)&&(st->last_bwidth==st->bwidth)) ) + { + lerp( st->buf_speech_enc, st->buf_speech_enc, st->L_frame, L_frame_old ); + + if( (st->last_core != TCX_20_CORE) && (st->last_core != TCX_10_CORE) ) + { + mvr2r( st->buf_speech_enc, st->buf_speech_ltp, st->L_frame ); + } + + mvr2r( st->old_wsp, st->buf_wspeech_enc+st->L_frame + L_SUBFR-L_WSP_MEM,L_WSP_MEM); + + /*Resamp buffers needed only for ACELP*/ + if( st->L_frame == L_FRAME && !st->tcxonly ) + { + mvr2r( st->old_inp_12k8, st->buf_speech_enc_pe+st->L_frame-L_INP_MEM,L_INP_MEM); + } + else if( st->L_frame == L_FRAME16k && !st->tcxonly ) + { + lerp( st->buf_wspeech_enc+st->L_frame + L_SUBFR-L_WSP_MEM, st->buf_wspeech_enc+st->L_frame + L_SUBFR-310, 310, L_WSP_MEM ); + mvr2r( st->old_inp_16k, st->buf_speech_enc_pe+st->L_frame-L_INP_MEM,L_INP_MEM); + } + + st->mem_preemph_enc = st->buf_speech_enc[st->L_frame-1]; + st->mem_wsp_enc = st->buf_wspeech_enc[st->L_frame+L_SUBFR-1]; + + } + /*coming from TCXonly modes*/ + else if( !st->tcxonly && st->last_total_brate>ACELP_32k ) + { + mvr2r( st->old_wsp, st->buf_wspeech_enc+st->L_frame + L_SUBFR-L_WSP_MEM,L_WSP_MEM); + + /*Resamp buffers needed only for ACELP*/ + if( st->L_frame == L_FRAME16k) + { + lerp( st->buf_wspeech_enc+st->L_frame + L_SUBFR-L_WSP_MEM, st->buf_wspeech_enc+st->L_frame + L_SUBFR-310, 310, L_WSP_MEM ); + } + st->LPDmem.mem_w0 = 0; + st->mem_wsp_enc = st->buf_wspeech_enc[st->L_frame+L_SUBFR-1]; + } + + 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, 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 + L_subfr; + + if( st->ini_frame == 0 || st->L_frame != L_frame_old || st->last_codec_mode == MODE1 ) + { + set_zero( st->buf_synth, OLD_SYNTH_SIZE_ENC+L_FRAME32k ); + } + st->synth = st->buf_synth + st->L_frame + L_subfr; + + return; + +} + + +/*-----------------------------------------------------------------------* + * init_core_sig_ana() + * + * + *-----------------------------------------------------------------------*/ + +static void init_core_sig_ana( + Encoder_State *st +) +{ + /* Pre-emphasis factor and memory */ + if (st->fscale < (16000*FSCALE_DENOM)/12800) + { + st->preemph_fac = PREEMPH_FAC; /*WB*/ + } + else if (st->fscale < (24000*FSCALE_DENOM)/12800) + { + st->preemph_fac = PREEMPH_FAC_16k; /*WB*/ + } + else + { + st->preemph_fac = PREEMPH_FAC_SWB; /*SWB*/ + } + + st->tcx_cfg.preemph_fac = st->preemph_fac; + + if ( st->sr_core==16000 ) + { + st->gamma = GAMMA16k; + } + else + { + st->gamma = GAMMA1; + } + + + if( st->narrowBand ) + { + st->min_band = 1; + st->max_band = 16; + } + else + { + st->min_band = 0; + st->max_band = 19; + } + + return; +} + + +/*-----------------------------------------------------------------------* + * init_acelp() + * + * + *-----------------------------------------------------------------------*/ + +static void init_acelp( + Encoder_State *st, + int L_frame_old +) +{ + short mem_syn_r_size_old; + short 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 == 0) + { + set_zero( st->LPDmem.syn, 1+M ); + + set_zero( st->LPDmem.Txnq, L_FRAME32k/2+64 ); + st->LPDmem.acelp_zir = st->LPDmem.Txnq + (st->L_frame/2); + set_zero( st->LPDmem.mem_syn_r, L_SYN_MEM ); + } + else /*Rate switching*/ + { + if( st->last_core == ACELP_CORE ) + { + lerp( st->LPDmem.Txnq,st->LPDmem.Txnq, st->L_frame/2, L_frame_old/2 ); + } + 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 + (st->L_frame/2); + + /* Rate switching */ + if( st->last_codec_mode == MODE1 ) + { + mvr2r( st->mem_syn1, st->LPDmem.mem_syn2, M ); + set_zero( st->LPDmem.Txnq, L_FRAME32k/2+64 ); + set_zero( st->LPDmem.syn, M ); + } + + if( st->last_core == AMR_WB_CORE ) + { + st->next_force_safety_net = 1; + st->last_core = ACELP_CORE; + } + + if( st->last_codec_mode == MODE1 && st->last_core == HQ_CORE ) + { + /*Reset of ACELP memories*/ + st->next_force_safety_net = 1; + st->rate_switching_reset = 1; + st->LPDmem.tilt_code = TILT_CODE; + set_zero( st->LPDmem.old_exc, L_EXC_MEM ); + set_zero( st->LPDmem.syn, 1+M ); + st->LPDmem.mem_w0 = 0.0f; + set_zero( st->LPDmem.mem_syn, M ); + set_zero( st->LPDmem.mem_syn2, M ); + + /* unquantized LPC*/ + if ( !((st->total_brate == ACELP_16k40 || st->total_brate == ACELP_24k40) && st->total_brate == st->last_total_brate && st->last_bwidth == st->bwidth) ) + { + mvr2r( st->lsp_old1, st->lspold_enc, M ); /*lsp old @12.8kHz*/ + if( st->L_frame == L_FRAME16k ) + { + lsp_convert_poly( st->lspold_enc, st->L_frame, 0 ); + } + } + mvr2r( st->lspold_enc, st->lsp_old, M ); /*used unquantized values for mid-LSF Q*/ + lsp2lsf( st->lsp_old, st->lsf_old, M, st->sr_core ); + + st->last_core = TCX_20_CORE; + + 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*/ + set_f( st->old_out, 0, st->L_frame ); + + } + else + { + if( st->L_frame != L_frame_old && st->L_frame <= L_FRAME16k && L_frame_old <= L_FRAME16k ) /* Rate switching between 12.8 and 16 kHz*/ + { + float tmp, A[M+1], Ap[M+1],tmp_buf[M+1]; + + /* convert quantized LSP vector */ + st->rate_switching_reset = lsp_convert_poly( st->lsp_old, st->L_frame, 0 ); + lsp2lsf( st->lsp_old, st->lsf_old, M, st->sr_core ); + + if( st->L_frame == L_FRAME16k ) + { + mvr2r( st->lsp_old, st->lspold_enc, M ); + } + else + { + mvr2r( st->lsp_old1, st->lspold_enc, M ); + } + + synth_mem_updt2( st->L_frame, st->last_L_frame, st->LPDmem.old_exc, st->LPDmem.mem_syn_r, st->LPDmem.mem_syn2, st->LPDmem.mem_syn, ENC ); + + /* Update wsyn */ + lsp2a_stab( st->lsp_old, A, M ); + weight_a( A, Ap, GAMMA1, M ); + tmp = 0.f; + tmp_buf[0] = 0.f; + mvr2r( st->LPDmem.mem_syn2, tmp_buf+1, M ); + deemph( tmp_buf+1, st->preemph_fac, M, &tmp ); + residu( Ap, M, tmp_buf+M, &tmp, 1 ); + st->LPDmem.mem_w0 = st->wspeech_enc[-1] - tmp; + } + else if( st->L_frame != L_frame_old ) /* Rate switching involving TCX only modes */ + { + /*Partial reset of ACELP memories*/ + st->next_force_safety_net = 1; + st->rate_switching_reset = 1; + + /*reset partly some memories*/ + st->LPDmem.tilt_code = TILT_CODE; + set_zero( st->LPDmem.old_exc, L_EXC_MEM ); + + /*Resamp others memories*/ + /*Size of LPC syn memory*/ + mem_syn_r_size_old = (int)(1.25*L_frame_old/20.f); + mem_syn_r_size_new = (int)(1.25*st->L_frame/20.f); + 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 ); + mvr2r( st->LPDmem.mem_syn_r+L_SYN_MEM-M, st->LPDmem.mem_syn, M ); + mvr2r( st->LPDmem.mem_syn, st->LPDmem.mem_syn2, M ); + + /*Untouched memories : st->LPDmem.syn & st->LPDmem.mem_w0*/ + st->LPDmem.mem_w0 = 0; + + /* unquantized LPC*/ + mvr2r( st->lsp_old1, st->lspold_enc, M ); /*lsp old @12.8kHz*/ + if( st->L_frame == L_FRAME16k ) + { + lsp_convert_poly( st->lspold_enc, st->L_frame, 0 ); + } + mvr2r( st->lspold_enc, st->lsp_old, M ); /*used unquantized values for mid-LSF Q*/ + lsp2lsf( st->lsp_old, st->lsf_old, M, st->sr_core ); + } + /* necessary in BASOP only, due to different representations of st->lsf_old */ + /* else if ( !st->tcxonly && (st->L_frame == L_FRAME16k) && (st->last_total_brate > ACELP_32k) ) */ + /* { */ + /* lsp2lsf( st->lsp_old, st->lsf_old, M, st->sr_core ); */ + /* } */ + } + } + + if( st->last_bwidth == NB && st->bwidth != NB && st->ini_frame != 0 ) + { + st->rate_switching_reset = 1; + } + + /* Post-processing */ + set_zero( st->dispMem, 8 ); + st->LPDmem.gc_threshold = 0.0f; + + /* Pulse Search configuration */ + st->acelp_autocorr = 1; + + /*Use for 12.8 kHz sampling rate and low bitrates, the conventional pulse search->better SNR*/ + if( ((st->total_brate <= ACELP_9k60 || st->rf_mode == 1) && (st->sr_core == 12800)) ) + { + st->acelp_autocorr = 0; + } + + /*BPF parameters for adjusting gain in function of background noise*/ + if( st->codec_mode == MODE2 ) + { + st->pst_lp_ener = 0.0f; + if( st->last_codec_mode == MODE1 ) + { + st->pst_mem_deemp_err = 0.0f; + } + } + + + return; +} + +/*-----------------------------------------------------------------------* + * init_modes() + * + * + *-----------------------------------------------------------------------*/ + +static void init_modes( + Encoder_State *st +) +{ + short n; + + /* Restrict ACE/TCX20/TCX10 mode */ + st->restrictedMode = getRestrictedMode(st->total_brate, st->Opt_AMR_WB); + st->acelpEnabled = (st->restrictedMode & 1) == 1; + st->tcx20Enabled = (st->restrictedMode & 2) == 2; + st->tcx10Enabled = (st->restrictedMode & 4) == 4; + + /* TCX mode (TCX20 TCX10_10 or NO_TCX) */ + st->tcxMode = NO_TCX; + + /*st->bits_frame_nominal = (int)( (float)st->L_frame * (float)FSCALE_DENOM * (float)st->total_brate / ( (float)st->fscale * 12800.0f ) );*/ + st->bits_frame_nominal = (int)( (float)st->L_frame/(float)st->fscale * (float)FSCALE_DENOM/128.0f * (float)st->total_brate/100.0f + 0.49f ); + + if( st->Opt_AMR_WB ) + { + st->bits_frame = st->bits_frame_nominal; + st->bits_frame_core = st->bits_frame_nominal; + st->frame_size_index = 0; + } + else + { + for (n=0; nbits_frame_nominal) + { + 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 000000000..696deb6ca --- /dev/null +++ b/lib_enc/core_enc_ol.c @@ -0,0 +1,1213 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "options.h" +#include "prot.h" +#include "rom_com.h" +#include "basop_proto_func.h" + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static void BITS_ALLOC_ACELP_config_rf( const short coder_type, float *tilt_code, short *rf_frame_type, + short *rf_target_bits, short nb_subfr, short rf_fec_indicator, float *pitch_buf ); + +static void BITS_ALLOC_TCX_config_rf( short *rf_frame_type, short *rf_target_bits, short PLC_Mode, + short coder_type, short last_core, int TD_Mode ); + +static void closest_centroid_rf( const float *data, const float *weights, const float *quantizer, + const short centroids, const short length, short *ind_vec ); + +/*-------------------------------------------------------------------* + * core_encode_openloop() + * + * Open-loop core encoder + *-------------------------------------------------------------------*/ + +void core_encode_openloop( + Encoder_State *st, /* i/o: encoder state structure */ + const short coder_type, /* i : coding type */ + const short pitch[3], /* i : open-loop pitch values for quantiz. */ + const float voicing[3], /* i : open-loop pitch gains */ + const float Aw[NB_SUBFR16k*(M+1)], /* i : weighted A(z) unquant. for subframes*/ + const float *lsp_new, /* i : LSPs at the end of the frame */ + const float *lsp_mid, /* i : LSPs at the middle of the frame */ + float *pitch_buf, /* i/o: floating pitch values for each subfr*/ + float *voice_factors, /* o : voicing factors */ + float *ptr_bwe_exc, /* o : excitation for SWB TBE */ + const short vad_hover_flag, + const short vad_flag_dtx + +) +{ + float lsf_q[M], lsp_q[M], lspmid_q[M]; + Word16 lspq_ind[M]; + Word16 A_q_ind[M+1]; + float A_q_ace[NB_SUBFR16k*(M+1)]; + float A_q_tcx[NB_SUBFR16k*(M+1)]; + int param_lpc[NPRM_LPC_NEW]; + int nbits_lpc; + int param_core[2*NPRM_DIV]; + int target_bits; + float stab_fac; + int indexBuffer[N_MAX+1]; + CONTEXT_HM_CONFIG hm_cfg; + float lsp_tcx_q[M], lsf_tcx_q[M]; + int tcx_lpc_cdk; + float A_w[M+1]; + float gain_pitch_buf[NB_SUBFR16k]; + float gain_code_buf[NB_SUBFR16k]; + short bits_param_lpc[10], no_param_lpc; + + /* lsf quant parameters */ + float lsp_q_rf[M]; + float Aq_rf[NB_SUBFR*(M+1)]; + float stab_fac_rf; + float *exc_rf; + float *syn_rf; + short rf_PLC_Mode; + short TD_Mode; + short rf_tcx_lpc_cdk; + float lsp[M], lsf[M]; + float rf_mem_MA[M]; + float exc_buf_rf[L_EXC_MEM + L_FRAME + 1]; + float syn_buf_rf[M+L_FRAME16k+L_FRAME16k/2]; + + float w_rf[M], lsf_uq_rf[M]; + float lsf_q_1st_rf[M], lsf_q_d_rf[M], lsf_q_rf[M]; + float lsp_old_q_rf[M], lsf_old_q_rf[M]; + + /*--------------------------------------------------------------* + * back up parameters for RF + *---------------------------------------------------------------*/ + + /* back up the old LSPs and LSFs */ + mvr2r( st->lsp_old, lsp_old_q_rf, M ); + mvr2r( st->lsf_old, lsf_old_q_rf, M ); + + /* back up old exc before primary encoding */ + set_f( exc_buf_rf, 0, (L_EXC_MEM+L_FRAME+1) ); + exc_rf = exc_buf_rf + L_EXC_MEM; + mvr2r(st->LPDmem.old_exc, exc_buf_rf, L_EXC_MEM); + + /* back up old synthesis before primary encoding */ + set_f( syn_buf_rf, 0, (M+L_FRAME16k+L_FRAME16k/2) ); + syn_rf = syn_buf_rf + M; + mvr2r(st->LPDmem.mem_syn, syn_buf_rf, M); + + /* back up syn2 mem */ + mvr2r(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 */ + mvr2r( st->clip_var, st->rf_clip_var, 6 ); + + /* back up tilt code */ + st->rf_tilt_code = st->LPDmem.tilt_code; + + /* back up dispMem */ + mvr2r( st->dispMem, st->rf_dispMem, 8 ); + + /* back up gc_threshold for noise addition */ + st->rf_gc_threshold = st->LPDmem.gc_threshold; + + + + /*--------------------------------------------------------------* + * Initializations + *---------------------------------------------------------------*/ + + tcx_lpc_cdk = 0; + set_i( param_lpc, 0, NPRM_LPC_NEW ); + set_i( param_core, 0, 2*NPRM_DIV ); + mvi2i( st->tcxltp_param, ¶m_core[1+NOISE_FILL_RANGES], LTPSIZE ); + + no_param_lpc = 0; /* avoid MSVC warnings */ + nbits_lpc = 0; /* avoid MSVC warnings */ + stab_fac = 0.0f; /* avoid MSVC warnings */ + + hm_cfg.indexBuffer = indexBuffer; + + /*--------------------------------------------------------------* + * LPC Quantization + *---------------------------------------------------------------*/ + + if( st->lpcQuantization == 1 && coder_type == VOICED ) + { + (&(st->acelp_cfg))->midLpc = 0; + } + else + { + (&(st->acelp_cfg))->midLpc=st->acelp_cfg.midLpc_enable; + } + + if( st->core == ACELP_CORE || !st->enableTcxLpc ) + { + if( st->envWeighted ) + { + /* Unweight the envelope */ + E_LPC_lsp_unweight( st->lsp_old, st->lsp_old, st->lsf_old, 1.0f/st->gamma ); + st->envWeighted = 0; + } + + if( st->core == TCX_20_CORE ) + { + lpc_quantization( st, st->core, st->lpcQuantization, st->lsf_old, lsp_new, lsp_mid, lsp_q, lsf_q, + lspmid_q, st->mem_MA, st->mem_AR, st->narrowBand, AUDIO, st->acelp_cfg.midLpc, param_lpc, &nbits_lpc, + &(st->seed_acelp), st->sr_core, st->Bin_E, st->Bin_E_old, bits_param_lpc, &no_param_lpc ); + } + else + { + lpc_quantization( st, st->core, st->lpcQuantization, st->lsf_old, lsp_new, lsp_mid, lsp_q, lsf_q, + lspmid_q, st->mem_MA, st->mem_AR, st->narrowBand, coder_type, st->acelp_cfg.midLpc, param_lpc, &nbits_lpc, + &(st->seed_acelp), st->sr_core, st->Bin_E, st->Bin_E_old, bits_param_lpc, &no_param_lpc ); + } + + /*-------------------------------------------------------------* + * Rate switching: reset + *-------------------------------------------------------------*/ + + if( st->rate_switching_reset ) + { + mvr2r( lsp_q, st->lsp_old, M ); + mvr2r( lsf_q, st->lsf_old, M ); + mvr2r( lsp_q, lspmid_q, M ); + } + + /*--------------------------------------------------------------* + * LPC Interpolation + *---------------------------------------------------------------*/ + + stab_fac = lsf_stab( lsf_q, st->lsf_old, 0, st->L_frame ); + } + + + + + /*--------------------------------------------------------------* + * Run ACELP + *---------------------------------------------------------------*/ + + if( st->core == ACELP_CORE ) + { + if( st->acelp_cfg.midLpc ) + { + int_lsp4( st->L_frame, st->lsp_old, lspmid_q, lsp_q, A_q_ace, M, 0 ); + } + else + { + int_lsp( st->L_frame, st->lsp_old, lsp_q, A_q_ace, M, interpol_frac_12k8, 0 ); + } + + /* Calculate target bits */ + target_bits = st->bits_frame_core - nbits_lpc - st->nb_bits_header_ace; + + if( st->rf_mode ) + { + /* joint bit allocation for redundant frame and TBE */ + /* calculate target bits for core coding */ + target_bits -= st->rf_target_bits_write; + } + + if( st->igf ) + { + target_bits -= get_tbe_bits( st->total_brate, st->bwidth, st->rf_mode ); + } + + if( st->acelp_cfg.midLpc ) + { + target_bits -= MIDLSF_NBITS; + } + + if( st->plcExt.enableGplc ) + { + target_bits -= st->plcExt.nBits; + } + + /* reset TBE buffers previous frame frame wasn't ACELP*/ + if( st->last_core != ACELP_CORE ) + { + TBEreset_enc( st, st->bwidth ); + } + + /* Run ACELP encoder */ + coder_acelp( &(st->acelp_cfg), coder_type, Aw, A_q_ace, st->speech_enc_pe, + st->synth, &(st->LPDmem), voicing, pitch, param_core, stab_fac, st, &st->plcExt, target_bits, + gain_pitch_buf, gain_code_buf, 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 ); + + mvr2r( lsf_q, st->plcExt.last_lsf_ref, M ); + mvr2r( st->plcExt.lsf_con, st->plcExt.last_lsf_con, M ); + + updateSpecPowDiffuseIdx( st, gain_pitch_buf, gain_code_buf ); + + if( st->last_stab_fac > 0.02 ) + { + st->glr_idx[0] = 0; + } + st->last_stab_fac = stab_fac; + + st->plcExt.LPDmem = &(st->LPDmem); + + encoderSideLossSimulation( st, &st->plcExt, lsf_q, stab_fac, st->plcExt.calcOnlylsf, st->L_frame ); + + st->tcxltp_norm_corr_past = voicing[1]; + st->tcx_cfg.tcx_curr_overlap_mode = st->tcx_cfg.tcx_last_overlap_mode = ALDO_WINDOW; + + } + + + + /*--------------------------------------------------------------* + * Run TCX20 + *---------------------------------------------------------------*/ + + if( st->core == TCX_20_CORE ) + { + if( st->enableTcxLpc ) + { + if( st->rf_mode ) + { + mvr2r( st->mem_MA, 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, lsp_new, A_q_tcx ); + + /* Weight the envelope */ + weight_a( A_q_tcx, A_q_tcx, st->gamma, M ); + + /* Save the weighted envelope */ + mvr2r( A_q_tcx, A_w, M+1 ); + + /* Convert to lsp and lsf */ + a2lsp_stab( A_q_tcx, lsp, lsp_new ); + lsp2lsf( lsp, lsf, M, INT_FS_12k8 ); + + /* Quantize */ + Q_lsf_tcxlpc( lsf, lsf_tcx_q, lspq_ind, param_lpc, st->narrowBand, tcx_lpc_cdk, st->mem_MA, st->tcx_cfg.coder_type, st->Bin_E ); + + /* Account for consumed bits */ + nbits_lpc = TCXLPC_NUMBITS; + if( param_lpc[0] ) + { + nbits_lpc += TCXLPC_IND_NUMBITS; + } + + /* Convert quantized lsf to lsp and A */ + lsf2lsp( lsf_tcx_q, lsp_tcx_q, M, INT_FS_12k8 ); + lsp2a_stab( lsp_tcx_q, A_q_tcx, M ); + } + else + { + E_LPC_int_lpc_tcx( st->lsp_old, lsp_q, A_q_tcx ); + } + + if( st->tcx_lpc_shaped_ari ) + { + basop_E_LPC_f_lsp_a_conversion(lspq_ind, A_q_ind, M); + } + + /* Calculate target bits */ + target_bits = st->bits_frame_core - nbits_lpc - st->nb_bits_header_tcx; + if( st->rf_mode ) + { + /* joint bit allocation for redundant frame and TBE */ + /* calculate target bits for core coding */ + target_bits -= st->rf_target_bits_write; + } + + if( st->mdct_sw == MODE1 ) + { + /* Account for core mode signalling bits difference: bandwidth and ACELP/TCX signaling bit are replaced */ + target_bits += (FrameSizeConfig[st->frame_size_index].bandwidth_bits + 1) - signalling_mode1_tcx20_enc(st, 0); + } + else if( st->mdct_sw_enable == MODE2 ) + { + --target_bits; + } + + if( st->plcExt.enableGplc ) + { + target_bits -= st->plcExt.nBits; + } + + /* subtract bits for TCX overlap mode (1 bit: full, 2 bits: half or no overlap) */ + target_bits -= (st->tcx_cfg.tcx_curr_overlap_mode == HALF_OVERLAP || st->tcx_cfg.tcx_curr_overlap_mode == MIN_OVERLAP) ? 2 : 1; + + target_bits -= st->tcxltp_bits; + + /* Run TCX20 encoder */ + + coder_tcx( 0, &(st->tcx_cfg), + A_q_tcx, A_q_ind, + st->synth, st->L_frame, st->L_frameTCX, st->tcx_cfg.tcx_coded_lines, target_bits, + st->tcxonly, st->spectrum_long, &(st->LPDmem), param_core, st, &hm_cfg); + + coder_tcx_post( st, &(st->LPDmem), &(st->tcx_cfg), st->synth, A_q_tcx, Aw, st->wspeech_enc ); + + + st->plcExt.LPDmem = &(st->LPDmem); + + GplcTcxEncSetup( st, &st->plcExt ); + + if( st->enableTcxLpc ) + { + E_LPC_lsp_unweight(lsp_tcx_q, lsp_q, lsf_q, 1.0f/st->gamma ); /* Update lsf_q for encoderSideLossSimulation() */ + } + encoderSideLossSimulation( st, &st->plcExt, lsf_q, stab_fac, 1, st->L_frame ); + + } + + + + /* Update lsp/lsf memory */ + mvr2r( lsp_new, st->lspold_enc, M ); + + if( st->enableTcxLpc && st->core != ACELP_CORE ) + { + /* Update lsf / lsp memory */ + mvr2r(lsf_tcx_q, st->lsf_old, M); + mvr2r(lsp_tcx_q, st->lsp_old, M); + st->envWeighted = 1; + + /* Update ACELP quantizer state */ + lsf_update_memory( st->narrowBand, st->lsf_old, st->mem_MA, st->mem_MA ); + st->pstreaklen = 0; + st->streaklimit = 1.0f; + /* check resonance for pitch clipping algorithm */ + gp_clip_test_lsf( st->core_brate, st->lsf_old, st->clip_var, 0 ); + mvr2r( st->lsf_old, st->mem_AR, M ); + } + else + { + mvr2r( lsf_q, st->lsf_old, M ); + mvr2r( lsp_q, st->lsp_old, M ); + } + + /* Update MODE1 CNG parameters */ + if( st->Opt_DTX_ON && vad_hover_flag ) + { + st->burst_ho_cnt++; + if( st->burst_ho_cnt > HO_HIST_SIZE ) + { + st->burst_ho_cnt = HO_HIST_SIZE; + } + } + else if ( st->Opt_DTX_ON && vad_flag_dtx ) + { + st->burst_ho_cnt = 0; + } + + if( st->Opt_DTX_ON ) + { + /* update CNG parameters in active frames */ + if( st->bwidth == NB && st->enableTcxLpc && st->core != ACELP_CORE ) + { + float buf[L_LP], res[L_FRAME], A[M+1], r[M+1], tmp, lsptmp[M]; + + assert( st->L_frame==L_FRAME ); + + mvr2r( st->synth+L_FRAME-L_LP, buf, L_LP ); + tmp = st->synth[L_FRAME-L_LP-1]; + preemph( buf, st->preemph_fac, L_LP, &tmp ); + autocorr( buf, r, M, L_LP, LP_assym_window, 0, 0, 0 ); + lag_wind( r, M, INT_FS_12k8, LAGW_WEAK ); + lev_dur( A, r, M, NULL ); + a2lsp_stab( A, lsptmp, lsp_new ); + + residu( A, M, buf+L_LP-L_FRAME, res, L_FRAME ); + + cng_params_upd( lsptmp, res, st->L_frame, &st->ho_circ_ptr, st->ho_ener_circ, + &st->ho_circ_size, st->ho_lsp_circ, ENC, st->ho_env_circ, + &st->cng_buf_cnt, st->cng_exc2_buf, st->cng_brate_buf, st->last_active_brate ); + } + else + { + cng_params_upd( lsp_new, st->LPDmem.old_exc+L_EXC_MEM-st->L_frame, st->L_frame, + &st->ho_circ_ptr, st->ho_ener_circ, &st->ho_circ_size, + st->ho_lsp_circ, ENC, st->ho_env_circ, &st->cng_buf_cnt, + st->cng_exc2_buf, st->cng_brate_buf, st->last_active_brate ); + } + + if( st->L_frame == L_FRAME ) + { + /* store LSPs@16k, potentially to be used in CNG@16k */ + mvr2r( st->lsp_old16k, &(st->ho_lsp_circ2[(st->ho_circ_ptr)*M]), M ); + } + + /* Set 16k LSP flag for CNG buffer */ + st->ho_16k_lsp[st->ho_circ_ptr] = (st->L_frame == L_FRAME ? 0 : 1 ); + + /* efficient DTX hangover control */ + if ( st->burst_ho_cnt > 1 ) + { + dtx_hangover_control( st, lsp_new ); + } + } + + /*--------------------------------------------------------------* + * Adaptive Bass Post-filter + *---------------------------------------------------------------*/ + + + if( st->core > ACELP_CORE || st->rate_switching_reset ) + { + /*TCX mode: copy values*/ + set_zero( st->mem_bpf, 2*L_FILT16k ); /*TCX->no gain*/ + set_zero( st->mem_error_bpf, 2*L_FILT16k ); /*TCX->no gain*/ + st->bpf_gain_param = 0; + } + else if( st->acelp_cfg.bpf_mode >= 1 ) + { + /*ACELP: estimate bpf parameter with delay=0*/ + + /*Estimate bpf parameter*/ + bass_pf_enc( st->speech_enc, st->synth, pitch_buf, gain_pitch_buf, st->L_frame, L_SUBFR, st->mem_bpf, st->mem_error_bpf, + &(st->bpf_gain_param), st->acelp_cfg.bpf_mode ,&(st->pst_lp_ener), &(st->pst_mem_deemp_err) ); + + } + + + /*--------------------------------------------------------------* + * Analysis Print Out + *---------------------------------------------------------------*/ + + + + /*--------------------------------------------------------------* + * Generate Bitstream + *---------------------------------------------------------------*/ + + enc_prm( coder_type, param_core, param_lpc, st, st->L_frame, &hm_cfg, bits_param_lpc, no_param_lpc ); + + /* Channel-aware mode - encode partial copy */ + if( st->rf_mode ) + { + set_f( lsf_q_1st_rf, 0.0f, M); + + if( st->core == ACELP_CORE ) + { + /* convert lsp to lsf */ + lsp2lsf( lsp_new, lsf_uq_rf, M, st->sr_core ); + + /* 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, st->sr_core, w_rf ); + v_sub( lsf_uq_rf, lsf_q_1st_rf, lsf_q_d_rf, M ); + + /* second stage vq */ + closest_centroid_rf( lsf_q_d_rf, w_rf, lsf_q_diff_cb_8b_rf, (1<<8), M, &st->rf_indx_lsf[0][1] ); + + /* 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 ); + + v_sort( lsf_q_rf, 0, M-1 ); + reorder_lsf( lsf_q_rf, LSF_GAP, M, st->sr_core ); + } + else + { + rf_tcx_lpc_cdk = tcxlpc_get_cdk( GENERIC ); + + /* Quantize */ + Q_lsf_tcxlpc( lsf, lsf_tcx_q, lspq_ind, param_lpc, st->narrowBand, rf_tcx_lpc_cdk, rf_mem_MA, GENERIC, st->Bin_E ); + + /* 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 (st->core == ACELP_CORE) + { + /* current n-th ACELP frame and its corresponding partial copy */ + lsf2lsp( lsf_q_rf, lsp_q_rf, M, st->sr_core ); + + /* Interpolate LSPs and convert to LPC */ + int_lsp( st->L_frame, lsp_old_q_rf, lsp_q_rf, Aq_rf, M, interpol_frac_12k8, 0 ); + + /* stability estimation */ + stab_fac_rf = lsf_stab( lsf_q_rf, lsf_old_q_rf, 0, st->L_frame ); + + /* 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( 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->rf_target_bits, st->speech_enc_pe, coder_type, st->rf_frame_type, Aw, Aq_rf, + voicing, pitch, stab_fac_rf, st, &(st->acelp_cfg_rf), exc_rf, syn_rf ); + } + } + else + { + + TD_Mode = 1; + st->rf_clas[0] = st->clas; + st->rf_gain_tcx[0] = param_core[0]; + + /* attenuate somewhat the gain for onset when the correlation with previous frame is too low: avoid preecho */ + if( st->rf_gain_tcx[1]!= 0 && st->rf_gain_tcx[0] > 1.6*st->rf_gain_tcx[1] && st->tcxltp_gain <= 0.2 ) + { + st->rf_gain_tcx[0] = 1.6*st->rf_gain_tcx[1]; + + if( st->rf_gain_tcx[0] > 127 ) + { + st->rf_gain_tcx[0] = 127; + } + } + + /* get concealment decision*/ + rf_PLC_Mode = 0; + if ((st->core == TCX_20_CORE) + &&(st->last_core == TCX_20_CORE) + && (st->rf_second_last_core == TCX_20_CORE) + && ((st->tcxltp_pitch_int <= 0.5f*st->L_frame) || (st->tcxltp_gain <= 0.4f)) + && (st->tcxltp_pitch_int == st->rf_tcxltp_pitch_int_past) + && !st->rf_last_tns_active + && !st->rf_second_last_tns_active + && !(st->tcx_cfg.fIsTNSAllowed & st->fUseTns[0]) + ) + { + rf_PLC_Mode = 1; + } + else if (st->last_core != 0) + { + if( (st->clas <= UNVOICED_TRANSITION || st->last_clas <= UNVOICED_TRANSITION || st->tcxltp_gain <= 0.4f) && st->last_core!=-1 ) + { + rf_PLC_Mode = st->last_core; + } + } + + /* call TD1 when the gain drop compare to previous frame*/ + if (rf_PLC_Mode == 0 && st->rf_gain_tcx[1]!= 0 && + ((st->transientDetection.transientDetector.bIsAttackPresent && st->rf_gain_tcx[0] < 0.97*st->rf_gain_tcx[1]) || + st->rf_gain_tcx[0] < 0.90*st->rf_gain_tcx[1])) + { + TD_Mode = 0; + } + else + { + TD_Mode = 1; + } + + /* updates */ + st->rf_tcxltp_pitch_int_past = st->tcxltp_pitch_int; + st->rf_second_last_tns_active = st->rf_last_tns_active; + st->rf_last_tns_active = st->tcx_cfg.fIsTNSAllowed & st->fUseTns[0]; + st->rf_second_last_core = st->last_core; + + st->rf_tcxltp_param[0] = st->tcxltp_param[1]; + + /* 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, TD_Mode ); + + /* RF frame type in the buffer */ + st->rf_indx_frametype[0] = st->rf_frame_type; + st->rf_targetbits_buff[0] = st->rf_target_bits; + } + } + + + return; +} + +/*-------------------------------------------------------------------* +* closest_centroid_rf() +* +* Determine a set of closest VQ centroids for a given input +*-------------------------------------------------------------------*/ + +static void closest_centroid_rf( + const float *data, /* i : input data */ + const float *weights, /* i : weights */ + const float *quantizer, /* i : quantizer table */ + const short centroids, /* i : number of centroids */ + const short length, /* i : dimension of quantiser */ + short *ind_vec /* o : list of best match indice vectors */ +) +{ + short i,j; + float tmp, werr, best_werr; + + ind_vec[0] = 0; + best_werr = 1.0E20f; + + for( i=0; iL_frame; + int overlap; + int tcx_offset = st->tcx_cfg.tcx_offset; + float *x = st->spectrum_long; + float target; + int T0; + float gain, noise, scale; + float *pt_ener_sfr, ener_sfr[NB_SUBFR16k]; + + /* Check minimum pitch for quantization */ + for( i = 0; i < 3; i++ ) + { + /* check minimum pitch for quantization */ + if( pitch[i] < PIT_MIN_SHORTER ) + { + pitch[i] *= 2; + } + + /* convert pitch values to 16kHz domain */ + if ( st->L_frame == L_FRAME16k ) + { + pitch[i] = (short)(pitch[i] * 1.25f + 0.5f); + } + } + if( st->narrowBand == 1 ) + { + pitchDoubling_det( st->wspeech_enc, pitch, pitch_fr, voicing_fr ); + } + + lsp2a_stab(lsp_mid, A_q_tcx, M); + + tcx_ltp_encode( st->tcxltp, st->tcxonly, TCX_20, st->L_frame, 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, + 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( st->mdct_sw == MODE1 ) + { + st->core = TCX_20_CORE; + } + else + { + /*--------------------------------------------------------------* + * Estimate TCX SNR + *---------------------------------------------------------------*/ + + target = 1000.f; + if (st->sr_core == 16000.f) + { + target = 850.f; + } + if (st->sr_core == 12800.f) + { + target = 850.f; + } + if (st->narrowBand == 1) + { + target = 500.f; + } + + if( st->last_core == ACELP_CORE ) + { + L_frame += tcx_offset; + + if( st->tcx_cfg.lfacNext < 0 ) + { + L_frame -= st->tcx_cfg.lfacNext; + tcx_offset = st->tcx_cfg.lfacNext; + } + else + { + tcx_offset = 0; + } + } + + overlap = st->tcx_cfg.tcx_mdct_window_delay; + + mvr2r(st->speech_ltp-(overlap>>1)+tcx_offset, xn_buf, L_frame+overlap); + + if( st->last_core == ACELP_CORE ) + { + if( tcx_offset < 0 ) + { + set_f( xn_buf, 0.0f, overlap>>1 ); + } + } + else + { + for (i = 0; i < overlap; i++) + { + xn_buf[i] *= st->tcx_cfg.tcx_mdct_window[i]; + } + } + + for (i = 0; i < overlap; i++) + { + xn_buf[L_frame+i] *= st->tcx_cfg.tcx_mdct_window[overlap-1-i]; + } + + TCX_MDCT( xn_buf, x, overlap, L_frame-overlap, overlap ); + + for( i = 0; i < L_frame; i++ ) + { + x[i] *= (float)L_frame / sqrt(2*NORM_MDCT_FACTOR); + } + + weight_a( A_q_tcx, Ap, st->gamma, M ); + + lpc2mdct( Ap, M, gainlpc ); + + mdct_preShaping( x, L_frame, gainlpc ); + + if( st->narrowBand == 1 ) + { + j = (int)( (float)L_frame*0.625f ); + + set_f( x + j, 0.0f, L_frame - j ); + } + + for( i = 0; i < L_frame; i+=4 ) + { + ener = 0.01f + x[i]*x[i] + x[i+1]*x[i+1] + x[i+2]*x[i+2] + x[i+3]*x[i+3]; + en[i/4] = 9.0f + 10.0f*(float)log10(ener); + } + + fac = 128.0f; + offset = fac; + + for( iter = 0; iter < 10; iter++ ) + { + fac *= 0.5f; + offset -= fac; + ener = 0.0f; + + for( i=0; i 3.0f ) + { + ener += tmp; + } + + if( ener > target ) + { + offset += fac; + break; + } + } + } + + if( offset <= 32.f ) + { + offset = -128.f; + } + + sqGain = (float)pow(10.0f, offset/20.0f); + ener = sqGain*sqGain/12.f*(float)sqrt(2.f)/(float)L_frame; + + snr_tcx = 0.0f; + pt_ener_sfr = ener_sfr; + + for( i = 0; i < st->L_frame; i += L_SUBFR ) + { + *pt_ener_sfr = sum2_f( st->wspeech_enc + i, L_SUBFR ) + 1e-6f; + + snr_tcx += (float)log10( *pt_ener_sfr/(ener*L_SUBFR) ); + pt_ener_sfr++; + } + snr_tcx *= ((float)(10*L_SUBFR))/(float)st->L_frame; + + + /*--------------------------------------------------------------* + * Estimate ACELP SNR + *---------------------------------------------------------------*/ + + scale = 0.055f; + if (st->sr_core == 16000) + { + scale = 0.092f; + } + if (st->sr_core == 12800) + { + scale = 0.059f; + } + if (st->narrowBand) + { + scale = 0.15f; + } + + snr_acelp = 0.0f; + fac = (float)st->sr_core/12800.f; + pt_ener_sfr = ener_sfr; + + for( i = 0; i < st->L_frame; i += L_SUBFR ) + { + T0 = (int)( (fac*pitch_fr[(int)((float)(i/L_SUBFR)/fac+0.5f)]) + 0.5f ); + gain = get_gain( st->wspeech_enc+i, st->wspeech_enc+i-T0, L_SUBFR, NULL ); + + noise = 1e-6f; + for( j = 0; j < L_SUBFR; j++ ) + { + tmp = st->wspeech_enc[i+j] - gain * st->wspeech_enc[i+j-T0]; + noise += tmp * tmp; + } + + noise *= scale; + snr_acelp += (float)log10( *pt_ener_sfr/noise ); + pt_ener_sfr++; + } + + snr_acelp *= ((float)(10*L_SUBFR))/(float)st->L_frame; + + + + /*--------------------------------------------------------------* + * Switching Decision + *---------------------------------------------------------------*/ + + dsnr = 0.0f; + /* hysteresis for very small SNR differences between ACELP and TCX */ + + /* try to use TCX instead of ACELP on temporally stationary frames */ + if( (snr_acelp > snr_tcx) && + (snr_acelp < snr_tcx + 2.0f) && + (st->prevTempFlatness + currFlatness < 3.25f || stab_fac == 1.0f || (st->sr_core == 12800 && sp_aud_decision0 == 1 && st->prevTempFlatness + currFlatness < 20.f)) && + (st->acelpFramesCount <= 6)) + { + dsnr = -2.0f; + } + + /* try to use ACELP instead of TCX on transient and "buzzy" frames */ + if( (snr_acelp < snr_tcx) && + (snr_acelp > snr_tcx - 2.0f) && + (st->prevTempFlatness + currFlatness > 3.25f) && + (st->acelpFramesCount >= 6)) + { + dsnr = 2.0f; + } + + if( (st->sr_core == 12800) && (offset < 74.0f) && (non_staX > 5.0f) && (snr_acelp >= snr_tcx - 4) && st->acelpFramesCount >= 1 && (((st->lps > st->lpm) && mean(voicing_fr, 4) >= 0.3f) || (st->acelpFramesCount >= 6 && (st->lps > st->lpm - 1.5f))) && (sp_aud_decision0 == 0) && vad_flag ) + { + /* Fine tuned across various databases based on various metrics to detect TCX frames in speech.*/ + dsnr = 4.0f; + } + + if( st->flag_noisy_speech_snr ) + { + if( vad_flag || st->Opt_DTX_ON ) + { + dsnr += 2.f; + } + else + { + dsnr -= 2.f; + } + } + + if (st->sr_core == 12800 && (non_staX < 2.f || (st->flag_noisy_speech_snr==0&& vad_flag==1&& offset==-128.f&& st->acelpFramesCount>=6)) && (st->last_core==ACELP_CORE|| st->last_core==TCX_20_CORE)) + { + st->core = st->last_core; + } + else if( snr_acelp + dsnr > snr_tcx ) + { + st->core = ACELP_CORE; + st->acelpFramesCount = min(32767-1, st->acelpFramesCount + 1); + } + else + { + st->core = TCX_20_CORE; + st->acelpFramesCount = 0; + } + } + + /* Fixed Decision (using -C) */ + if( st->acelpEnabled == 1 && st->tcx20Enabled == 0 ) + { + st->core = ACELP_CORE; + } + + if( st->acelpEnabled == 0 && st->tcx20Enabled == 1 ) + { + st->core = TCX_20_CORE; + } + + + st->prevTempFlatness = currFlatness; + + return; +} + +/*-------------------------------------------------------------------* + * BITS_ALLOC_ACELP_config_rf() + * + * configure channel aware mode + *-------------------------------------------------------------------*/ +static void BITS_ALLOC_ACELP_config_rf( + const short coder_type, + float *tilt_code, + short *rf_frame_type, + short *rf_target_bits, + short nb_subfr, + short rf_fec_indicator, + float *pitch_buf +) +{ + float mean_tc, min_tilt_code, max_tilt_code; + short nrgMode, ltfMode, ltpMode, gainsMode; + + short en_partial_red = 1; + float dpit1, dpit2, dpit3; + + /* Init */ + *rf_target_bits = 0; + + /* ----------------------------------------* + * RF frame type selection * + *-----------------------------------------*/ + + /* Mean tilt code estimation */ + mean_tc = 0; + mean_tc = mean(tilt_code, nb_subfr); + + /* Maximum tilt code estimation */ + max_tilt_code = tilt_code[0]; + maximum(tilt_code, nb_subfr, &max_tilt_code); + + /* Minimum tilt code estimation */ + min_tilt_code=tilt_code[0]; + minimum(tilt_code, nb_subfr, &min_tilt_code); + + /* ----------------------------------------*/ + /* Decide Criticality */ + /*-----------------------------------------*/ + dpit1 = (float)fabs( pitch_buf[0] - pitch_buf[1] ); + dpit2 = (float)fabs( pitch_buf[1] - pitch_buf[2] ); + dpit3 = (float)fabs( pitch_buf[2] - pitch_buf[3] ); + + if ( rf_fec_indicator == 1) + { + if ( max_tilt_code > 0.48f && dpit1 <= 0.0f && dpit2 <= 0.0f && dpit3 <= 0.0f && coder_type == VOICED ) + { + en_partial_red = 0; + } + if ( max_tilt_code > 0.47f && dpit1 <= 1.0f && dpit2 <= 1.0f && dpit3 <= 1.0f && coder_type == GENERIC) + { + en_partial_red = 0; + } + } + else + { + if ( max_tilt_code > 0.47 && dpit1 <= 0.25f && dpit2 <= 0.25f && dpit3 <= 0.25f && coder_type == VOICED ) + { + en_partial_red = 0; + } + if ( max_tilt_code > 0.45 && dpit1 <= 1.25f && dpit2 <= 1.25f && dpit3 <= 1.25f && coder_type == GENERIC) + { + en_partial_red = 0; + } + } + + + /* ---------------------------------------------------------* + * Identify number of bits required as per rf frame type * + * ---------------------------------------------------------*/ + + /* rf_mode, 1 bit */ + *rf_target_bits += 1; + + /* rf_fec_offset 2 bits */ + *rf_target_bits += 2; + + /* rf_frame_type, 3 bits */ + *rf_target_bits += 3; + + /* LSF bits 8 + 8 bits */ + *rf_target_bits += 16; + + /* Intialize the RF mode frame type to all-pred */ + *rf_frame_type = RF_ALLPRED; + + if ( coder_type == INACTIVE || en_partial_red == 0 ) + { + *rf_frame_type = RF_NO_DATA; + } + else if ( coder_type == UNVOICED || coder_type == INACTIVE ) + { + *rf_frame_type = RF_NELP; + } + else if( ( coder_type == GENERIC ) && max_tilt_code < 0.05f) + { + *rf_frame_type = RF_NOPRED; + } + else if( ( coder_type == GENERIC ) && mean_tc < 0.3f) + { + *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 + *-------------------------------------------------------------------*/ +static void BITS_ALLOC_TCX_config_rf( + short *rf_frame_type, + short *rf_target_bits, + short PLC_Mode, + short coder_type, + short last_core, + int TD_Mode +) +{ + /* Init: rf_mode + rf_fec_offset + rf_frame_type */ + *rf_target_bits = 1 + 2 + 3; + + if( coder_type == INACTIVE || last_core == ACELP_CORE ) + { + *rf_frame_type = RF_NO_DATA; + } + else + { + /* classification */ + *rf_target_bits += 2; + + if( PLC_Mode ) + { + /* TCX global gain = 7 bits */ + *rf_target_bits += 7; + *rf_frame_type = RF_TCXFD; + } + else + { + /* pitch and gain */ + /* LTP data */ + if( TD_Mode ) + { + *rf_target_bits += 9; + *rf_frame_type = RF_TCXTD2; + } + else + { + *rf_target_bits += 9; + *rf_frame_type = RF_TCXTD1; + } + } + + if( *rf_frame_type == RF_TCXFD ) + { + /* TCXFD: LSF bits 5 + 4 + 4 bits */ + /* only embed LSF for FD concealment */ + *rf_target_bits += TCXLPC_NUMBITS; + } + } + return; +} diff --git a/lib_enc/core_enc_reconf.c b/lib_enc/core_enc_reconf.c new file mode 100644 index 000000000..4e0877375 --- /dev/null +++ b/lib_enc/core_enc_reconf.c @@ -0,0 +1,174 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "options.h" +#include "prot.h" +#include "rom_com.h" +#include "rom_enc.h" + + +/*-----------------------------------------------------------------* + * Funtion core_coder_reconfig * + * ~~~~~~~~~~~~~~~~~~~ * + * - reconfig core coder when switching to another frame type * + *-----------------------------------------------------------------*/ + +void core_coder_reconfig( + Encoder_State *st +) +{ + short bandwidth, i; + + /*Configuration of ACELP*/ + BITS_ALLOC_init_config_acelp( st->total_brate, 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; + + if( st->tcxonly ) + { + st->nb_bits_header_tcx = 1+1; /*TCX20/TCX10 + last_core*/ + st->nb_bits_header_tcx += 2; /* Siganl class*/ + } + else + { + st->nb_bits_header_ace = 1+2+1; /*TCX/ACELP+coder_type + last_core*/ + st->nb_bits_header_tcx = st->nb_bits_header_ace; + + if ( st->tcx_cfg.lfacNext<=0 ) + { + st->nb_bits_header_ace--; /*No last_core*/ + } + } + + /*Switch off TCX or ACELP?*/ + if( st->sr_core==12800 ) + { + st->acelpEnabled = (st->restrictedMode & 1) == 1; + st->tcx20Enabled = (st->restrictedMode & 2) == 2; + } + st->prevEnergyHF = st->currEnergyHF = 65535.0f; /* prevent block switch */ + + + /* 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; + if( ((st->total_brate <= ACELP_9k60) && (st->sr_core == 12800)) ) + { + st->acelp_autocorr = 0; + } + + /*Get bandwidth mode*/ + if( st->narrowBand ) + { + bandwidth = NB; + } + else if(st->sr_core<=16000) + { + bandwidth = WB; + } + else + { + bandwidth = SWB; + } + + /*Scale TCX for non-active frames to adjust loudness with ACELP*/ + st->tcx_cfg.na_scale = 1.f; + if( bandwidth < SWB && !(st->tcxonly) ) + { + int scaleTableSize = sizeof (scaleTcxTable) / sizeof (scaleTcxTable[0]); + for (i = 0 ; i < scaleTableSize ; i++) + { + + if ( (bandwidth == scaleTcxTable[i].bwmode) && + (st->total_brate >= scaleTcxTable[i].bitrateFrom) && + (st->total_brate < scaleTcxTable[i].bitrateTo) ) + { + if( st->rf_mode ) + { + i--; + } + st->tcx_cfg.na_scale=scaleTcxTable[i].scale; + break; + } + } + } + + st->enableTcxLpc = (st->lpcQuantization == 1) && (st->total_brate <= LOWRATE_TCXLPC_MAX_BR || st->rf_mode); + + if( st->ini_frame == 0 || st->last_codec_mode == MODE1 ) + { + st->envWeighted = 0; + } + + if( st->bwidth == SWB && (st->total_brate == ACELP_16k40 || st->total_brate == ACELP_24k40) ) + { + if(st->tec_tfa == 0) + { + set_zero(st->tecEnc.loBuffer, MAX_TEC_SMOOTHING_DEG); + } + st->tec_tfa = 1; + } + else + { + st->tec_tfa = 0; + } + + st->enablePlcWaveadjust = 0; + if( st->total_brate >= HQ_48k ) + { + st->enablePlcWaveadjust = 1; + } + + st->glr = 0; + if( st->total_brate == ACELP_9k60 || st->total_brate == ACELP_16k40 || st->total_brate == ACELP_24k40 ) + { + st->glr = 1; + } + + if( st->glr ) + { + st->nb_bits_header_ace += G_LPC_RECOVERY_BITS; + } + + if( st->bwidth == NB || st->bwidth == WB ) + { + st->nmStartLine = startLineWB[min((sizeof(startLineWB)/sizeof(startLineWB[0])-1), (unsigned)max(0, (st->rf_mode==0) ? st->frame_size_index: st->frame_size_index-1))]; + } + else /* (st->bwidth == SWB || st->bwidth == FB) */ + { + st->nmStartLine = startLineSWB[min((sizeof(startLineSWB)/sizeof(startLineSWB[0])-1), (unsigned)max(3, (st->rf_mode==0) ? st->frame_size_index: st->frame_size_index-1) - 3)]; + } + + if( (st->total_brate < ACELP_24k40) && ( (st->total_brate > st->last_total_brate) || (st->last_codec_mode == MODE1) ) ) + { + /* low-freq memQuantZeros must be reset partially if bitrate increased */ + set_i( st->memQuantZeros, 0, st->nmStartLine ); + } + else + { + if( (st->total_brate >= ACELP_24k40) && (st->total_brate <= ACELP_32k) && (st->last_total_brate >= ACELP_13k20) && (st->last_total_brate < ACELP_24k40) ) + { + set_i(st->memQuantZeros, 0, st->L_frame); + } + } + + + return; +} diff --git a/lib_enc/core_enc_switch.c b/lib_enc/core_enc_switch.c new file mode 100644 index 000000000..7e099b5fe --- /dev/null +++ b/lib_enc/core_enc_switch.c @@ -0,0 +1,166 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "options.h" +#include "prot.h" +#include "rom_com.h" + +/*-------------------------------------------------------------------* + * core_coder_mode_switch() + * + * + *-------------------------------------------------------------------*/ + +void core_coder_mode_switch( + Encoder_State *st, + int bandwidth_in, + int bitrate +) +{ + int i, fscale, switchWB, sr_core; + int bSwitchFromAmrwbIO; + int bandwidth; + + bandwidth = bandwidth_in; + + switchWB = 0; + bSwitchFromAmrwbIO = 0; + if( st->last_core == AMR_WB_CORE ) + { + bSwitchFromAmrwbIO = 1; + } + + /* force active frame for the first frame when switching from high bitrates when dtx is enabled*/ + sr_core = getCoreSamplerateMode2(bitrate, bandwidth, st->rf_mode); + fscale = sr2fscale(sr_core); + + if ( (bandwidth >= WB) && (fscale==(FSCALE_DENOM*16000)/12800) && (fscale == st->fscale) ) + { + if ( ((bitrate>32000) && (st->tcxonly==0)) || ((bitrate<=32000) && (st->tcxonly==1)) ) + { + switchWB = 1; + } + } + if( st->last_codec_mode == MODE1 ) + { + switchWB = 1; /*force init when coming from MODE1*/ + } + + if( st->last_total_brate > ACELP_32k && st->total_brate <= ACELP_32k ) + { + switchWB = 1; /*force init when coming from MODE1*/ + } + + if( fscale == st->fscale && !bSwitchFromAmrwbIO && !switchWB ) + { + + st->total_brate = bitrate; + st->sr_core = sr_core; + st->L_frame = sr_core / 50; + st->tcxonly = getTcxonly(st->total_brate); + st->bits_frame_nominal = (int)( (float)st->L_frame/(float)st->fscale * (float)FSCALE_DENOM/128.0f * (float)st->total_brate/100.0f + 0.49f ); + st->igf = getIgfPresent(bitrate, bandwidth, st->rf_mode ); + + /* switch IGF configuration */ + if (st->igf) + { + IGFEncSetMode( &st->hIGFEnc, st->total_brate, bandwidth, st->rf_mode ); + } + + st->tcx_cfg.tcx_coded_lines = getNumTcxCodedLines(bandwidth); + st->tcx_cfg.bandwidth = getTcxBandwidth(bandwidth); + st->tcx_cfg.tcxRateLoopOpt = (st->tcxonly) ? 2 : 0; + st->tcx_cfg.ctx_hm = getCtxHm(st->total_brate, st->rf_mode ); + st->tcx_cfg.resq = getResq(st->total_brate); + st->tcx_lpc_shaped_ari = getTcxLpcShapedAri( st->total_brate, st->bwidth, st->rf_mode ); + + st->tcx_cfg.tcxRateLoopOpt = (st->tcx_cfg.resq && !st->tcxonly) ? 1 : st->tcx_cfg.tcxRateLoopOpt; + st->tcx_cfg.fIsTNSAllowed = getTnsAllowed(st->total_brate, st->igf); + + if (st->tcx_cfg.fIsTNSAllowed) + { + InitTnsConfigs( bwMode2fs[bandwidth], st->tcx_cfg.tcx_coded_lines, st->tcx_cfg.tnsConfig, (&st->hIGFEnc)->infoStopFrequency, st->total_brate); + } + + if( bandwidth == NB ) + { + st->narrowBand = 1; + st->min_band = 1; + st->max_band = 16; + } + else + { + st->narrowBand = 0; + st->min_band = 0; + st->max_band = 19; + } + + for (i=0; ibits_frame_nominal) + { + 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, 0 ); + + core_coder_reconfig( st ); + } + else + { + st->igf = getIgfPresent(bitrate, bandwidth, st->rf_mode ); + init_coder_ace_plus( st ); + } + + if( st->igf ) + { + /* reset TBE */ + if( ( st->bwidth == WB && st->last_extl != WB_TBE ) || + ( st->bwidth == SWB && st->last_extl != SWB_TBE ) || + ( st->bwidth == FB && st->last_extl != FB_TBE ) ) + { + TBEreset_enc( st, st->bwidth ); + } + else + { + set_f( st->state_lpc_syn, 0.0f, LPC_SHB_ORDER ); + set_f( st->state_syn_shbexc, 0.0f, L_SHB_LAHEAD ); + set_f( st->mem_stp_swb, 0.0f, LPC_SHB_ORDER ); + set_f( st->mem_zero_swb, 0, LPC_SHB_ORDER ); + st->gain_prec_swb = 1.0f; + } + } + + if (st->envWeighted && !st->enableTcxLpc) + { + /* Unweight the envelope */ + E_LPC_lsp_unweight( st->lsp_old, st->lsp_old, st->lsf_old, 1.0f/st->gamma ); + st->envWeighted = 0; + } + + if( bitrate >= HQ_48k ) + { + st->enablePlcWaveadjust = 1; + } + else + { + st->enablePlcWaveadjust = 0; + } + + if( (st->last_total_brate > HQ_32k) || (st->last_codec_mode == MODE1) ) + { + st->glr_reset = 1; + } + + return; +} diff --git a/lib_enc/core_enc_updt.c b/lib_enc/core_enc_updt.c new file mode 100644 index 000000000..d4ae35740 --- /dev/null +++ b/lib_enc/core_enc_updt.c @@ -0,0 +1,186 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "options.h" +#include "prot.h" +#include "rom_com.h" +#include "cnst.h" + + +/*-------------------------------------------------------------------* +* core_encode_update() +* +* Common updates of buffers +*-------------------------------------------------------------------*/ + +void core_encode_update( + Encoder_State *st /* i/o: Encoder state structure */ +) +{ + short n; + + /* Update Input Signal Buffers */ + n = st->encoderPastSamples_enc + st->encoderLookahead_enc; + + mvr2r( st->buf_speech_enc_pe + st->L_frame, st->buf_speech_enc_pe, n ); + mvr2r( st->buf_speech_enc + st->L_frame, st->buf_speech_enc, n ); + + if( !st->tcxonly ) + { + n = st->L_frame + st->L_frame/4; + mvr2r( st->buf_wspeech_enc + st->L_frame, st->buf_wspeech_enc, n ); + } + + if( st->core == ACELP_CORE || st->core == AMR_WB_CORE || st->core_brate == SID_2k40 || st->core_brate == FRAME_NO_DATA ) + { + mvr2r( st->buf_speech_enc + st->L_frame, st->buf_speech_ltp + st->L_frame, st->L_frame ); + } + + n = st->encoderPastSamples_enc + st->encoderLookahead_enc; + mvr2r( st->buf_speech_ltp + st->L_frame, st->buf_speech_ltp, n ); + mvr2r( st->buf_synth + st->L_frame, st->buf_synth, st->L_frame+L_SUBFR ); + + if( (st->core_brate <= SID_2k40 && st->cng_type == FD_CNG) || (st->tcxonly && st->codec_mode == MODE2) ) + { + /* reset LP memories */ + set_zero( st->mem_MA, M ); + mvr2r( GEWB_Ave, st->mem_AR, M ); + } + + + return; +} + +/*-------------------------------------------------------------------* +* core_encode_update_cng() +* +* Common updates in case of CNG +*-------------------------------------------------------------------*/ + +void core_encode_update_cng( + Encoder_State *st, + float *timeDomainBuffer, + float *A, + const float Aw[] /* i : weighted A(z) unquant. for subframes*/ +) +{ + float lsp[M], lsf[M]; + float *synth, synth_buf[M+1+L_FRAME_PLUS+L_FRAME_PLUS/2], wsyn[L_FRAME_PLUS]; + float tmp; + float enr; + float att; + float enr_index; + + /* LPC -> LSP/lsp */ + a2lsp_stab( A, lsp, st->lsp_old ); + + /* LSP/lsp -> LSF/lsf */ + if( st->L_frame == L_FRAME16k ) + { + lsp2lsf( lsp, lsf, M, INT_FS_16k ); + } + else + { + lsp2lsf( lsp, lsf, M, INT_FS_12k8 ); + } + + /* Update synth memory */ + synth = synth_buf + (1+M); + mvr2r( st->LPDmem.syn, synth_buf, 1+M ); + mvr2r( timeDomainBuffer, synth, st->L_frame); + mvr2r( synth+st->L_frame-(1+M), st->LPDmem.syn, 1+M ); + mvr2r( synth, st->synth, st->L_frame); + + /* Update ZIR */ + set_zero( synth+st->L_frame, st->L_frame/2 ); + syn_filt( A, M,synth+st->L_frame, synth+st->L_frame, st->L_frame/2, &synth[st->L_frame-M], 0 ); + mvr2r( synth+st->L_frame-(st->L_frame/2), st->LPDmem.Txnq, st->L_frame/2 ); + + /* Update pe-synth memory */ + tmp = synth[-(1+M)]; + preemph( synth-M, st->preemph_fac, M+st->L_frame, &tmp ); + mvr2r( synth+st->L_frame-M, st->LPDmem.mem_syn, M ); + mvr2r( synth+st->L_frame-M, st->LPDmem.mem_syn2, M ); + + /* Update excitation memory */ + mvr2r( st->LPDmem.old_exc+st->L_frame, st->LPDmem.old_exc, max(L_EXC_MEM-st->L_frame,0)); + residu( A, M,synth, st->LPDmem.old_exc+max(L_EXC_MEM-st->L_frame,0), st->L_frame ); + if ( st->core_brate == SID_2k40 ) + { + enr = dotp( st->LPDmem.old_exc+max(L_EXC_MEM-st->L_frame,0), st->LPDmem.old_exc+max(L_EXC_MEM-st->L_frame,0), st->L_frame ) / st->L_frame; + enr = (float)log10( enr + 0.1f ) / (float)log10( 2.0f ); + + /* decrease the energy in case of WB input */ + if( st->bwidth != NB ) + { + if( st->bwidth == WB ) + { + if( st->CNG_mode >= 0 ) + { + /* Bitrate adapted attenuation */ + att = ENR_ATT[st->CNG_mode]; + } + else + { + /* Use least attenuation for higher bitrates */ + att = ENR_ATT[4]; + } + } + else + { + att = 1.5f; + } + + enr -= att; + } + + enr_index = (short)( (enr + 2.0f) * STEP_SID ); + if( enr_index > 127 ) + { + enr_index = 127; + } + + if( enr_index < 0 ) + { + enr_index = 0; + } + st->old_enr_index = enr_index; + } + + /* Update weighted synthesis memory */ + calc_residu( synth, wsyn, Aw, st->L_frame ); + tmp = st->wspeech_enc[-1]-st->LPDmem.mem_w0; + deemph( wsyn, st->preemph_fac, st->L_frame, &tmp ); + st->LPDmem.mem_w0 = st->wspeech_enc[st->L_frame-1]-wsyn[st->L_frame-1]; + + /* Update LPC-related memories */ + mvr2r( lsp, st->lsp_old, M ); + mvr2r( lsf, st->lsf_old, M ); + st->envWeighted = 0; + mvr2r( A, st->old_Aq_12_8, M+1 ); + st->old_Es_pred = 0; + + /* Reset acelp memories */ + set_zero( st->dispMem, 8 ); + st->LPDmem.tilt_code = TILT_CODE; + st->LPDmem.gc_threshold = 0.0f; + + /* Update ace/tcx mode */ + st->core = ACELP_CORE; + + /* Reset TCX overlap */ + st->tcx_cfg.tcx_curr_overlap_mode = st->tcx_cfg.tcx_last_overlap_mode = ALDO_WINDOW; + + if( st->first_CNG == 0 ) + { + mvr2r( st->lsp_old, st->lspCNG, M ); + } + + return; +} diff --git a/lib_enc/core_switching_enc.c b/lib_enc/core_switching_enc.c new file mode 100644 index 000000000..b21a867de --- /dev/null +++ b/lib_enc/core_switching_enc.c @@ -0,0 +1,418 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_enc.h" +#include "rom_com.h" +#include "prot.h" +#include "math.h" +#include "assert.h" + +/*---------------------------------------------------------------------* + * core_switching_pre_enc() + * + * Preprocessing (preparing) for ACELP/HQ core switching + *---------------------------------------------------------------------*/ + +void core_switching_pre_enc( + Encoder_State *st, /* i/o: encoder state structure */ + LPD_state *mem, /* i/o: encoder state structure */ + const float *old_inp_12k8, /* i : old input signal @12.8kHz */ + const float *old_inp_16k /* i : old input signal @16kHz */ +) +{ + short Sample_Delay_HP, Sample_Delay_LP; + + + /* Codec mode switching */ + if( st->last_codec_mode == MODE2 ) + { + st->mem_deemph = st->LPDmem.syn[M]; + + mvr2r( mem->mem_syn2, st->mem_syn1, M ); + + st->igf = 0; + + if( st->last_core != ACELP_CORE ) + { + /* reset BWE memories */ + set_f( st->old_bwe_exc, 0, PIT16k_MAX*2 ); + st->bwe_non_lin_prev_scale = 0.0f; + } + set_f( st->old_syn_12k8_16k, 0, NS2SA(16000, DELAY_FD_BWE_ENC_NS) ); + + if( st->last_core == TCX_20_CORE || st->last_core == TCX_10_CORE ) + { + st->last_core = HQ_CORE; + + + set_f( st->last_ni_gain, 0, BANDS_MAX ); + set_f( st->last_env, 0, BANDS_MAX ); + st->last_max_pos_pulse = 0; + + st->mode_count = 0; + st->mode_count1 = 0; + + set_s( st->prev_SWB_peak_pos, 0, SPT_SHORTEN_SBNUM ); + st->prev_frm_hfe2 = 0; + st->prev_stab_hfe2 = 0; + + /*ALDO overlap windowed past: also used in MODE2 but for other MDCT-LB*/ + set_f( st->old_out, 0, L_FRAME32k ); + + } + if( st->L_frame == L_FRAME16k && st->last_L_frame==L_FRAME ) + { + mvr2r( st->lsp_old, st->lsp_old16k, M ); + st->rate_switching_reset_16kHz = lsp_convert_poly( st->lsp_old16k, L_FRAME16k, 0 ); + } + + st->use_acelp_preq = 0; + } + + if( st->last_core == -1 && st->core == HQ_CORE ) + { + /* very first frame is HQ_CORE */ + st->last_core = HQ_CORE; + } + + if( st->core == HQ_CORE && (st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE) ) /* HQ init */ + { + + set_f( st->last_ni_gain, 0, BANDS_MAX ); + set_f( st->last_env, 0, BANDS_MAX ); + st->last_max_pos_pulse = 0; + + st->mode_count = 0; + st->mode_count1 = 0; + + set_s( st->prev_SWB_peak_pos, 0, SPT_SHORTEN_SBNUM ); + st->prev_frm_hfe2 = 0; + st->prev_stab_hfe2 = 0; + + set_f( st->old_out, 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 */ + if( sub(st->core, ACELP_CORE) == 0 && ( st->last_core != ACELP_CORE || st->last_codec_mode == MODE2)) + { + st->last_last_ppp_mode = 0; + st->last_ppp_mode = 0; + st->last_nelp_mode =0; + } + + /* Handle state reset of stat_noise_uv_mod memory */ + if( st->core == ACELP_CORE && (st->last_core != ACELP_CORE || st->last_codec_mode == MODE2 || st->last_total_brate <= PPP_NELP_2k80 ) ) + { + st->act_count = 3; + st->uv_count = 0; + } + + if( (st->core == ACELP_CORE || st->core == AMR_WB_CORE) && st->last_core == HQ_CORE ) + { + /* Reset the ACELP core in case of HQ->ACELP core switching */ + + if(st->L_frame == L_FRAME16k ) + { + mvr2r( TRWB2_Ave, st->lsf_old, M ); /* init of LSP */ + lsf2lsp( st->lsf_old, st->lsp_old, M, INT_FS_16k ); + } + else + { + mvr2r( TRWB_Ave, st->lsf_old, M ); /* init of LSP */ + lsf2lsp( st->lsf_old, st->lsp_old, M, INT_FS_12k8 ); + } + + st->mem_deemph = 0; + st->LPDmem.syn[M] = 0; + set_f( mem->mem_syn2, 0.0f, M ); + set_f( mem->mem_syn, 0.0f, M ); + set_f( st->mem_syn1, 0.0f, M ); + st->Nb_ACELP_frames = 0; + + /* Reset ACELP parameters */ + set_zero( st->mem_MA, M ); + mvr2r( GEWB_Ave, st->mem_AR, M ); + mem->mem_w0 = 0.0f; + mem->tilt_code = 0.0f; + init_gp_clip(st->clip_var); + mem->gc_threshold = 0.0f; + set_f( st->dispMem, 0, 8 ); + + st->last_coder_type = GENERIC; + + mvr2r( st->old_pitch_buf + st->L_frame/L_SUBFR, st->old_pitch_buf, st->L_frame/L_SUBFR ); + set_f( st->old_pitch_buf + st->L_frame/L_SUBFR, L_SUBFR, st->L_frame/L_SUBFR ); + /* Reset old ACELP buffers */ + set_f( mem->old_exc, 0, L_EXC_MEM ); + set_f( st->old_bwe_exc, 0, PIT16k_MAX*2 ); + + + /* reset BWE memories */ + st->bwe_non_lin_prev_scale = 0.0; + set_f( st->old_syn_12k8_16k, 0, NS2SA(16000, DELAY_FD_BWE_ENC_NS) ); + } + + if( st->input_Fs >= 16000 && st->last_extl != WB_BWE && st->extl == WB_BWE ) + { + if( st->last_extl != SWB_BWE && st->last_extl != FB_BWE ) + { + st->prev_mode = NORMAL; + st->modeCount = 0; + } + + st->prev_L_swb_norm1 = 8; + } + + if( ( st->input_Fs >= 32000 && st->last_extl != SWB_BWE && st->extl == SWB_BWE ) || + ( st->input_Fs >= 48000 && st->last_extl != FB_BWE && st->extl == FB_BWE ) ) + { + /* we are switching to SWB BWE - reset SWB BWE buffers */ + if( st->L_frame == 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 ); + + mvr2r( old_inp_12k8 + L_INP_MEM + L_FRAME - Sample_Delay_LP, st->old_input_lp, 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 ); + + mvr2r( old_inp_16k + L_INP_MEM + L_FRAME - Sample_Delay_LP, st->old_input_lp, Sample_Delay_LP ); + } + mvr2r( st->old_speech_shb + L_LOOK_16k + L_SUBFR16k - Sample_Delay_HP, st->new_input_hp, Sample_Delay_HP ); + + if (st->last_extl != WB_BWE) + { + st->prev_mode = NORMAL; + st->modeCount = 0; + } + st->EnergyLF = 0.0f; + st->prev_L_swb_norm1 = 8; + } + + + + return; +} + + +/*---------------------------------------------------------------------* + * core_switching_post_enc() + * + * Postprocessing for ACELP/HQ core switching + *---------------------------------------------------------------------*/ + +void core_switching_post_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const float *old_inp_12k8, /* i : old input signal @12.8kHz */ + const float *old_inp_16k, /* i : old input signal @16kHz */ + const short pitch[3], /* i : open-loop pitch values for quantiz. */ + const float voicing[3], /* i : Open-loop pitch gains */ + const float A[] /* i : unquant. LP filter coefs. */ +) +{ + short T_op[3]; + + + + mvs2s( pitch, T_op, 3 ); + + + if( st->core == HQ_CORE ) + { + st->use_acelp_preq = 0; + + if( (st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE) ) /* core switching ==> CELP subframe encoding */ + { + acelp_core_switch_enc( st, &(st->LPDmem), old_inp_12k8 + L_INP_MEM - NS2SA(INT_FS_12k8, ACELP_LOOK_NS), + old_inp_16k + L_INP_MEM - NS2SA(INT_FS_16k, ACELP_LOOK_NS), T_op, voicing, A ); + } + + st->bwe_non_lin_prev_scale = 0.0; + st->mem_deemph_old_syn = 0.0f; + } + else + { + + /* reset SWB TBE buffers */ + if( st->extl == WB_TBE && st->last_extl != WB_TBE ) + { + wb_tbe_extras_reset( st->mem_genSHBexc_filt_down_wb2, st->mem_genSHBexc_filt_down_wb3 ); + + if( st->last_extl != WB_BWE ) + { + set_f( st->decim_state1, 0.0f, (2*ALLPASSSECTIONS_STEEP+1) ); + set_f( st->decim_state2, 0.0f, (2*ALLPASSSECTIONS_STEEP+1) ); + } + + set_f( st->state_syn_shbexc, 0, L_SHB_LAHEAD/4 ); + set_f( st->syn_overlap, 0, L_SHB_LAHEAD ); + set_f( st->mem_csfilt, 0, 2 ); + } + + if( (st->extl == SWB_TBE || st->extl == FB_TBE) && + ( st->last_core == HQ_CORE || st->L_frame != st->last_L_frame || (st->last_extl != SWB_TBE && st->last_extl != FB_TBE) ) + ) + { + set_f( st->state_ana_filt_shb, 0.0f, (2*ALLPASSSECTIONS_STEEP+1) ); + set_f( st->old_speech_shb, 0.0f, L_LOOK_16k + L_SUBFR16k ); + + swb_tbe_reset( st->mem_csfilt, st->mem_genSHBexc_filt_down_shb, st->state_lpc_syn, st->syn_overlap, + st->state_syn_shbexc, &(st->tbe_demph), &(st->tbe_premph), st->mem_stp_swb, &(st->gain_prec_swb) ); + + set_f( st->dec_2_over_3_mem,0.0f, 12 ); + set_f( st->dec_2_over_3_mem_lp,0.0f, 6 ); + + } + else if( (st->extl == SWB_TBE || st->extl == FB_TBE) && + ( (st->last_total_brate != st->total_brate) || (st->last_bwidth != st->bwidth) || + (st->last_codec_mode != MODE1) || (st->rf_mode_last != st->rf_mode) ) ) + { + set_f( st->state_lpc_syn, 0.0f, LPC_SHB_ORDER ); + set_f( st->state_syn_shbexc, 0.0f, L_SHB_LAHEAD ); + set_f( st->mem_stp_swb, 0.0f, LPC_SHB_ORDER ); + set_f( st->mem_zero_swb, 0, LPC_SHB_ORDER ); + st->gain_prec_swb = 1.0f; + } + + /* Interp_3_2 CNG buffers reset */ + + if( st->extl == FB_TBE && ( st->last_extl != FB_TBE || st->L_frame != st->last_L_frame ) ) + { + set_f(st->fb_state_lpc_syn, 0, LPC_SHB_ORDER); + st->fb_tbe_demph = 0; + fb_tbe_reset_enc( st->elliptic_bpf_2_48k_mem, &st->prev_fb_energy ); + } + } + + + + return; +} + + +/*---------------------------------------------------------------------* + * core_switching_hq_prepare_enc() + * + * Preprocessing in the first HQ frame after ACELP frame + * - modify bit allocation for HQ core removing CELP subframe budget + * - update st->old_wtda to modify windows at the encoder + *---------------------------------------------------------------------*/ + +void core_switching_hq_prepare_enc( + Encoder_State *st, /* i/o: encoder state structure */ + short *num_bits, /* i/o: bit budget update */ + const short input_frame, /* i : frame length */ + float *wtda_audio, + const float *audio +) +{ + short delta, Loverlapp, i; + short n; + long cbrate; + + /* set multiplication factor according to the sampling rate */ + delta = 1; + if( input_frame == L_FRAME16k ) + { + delta = 2; + } + else if( input_frame == L_FRAME32k ) + { + delta = 4; + } + else if( input_frame == L_FRAME48k ) + { + delta = 6; + } + + /* set switching frame bit-rate */ + if( st->last_L_frame == L_FRAME) + { + if( st->core_brate > ACELP_24k40 ) + { + cbrate = ACELP_24k40; + } + else + { + cbrate = st->core_brate; + } + /* subtract ACELP switching frame bits */ + if( st->core_brate >= ACELP_11k60 ) + { + /* subtract one bit for LP filtering flag */ + (*num_bits)--; + } + + *num_bits -= ACB_bits_tbl[BIT_ALLOC_IDX(cbrate, GENERIC, 0, 0)]; /* pitch bits */ + *num_bits -= gain_bits_tbl[BIT_ALLOC_IDX(cbrate, TRANSITION, 0, 0)]; /* gain bits */ + *num_bits -= FCB_bits_tbl[BIT_ALLOC_IDX(cbrate, GENERIC, 0, 0)]; /* FCB bits */ + } + else /* L_frame == L_FRAME16k */ + { + if( st->core_brate <= ACELP_8k00 ) + { + cbrate = ACELP_8k00; + } + else if( st->core_brate <= ACELP_14k80 ) + { + cbrate = ACELP_14k80; + } + else + { + cbrate = min(st->core_brate,ACELP_22k60); + } + + /* subtract ACELP switching frame bits */ + if( st->core_brate >= ACELP_11k60 ) + { + /* subtract one bit for LP filtering flag */ + (*num_bits)--; + } + + + *num_bits -= ACB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ(cbrate, GENERIC, 0, 0)]; /* pitch bits */ + *num_bits -= gain_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ(cbrate, GENERIC, 0, 0)]; /* gain bits */ + *num_bits -= FCB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ(cbrate, GENERIC, 0, 0)]; /* FCB bits */ + } + + /* subtract BWE bits */ + if ( !((inner_frame_tbl[st->bwidth]==L_FRAME16k && st->last_L_frame==L_FRAME16k)|| inner_frame_tbl[st->bwidth] == L_FRAME8k) ) + { + *num_bits -= (NOOFGAINBITS1 + AUDIODELAYBITS); + } + + + n = ((float)input_frame * N_ZERO_MDCT_NS/FRAME_SIZE_NS); + + /* Transition window at the encoder */ + Loverlapp = delta*SWITCH_OVERLAP_8k; + for( i = 0; i old_out, 0.0f, L_FRAME32k ); + + return; +} diff --git a/lib_enc/corr_xh.c b/lib_enc/corr_xh.c new file mode 100644 index 000000000..3a5b07ddd --- /dev/null +++ b/lib_enc/corr_xh.c @@ -0,0 +1,42 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "prot.h" +#include "cnst.h" + +/*-------------------------------------------------------------------* + * corr_xh() + * + * 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( + const float *x, /* i : target signal */ + float *y, /* o : correlation between x[] and h[] */ + const float *h, /* i : impulse response (of weighted synthesis filter) */ + const int L_subfr /* i : length of the subframe */ +) +{ + short i, j; + float s; + + for (i = 0; i < L_subfr; i++) + { + s = 0.0f; + for (j = i; j < L_subfr; j++) + { + s += x[j]*h[j-i]; + } + + y[i] = s; + } + + return; +} diff --git a/lib_enc/decision_matrix_enc.c b/lib_enc/decision_matrix_enc.c new file mode 100644 index 000000000..823fe8ce1 --- /dev/null +++ b/lib_enc/decision_matrix_enc.c @@ -0,0 +1,637 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "prot.h" +#include "stat_enc.h" +#include "stat_dec.h" +#include "rom_com.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 1 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 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( + Encoder_State *st, /* i : encoder state structure */ + const short sp_aud_decision1, /* i : 1st stage speech/music classification */ + const short sp_aud_decision2, /* i : 2nd stage speech/music classification */ + const short coder_type, /* i : coder type */ + const short vad_flag, + short *hq_core_type /* o : HQ core type */ +) +{ + /* initialization */ + st->core = -1; + st->extl = -1; + st->extl_brate = 0; + *hq_core_type = -1; + st->igf = 0; + + /* SID and FRAME_NO_DATA frames */ + if( st->Opt_DTX_ON && (st->core_brate == SID_2k40 || st->core_brate == FRAME_NO_DATA ) ) + { + st->core = ACELP_CORE; + + if( st->input_Fs >= 32000 && st->bwidth >= SWB ) + { + st->extl = SWB_CNG; + } + + st->rf_mode = 0; + + return; + } + + st->core_brate = 0; + + /* SC-VBR */ + if ( st->Opt_SC_VBR ) + { + /* SC-VBR */ + st->core = ACELP_CORE; + st->core_brate = ACELP_7k20; + st->total_brate = ACELP_7k20; + + if ( st->ppp_mode == 1 ) + { + /* PPP mode */ + st->core_brate = PPP_NELP_2k80; + } + else if( ((coder_type == UNVOICED || coder_type == TRANSITION) && !sp_aud_decision1) || st->bwidth != NB ) + { + + if( coder_type == UNVOICED && vad_flag == 1 && ( ( st->last_bwidth >= SWB && st->last_Opt_SC_VBR ) || st->last_bwidth < SWB ) + && (st->last_core!=HQ_CORE || st->bwidth != NB) ) + { + /* NELP mode */ + st->nelp_mode = 1; + st->core_brate = PPP_NELP_2k80; + } + else if ( coder_type == TRANSITION || ( coder_type == UNVOICED && st->nelp_mode != 1 ) || + ( ( coder_type == AUDIO || coder_type == INACTIVE ) && st->bwidth != NB ) ) + { + /* silence portions */ + st->core_brate = ACELP_8k00; + st->total_brate = ACELP_8k00; + } + } + + return; + } + + /*---------------------------------------------------------------------* + * NB + *---------------------------------------------------------------------*/ + + else if ( st->bwidth == NB ) + { + st->core = ACELP_CORE; + + if( st->total_brate >= HQCORE_NB_MIN_RATE && sp_aud_decision1 == 1 ) + { + st->core = HQ_CORE; + } + } + + /*---------------------------------------------------------------------* + * WB + *---------------------------------------------------------------------*/ + + else if ( st->bwidth == WB ) + { + st->core = ACELP_CORE; + + if( ( st->total_brate >= HQCORE_WB_MIN_RATE && sp_aud_decision1 == 1 ) || st->total_brate >= HQ_96k ) + { + st->core = HQ_CORE; + } + else + { + if ( st->bwidth == WB && st->total_brate < ACELP_9k60 ) + { + st->extl = WB_BWE; + } + else if ( st->bwidth == WB && st->total_brate >= ACELP_9k60 && st->total_brate <= ACELP_16k40 ) + { + /* Note: WB BWE is used exceptionally at 13.2 kbps if GSC is selected instead of LR-MDCT */ + if ( sp_aud_decision1 == 1 || coder_type == INACTIVE || ( sp_aud_decision1 == 0 && sp_aud_decision2 == 1 ) ) + { + st->extl = WB_BWE; + st->extl_brate = WB_BWE_0k35; + } + else + { + st->extl = WB_TBE; + st->extl_brate = WB_TBE_1k05; + } + } + } + } + + /*---------------------------------------------------------------------* + * SWB and FB + *---------------------------------------------------------------------*/ + + else if ( st->bwidth == SWB || st->bwidth == FB ) + { + if( ( st->total_brate >= HQCORE_SWB_MIN_RATE && sp_aud_decision1 == 1 ) || st->total_brate >= HQ_96k ) + { + st->core = HQ_CORE; + } + else + { + st->core = ACELP_CORE; + + if ( st->total_brate >= ACELP_13k20 && st->total_brate < 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 */ + if ( ( sp_aud_decision1 == 1 || coder_type == INACTIVE || ( sp_aud_decision1 == 0 && sp_aud_decision2 == 1 ) ) && !st->GSC_noisy_speech ) + { + st->extl = SWB_BWE; + st->extl_brate = SWB_BWE_1k6; + + if ( st->bwidth == FB && st->total_brate >= ACELP_24k40 ) + { + st->extl = FB_BWE; + st->extl_brate = FB_BWE_1k8; + } + } + else + { + st->extl = SWB_TBE; + st->extl_brate = SWB_TBE_1k6; + + if( st->total_brate >= ACELP_24k40 ) + { + st->extl_brate = SWB_TBE_2k8; + } + + if ( st->bwidth == FB && st->total_brate >= ACELP_24k40 ) + { + st->extl = FB_TBE; + st->extl_brate = FB_TBE_3k0; + } + } + } + else if ( st->total_brate >= ACELP_48k ) + { + st->extl = SWB_BWE_HIGHRATE; + st->extl_brate = SWB_BWE_16k; + + if( st->bwidth == FB ) + { + st->extl = FB_BWE_HIGHRATE; + } + } + } + } + + /*-----------------------------------------------------------------* + * Set HQ core type + *-----------------------------------------------------------------*/ + + if( st->core == HQ_CORE ) + { + *hq_core_type = NORMAL_HQ_CORE; + + if( (st->bwidth == SWB || st->bwidth == WB) && st->total_brate <= LRMDCT_CROSSOVER_POINT ) + { + /* note that FB (bit-rate >= 24400bps) is always coded with NORMAL_HQ_CORE */ + *hq_core_type = LOW_RATE_HQ_CORE; + } + else if( st->bwidth == NB ) + { + *hq_core_type = LOW_RATE_HQ_CORE; + } + } + + /* set core bitrate */ + st->core_brate = st->total_brate - st->extl_brate; + + if ( st->ini_frame == 0 ) + { + /* avoid switching in the very first frame */ + st->last_core = st->core; + st->last_core_brate = st->core_brate; + st->last_extl = st->extl; + } + + return; +} + +/*---------------------------------------------------------------------* + * signalling_mode1_tcx20_enc() + * + * write MODE1 TCX20 signalling information into the bit-stream + *---------------------------------------------------------------------*/ + +short signalling_mode1_tcx20_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const short push /* i : flag to push indice */ +) +{ + short num_bits; + short nBits, idx, start_idx; + + assert(st->core == TCX_20_CORE); + + num_bits = 0; + + /* Use ACELP signaling for LR MDCT */ + if ( st->total_brate <= ACELP_16k40 ) + { + /* find the section in the ACELP signalling table corresponding to bitrate */ + idx = 0; + while ( acelp_sig_tbl[idx] != st->total_brate ) + { + idx++; + } + + /* retrieve the number of bits for signalling */ + nBits = (short) acelp_sig_tbl[++idx]; + + /* retrieve the signalling index */ + start_idx = ++idx; + while( acelp_sig_tbl[idx] != SIG2IND(LR_MDCT, st->bwidth, 0, 0) ) + { + idx++; + } + + num_bits += nBits; + if( push ) + { + push_indice( st, IND_ACELP_SIGNALLING, idx - start_idx, nBits ); + } + + /* HQ/TCX core switching flag */ + ++num_bits; + if( push ) + { + push_indice( st, IND_MDCT_CORE, 1, 1 ); + } + } + else + { + if( st->core_brate <= ACELP_64k ) + { + /* write ACELP/HQ core indication flag */ + ++num_bits; + if( push ) + { + push_indice( st, IND_CORE, 1, 1 ); + } + } + + /* HQ/TCX core switching flag */ + ++num_bits; + if( push ) + { + push_indice( st, IND_MDCT_CORE, 1, 1 ); + } + + num_bits += 2; + if( push ) + { + /* write band-width (needed for different I/O sampling rate support) */ + if( st->bwidth == NB ) + { + push_indice( st, IND_HQ_BWIDTH, 0, 2 ); + } + else if( st->bwidth == WB ) + { + push_indice( st, IND_HQ_BWIDTH, 1, 2 ); + } + else if( st->bwidth == SWB ) + { + push_indice( st, IND_HQ_BWIDTH, 2, 2 ); + } + else /* st->bwidth == FB */ + { + push_indice( st, IND_HQ_BWIDTH, 3, 2 ); + } + } + } + + return num_bits; +} + + +/*---------------------------------------------------------------------* + * signalling_enc() + * + * write signalling information into the bit-stream + *---------------------------------------------------------------------*/ + +void signalling_enc( + Encoder_State *st, /* i : encoder state structure */ + const short coder_type, /* i : coder type */ + const short sharpFlag /* i : formant sharpening flag */ +) +{ + short nBits, idx, start_idx; + + if( st->mdct_sw == MODE2 ) + { + + assert(!st->tcxonly); + assert(st->core == HQ_CORE); + + push_next_indice(st, 1, 1); /* TCX */ + push_next_indice(st, 1, 1); /* HQ_CORE */ + + /* write ACELP->HQ core switching flag */ + if( st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE ) + { + push_indice( st, IND_HQ_SWITCHING_FLG, 1, 1 ); + + /* write ACELP L_frame info */ + if( st->last_L_frame == L_FRAME ) + { + push_indice( st, IND_LAST_L_FRAME, 0, 1 ); + } + else + { + push_indice( st, IND_LAST_L_FRAME, 1, 1 ); + } + } + else + { + push_indice( st, IND_HQ_SWITCHING_FLG, 0, 1 ); + } + + return; + } + + if( st->core == ACELP_CORE ) + { + if( st->ppp_mode == 1 || st->nelp_mode == 1 ) + { + /* 1 bit to distinguish between 2.8kbps PPP/NELP frame and SID frame */ + push_indice( st, IND_CORE, 0, 1 ); + + /* SC-VBR: 0 - PPP_NB, 1 - PPP_WB, 2 - NELP_NB, 3 - NELP_WB */ + if ( coder_type == VOICED && st->bwidth == NB && st->ppp_mode == 1 ) + { + push_indice( st, IND_PPP_NELP_MODE, 0, 2 ); + } + else if ( coder_type == VOICED && st->bwidth != NB && st->ppp_mode == 1 ) + { + push_indice( st, IND_PPP_NELP_MODE, 1, 2 ); + } + else if ( coder_type == UNVOICED && st->bwidth == NB && st->nelp_mode == 1 ) + { + push_indice( st, IND_PPP_NELP_MODE, 2, 2); + } + else if ( coder_type == UNVOICED && st->bwidth != NB && st->nelp_mode == 1 ) + { + push_indice( st, IND_PPP_NELP_MODE, 3, 2 ); + } + } + else if( st->core_brate != SID_2k40 && st->core_brate != FRAME_NO_DATA ) + { + /* write the ACELP/HQ core selection bit */ + if (st->total_brate >= ACELP_24k40 ) + { + push_indice( st, IND_CORE, 0, 1 ); + } + + /* find the section in the ACELP signalling table corresponding to bitrate */ + idx = 0; + while ( acelp_sig_tbl[idx] != st->total_brate ) + { + idx++; + } + + /* retrieve the number of bits for signalling */ + nBits = (short) acelp_sig_tbl[++idx]; + + /* retrieve the signalling index */ + start_idx = ++idx; + while( acelp_sig_tbl[idx] != SIG2IND(coder_type, st->bwidth, sharpFlag, st->rf_mode) ) + { + idx++; + } + + push_indice( st, IND_ACELP_SIGNALLING, idx - start_idx, nBits ); + } + + /* write extension layer flag to distinguish between TBE (0) and BWE (1) */ + if( st->extl_brate > 0 ) + { + if( st->extl == WB_TBE || st->extl == SWB_TBE || st->extl == FB_TBE ) + { + push_indice( st, IND_BWE_FLAG, 0, 1 ); + } + else if( st->extl == WB_BWE || st->extl == SWB_BWE || st->extl == FB_BWE ) + { + push_indice( st, IND_BWE_FLAG, 1, 1 ); + } + } + } + else /* HQ core */ + { + /* write ACELP->HQ core switching flag */ + if( st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE ) + { + push_indice( st, IND_HQ_SWITCHING_FLG, 1, 1 ); + + /* write ACELP L_frame info */ + if( st->last_L_frame == L_FRAME ) + { + push_indice( st, IND_LAST_L_FRAME, 0, 1 ); + } + else + { + push_indice( st, IND_LAST_L_FRAME, 1, 1 ); + } + } + else + { + push_indice( st, IND_HQ_SWITCHING_FLG, 0, 1 ); + } + + /* HQ/TCX core switching flag */ + push_indice( st, IND_MDCT_CORE, 0, 1 ); + + /* Use ACELP signaling for LR MDCT */ + if ( st->total_brate <= ACELP_16k40 ) + { + /* find the section in the ACELP signalling table corresponding to bitrate */ + idx = 0; + while ( acelp_sig_tbl[idx] != st->total_brate ) + { + idx++; + } + + /* retrieve the number of bits for signalling */ + nBits = (short) acelp_sig_tbl[++idx]; + + /* retrieve the signalling index */ + start_idx = ++idx; + while( acelp_sig_tbl[idx] != SIG2IND(LR_MDCT, st->bwidth, 0, 0) ) + { + idx++; + } + + push_indice( st, IND_ACELP_SIGNALLING, idx - start_idx, nBits ); + } + else + { + if( st->core_brate <= ACELP_64k ) + { + /* write ACELP/HQ core indication flag */ + push_indice( st, IND_CORE, 1, 1 ); + } + + /* write band-width (needed for different I/O sampling rate support) */ + if( st->bwidth == NB ) + { + push_indice( st, IND_HQ_BWIDTH, 0, 2 ); + } + else if( st->bwidth == WB ) + { + push_indice( st, IND_HQ_BWIDTH, 1, 2 ); + } + else if( st->bwidth == SWB ) + { + push_indice( st, IND_HQ_BWIDTH, 2, 2 ); + } + else /* st->bwidth == FB */ + { + push_indice( st, IND_HQ_BWIDTH, 3, 2 ); + } + } + } + + return; +} + +/*---------------------------------------------------------------------* + * signalling_enc_rf() + * + * write channel-aware signalling information into the bit-stream + *---------------------------------------------------------------------*/ + +void signalling_enc_rf( + Encoder_State *st /* i/o: encoder state structure */ +) +{ + short i, tmp_rf, sfr; + + /* write partial copy into bitstream */ + if( 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.c b/lib_enc/detect_transient.c new file mode 100644 index 000000000..b8bbc1e64 --- /dev/null +++ b/lib_enc/detect_transient.c @@ -0,0 +1,229 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "prot.h" +#include "cnst.h" +#include "rom_com.h" + + +/*-------------------------------------------------------------------------- + * hp_filter() + * + * High pass filter + *--------------------------------------------------------------------------*/ + +static void hp_filter( + const float *x, /* i : input signal */ + float *y, /* o : output signal */ + float *oldx, /* i/o: previous filter input */ + float *oldy, /* i/o: previous filter output */ + const short L /* i : length (32 or 48Hz) */ +) +{ + short i; + + y[0] = 0.4931f * *oldy + 0.7466f*(x[0] - *oldx); + + for(i = 1; i < L; i++) + { + y[i] = 0.4931f*y[i-1] + 0.7466f*(x[i] - x[i-1]); + } + + *oldx = x[L - 1]; + *oldy = y[L - 1]; + + return; +} + +/*-------------------------------------------------------------------------- + * detect_transient() + * + * Detect if the signal is a transient + *--------------------------------------------------------------------------*/ + +short detect_transient( /* o : transient flag */ + const float *in, /* i : input signal */ + Encoder_State *st, /* i/o: Encoder state structure */ + const short L, /* i : length (32 or 48kHz) */ + const short coder_type /* i : coder type */ +) +{ + float Energy; + float EnergyLT; + short i, blk; + short IsTransient; + float out_filt[L_FRAME48k]; + short position = 0; + float thr; + float Thres = 0.f; + float Energy_in[5]; + float E_low, E_high; + float E_in = 0.0f, E_out = 0.0f; + + IsTransient = 0; + + if( st->last_extl != st->extl ) + { + st->TransientHangOver = 0; + st->old_hpfilt_in = 0; + st->old_hpfilt_out = 0; + st->Energy_Old = 0; + } + + /* High-pass filter */ + hp_filter( in, out_filt, &(st->old_hpfilt_in), &(st->old_hpfilt_out), L ); + + /* Long-term energy */ + if( st->last_extl != st->extl || (st->last_extl == st->extl && st->last_core != st->core) || st->last_codec_mode == MODE2 ) + { + EnergyLT = EPSILON; + for ( i = 0; i < L/4; i++ ) + { + EnergyLT += out_filt[i] * out_filt[i]; + } + } + else + { + EnergyLT = st->EnergyLT; + } + + if(L == L_FRAME8k) + { + Energy_in[0] = st->Energy_Old; + E_in = 0; + E_out = 0; + + /* Compute block energy */ + for ( blk = 0; blk < 4; blk++ ) + { + Energy = EPSILON; + Energy_in[blk+1] = EPSILON; + + for ( i = 0; i < L/4; i++ ) + { + Energy += out_filt[i + blk*(L/4)] * out_filt[i + blk*(L/4)]; + Energy_in[blk+1] += in[i + blk*(L/4)] * in[i + blk*(L/4)]; + } + + E_in += Energy_in[blk+1]; + E_out += Energy; + + Thres = 15.f; + + if(Energy > 6.0f * EnergyLT) + { + IsTransient = 1; + position = blk; + } + + EnergyLT = 0.75f*EnergyLT + 0.25f*Energy; + } + } + else + { + /* Compute block energy */ + for ( blk = 0; blk < 4; blk++ ) + { + Energy = EPSILON; + for ( i = 0; i < L/4; i++ ) + { + Energy += out_filt[i + blk*(L/4)] * out_filt[i + blk*(L/4)]; + } + + if( st->extl == SWB_BWE || st->extl == FB_BWE ) + { + if( ( Energy > 13.5f * EnergyLT ) || ( Energy > 10.0f * EnergyLT && coder_type == INACTIVE ) ) + { + IsTransient = 1; + position = blk; + } + } + else + { + if( st->total_brate <= HQ_16k40 && st->bwidth == SWB ) + { + thr = 13.5f; + } + else + { + thr = 6.0f; + } + + if( Energy > thr * EnergyLT ) + { + IsTransient = 1; + position = blk; + } + } + + EnergyLT = 0.75f*EnergyLT + 0.25f*Energy; + } + } + + st->EnergyLT = EnergyLT; + + if( ( st->last_extl != SWB_BWE && st->last_extl != SWB_TBE && st->extl == SWB_BWE ) || + ( st->last_extl != FB_BWE && st->last_extl != FB_TBE && st->extl == FB_BWE ) ) + { + IsTransient = 0; + } + + if( IsTransient && L == L_FRAME8k ) + { + E_low = 0.f; + blk = 0; + for(i=0; i0.7f)) && ((E_in/E_out)>Thres) ) + { + IsTransient = 0; + } + } + + if ( IsTransient ) + { + if(L == L_FRAME8k) + { + if( position == 3 ) + { + st->TransientHangOver = 1; + } + } + else + { + st->TransientHangOver = 1; + } + } + else + { + if( st->TransientHangOver ) + { + st->TransientHangOver = 0; + IsTransient = 1; + } + } + + if( L == L_FRAME8k ) + { + st->Energy_Old = Energy_in[4]; + } + + return IsTransient; +} diff --git a/lib_enc/diffcod.c b/lib_enc/diffcod.c new file mode 100644 index 000000000..474ae0560 --- /dev/null +++ b/lib_enc/diffcod.c @@ -0,0 +1,125 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "prot.h" +#include "rom_com.h" + + +/*--------------------------------------------------------------------------*/ +/* Function diffcod */ +/* ~~~~~~~~~~~~~~~~~ */ +/* */ +/* Differential coding for indices of quantized norms */ +/*--------------------------------------------------------------------------*/ +/* short *normqlg2 (o) quantized norms in log2 */ +/* short N (i) number of sub-vectors */ +/* short *y (i/o) indices of quantized norms */ +/* short *difidx (o) differential code */ +/*--------------------------------------------------------------------------*/ + +void diffcod( + const short N, + short *y, + short *difidx +) +{ + short i, k, r; + + for (i=N-1; i>0; i--) + { + r = i - 1; + k = y[i] - y[r]; + if (k<(-15)) + { + y[r] = y[i] + 15; + } + } + + for (i=1; i16) + { + k = 16; + y[i] = y[r] + 16; + } + difidx[r] = k + 15; + } + + return; +} + + + + +/*-------------------------------------------------------------------------- + * diffcod_lrmdct() + * + * Differential coding for indices of quantized norms + *--------------------------------------------------------------------------*/ + +void diffcod_lrmdct( + const short N, /* i : number of sub-vectors */ + const int be_ref, /* o : band energy reference */ + int *y, /* i/o: indices of quantized norms */ + int *difidx, /* o : differential code */ + const short is_transient /* i : transient flag */ +) +{ + short i, m, r; + int k; + int thr_l,thr_h; + + if(is_transient) + { + thr_l=-15; + thr_h=16; + } + else + { + thr_l=-32; + thr_h=31; + } + + difidx[0] = y[0] - be_ref; + if(difidx[0]>thr_h) + { + difidx[0] = thr_h; + y[0] = be_ref + thr_h; + } + + if(difidx[0]0; i--) + { + r = i - 1; + k = y[i] - y[r]; + if (kthr_h) + { + k = thr_h; + y[i] = y[r] + thr_h; + } + difidx[i] = k; + } + + return; +} diff --git a/lib_enc/dtx.c b/lib_enc/dtx.c new file mode 100644 index 000000000..96d8de74b --- /dev/null +++ b/lib_enc/dtx.c @@ -0,0 +1,665 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define ALPHA_ENER_SLOW 0.99f /* Slow adaptation (noise up, speech down) */ +#define ALPHA_ENER_FAST 0.90f /* Fast adaptation (noise down, speech up) */ +#define MIN_CNT 50 /* Minimum frame number before SID interval adaptation */ + +#define SNR_H 51.0f /* Estimated SNR and corresponding SID interval */ +/* 51dB corresponds to 25dB SNR before noise supressor */ +#define SNR_L 36.0f +#define INT_H 50 +#define INT_L 8 + +#define LTE_VAR -4.0f + +#define CNG_TYPE_HO 20 /* hangover for switching between CNG types */ + + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static void update_SID_cnt( Encoder_State *st ); + + +/*-------------------------------------------------------------------* + * dtx() + * + * Discontinuous transmission operation + *-------------------------------------------------------------------*/ + +void dtx( + Encoder_State *st, /* i/o: encoder state structure */ + const short vad, /* i : vad flag */ + const float speech[] /* i : Pointer to the speech frame */ +) +{ + float alpha; + + /* Initialization */ + if( st->ini_frame == 0 ) + { + st->active_cnt = CNG_TYPE_HO; + if( st->codec_mode == MODE1 || st->Opt_AMR_WB ) + { + st->cng_type = LP_CNG; + } + else + { + st->cng_type = FD_CNG; + } + } + + if( st->Opt_DTX_ON && vad == 0 && + st->ini_frame > 2 && /* CNG coding starts after 3 frames */ + st->fd_cng_reset_flag == 0 && + st->last_core != AMR_WB_CORE && + st->Opt_AMR_WB == 0 ) + { + if ( st->last_core_brate > SID_2k40 && + st->last_total_brate_cng != -1 && + st->last_total_brate_cng != st->total_brate && + (st->last_total_brate_cng <= ACELP_24k40 || st->lp_noise < 15) + ) + { + st->total_brate = st->last_total_brate_cng; + if( !(st->total_brate == ACELP_7k20 && st->Opt_SC_VBR) ) + { + st->Opt_SC_VBR = 0; + } + + st->rf_mode = st->last_rf_mode_cng; + st->bwidth = st->last_bwidth_cng; + st->codec_mode = st->last_codec_mode_cng; + } + if ( st->last_core_brate <= SID_2k40 && + st->last_total_brate != st->total_brate && + ( st->last_total_brate <= ACELP_24k40 || st->lp_noise < 15 ) ) + { + st->total_brate = st->last_total_brate; + if( !(st->total_brate == ACELP_7k20 && st->Opt_SC_VBR) ) + { + st->Opt_SC_VBR = 0; + } + + st->Opt_RF_ON = 0; + if( st->rf_mode && st->rf_fec_offset > 0 && st->total_brate == ACELP_13k20 && st->bwidth != NB ) + { + st->Opt_RF_ON = 1; + } + st->rf_mode = st->Opt_RF_ON; + st->bwidth = st->last_bwidth; + switch ( st->total_brate ) + { + case 5900: + st->codec_mode = MODE1; + break; + case 7200: + st->codec_mode = MODE1; + break; + case 8000: + st->codec_mode = MODE1; + break; + case 9600: + st->codec_mode = MODE2; + break; + case 13200: + st->codec_mode = MODE1; + break; + case 16400: + st->codec_mode = MODE2; + break; + case 24400: + st->codec_mode = MODE2; + break; + case 32000: + st->codec_mode = MODE1; + break; + case 48000: + st->codec_mode = MODE2; + break; + case 64000: + st->codec_mode = MODE1; + break; + case 96000: + st->codec_mode = MODE2; + break; + case 128000: + st->codec_mode = MODE2; + break; + } + } + } + + /*------------------------------------------------------------------------* + * Select SID or FRAME_NO_DATA frame if DTX is enabled + *------------------------------------------------------------------------*/ + + if( st->Opt_DTX_ON && vad == 0 && + st->ini_frame > 2 && /* CNG coding starts after 3 frames */ + ( st->total_brate <= ACELP_24k40 || st->lp_noise < 15 ) && /* at higher bitrates, DTX kicks in only when the level of background noise is low */ + st->fd_cng_reset_flag == 0 ) + { + /* reset counter */ + st->active_cnt = 0; + + if ( st->Opt_AMR_WB ) + { + st->last_total_brate_cng = -1; + } + else + { + st->last_total_brate_cng = st->total_brate; + st->last_bwidth_cng = st->bwidth; + st->last_codec_mode_cng = st->codec_mode; + st->last_rf_mode_cng = st->rf_mode; + } + + if( st->cnt_SID == 0 ) + { + /* this will be a SID frame */ + if ( st->Opt_AMR_WB ) + { + st->core_brate = SID_1k75; + } + else + { + st->core_brate = SID_2k40; + } + } + else + { + /* this will be a no data frame */ + st->core_brate = FRAME_NO_DATA; + } + + if( st->core_brate == FRAME_NO_DATA && st->last_core != ACELP_CORE && !st->Opt_AMR_WB ) + { + /* force SID frame when switching from HQ core or AMR-WB IO mode into inactive frame in ACELP core when DTX is on */ + st->core_brate = SID_2k40; + } + + if( st->cng_type == FD_CNG && st->total_brate <= ACELP_24k40 ) /* at highest bit-rates, use exclusively LP_CNG */ + { + if ( st->total_brate == ACELP_9k60 || st->total_brate == ACELP_16k40 || st->total_brate == ACELP_24k40 ) + { + st->codec_mode = MODE2; + } + } + else + { + st->cng_type = LP_CNG; + if ( st->codec_mode == MODE2 ) + { + st->lp_cng_mode2 = 1; + } + st->codec_mode = MODE1; + } + } + + /*------------------------------------------------------------------------* + * Reset counters when in active frame (neither SID nor FRAME_NO_DATA frame) + *------------------------------------------------------------------------*/ + + if( st->core_brate != SID_2k40 && st->core_brate != SID_1k75 && st->core_brate != 0 ) + { + st->cnt_SID = 0; + + /* change SID update rate */ + /* first SID update is only 8 (3 in AMR-WB IO mode) frames after the active speech end */ + if( !st->Opt_AMR_WB ) + { + st->max_SID = FIXED_SID_RATE; + } + else + { + st->max_SID = 3; + } + + if ( st->max_SID > st->interval_SID ) + { + st->max_SID = st->interval_SID; + } + + /* reset the counter of CNG frames for averaging */ + st->cng_cnt = 0; + + if( st->active_cnt >= CNG_TYPE_HO && !st->Opt_AMR_WB ) + { + if ( st->cng_type == LP_CNG && ( (st->input_bwidth == NB && st->bckr_tilt_lt > 9.f) || (st->input_bwidth > NB && st->bckr_tilt_lt > 45.f) ) ) + { + st->cng_type = FD_CNG; + } + else if ( st->cng_type == FD_CNG && ( (st->input_bwidth == NB && st->bckr_tilt_lt < 2.f) || (st->input_bwidth > NB && st->bckr_tilt_lt < 10.f) ) ) + { + st->cng_type = LP_CNG; + } + st->last_total_brate_cng = -1; + } + else if( st->Opt_AMR_WB ) + { + st->cng_type = LP_CNG; + } + + st->active_cnt++; + st->active_cnt = min(st->active_cnt,200); + } + + /*------------------------------------------------------------------------* + * Update speech and background noise long-term energy + *------------------------------------------------------------------------*/ + + st->frame_ener = 0.0f; + + if ( st->Opt_DTX_ON ) + { + st->frame_ener = sum2_f( speech, L_FRAME ); + + /* Active speech (voiced) */ + if ( st->clas == VOICED_CLAS ) + { + alpha = ALPHA_ENER_SLOW; + if ( st->frame_ener > st->lt_ener_voiced ) + { + alpha = ALPHA_ENER_FAST; + } + + st->lt_ener_voiced = alpha * st->lt_ener_voiced + (1.0f-alpha) * st->frame_ener; + + (st->VarDTX_cnt_voiced)++; + + if (st->VarDTX_cnt_voiced > MIN_CNT) + { + st->VarDTX_cnt_voiced = MIN_CNT; + } + } + + /* Background noise */ + else if( !st->Opt_AMR_WB ) + { + alpha = ALPHA_ENER_SLOW; + if (st->frame_ener < st->lt_ener_noise) + { + alpha = ALPHA_ENER_FAST; + } + + st->lt_ener_noise = alpha * st->lt_ener_noise + (1.0f-alpha) * st->frame_ener; + + (st->VarDTX_cnt_noise)++; + + if ( st->VarDTX_cnt_noise > MIN_CNT) + { + st->VarDTX_cnt_noise = MIN_CNT; + } + } + } + + /* Update of the SID counter */ + update_SID_cnt( st ); + + /* Update encoded bandwidth */ + if( st->Opt_DTX_ON && (st->core_brate == SID_2k40 || st->core_brate == FRAME_NO_DATA ) ) + { + st->bwidth = st->last_bwidth; + if( st->last_core_brate > SID_2k40 && st->last_total_brate_cng != -1 ) + { + st->bwidth = st->last_bwidth_cng; + } + + if( st->Opt_RF_ON && st->total_brate == ACELP_13k20 && st->bwidth == NB ) + { + st->codec_mode = MODE1; + reset_rf_indices(st); + st->Opt_RF_ON = 0; + st->rf_mode = 0; + } + + if( st->Opt_RF_ON && st->total_brate != ACELP_13k20 ) + { + reset_rf_indices(st); + st->Opt_RF_ON = 0; + st->rf_mode = 0; + } + + if ( st->codec_mode == MODE2 ) + { + short n, bits_frame_nominal, tmpBandwidthMin; + + bits_frame_nominal = st->total_brate / 50; + for( n=0; nrf_mode ) + { + tmpBandwidthMin = WB; + } + + st->bwidth = max(min(st->bwidth, FrameSizeConfig[n].bandwidth_max), tmpBandwidthMin); + } + + } + + return; +} + + +/*---------------------------------------------------------------------* + * update_SID_cnt() + * + * Update of the SID counter + *---------------------------------------------------------------------*/ + +static void update_SID_cnt( + Encoder_State *st /* i/o: State structure */ +) +{ + float EstimatedSNR, delta; + + if( st->core_brate == SID_2k40 || st->core_brate == SID_1k75 || st->core_brate == FRAME_NO_DATA ) + { + /* Adapt the SID interval */ + if ( st->var_SID_rate_flag && st->VarDTX_cnt_voiced == MIN_CNT && st->VarDTX_cnt_noise == MIN_CNT ) + { + EstimatedSNR = 10.0f * (float)log10( (0.01f + st->lt_ener_voiced) / (0.01f + st->lt_ener_noise) ); + if ( EstimatedSNR > SNR_H ) + { + st->interval_SID = INT_H; + } + else if ( EstimatedSNR < SNR_L ) + { + st->interval_SID = INT_L; + } + else + { + st->interval_SID = INT_L + (short)((INT_H - INT_L) * (EstimatedSNR - SNR_L)/(SNR_H - SNR_L)); + } + st->interval_SID = min(max(st->interval_SID, INT_L), INT_H); + + if( !st->Opt_AMR_WB || st->max_SID != 3 ) + { + st->max_SID = st->interval_SID; /* change SID update rate */ + } + } + + if( st->Opt_DTX_ON == 1 && st->cnt_SID != 0 ) + { + /* Send SID frame only if long-term energy variation is above threshold */ + delta = 10.0f * (float)log10((0.01f + st->lt_ener_noise)/(0.01f + st->lt_ener_last_SID)); + if ( delta < LTE_VAR && st->VarDTX_cnt_voiced == MIN_CNT && st->VarDTX_cnt_noise == MIN_CNT ) + { + /* Send SID frame, and reset lt_ener_noise */ + st->lt_ener_noise = st->frame_ener; + } + } + else + { + /* If SID frame was sent, update long-term energy */ + st->lt_ener_last_SID = st->lt_ener_noise; + } + + (st->cnt_SID)++; + + if( st->var_SID_rate_flag ) + { + if( st->Opt_AMR_WB && st->max_SID == 3 && st->cnt_SID == 3 ) + { + /* set the size of CNG history buffer for averaging to 3 frames */ + st->cng_hist_size = 3; + } + else if ( st->max_SID != 3 && st->cnt_SID == DTX_HIST_SIZE ) + { + /* set the size of CNG history buffer for averaging to DTX_HIST_SIZE frames */ + /* be sure that DTX_HIST_SIZE >= INT_L */ + st->cng_hist_size = DTX_HIST_SIZE; + } + } + + if( !st->var_SID_rate_flag && st->interval_SID > 1 ) + { + /* set the size of CNG history buffer for averaging to interval_SID frames */ + st->cng_hist_size = st->interval_SID; + if (st->cng_hist_size > DTX_HIST_SIZE) + { + st->cng_hist_size = DTX_HIST_SIZE; + } + } + + if( st->cnt_SID >= st->max_SID ) + { + /* adaptive SID update interval */ + st->max_SID = st->interval_SID; + st->cnt_SID = 0; + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * dtx_hangover_control() + * + * + *-------------------------------------------------------------------*/ + +void dtx_hangover_control( + Encoder_State *st, /* i/o: encoder state structure */ + const float lsp_new[M] /* i : current frame LSPs */ +) +{ + short ptr; + short i, j, m; + float tmp_lsp[max(DTX_HIST_SIZE,HO_HIST_SIZE)*M]; + float tmp_enr[max(DTX_HIST_SIZE,HO_HIST_SIZE)]; + float tmp[max(DTX_HIST_SIZE,HO_HIST_SIZE)*M]; + float enr_new; + float weights; + float enr_est, lsp_est[M]; + float Dlsp, Denr; + float lsf_tmp[M]; + float C[M]; + float max[2]; + short max_idx[2]; + float ftmp; + float Dlsp_n2e, Denr_n2e; + + /* get current frame exc energy in log2 */ + enr_new = (float)(log10(st->ho_ener_circ[st->ho_circ_ptr]) / log10(2.0f)); + + if( enr_new < 0.0f ) + { + enr_new = 0.0f; + } + + /* get energies and lsps of hangover frames */ + ptr = st->ho_circ_ptr - (st->burst_ho_cnt-1); + if( ptr < 0 ) + { + ptr += st->ho_circ_size; + } + + for( i=0; iburst_ho_cnt-1; i++ ) + { + mvr2r( &(st->ho_lsp_circ[ptr*M]), &(tmp_lsp[i*M]), M ); + tmp_enr[i] = st->ho_ener_circ[ptr]; + + ptr++; + if( ptr == st->ho_circ_size ) + { + ptr = 0; + } + } + + /* get estimated CNG energy and lsps assuming terminate hangover at current frame */ + ptr = st->burst_ho_cnt - 2; + enr_est = W_DTX_HO[0] * tmp_enr[ptr]; + weights = W_DTX_HO[0]; + mvr2r( &(tmp_lsp[ptr*M]), tmp, M ); + m = 1; + + for( i = 1; i < st->burst_ho_cnt-2; i++ ) + { + if ( tmp_enr[ptr-i] < tmp_enr[ptr] * BUF_H_NRG && tmp_enr[ptr-i] > tmp_enr[ptr] * BUF_L_NRG ) + { + enr_est += W_DTX_HO[i] * tmp_enr[ptr-i]; + weights += W_DTX_HO[i]; + mvr2r( &tmp_lsp[(ptr-i)*M], &tmp[m*M], M ); + m++; + } + } + + enr_est /= weights; + + if( enr_est < 1.0f ) + { + enr_est = 1.0f; + } + + Denr_n2e = (float)fabs(enr_new - log10(enr_est) / log10(2.0f)); + + if( m < 3 ) + { + enr_est = 0.8f*enr_est + (1-0.8f)*st->ho_ener_circ[st->ho_circ_ptr]; + } + else + { + enr_est = 0.95f*enr_est + (1-0.95f)*st->ho_ener_circ[st->ho_circ_ptr]; + } + + enr_est = (float)(log10(enr_est) / log10(2.0f)); + + if( enr_est < 0.0f ) + { + enr_est = 0.0f; + } + + set_f( max, 0.0f, 2 ); + set_s( max_idx, 0, 2 ); + + for( i=0; iL_frame == L_FRAME ) + { + lsp2lsf( &tmp[i*M], lsf_tmp, M, INT_FS_12k8 ); + ftmp = 6400.0f / (M+1); + C[i] = (6400.0f - lsf_tmp[M-1] - ftmp) * (6400.0f - lsf_tmp[M-1] - ftmp); + } + else + { + lsp2lsf( &tmp[i*M], lsf_tmp, M, INT_FS_16k ); + ftmp = 8000.0f / (M+1); + C[i] = (8000.0f - lsf_tmp[M-1] - ftmp) * (8000.0f - lsf_tmp[M-1] - ftmp); + } + + C[i] += (lsf_tmp[0] - ftmp) * (lsf_tmp[0] - ftmp); + for ( j=0; j max[0] ) + { + max[1] = max[0]; + max_idx[1] = max_idx[0]; + max[0] = C[i]; + max_idx[0] = i; + } + else if ( C[i] > max[1] ) + { + max[1] = C[i]; + max_idx[1] = i; + } + } + + if( m == 1 ) + { + mvr2r( tmp, lsp_est, M ); + } + else if( m < 4 ) + { + for( i=0; ilspCNG[i] - lsp_est[i]); + if ( fabs(st->lspCNG[i] - lsp_est[i]) > max[0] ) + { + max[0] = (float)fabs(st->lspCNG[i] - lsp_est[i]); + } + } + Denr = (float)fabs((log10(st->lp_ener+0.1f)/log10(2.0f)) - enr_est); + + /* make decision if DTX hangover can be terminated */ + st->hangover_terminate_flag = 0; + + if (( Dlsp < 0.4f && Denr < 1.4f && max[0] < 0.1f && Dlsp_n2e < 0.4f && Denr_n2e < 1.2f && st->Opt_SC_VBR)|| + ( Dlsp < 0.4f && Denr < 0.8f && max[0] < 0.1f && Dlsp_n2e < 0.4f && Denr_n2e < 0.8f && !st->Opt_SC_VBR)) + { + st->hangover_terminate_flag = 1; + } + + return; +} diff --git a/lib_enc/enc_acelp.c b/lib_enc/enc_acelp.c new file mode 100644 index 000000000..6a6a638ec --- /dev/null +++ b/lib_enc/enc_acelp.c @@ -0,0 +1,1458 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include "typedef.h" +#include "options.h" +#include "prot.h" +#include "rom_com.h" +#include "rom_enc.h" + + + +/*---------------------------------------------------------------------* +* Local functions +*---------------------------------------------------------------------*/ + +static void E_ACELP_codearithp(const float v[], long unsigned *n, long unsigned *ps, int *p, int trackstep, int tracklen); + +/*---------------------------------------------------------------------* +* Local constants +*---------------------------------------------------------------------*/ + +#define NB_MAX 8 + +/* + * 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 + */ +static void acelp_h_vec_corr1( + Float32 h[], + Float32 vec[], + UWord8 track, + Float32 sign[], + Float32 (*rrixix)[16], + Float32 cor[], + Word16 dn2_pos[], + Word32 nb_pulse +) +{ + Word16 i, j; + Word32 dn; + Word16 *dn2; + Float32 *p0; + Float32 s; + + dn2 = &dn2_pos[track * 8]; + p0 = rrixix[track]; + for (i = 0; i < nb_pulse; i++) + { + dn = dn2[i]; + s = 0.0F; + /* L_SUBFR-dn */ + /* vec[dn] */ + for (j = 0; j < (L_SUBFR - dn); j++) + { + s += h[j] * vec[dn + j]; + } + + cor[dn >> 2] = sign[dn] * s + p0[dn >> 2]; + } + return; +} + +static void acelp_h_vec_corr2( + Float32 h[], + Float32 vec[], + UWord8 track, + Float32 sign[], + Float32 (*rrixix)[16], + Float32 cor[]) +{ + Word32 i, j; + Float32 *p0; + Float32 s; + + + p0 = rrixix[track]; + /* sign[track] */ + for (i = 0; i < 16; i++) + { + s = 0.0F; + /* h[0], vec[track] */ + /* L_SUBFR-track */ + for (j = 0; j < L_SUBFR - track; j++) + { + s += h[j] * vec[track + j]; + } + + cor[i] = s * sign[track] + p0[i]; + track += 4; + } + return; +} + + +/* + * 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 acelp_2pulse_search( Word32 nb_pos_ix, UWord8 track_x, + UWord8 track_y, Float32 *ps, Float32 *alp, + Word16 *ix, Word16 *iy, Float32 dn[], + Word16 *dn2, Float32 cor_x[], + Float32 cor_y[], Float32 (*rrixiy)[256]) +{ + Word16 x, x2, y, x_save = 0, y_save = 0, i, *pos_x; + Float32 ps0, alp0; + Float32 ps1, ps2, sq, sqk; + Float32 alp1, alp2, alpk; + Float32 *p1, *p2; + Float32 s; + + /* x_save=y_save=0 */ + /* eight dn2 max positions per track */ + pos_x = &dn2[track_x << 3]; + /* save these to limit memory searches */ + ps0 = *ps; + alp0 = *alp; + + alpk = 1.0F; + sqk = -1.0F; + x2 = pos_x[0] >> 2; + if( (alp0 + cor_x[x2] + cor_y[0] + rrixiy[track_x][x2 << 4]) < 0 ) + { + sqk = 1.0F; + } + + /* loop track 1 */ + for (i = 0; i < nb_pos_ix; i++) + { + x = pos_x[i]; + x2 = x >> 2; + /* dn[x] has only nb_pos_ix positions saved */ + ps1 = ps0 + dn[x]; + alp1 = alp0 + cor_x[x2]; + p1 = cor_y; + p2 = &rrixiy[track_x][x2 << 4]; + for (y = track_y; y < L_SUBFR; y += 4) + { + ps2 = ps1 + dn[y]; + alp2 = alp1 + (*p1++) + (*p2++); + + sq = ps2 * ps2; + + s = (alpk * sq) - (sqk * alp2); + + if (s > 0.0F) + { + sqk = sq; + alpk = alp2; + y_save = y; + x_save = x; + } + } + } + + *ps = ps0 + dn[x_save] + dn[y_save]; + *alp = alpk; + *ix = x_save; + *iy = y_save; + return; +} + + +/* + * 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 track_x, + UWord8 track_y, + Float32 *ps, + Float32 *alp, + Word16 *ix, + Float32 dn[], + Float32 cor_x[], + Float32 cor_y[]) +{ + Word16 x, x_save = 0; + Float32 ps0, alp0; + Float32 ps1, sq, sqk; + Float32 alp1, alpk; + Float32 s; + + /* save these to limit memory searches */ + ps0 = *ps; + alp0 = *alp; + alpk = 1.0F; + sqk = -1.0F; + + if ( (alp0 + cor_x[(track_x >> 2)]) < 0) + { + sqk = 1.0F; + } + for (x = track_x; x < L_SUBFR; x += 4) + { + ps1 = ps0 + dn[x]; + alp1 = alp0 + cor_x[x>>2]; + sq = ps1 * ps1; + s = (alpk * sq) - (sqk * alp1); + + if (s > 0.0F) + { + sqk = sq; + alpk = alp1; + x_save = x; + } + } + if(track_y!=track_x) + { + for (x = track_y; x < L_SUBFR; x += 4) + { + ps1 = ps0 + dn[x]; + alp1 = alp0 + cor_y[x>>2]; + sq = ps1 * ps1; + s = (alpk * sq) - (sqk * alp1); + + if (s > 0.0F) + { + sqk = sq; + alpk = alp1; + x_save = x; + } + } + } + + *ps = ps0 + dn[x_save]; + *alp = alpk; + *ix = x_save; + return; +} + + +/* + * acelp_pulsesign + * + * Parameters: + * cn I: residual after Word32 term prediction + * dn I: corr. between target and h[]. + * dn2 O: dn2[] = mix of dn[] and cn[] + * sign O: sign of pulse + * vec O: negative sign of pulse + * + * Function: + * Determine sign of each pulse position, store them in "sign" + * and change dn to all positive. + * Subframe size = L_SUBFR + * Returns: + * void + */ +void acelp_pulsesign( + const float cn[], + float dn[], + float dn2[], + float sign[], + float vec[], + float alp +) +{ + int i; + float val; + float s, cor; + + /* calculate energy for normalization of cn[] and dn[] */ + val = (cn[0] * cn[0]) + 1.0F; + cor = (dn[0] * dn[0]) + 1.0F; + for (i = 1; i < L_SUBFR; i ++) + { + val += (cn[i] * cn[i]); + cor += (dn[i] * dn[i]); + } + + s = (float)sqrt(cor / val); + for (i = 0; i < L_SUBFR; i++) + { + cor = (s * cn[i]) + (alp * dn[i]); + if (cor >= 0.0F) + { + sign[i] = 1.0F; + vec[i] = -1.0F; + dn2[i] = cor; /* dn2[] = mix of dn[] and cn[] */ + } + else + { + sign[i] = -1.0F; + vec[i] = 1.0F; + dn[i] = -dn[i]; /* modify dn[] according to the fixed sign */ + dn2[i] = -cor; /* dn2[] = mix of dn[] and cn[] */ + } + } + return; +} + +void acelp_findcandidates(float dn2[], short dn2_pos[], short pos_max[], int L_subfr, int tracks) +{ + int i,k,j; + float *ps_ptr; + /* &pos_max[0], &dn2_pos[0] */ + for (i = 0; i < tracks; i++) + { + for (k = 0; k < NB_MAX; k++) + { + ps_ptr = &dn2[i]; + for (j = i+tracks; j < L_subfr; j += tracks) + { + if (dn2[j] > *ps_ptr) + { + ps_ptr = &dn2[j]; + } + } + *ps_ptr = (float)k - NB_MAX; /* dn2 < 0 when position is selected */ + dn2_pos[i * 8 + k] = ps_ptr - dn2; + } + pos_max[i] = dn2_pos[i * 8]; + } +} + +static void acelp_hbuf(float *h_buf, float **h, float **h_inv, const float *H) +{ + int i; + *h = h_buf + L_SUBFR; + *h_inv = h_buf + (3*L_SUBFR); + for (i=0; i i3i3, i2i2, i1i1, i0i0 */ + + /* Init pointers to last position of rrixix[] */ + p0 = &rrixix[0][16 - 1]; + p1 = &rrixix[1][16 - 1]; + p2 = &rrixix[2][16 - 1]; + p3 = &rrixix[3][16 - 1]; + + ptr_h1 = h; + cor = 0.0F; + for(i = 0; i < 16; i++) + { + cor += (*ptr_h1) * (*ptr_h1); + ptr_h1++; + *p3-- = cor * 0.5F; + cor += (*ptr_h1) * (*ptr_h1); + ptr_h1++; + *p2-- = cor * 0.5F; + cor += (*ptr_h1) * (*ptr_h1); + ptr_h1++; + *p1-- = cor * 0.5F; + cor += (*ptr_h1) * (*ptr_h1); + ptr_h1++; + *p0-- = cor * 0.5F; + } + + + /* + * 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 = 0.0F; + ptr_h1 = h; + ptr_h2 = ptr_hf; + for(i = k; i < 15; i++) + { + cor += (*ptr_h1) * (*ptr_h2); + ptr_h1++; + ptr_h2++; + *p3 = cor; + cor += (*ptr_h1) * (*ptr_h2); + ptr_h1++; + ptr_h2++; + *p2 = cor; + cor += (*ptr_h1) * (*ptr_h2); + ptr_h1++; + ptr_h2++; + *p1 = cor; + cor += (*ptr_h1) * (*ptr_h2); + ptr_h1++; + ptr_h2++; + *p0 = cor; + + p3 -= (16 + 1); + p2 -= (16 + 1); + p1 -= (16 + 1); + p0 -= (16 + 1); + } + + cor += (*ptr_h1) * (*ptr_h2); + ptr_h1++; + ptr_h2++; + *p3 = cor; + cor += (*ptr_h1) * (*ptr_h2); + ptr_h1++; + ptr_h2++; + *p2 = cor; + cor += (*ptr_h1) * (*ptr_h2); + ptr_h1++; + ptr_h2++; + *p1 = 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 = 0.0F; + ptr_h1 = h; + ptr_h2 = ptr_hf; + for(i= k + 1; i < 16; i++ ) + { + cor += (*ptr_h1) * (*ptr_h2); + ptr_h1++; + ptr_h2++; + *p3 = cor; + cor += (*ptr_h1) * (*ptr_h2); + ptr_h1++; + ptr_h2++; + *p2 = cor; + cor += (*ptr_h1) * (*ptr_h2); + ptr_h1++; + ptr_h2++; + *p1 = cor; + cor += (*ptr_h1) * (*ptr_h2); + ptr_h1++; + ptr_h2++; + *p0 = cor; + + p3 -= (16 + 1); + p2 -= (16 + 1); + p1 -= (16 + 1); + p0 -= (16 + 1); + } + + cor += (*ptr_h1) * (*ptr_h2); + *p3 = 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) + { + if (sign[i+0] < 0.0F) psign0 = &vec[1]; + else psign0 = &sign[1]; + if (sign[i+1] < 0.0F) psign1 = &vec[2]; + else psign1 = &sign[2]; + if (sign[i+2] < 0.0F) psign2 = &vec[3]; + else psign2 = &sign[3]; + if (sign[i+3] < 0.0F) psign3 = &vec[0]; + else psign3 = &sign[0]; + p0[0] = p0[0] * psign0[ 0]; + p0[1] = p0[1] * psign0[ 4]; + p0[2] = p0[2] * psign0[ 8]; + p0[3] = p0[3] * psign0[12]; + p0[4] = p0[4] * psign0[16]; + p0[5] = p0[5] * psign0[20]; + p0[6] = p0[6] * psign0[24]; + p0[7] = p0[7] * psign0[28]; + p0[8] = p0[8] * psign0[32]; + p0[9] = p0[9] * psign0[36]; + p0[10] = p0[10] * psign0[40]; + p0[11] = p0[11] * psign0[44]; + p0[12] = p0[12] * psign0[48]; + p0[13] = p0[13] * psign0[52]; + p0[14] = p0[14] * psign0[56]; + p0[15] = p0[15] * psign0[60]; + p0 += 16; + + p1[0] = p1[0] * psign1[ 0]; + p1[1] = p1[1] * psign1[ 4]; + p1[2] = p1[2] * psign1[ 8]; + p1[3] = p1[3] * psign1[12]; + p1[4] = p1[4] * psign1[16]; + p1[5] = p1[5] * psign1[20]; + p1[6] = p1[6] * psign1[24]; + p1[7] = p1[7] * psign1[28]; + p1[8] = p1[8] * psign1[32]; + p1[9] = p1[9] * psign1[36]; + p1[10] = p1[10] * psign1[40]; + p1[11] = p1[11] * psign1[44]; + p1[12] = p1[12] * psign1[48]; + p1[13] = p1[13] * psign1[52]; + p1[14] = p1[14] * psign1[56]; + p1[15] = p1[15] * psign1[60]; + p1 += 16; + + p2[0] = p2[0] * psign2[ 0]; + p2[1] = p2[1] * psign2[ 4]; + p2[2] = p2[2] * psign2[ 8]; + p2[3] = p2[3] * psign2[12]; + p2[4] = p2[4] * psign2[16]; + p2[5] = p2[5] * psign2[20]; + p2[6] = p2[6] * psign2[24]; + p2[7] = p2[7] * psign2[28]; + p2[8] = p2[8] * psign2[32]; + p2[9] = p2[9] * psign2[36]; + p2[10] = p2[10] * psign2[40]; + p2[11] = p2[11] * psign2[44]; + p2[12] = p2[12] * psign2[48]; + p2[13] = p2[13] * psign2[52]; + p2[14] = p2[14] * psign2[56]; + p2[15] = p2[15] * psign2[60]; + p2 += 16; + + p3[0] = p3[0] * psign3[ 0]; + p3[1] = p3[1] * psign3[ 4]; + p3[2] = p3[2] * psign3[ 8]; + p3[3] = p3[3] * psign3[12]; + p3[4] = p3[4] * psign3[16]; + p3[5] = p3[5] * psign3[20]; + p3[6] = p3[6] * psign3[24]; + p3[7] = p3[7] * psign3[28]; + p3[8] = p3[8] * psign3[32]; + p3[9] = p3[9] * psign3[36]; + p3[10] = p3[10] * psign3[40]; + p3[11] = p3[11] * psign3[44]; + p3[12] = p3[12] * psign3[48]; + p3[13] = p3[13] * psign3[52]; + p3[14] = p3[14] * psign3[56]; + p3[15] = p3[15] * psign3[60]; + p3 += 16; + } +} + +void E_ACELP_4tsearch(Float32 dn[], const Float32 cn[], const Float32 H[], float code[], + PulseConfig *config, Word16 ind[], Float32 y[]) +{ + Float32 sign[L_SUBFR], vec[L_SUBFR]; + Float32 cor_x[16], cor_y[16], h_buf[4 * L_SUBFR]; + Float32 rrixix[4][16]; + Float32 rrixiy[4][256]; + Float32 dn2[L_SUBFR]; + Float32 psk, ps, alpk, alp = 0.0F; + Word16 codvec[NB_PULSE_MAX]; + Word16 pos_max[4]; + Word16 dn2_pos[8 * 4]; + UWord8 ipos[NB_PULSE_MAX]; + Float32 *p0, *p1, *p2, *p3; + Float32 *h, *h_inv; + Word32 i, j, k, l, st, pos = 0, index, track; + UWord8 iPulse; + Float32 val; + Float32 s; + UWord8 restpulses; + + + alp = config->alp; /* initial value for energy of all fixed pulses */ + /* set_i( (int *)codvec, 0, config->nb_pulse); */ + + for (k=0; knb_pulse; k++) codvec[k] = 0; + + /* + * Find sign for each pulse position. + */ + + acelp_pulsesign(cn, dn, dn2, sign, vec, alp); + + /* + * Select the most important 8 position per track according to dn2[]. + */ + + acelp_findcandidates(dn2, dn2_pos, pos_max, L_SUBFR, NB_TRACK_FCB_4T); + + /* + * Compute h_inv[i]. + */ + + acelp_hbuf( h_buf, &h, &h_inv, H ); + + /* + * 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.0; + alpk = 1.0; + /*Number of iterations*/ + for (k = 0; k < config->nbiter; k++) + { + /* copy search order from hash-table */ + for ( l=0; lnb_pulse; l++ ) + { + ipos[l] = tipos[(k * 4) + l]; + } + + /* if all tracks do not have equal number of pulses */ + restpulses = 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; iPulse < restpulses; iPulse++) + { + ipos[config->nb_pulse-restpulses+iPulse] = iPulse; + } + /* 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]; + break; + case TRACKPOS_FIXED_EVEN: /* fixed track positions, odd tracks */ + /* odd tracks, switch order for every iteration */ + ipos[config->nb_pulse-restpulses] = (k<<1) & 2; /* 0 for even k, 2 for odd*/ + ipos[config->nb_pulse-restpulses+1] = ipos[config->nb_pulse-restpulses] ^ 2; /* 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] = (ipos[config->nb_pulse-1]+1) & 3; + break; + default: /* one or three free track positions */ + /* copy an extra position from table - 1pulse search will access this */ + ipos[config->nb_pulse] = tipos[(k*4)+config->nb_pulse]; + break; + } + } + if (config->fixedpulses == 0)/* 1100, 11, 1110, 1111, 2211 */ + { + pos = 0; + ps = 0.0F; + alp = 0.0F; + memset(vec, 0, L_SUBFR * sizeof(Float32)); + } + else if (config->fixedpulses == 2) /* 2222 and 3322 */ + { + /* first stage: fix 2 pulses */ + pos = 2; + + ind[0] = pos_max[ipos[0]]; + ind[1] = pos_max[ipos[1]]; + ps = dn[ind[0]] + dn[ind[1]]; + + + /*ind[1]>>2 and ind[0]>>2 and save*/ + /* ipos[1] and ipos[0] and save*/ + alp = rrixix[ipos[0]][ind[0] >> 2] + rrixix[ipos[1]][ind[1] >> 2] + + rrixiy[ipos[0]][((ind[0] >> 2) << 4) + (ind[1] >> 2)]; + + if (sign[ind[0]] < 0.0) + { + p0 = h_inv - ind[0]; + } + else + { + p0 = h - ind[0]; + } + if (sign[ind[1]] < 0.0) + { + p1 = h_inv - ind[1]; + } + else + { + p1 = h - ind[1]; + } + /*ptx = &vec p1 and p0 already initialize*/ + vec[0] = p0[0] + p1[0]; + vec[1] = p0[1] + p1[1]; + vec[2] = p0[2] + p1[2]; + vec[3] = p0[3] + p1[3]; + for (i = 4; i < L_SUBFR; i += 6) + { + vec[i] = p0[i] + p1[i]; + vec[i + 1] = p0[i + 1] + p1[i + 1]; + vec[i + 2] = p0[i + 2] + p1[i + 2]; + vec[i + 3] = p0[i + 3] + p1[i + 3]; + vec[i + 4] = p0[i + 4] + p1[i + 4]; + vec[i + 5] = p0[i + 5] + p1[i + 5]; + } + } + else /* 3333 and above */ + { + /* first stage: fix 4 pulses */ + pos = 4; + + ind[0] = pos_max[ipos[0]]; + ind[1] = pos_max[ipos[1]]; + ind[2] = pos_max[ipos[2]]; + ind[3] = pos_max[ipos[3]]; + ps = dn[ind[0]] + dn[ind[1]] + dn[ind[2]] + dn[ind[3]]; + + p0 = h - ind[0]; + if (sign[ind[0]] < 0.0) + { + p0 = h_inv - ind[0]; + } + + p1 = h - ind[1]; + if (sign[ind[1]] < 0.0) + { + p1 = h_inv - ind[1]; + } + + p2 = h - ind[2]; + if (sign[ind[2]] < 0.0) + { + p2 = h_inv - ind[2]; + } + + p3 = h - ind[3]; + if (sign[ind[3]] < 0.0) + { + p3 = h_inv - ind[3]; + } + /* pt =&vec; others already defined*/ + vec[0] = p0[0] + p1[0] + p2[0] + p3[0]; + for (i = 1; i < L_SUBFR; i += 3) + { + vec[i] = p0[i] + p1[i] + p2[i] + p3[i]; + vec[i + 1] = p0[i + 1] + p1[i + 1] + p2[i + 1] + p3[i + 1]; + vec[i + 2] = p0[i + 2] + p1[i + 2] + p2[i + 2] + p3[i + 2]; + } + + alp = 0.0F; + alp += vec[0] * vec[0] + vec[1] * vec[1]; + alp += vec[2] * vec[2] + vec[3] * vec[3]; + + for (i = 4; i < L_SUBFR; i += 6) + { + alp += vec[i] * vec[i]; + alp += vec[i + 1] * vec[i + 1]; + alp += vec[i + 2] * vec[i + 2]; + alp += vec[i + 3] * vec[i + 3]; + alp += vec[i + 4] * vec[i + 4]; + alp += vec[i + 5] * vec[i + 5]; + } + + alp *= 0.5F; + } + + /* other stages of 2 pulses */ + for (j = pos, st = 0; j < config->nb_pulse; j += 2, st++) + { + if ((config->nb_pulse-j) >= 2) /*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. + */ + acelp_h_vec_corr1(h, vec, ipos[j], sign, rrixix, cor_x, dn2_pos, + config->nbpos[st]); + acelp_h_vec_corr2(h, vec, ipos[j + 1], sign, rrixix, cor_y); + + /* + * Find best positions of 2 pulses. + */ + 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*/ + { + acelp_h_vec_corr2(h, vec, ipos[j], sign, rrixix, cor_x); + acelp_h_vec_corr2(h, vec, ipos[j + 1], sign, rrixix, cor_y); + E_ACELP_1pulse_search(ipos[j], ipos[j+1], &ps, &alp, + &ind[j], dn, cor_x, cor_y); + } + if( j < (config->nb_pulse - 2) ) + { + p0 = h - ind[j]; + if (sign[ind[j]] < 0.0) + { + p0 = h_inv - ind[j]; + } + + p1 = h - ind[j + 1]; + if (sign[ind[j + 1]] < 0.0) + { + p1 = h_inv - ind[j + 1]; + } + + vec[0] += p0[0] + p1[0]; + vec[1] += p0[1] + p1[1]; + vec[2] += p0[2] + p1[2]; + vec[3] += p0[3] + p1[3]; + for (i = 4; i < L_SUBFR; i += 6) + { + vec[i] += p0[i] + p1[i]; + vec[i + 1] += p0[i + 1] + p1[i + 1]; + vec[i + 2] += p0[i + 2] + p1[i + 2]; + vec[i + 3] += p0[i + 3] + p1[i + 3]; + vec[i + 4] += p0[i + 4] + p1[i + 4]; + vec[i + 5] += p0[i + 5] + p1[i + 5]; + + } + } + } + + /* memorise the best codevector */ + + ps = ps * ps; + s = (alpk * ps) - (psk * alp); + + if (psk < 0) + { + s = 1.0F; + } + if (s > 0.0F) + { + psk = ps; + alpk = alp; + memcpy(codvec, ind, config->nb_pulse * sizeof(Word16)); + } + } + + /* + * Build the codeword, the filtered codeword and index of codevector, as well as store weighted correlations. + */ + + memset(code, 0, L_SUBFR * sizeof(float)); + memset(y, 0, L_SUBFR * sizeof(float)); + memset(ind, 0xffffffff, NPMAXPT * 4 * sizeof(Word16)); + for (k = 0; k < config->nb_pulse; k++) + { + i = codvec[k]; /* read pulse position */ + val = sign[i]; /* read sign */ + + index = i / 4; /* pos of pulse (0..15) */ + track = i % 4; + if (val > 0) + { + code[i] += 1.0f; + codvec[k] += (2 * L_SUBFR); + } + else + { + code[i] -= 1.0f; + index += 16; + } + + i = track * NPMAXPT; + while (ind[i] >= 0) + { + i++; + } + + ind[i] = index; + + p0 = h_inv - codvec[k]; + 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( + Float32 dn[], + Float32 cn[], + Float32 H[], + Float32 R[], + int acelpautoc, + float code[], + int cdk_index, + int _index[] + ,const short L_frame, + const short last_L_frame, + const long total_brate, + const short i_subfr +) +{ + PulseConfig config; + Word16 ind[NPMAXPT*4]; + Float32 y[L_SUBFR]; + + config = PulseConfTable[cdk_index]; + + if( L_frame != last_L_frame && total_brate == ACELP_24k40 && i_subfr < 5*L_SUBFR ) + { + (config.nbiter)--; + config.nbiter = max(config.nbiter,1); + } + + if (acelpautoc & 0x01) + { + 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); + + return; +} + +short E_ACELP_indexing( + Float32 code[], + PulseConfig config, + int num_tracks, + int prm[] +) +{ + unsigned short track; + int p[NB_TRACK_FCB_4T], wordcnt; + int k; + unsigned short idxs[MAX_IDX_LEN], maxppos; + unsigned long s[NB_TRACK_FCB_4T], n[NB_TRACK_FCB_4T]; + int maxp; + short saved_bits; + + assert(num_tracks == NB_TRACK_FCB_4T); + + saved_bits = 0; + + /* + * Code state of pulses of all tracks + * */ + wordcnt = (config.bits + 15) >> 4; /* ceil(bits/16) */ + for (k=0; kp[2]) + { + track = 0; /* 1100 */ + } + else + { + track = 2; /* 0011 */ + } + } + else + { + /* Either 0110 or 1001 */ + if (p[0] < p[1]) + { + track = 1; /* 0110 */ + } + else + { + track = 3; /* 1001 */ + } + } + /* Multiply by number of possible states (=shift by two) and + * add actual state. */ + longshiftleft(idxs,2,idxs,wordcnt); + longadd(idxs, &track, wordcnt, 1); + break; + case TRACKPOS_FREE_THREE: + /* Code position of track with one pulse less than others */ + + /* Find track with one pulse less. */ + maxp = p[0]; + maxppos = 0; + for (track=1; track < 4; track++) + { + if (p[track] < maxp) + { + maxppos = track; + break; + } + } + /* Multiply by number of possible states (=shift by two) and + * add actual state. */ + longshiftleft(idxs,2,idxs,wordcnt); + longadd(idxs, &maxppos, wordcnt, 1); + break; + case TRACKPOS_FREE_ONE: + /* Code position of track with one pulse more than others */ + + /* Find track with one pulse more. */ + maxp = p[0]; + maxppos = 0; + for (track=1; track < 4; track++) + { + if (p[track] > maxp) + { + maxppos = track; + break; + } + } + /* Multiply by number of possible states (=shift by two) and + * add actual state. */ + longshiftleft(idxs, 2, idxs, wordcnt); + longadd(idxs, &maxppos, wordcnt, 1); + break; + case TRACKPOS_FIXED_EVEN: + case TRACKPOS_FIXED_FIRST: + break; + default: + printf("Codebook mode not implemented."); + assert(0); /* mode not yet implemented*/ + break; + } + + /* cast to output buffer */ + for (k=0; k0? 1:-1); /* sign */ + for (h=0; h < v[k]*tmp; h++) + { + pos[posno] = t; + sig[posno] = tmp; + posno++; + if (posno >= 9) + { + break; + } + } + if (posno >= 9) + { + break; + } + } + *p = posno; + + s = 0; + for (k=0; k < posno; k++) + { + /* check if next position is the same as this one */ + if ((k==posno-1) || (pos[k] != pos[k+1])) + { + /* next position is not the same (or we are at the last position) + * -> save sign */ + s <<= 1; + if (sig[k] < 0) + { + s++; + } + } + s += pulsestostates[pos[k]][k]; + } + *ps = s; + if (posno) + { + *n = pulsestostates[tracklen][posno-1]; + } + else + { + *n = 0; + } + +} + +void fcb_pulse_track_joint( unsigned short *idxs, int wordcnt, long unsigned *index_n, int *pulse_num, int track_num ) +{ + int hi_to_low[10] = { 0, 0, 0, 3, 9, 5, 3, 1, 8, 8}; + + unsigned long long index; + unsigned int index_mask; + int indx_tmp,indx_flag,indx_flag_1; + int track,track_num1,pulse_num0,pulse_num1; + int indx_flag_2; + + indx_flag=0; + indx_flag_1=0; + indx_flag_2 = 0; + for (track=0; track < track_num; track++) + { + indx_flag += (pulse_num[track]>>2); + indx_flag_1 += (pulse_num[track]>>1); + indx_flag_2 += (pulse_num[track]>>3); + } + + if (indx_flag_2 >= 1) + { + hi_to_low[7] = 9; + index_mask = 0xffffff; + } + else + { + hi_to_low[7] = 1; + if (indx_flag>=track_num) + { + hi_to_low[4]=9; + index_mask = 0xffff; + } + else + { + hi_to_low[4]=1; + index_mask = 0xff; + } + } + + if (indx_flag_1>=track_num) + { + indx_tmp = 0; + index = index_n[0] >> low_len[pulse_num[0]]; + for (track=1; track < track_num; track++) + { + pulse_num0 = pulse_num[track-1]; + pulse_num1 = pulse_num[track]; + indx_tmp = index_n[track] >> low_len[pulse_num1]; + index = index * indx_fact[pulse_num1] + indx_tmp; + + index_n[track-1] = ( index_n[track-1] & low_mask[pulse_num0] ) + ( ( index << low_len[pulse_num0] )& index_mask ) ; + index = index >> hi_to_low[pulse_num0]; + } + track_num1 = track_num - 1; + pulse_num1 = pulse_num[track_num1]; + index_n[track_num1] = ( ( index_n[track_num1] & low_mask[pulse_num1] ) + ( index << low_len[pulse_num1] ) ) & index_mask; + index = index >> hi_to_low[pulse_num1]; + if (indx_flag>=track_num) + { + if (indx_flag_2 >= 1) + { + idxs[0] = index_n[0] & 0xffff; + idxs[1] = ( ( index_n[1] << 8 ) + ( index_n[0] >> 16) ) & 0xffff; + idxs[2] = index_n[1] >> 8; + idxs[3] = index_n[2] & 0xffff; + idxs[4] = ( ( index_n[3] << 8 ) + ( index_n[2] >> 16) ) & 0xffff; + idxs[5] = index_n[3] >> 8; + for (track=6; track < wordcnt; track++) + { + idxs[track] = index&0xffff; + index = index >> 16; + } + } + else + { + for (track=0; track < track_num; track++) + { + idxs[track] = index_n[track]; + } + for (track=track_num; track < wordcnt; track++) + { + idxs[track] = index&0xffff; + index = index >> 16; + } + } + } + else + { + idxs[0] = ( index_n[0] << 8 ) + index_n[1]; + idxs[1] = ( index_n[2] << 8 ) + index_n[3]; + for (track=2; track < wordcnt; track++) + { + idxs[track] = index&0xffff; + index = index >> 16; + } + } + } + else + { + index = index_n[0]; + for (track=1; track < 4; track++) + { + pulse_num1 = pulse_num[track]; + index = ( index << index_len[pulse_num1] ) + index_n[track]; + } + for (track=0; track < wordcnt; track++) + { + idxs[track] = index&0xffff; + index = index >> 16; + } + } + + return; +} diff --git a/lib_enc/enc_acelp_tcx_main.c b/lib_enc/enc_acelp_tcx_main.c new file mode 100644 index 000000000..d3c195369 --- /dev/null +++ b/lib_enc/enc_acelp_tcx_main.c @@ -0,0 +1,105 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "options.h" +#include "prot.h" +#include "rom_com.h" + + +/*-------------------------------------------------------------------* + * enc_acelp_tcx_main() + * + * encoder function for coding ACELP/TCX + *--------------------------------------------------------------------*/ + +void enc_acelp_tcx_main( + const float new_samples[], /* i : new samples */ + Encoder_State *st, /* i/o: encoder state structure */ + const short coder_type, /* i : coding type */ + const short pitch[3], /* i : open-loop pitch values for quantiz. */ + const float voicing[3], /* i : open-loop pitch gains */ + float Aw[NB_SUBFR16k*(M+1)], /* i : weighted A(z) unquant. for subframes*/ + const float lsp_new[M], /* i : LSPs at the end of the frame */ + const float lsp_mid[M], /* i : LSPs at the middle of the frame */ + HANDLE_FD_CNG_ENC hFdCngEnc, /* i/o: FD CNG handle */ + float bwe_exc_extended[], /* i/o: bandwidth extended excitation */ + float *voice_factors, /* o : voicing factors */ + float pitch_buf[], /* o : floating pitch for each subframe */ + short vad_hover_flag, + short vad_flag_dtx +) +{ + + float old_bwe_exc[(PIT16k_MAX + (L_FRAME16k + 1) + L_SUBFR16k) * 2]; /* excitation buffer */ + float *ptr_bwe_exc; /* pointer to BWE excitation signal in the current frame */ + + ptr_bwe_exc = old_bwe_exc + PIT16k_MAX * 2; + + if (st->last_core == ACELP_CORE) + { + set_f( old_bwe_exc + PIT16k_MAX * 2, 0.f, ((L_FRAME16k + 1) + L_SUBFR16k) * 2 ); + mvr2r( st->old_bwe_exc, old_bwe_exc, PIT16k_MAX * 2 ); + } + else + { + set_f( old_bwe_exc, 0.f, ((L_FRAME16k + 1) + L_SUBFR16k + PIT16k_MAX) * 2 ); + } + + + /* Guided ACELP PLC */ + gPLC_encInfo( &st->plcExt, st->total_brate, st->bwidth, st->clas, coder_type ); + + if( st->core_brate != FRAME_NO_DATA && st->core_brate != 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 ); + } + else + { + core_encode_twodiv( new_samples, st, coder_type, pitch, voicing, Aw ); + } + + /* Apply non linearity to the SHB excitation */ + if( st->core == ACELP_CORE && st->igf ) + { + non_linearity( ptr_bwe_exc, bwe_exc_extended, st->old_bwe_exc_extended, L_FRAME32k, &st->bwe_non_lin_prev_scale, coder_type, voice_factors, st->L_frame ); + + /* update the old_BWE_exc memory */ + mvr2r( &old_bwe_exc[L_FRAME32k], st->old_bwe_exc, PIT16k_MAX * 2 ); + } + else + { + set_f( st->old_bwe_exc_extended, 0, NL_BUFF_OFFSET ); + set_f( st->old_bwe_exc, 0, PIT16k_MAX * 2 ); /* reset old non_linear exc during igf frames */ + st->bwe_non_lin_prev_scale = 0.0f; + } + } + else + { + /* Run SID Coder */ + if( st->core_brate == SID_2k40 ) + { + FdCng_encodeSID( hFdCngEnc, st, st->preemph_fac ); + } + + /* Generate Comfort Noise */ + generate_comfort_noise_enc( st ); + + /* Update Core Encoder */ + core_encode_update_cng( st, hFdCngEnc->hFdCngCom->timeDomainBuffer, hFdCngEnc->hFdCngCom->A_cng, Aw ); + } + + /* coreSwitching update of Mode 1 parameters in the last frame */ + st->last_coder_type = coder_type; + + + return; +} diff --git a/lib_enc/enc_acelpx.c b/lib_enc/enc_acelpx.c new file mode 100644 index 000000000..330543640 --- /dev/null +++ b/lib_enc/enc_acelpx.c @@ -0,0 +1,474 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include "typedef.h" +#include "options.h" +#include "prot.h" +#include "rom_enc.h" + + + +/* Iterations: nb_pos_ix*16 */ +static +void E_ACELP_2pulse_searchx(Word32 nb_pos_ix, UWord8 track_x, + UWord8 track_y, Float32 *R, Float32 *ps, Float32 *alp, + Word16 *ix, Word16 *iy, Float32 dn[], + Word16 *dn2, Float32 cor[], Float32 sign[]) +{ + Word32 i,y, x_save=0, y_save=0; + Word16 x, *pos_x; + Float32 ps0, alp0, alp1, ps1, alp2, ps2, sq, s, sqk, alpk, *pR, sgnx, *pRx, *pRy, sign_x, sign_y; + /* x_save=y_save=0 */ + /* eight dn2 max positions per track */ + pos_x = &dn2[track_x << 3]; + /* save these to limit memory searches */ + ps0 = *ps; + alp0 = *alp + 2.0f*R[0]; + + sqk = -1.0F; + alpk = 1.0F; + + x = pos_x[0]; + sgnx = sign[track_y]; + if (sign[x] < 0) + { + sgnx = -sgnx; + } + if ( (alp0 + (cor[x] * sign[x]) + (cor[track_y] * sign[track_y]) + (R[track_y-x] * sgnx)) < 0.0F ) + { + sqk = 1.0F; + } + + + /* loop track 1 */ + for (i=0; i 0.0F) + { + sqk = sq; + alpk = alp2; + y_save = y; + x_save = x; + } + } + } + /* Update numerator */ + *ps = ps0 + dn[x_save] + dn[y_save]; + /* Update denominator */ + *alp = alpk; + + /* Update product of autocorrelation and already fixed pulses. with the + * two newly found ones */ + pRx = R-x_save; + pRy = R-y_save; + sign_x = sign[x_save]; + sign_y = sign[y_save]; + for (i=0; i 0.0F) + { + sqk = sq; + alpk = alp1; + x_save = x; + } + } + if(track_y!=track_x) + { + for (x = track_y; x < L_SUBFR; x += 4) + { + ps1 = ps0 + dn[x]; + alp1 = alp0 + 2*sign[x]*cor[x]; + sq = ps1 * ps1; + s = (alpk * sq) - (sqk * alp1); + if (s > 0.0F) + { + sqk = sq; + alpk = alp1; + x_save = x; + } + } + } + + *ps = ps0 + dn[x_save]; + *alp = alpk; + *ix = x_save; + return; +} + + +/* Autocorrelation method for searching pulse positions effectively + * Algorithm is identical to traditional covariance method. */ +void E_ACELP_4tsearchx( + Float32 dn[], + const Float32 cn[], + Float32 Rw[], + float code[], + PulseConfig *config + , Word16 ind[] +) +{ + Float32 sign[L_SUBFR], vec[L_SUBFR]; + Float32 cor[L_SUBFR]; + Float32 R_buf[2*L_SUBFR-1], *R; + Float32 dn2[L_SUBFR]; + Float32 psk = 0.0F, ps2k, ps, ps2, alpk, alp = 0.0F; + Word16 codvec[NB_PULSE_MAX]; + Word16 pos_max[4]; + Word16 dn2_pos[8 * 4]; + UWord8 ipos[NB_PULSE_MAX]; + Float32 *p0; + Word32 i, j, k, l, st, pos = 0, index, track; + UWord8 iPulse; + Float32 val; + Float32 s; + UWord8 restpulses; + + + alp = config->alp; + for (k=0; knb_pulse; k++) + { + codvec[k] = (k & 3); + } + + set_f( cor, 0.0f, L_SUBFR); + + /* Set up autocorrelation vector */ + R = R_buf+L_SUBFR-1; + R[0] = Rw[0]; + for (k=1; knbiter; k++) + { + /* copy search order from hash-table */ + assert(config->nb_pulse+(k*4) <= 40); + for ( l=0; lnb_pulse; l++ ) + { + ipos[l] = tipos[(k * 4) + l]; + } + + /* if all tracks do not have equal number of pulses */ + restpulses = 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; iPulse < restpulses; iPulse++) + { + ipos[config->nb_pulse-restpulses+iPulse] = iPulse; + } + /* 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]; + break; + case TRACKPOS_FIXED_EVEN: /* fixed track positions, odd tracks */ + /* odd tracks, switch order for every iteration */ + ipos[config->nb_pulse-restpulses] = (k<<1) & 2; /* 0 for even k, 2 for odd*/ + ipos[config->nb_pulse-restpulses+1] = ipos[config->nb_pulse-restpulses] ^ 2; /* 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] = (ipos[config->nb_pulse-1]+1) & 3; + break; + default: /* one or three free track positions */ + /* copy an extra position from table - 1pulse search will access this */ + ipos[config->nb_pulse] = tipos[(k*4)+config->nb_pulse]; + break; + } + } + if (config->fixedpulses == 0)/* 1100, 11, 1110, 1111, 2211 */ + { + pos = 0; + ps = 0.0F; + alp = 0.0F; + memset(cor, 0, L_SUBFR * sizeof(Float32)); + } + else if (config->fixedpulses == 2) /* 2222 and 3322 */ + { + /* --- first stage: fix 2 pulses --- */ + /* index to first non-fixed position */ + pos = 2; + + /* set fixed positions */ + ind[0] = pos_max[ipos[0]]; + ind[1] = pos_max[ipos[1]]; + + /* correlation of fixed part with residual */ + ps = dn[ind[0]] + dn[ind[1]]; + + /* multiplication of autocorrelation with signed fixed pulses */ + /* first pulse */ + p0 = R-ind[0]; + if (sign[ind[0]]>0) + { + for (i=0; i0) + { + for (i=0; ifixedpulses == 4) */ /* 3333 and above */ + { + /* first stage: fix 4 pulses */ + pos = 4; + + ind[0] = pos_max[ipos[0]]; + ind[1] = pos_max[ipos[1]]; + ind[2] = pos_max[ipos[2]]; + ind[3] = pos_max[ipos[3]]; + + /* correlation of fixed part with residual */ + ps = dn[ind[0]] + dn[ind[1]] + dn[ind[2]] + dn[ind[3]]; + + /* multiplication of autocorrelation with signed fixed pulses */ + /* first pulse */ + p0 = R-ind[0]; + if (sign[ind[0]]>0) + { + for (i=0; i0) + { + for (i=0; inb_pulse; j += 2, st++) + { + if ((config->nb_pulse-j) >= 2) + { + /*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); + + } + else + { + /*single pulse search*/ + E_ACELP_1pulse_searchx(ipos[j], ipos[j + 1], R, &ps, &alp,&ind[j], dn, cor, sign); + } + } + + /* memorise the best codevector */ + ps2 = ps * ps; + s = (alpk * ps2) - (ps2k * alp); + if (s > 0.0F) + { + ps2k = ps2; + psk = ps; + alpk = alp; + memcpy(codvec, ind, config->nb_pulse * sizeof(Word16)); + } + + } + + /* + * Store weighted energy of code, build the codeword and index of codevector. + */ + + memset(code, 0, L_SUBFR * sizeof(float)); + memset(ind, 0xffffffff, NPMAXPT * 4 * sizeof(Word16)); + for (k = 0; k < config->nb_pulse; k++) + { + i = codvec[k]; /* read pulse position */ + val = sign[i]; /* read sign */ + + index = i / 4; /* pos of pulse (0..15) */ + track = i % 4; + if (val*psk > 0) + { + code[i] += 1.0f; + codvec[k] += (2 * L_SUBFR); + } + else + { + code[i] -= 1.0f; + index += 16; + } + + i = track * NPMAXPT; + while (ind[i] >= 0) + { + i++; + } + + ind[i] = index; + + } + + return; + +} diff --git a/lib_enc/enc_amr_wb.c b/lib_enc/enc_amr_wb.c new file mode 100644 index 000000000..53de5dded --- /dev/null +++ b/lib_enc/enc_amr_wb.c @@ -0,0 +1,199 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + + +/*-------------------------------------------------------------------* + * encod_amr_wb() + * + * Encode excitation signal in AMR-WB IO mode + *-------------------------------------------------------------------*/ + +void encod_amr_wb( + Encoder_State *st, /* i/o: state structure */ + LPD_state *mem, /* i/o: encoder state structure */ + const float speech[], /* i : input speech */ + const float Aw[], /* i : weighted A(z) unquantized for subframes */ + const float Aq[], /* i : 12k8 Lp coefficient */ + const short pitch[3], /* i : open-loop pitch values for quantiz. */ + const float voicing[], /* i : voicing */ + const float *res, /* i : residual signal */ + float *syn, /* i/o: core synthesis */ + float *exc, /* i/o: current non-enhanced excitation */ + float *exc2, /* i/o: current enhanced excitation */ + float *pitch_buf, /* i/o: floating pitch values for each subframe */ + short hf_gain[NB_SUBFR], /* o : decoded HF gain */ + const float *speech16k /* i : input speech @16kHz */ +) +{ + float xn[L_SUBFR]; /* Target vector for pitch search */ + float xn2[L_SUBFR]; /* Target vector for codebook search */ + float cn[L_SUBFR]; /* Target vector in residual domain */ + float h1[L_SUBFR+(M+1)]; /* Impulse response vector */ + float code[L_SUBFR]; /* Fixed codebook excitation */ + float y1[L_SUBFR]; /* Filtered adaptive excitation */ + float y2[L_SUBFR]; /* Filtered algebraic excitation */ + float gain_pit ; /* Pitch gain */ + float voice_fac; /* Voicing factor */ + float gain_code; /* Gain of code */ + float gain_inov; /* inovation gain */ + short i, i_subfr; /* tmp variables */ + short T_op[3]; /* pitch period for quantization */ + short T0, T0_frac; /* close loop integer pitch and fractional part */ + short T0_min, T0_max; /* pitch variables */ + float *pt_pitch; /* pointer to floating pitch buffer */ + float g_corr[6]; /* ACELP correl, values + gain pitch */ + short clip_gain; /* LSF clip gain */ + const float *p_Aw, *p_Aq; /* pointer to LP filter coeff. vector*/ + short unbits = 0; + float norm_gain_code; + short pitch_limit_flag; + short lp_select, lp_flag; + + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + + pitch_limit_flag = 0; /* always restrained pitch Q range in IO mode */ + T0_max = PIT_MAX; + T0_min = PIT_MIN; + + p_Aw = Aw; + p_Aq = Aq; + pt_pitch = pitch_buf; + + mvs2s( pitch, T_op, 2 ); + if( T_op[0] <= PIT_MIN ) + { + T_op[0] *= 2; + } + + if( T_op[1] <= PIT_MIN ) + { + T_op[1] *= 2; + } + + /*------------------------------------------------------------------* + * 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 + *----------------------------------------------------------------*/ + + mvr2r( &res[i_subfr], &exc[i_subfr], L_SUBFR ); + + find_targets( speech, mem->mem_syn, i_subfr, &mem->mem_w0, p_Aq, res, L_SUBFR, p_Aw, TILT_FAC, xn, cn, h1 ); + + /*----------------------------------------------------------------* + * Close-loop pitch search and quantization + * Adaptive exc. construction + *----------------------------------------------------------------*/ + + *pt_pitch = pit_encode( st, st->core_brate, 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, 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( st->core_brate, voicing, i_subfr, 0, xn, st->clip_var ); + + /*-----------------------------------------------------------------* + * LP filtering of the adaptive excitation, codebook target computation + *-----------------------------------------------------------------*/ + + lp_select = lp_filt_exc_enc( MODE1, st->core_brate, 1, -1, i_subfr, exc, h1, xn, y1, xn2, + L_SUBFR, L_FRAME, g_corr, clip_gain, &gain_pit, &lp_flag ); + + if( lp_flag == NORMAL_OPERATION ) + { + push_indice( st, IND_LP_FILT_SELECT, lp_select, 1 ); + } + + /*-----------------------------------------------------------------* + * Innovation encoding + *-----------------------------------------------------------------*/ + + inov_encode( st, st->core_brate, 1, L_FRAME, st->last_L_frame, -1, -1, 0, i_subfr, -1, p_Aq, + gain_pit, cn, exc, h1, mem->tilt_code, *pt_pitch, xn2, code, y2, &unbits); + + /*-----------------------------------------------------------------* + * Gain encoding + * Pitch gain clipping test + * Estimate spectrum tilt and voicing + *-----------------------------------------------------------------*/ + + gain_enc_amr_wb( st, xn, y1, y2, code, st->core_brate, &gain_pit, &gain_code, + &gain_inov, &norm_gain_code, g_corr, clip_gain, st->past_qua_en ); + + gp_clip_test_gain_pit( st->core_brate, gain_pit, st->clip_var); + + mem->tilt_code = est_tilt( exc+i_subfr, gain_pit, code, gain_code, &voice_fac, L_SUBFR, 0 ); + + /*-----------------------------------------------------------------* + * Update memory of the weighting filter + *-----------------------------------------------------------------*/ + + mem->mem_w0 = xn[L_SUBFR-1] - gain_pit * y1[L_SUBFR-1] - gain_code * y2[L_SUBFR-1]; + + /*-----------------------------------------------------------------* + * Find the total excitation + *-----------------------------------------------------------------*/ + + for ( i = 0; i < L_SUBFR; i++ ) + { + exc2[i+i_subfr] = gain_pit * exc[i+i_subfr]; + exc[i+i_subfr] = exc2[i+i_subfr] + gain_code * code[i]; + } + + + /*-----------------------------------------------------------------* + * Synthesize speech to update mem_syn[] + * Update A(z) filters + *-----------------------------------------------------------------*/ + + syn_filt( p_Aq, M, &exc[i_subfr], &syn[i_subfr], L_SUBFR, mem->mem_syn, 1 ); + + /*-----------------------------------------------------------------* + * HF gain modification factors at 23.85 kbps + *-----------------------------------------------------------------*/ + + if ( st->core_brate == ACELP_23k85 ) + { + if( st->input_Fs >= 16000 ) + { + hf_cod( st->core_brate, &speech16k[i_subfr * L_SUBFR16k/L_SUBFR], p_Aq, &exc[i_subfr], &syn[i_subfr], + &st->seed2_enc, st->mem_hp400_enc, st->mem_syn_hf_enc, st->mem_hf_enc, st->mem_hf2_enc, &st->hangover_cnt, + &st->gain_alpha, &hf_gain[i_subfr/L_SUBFR] ); + } + + push_indice( st, IND_HF_GAIN_MODIFICATION, hf_gain[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 000000000..01332f505 --- /dev/null +++ b/lib_enc/enc_gain.c @@ -0,0 +1,233 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include +#include "typedef.h" +#include "prot.h" +#include "rom_enc.h" +#include "rom_com.h" + + + + +/* + * E_GAIN_norm_corr_interpolate + * + * Parameters: + * x I: input vector + * frac I: fraction (-4..+3) + * + * Function: + * Interpolating the normalized correlation + * + * Returns: + * interpolated value + */ +static Float32 E_GAIN_norm_corr_interpolate(Float32 *x, Word32 frac) +{ + Float32 s, *x1, *x2; + const Float32 *c1, *c2; + + if (frac < 0) + { + 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]; + return s; +} + +static Float32 E_GAIN_norm_corr_interpolate6(Float32 *x, Word32 frac) +{ + Float32 s, *x1, *x2; + const Float32 *c1, *c2; + + if (frac < 0) + { + 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]; + return s; +} + +/* + * 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 + */ +Word32 E_GAIN_closed_loop_search(Float32 exc[], + Float32 xn[], Float32 h[], + Word32 t0_min, Word32 t0_min_frac, Word32 t0_max, Word32 t0_max_frac, Word32 t0_min_max_res, Word32 *pit_frac, Word32 *pit_res, Word32 pit_res_max, + Word32 i_subfr, Word32 pit_min, Word32 pit_fr2, Word32 pit_fr1, Word32 L_subfr) +{ + Float32 corr_v[32 + 2 * L_INTERPOL1 + 1]; + Float32 cor_max, max, temp; + Float32 *corr; + Word32 i, fraction, frac1, frac2, step; + Word32 t0, t_min, t_max; + (void)t0_min_frac; + (void)t0_max_frac; + (void)t0_min_max_res; + + /* Find interval to compute normalized correlation */ + if (t0_min_frac>0) + { + t0_min++; + } + t_min = t0_min - L_INTERPOL1; + t_max = t0_max + L_INTERPOL1; + + /* allocate memory to normalized correlation vector */ + corr = &corr_v[-t_min]; /* corr[t_min..t_max] */ + + /* Compute normalized correlation between target and filtered excitation */ + norm_corr(exc, xn, h, t_min, t_max, corr, L_subfr); + + /* find integer pitch */ + max = corr[t0_min]; + t0 = t0_min; + for(i = t0_min + 1; i <= t0_max; i++) + { + if( corr[i] >= max) + { + max = corr[i]; + t0 = i; + } + } + + + + /* If first subframe and t0 >= pit_fr1, do not search fractionnal pitch */ + if((i_subfr == 0) & (t0 >= pit_fr1)) + { + *pit_frac = 0; + *pit_res = 1; + return(t0); + } + + + /* + * Search fractionnal pitch + * Test the fractions around t0 and choose the one which maximizes + * the interpolated normalized correlation. + */ + + if ( t0_min_max_res == (pit_res_max>>1) ) + { + t0_min_frac = t0_min_frac << 1; + t0_max_frac = t0_max_frac << 1; + } + + step = 1; + frac1 = -(pit_res_max-1); + frac2 = pit_res_max-1; + if (((i_subfr == 0) & (t0 >= pit_fr2)) | (pit_fr2 <= pit_min)) + { + step = 2; + frac1 = -(pit_res_max-2); + frac2 = pit_res_max-2; + } + + if ( (t0 == t0_min) && (t0_min_frac==0) ) + { + frac1 = t0_min_frac; + } + else if ( (t0 == t0_min) && (frac1+pit_res_max=0 && frac2>frac1); + if (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 (temp > cor_max) + { + cor_max = temp; + fraction = i; + } + + } + } + 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 (temp > cor_max) + { + cor_max = temp; + fraction = i; + } + + } + } + + /* limit the fraction value */ + if (fraction < 0) + { + fraction += pit_res_max; + t0 -= 1; + } + if (((i_subfr == 0) & (t0 >= pit_fr2)) | (pit_fr2 <= pit_min)) + { + *pit_res = pit_res_max>>1; + *pit_frac = fraction>>1; + } + else + { + *pit_res = pit_res_max; + *pit_frac = fraction; + } + return (t0); +} diff --git a/lib_enc/enc_gen_voic.c b/lib_enc/enc_gen_voic.c new file mode 100644 index 000000000..d57963d4b --- /dev/null +++ b/lib_enc/enc_gen_voic.c @@ -0,0 +1,309 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + + +/*-------------------------------------------------------------------* + * encod_gen_voic() + * + * Encode excitation signal + *-------------------------------------------------------------------*/ + +void encod_gen_voic( + Encoder_State *st, /* i/o: state structure */ + LPD_state *mem, /* i/o: encoder memories */ + const short L_frame, /* i : length of the frame */ + const short sharpFlag, /* i : formant sharpening flag */ + const float speech[], /* i : input speech */ + const float Aw[], /* i : weighted A(z) unquantized for subframes */ + const float Aq[], /* i : LP coefficients */ + const short coder_type, /* i : coding type */ + const float Es_pred, /* i : predicted scaled innov. energy */ + const short T_op[], /* i : open loop pitch */ + const float voicing[], /* i : voicing */ + const float *res, /* i : residual signal */ + float *syn, /* i/o: core synthesis */ + float *exc, /* i/o: current non-enhanced excitation */ + float *exc2, /* i/o: current enhanced excitation */ + float *pitch_buf, /* i/o: floating pitch values for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *bwe_exc, /* o : excitation for SWB TBE */ + short *unbits /* i/o: number of unused bits */ +) +{ + float xn[L_SUBFR]; /* Target vector for pitch search */ + float xn2[L_SUBFR]; /* Target vector for codebook search */ + float cn[L_SUBFR]; /* Target vector in residual domain */ + float h1[L_SUBFR+(M+1)]; /* Impulse response vector */ + float code[L_SUBFR]; /* Fixed codebook excitation */ + float y1[L_SUBFR]; /* Filtered adaptive excitation */ + float y2[L_SUBFR]; /* Filtered algebraic excitation */ + float gain_pit; /* Pitch gain */ + float voice_fac; /* Voicing factor */ + float gain_code; /* Gain of code */ + float gain_inov; /* inovation gain */ + short i, i_subfr; /* tmp variables */ + short T0, T0_frac; /* close loop integer pitch and fractional part */ + short T0_min, T0_max; /* pitch variables */ + float *pt_pitch; /* pointer to floating pitch buffer */ + float g_corr[6]; /* ACELP correl, values + gain pitch */ + float gains_mem[2*(NB_SUBFR-1)]; /* pitch gain and code gain from previous subframes */ + short clip_gain; /* LSF clip gain */ + const float *p_Aw, *p_Aq; /* pointer to LP filter coeff. vector*/ + float error; + int offset; + float gain_preQ; /* Gain of prequantizer excitation */ + float code_preQ[L_SUBFR]; /* Prequantizer excitation */ + short unbits_PI; /* number of unused bits for EVS_PI */ + float norm_gain_code; + short pitch_limit_flag; + short harm_flag_acelp; + short lp_select, lp_flag; + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + + gain_pit = 0; + gain_code = 0; + gain_preQ = 0; + unbits_PI = 0; + error = 0.0f; + + if( L_frame == L_FRAME ) + { + T0_max = PIT_MAX; + T0_min = PIT_MIN; + } + else /* L_frame == L_FRAME16k */ + { + T0_max = PIT16k_MAX; + T0_min = PIT16k_MIN; + } + + p_Aw = Aw; + p_Aq = Aq; + pt_pitch = pitch_buf; + gain_preQ = 0; + set_f( code_preQ, 0, L_SUBFR ); + + /* set and write harmonicity flag */ + harm_flag_acelp = 0; + + if( st->core_brate > ACELP_24k40 && st->core_brate <= ACELP_32k && coder_type == GENERIC ) + { + if( st->last_harm_flag_acelp > 2 ) + { + harm_flag_acelp = 1; + } + + push_indice( st, IND_HARM_FLAG_ACELP, harm_flag_acelp, 1 ); + } + + /*------------------------------------------------------------------* + * ACELP subframe loop + *------------------------------------------------------------------*/ + + for( i_subfr=0; i_subfrmem_syn, i_subfr, &mem->mem_w0, p_Aq, res, L_SUBFR, p_Aw, st->preemph_fac, xn, cn, h1 ); + + /*----------------------------------------------------------------* + * Close-loop pitch search and quantization + * Adaptive exc. construction + *----------------------------------------------------------------*/ + + *pt_pitch = pit_encode( st, st->core_brate, 0, L_frame, coder_type, &pitch_limit_flag, i_subfr, + exc, L_SUBFR, T_op, &T0_min, &T0_max, &T0, &T0_frac, h1, xn ); + + if( L_frame == L_FRAME ) + { + offset = tbe_celp_exc_offset( T0, T0_frac ); + for (i=0; icore_brate, voicing, i_subfr, coder_type, xn, st->clip_var ); + + if( coder_type == INACTIVE ) + { + /* in case of AVQ inactive, limit the gain to 0.65 */ + clip_gain = 2; + } + + /*-----------------------------------------------------------------* + * LP filtering of the adaptive excitation, codebook target computation + *-----------------------------------------------------------------*/ + + lp_select = lp_filt_exc_enc( MODE1, st->core_brate, 0, coder_type, i_subfr, exc, h1, xn, y1, xn2, L_SUBFR, + L_frame, g_corr, clip_gain, &gain_pit, &lp_flag ); + + if( lp_flag == NORMAL_OPERATION ) + { + push_indice( st, IND_LP_FILT_SELECT, lp_select, 1 ); + } + + /* update long-term pitch gain for speech/music classifier */ + st->lowrate_pitchGain = 0.9f * st->lowrate_pitchGain + 0.1f * gain_pit; + + /*-----------------------------------------------------------------* + * Transform-domain contribution (active frames) + *-----------------------------------------------------------------*/ + + if( st->core_brate > ACELP_24k40 && coder_type != INACTIVE ) + { + transf_cdbk_enc( st, st->core_brate, st->extl, coder_type, harm_flag_acelp, i_subfr, -1, cn, exc, + p_Aq, p_Aw, h1, xn, xn2, y1, y2, Es_pred, &gain_pit, gain_code, g_corr, clip_gain, + &(st->mem_deemp_preQ), &(st->mem_preemp_preQ), &gain_preQ, code_preQ, unbits ); + } + + /*-----------------------------------------------------------------* + * Innovation encoding + *-----------------------------------------------------------------*/ + + inov_encode( st, st->core_brate, 0, L_frame, st->last_L_frame, coder_type, st->bwidth, sharpFlag, i_subfr, -1, p_Aq, + gain_pit, cn, exc, h1, mem->tilt_code, *pt_pitch, xn2, code, y2, &unbits_PI ); + + /*-----------------------------------------------------------------* + * Gain encoding + *-----------------------------------------------------------------*/ + + if ( st->core_brate <= ACELP_8k00 ) + { + gain_enc_lbr( st, st->core_brate, coder_type, i_subfr, xn, y1, y2, code, + &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, gains_mem, clip_gain ); + } + else if ( st->core_brate > ACELP_32k ) + { + gain_enc_SQ( st, st->core_brate, coder_type, i_subfr, -1, xn, y1, y2, code, Es_pred, + &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, clip_gain ); + } + else + { + gain_enc_mless( st, st->core_brate, L_frame, coder_type, i_subfr, -1, xn, y1, y2, code, Es_pred, + &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, clip_gain ); + } + + if ( st->last_ppp_mode == 1 ) + { + /* SC-VBR - all other st->clip_var values will be updated even in a PPP frame */ + st->clip_var[1] = gain_pit; + } + + /*-----------------------------------------------------------------* + * update LP-filtered gains for the case of frame erasures + *-----------------------------------------------------------------*/ + + gp_clip_test_gain_pit( st->core_brate, gain_pit, st->clip_var); + mem->tilt_code = est_tilt( exc+i_subfr, gain_pit, code, gain_code, &voice_fac, L_SUBFR, 0 ); + + /*-----------------------------------------------------------------* + * Transform-domain contribution (inactive frames) + *-----------------------------------------------------------------*/ + + if ( st->core_brate > ACELP_24k40 && coder_type == INACTIVE ) + { + transf_cdbk_enc( st, st->core_brate, st->extl, coder_type, 0, i_subfr, -1, cn, exc, + p_Aq, p_Aw, h1, xn, xn2, y1, y2, Es_pred, &gain_pit, gain_code, g_corr, clip_gain, + &(st->mem_deemp_preQ), &(st->mem_preemp_preQ), &gain_preQ, code_preQ, unbits ); + } + + /*-----------------------------------------------------------------* + * Update memory of the weighting filter + *-----------------------------------------------------------------*/ + + mem->mem_w0 = xn[L_SUBFR-1] - (gain_pit*y1[L_SUBFR-1]) - (gain_code*y2[L_SUBFR-1]); + + /*-----------------------------------------------------------------* + * Construct adaptive part of the excitation + * Save the non-enhanced excitation for FEC_exc + *-----------------------------------------------------------------*/ + + for ( i = 0; i < L_SUBFR; i++ ) + { + exc2[i+i_subfr] = gain_pit * exc[i+i_subfr]; + exc[i+i_subfr] = exc2[i+i_subfr] + gain_code * code[i]; + } + + /*-----------------------------------------------------------------* + * Add the ACELP pre-quantizer contribution + *-----------------------------------------------------------------*/ + if( st->core_brate > ACELP_24k40 ) + { + for ( i = 0; i < L_SUBFR; i++ ) + { + exc2[i+i_subfr] += gain_preQ * code_preQ[i]; + exc[i+i_subfr] += gain_preQ * code_preQ[i]; + } + } + + /*-----------------------------------------------------------------* + * Prepare TBE excitation + *-----------------------------------------------------------------*/ + + prep_tbe_exc( L_frame, i_subfr, gain_pit, gain_code, code, voice_fac, &voice_factors[i_subfr/L_SUBFR], + bwe_exc, gain_preQ, code_preQ, T0, coder_type, st->core_brate ); + + + /*-----------------------------------------------------------------* + * Synthesize speech to update mem_syn[]. + * Update A(z) filters + *-----------------------------------------------------------------*/ + + syn_filt( p_Aq, M, &exc[i_subfr], &syn[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 = min(unbits_PI, 16); + push_indice( st, IND_UNUSED, 0, i ); + unbits_PI -= i; + } + + /* SC-VBR */ + st->prev_ppp_gain_pit = gain_pit; + st->prev_tilt_code = mem->tilt_code; + + return; +} diff --git a/lib_enc/enc_gen_voic_rf.c b/lib_enc/enc_gen_voic_rf.c new file mode 100644 index 000000000..5a85c602a --- /dev/null +++ b/lib_enc/enc_gen_voic_rf.c @@ -0,0 +1,384 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + + +/*-------------------------------------------------------------------* + * reset_rf_indices() + * + * Initialization of oartial redundancy coding + *-------------------------------------------------------------------*/ + +void reset_rf_indices( + Encoder_State *st /* i: state structure - contains partial RF indices */ +) +{ + short i, j; + + 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 */ + + st->rf_mem_w0 = 0; + set_f( st->rf_clip_var, 0, 6 ); + st->rf_tilt_code = 0; + set_f( st->rf_mem_syn2, 0, M ); + set_f( st->rf_dispMem, 0, 8 ); + st->rf_gc_threshold = 0; + set_f( st->rf_tilt_buf, 0, NB_SUBFR16k ); + + st->rf_target_bits = 0; + st->rf_target_bits_write = 0; + st->rf_tcxltp_pitch_int_past = st->L_frame; + st->rf_last_tns_active = 0; + st->rf_second_last_tns_active = 0; + st->rf_second_last_core= 0; + + for( i = 0; i < MAX_RF_FEC_OFFSET; i++ ) + { + st->rf_indx_frametype[i] = RF_NO_DATA; + st->rf_targetbits_buff[i] = 6; /* rf_mode: 1, rf_frame_type: 3, and fec_offset: 2 */ + st->rf_indx_lsf[i][0] = 0; + st->rf_indx_lsf[i][1] = 0; + st->rf_indx_lsf[i][2] = 0; + st->rf_indx_EsPred[i] = 0; + st->rf_indx_nelp_fid[i] = 0; + st->rf_indx_nelp_iG1[i] = 0; + st->rf_indx_nelp_iG2[i][0] = 0; + st->rf_indx_nelp_iG2[i][1] = 0; + + for( j = 0; j < NB_SUBFR16k; j++ ) + { + st->rf_indx_ltfMode[i][j] = 0; + st->rf_indx_pitch[i][j] = 0; + st->rf_indx_fcb[i][j] = 0; + st->rf_indx_gain[i][j] = 0; + } + + st->rf_clas[i] = UNVOICED_CLAS; + st->rf_gain_tcx[i] = 0; + st->rf_tcxltp_param[i] = 0; + + st->rf_indx_tbeGainFr[i] = 0; + } + + return; +} + + +/*-------------------------------------------------------------------* + * coder_acelp_rf() + * + * Encode excitation signal (partial redundancy) + *-------------------------------------------------------------------*/ + +void coder_acelp_rf( + const short target_bits, /* i: target bits */ + const float speech[], /* i : speech[-M..lg] */ + const short coder_type, /* i : coding type */ + const short rf_frame_type, /* i : rf_frame_type */ + const float A[], /* i : coefficients 4xAz[M+1] */ + const float Aq[], /* i : coefficients 4xAz_q[M+1] */ + const float voicing[], /* i : open-loop LTP gain */ + const short T_op[], /* i : open-loop LTP lag */ + const float stab_fac, /* i : LP stability factor */ + Encoder_State *st, /* i/o : coder memory state */ + ACELP_config *acelp_cfg, /* i/o: configuration of the ACELP */ + float *exc_rf, /* i/o: pointer to RF excitation */ + float *syn_rf /* i/o: pointer to RF synthesis */ +) +{ + short i, i_subfr, nSubfr; + int T0, T0_min, T0_min_frac, T0_max, T0_max_frac, T0_res; + int T0_frac; + float Es_pred_rf; + float gain_pit, gain_code, voice_fac; + float prev_gain_pit; + ACELP_CbkCorr g_corr; + float g_corr2[6]; + const float *p_A, *p_Aq; + float code[L_SUBFR]; + float xn[L_SUBFR], cn[L_SUBFR], h1[L_SUBFR]; + float xn2[L_SUBFR], y1[L_SUBFR], y2[L_SUBFR]; + float res_save; + float exc2[L_SUBFR]; + float exc_nelp[L_FRAME]; + float syn2[L_FRAME16k]; + float past_gcode, gain_inov; + short clip_gain; + float gain_code2; + float code2[L_SUBFR]; + float y22[L_SUBFR]; + float lp_select; + int *prm_rf; + + /*-----------------------------------------------------------------------* + * Initialization + *------------------------------------------------------------------------*/ + past_gcode = 0; + gain_inov = 0; + T0 = 0; + T0_res = 0; + T0_frac = 0; + gain_pit = 0; + gain_code = 0; + voice_fac = 0; + prev_gain_pit=0; + Es_pred_rf = 0; + set_f(code, 0.0f, L_SUBFR); + + /*-----------------------------------------------------------------------* + * Configure ACELP partial copy * + *-----------------------------------------------------------------------*/ + + BITS_ALLOC_config_acelp( target_bits, rf_frame_type, &(st->acelp_cfg_rf), 0, st->nb_subfr ); + + /* Reset phase dispersion */ + if( st->last_core > 0 ) + { + set_zero( st->rf_dispMem, 8 ); + } + + /*---------------------------------------------------------------* + * Calculation of LP residual (filtering through A[z] filter) + *---------------------------------------------------------------*/ + + calc_residu( speech, exc_rf, Aq, st->L_frame ); + + /*------------------------------------------------------------------------* + * Find and quantize mean_ener_code for gain quantizer * + *------------------------------------------------------------------------*/ + + Es_pred_rf = 0; + if( acelp_cfg->nrg_mode > 0 && rf_frame_type != RF_NELP ) + { + Es_pred_enc( &Es_pred_rf, &st->rf_indx_EsPred[0], st->L_frame, L_SUBFR, exc_rf, voicing, + acelp_cfg->nrg_bits, acelp_cfg->nrg_mode>1 ); + } + + /*------------------------------------------------------------------* + * ACELP subframe loop + *------------------------------------------------------------------*/ + + p_A = A; + p_Aq = Aq; + + res_save = exc_rf[0]; + nSubfr = 0; + + for( i_subfr = 0; i_subfr < st->L_frame; i_subfr += L_SUBFR ) + { + if( rf_frame_type != RF_NELP ) + { + /* Restore exc[i_subfr] and save next exc[L_SUBFR+i_subfr] */ + exc_rf[i_subfr] = res_save; + res_save = exc_rf[L_SUBFR + i_subfr]; + + /*--------------------------------------------------------------------------* + * Find target for pitch search (xn[]), target for innovation search (cn[]) * + * and impulse response of the weighted synthesis filter (h1[]). * + *--------------------------------------------------------------------------*/ + + find_targets( speech, &syn_rf[i_subfr-M], i_subfr, &(st->rf_mem_w0), + p_Aq, exc_rf, L_SUBFR, p_A, st->preemph_fac, xn, cn, h1 ); + } + + /* full frame nelp partial copy encoding */ + if( rf_frame_type == RF_NELP ) + { + if( i_subfr == 0 ) + { + nelp_encoder( st, exc_rf, exc_nelp + ,0 + ); + } + mvr2r( &exc_nelp[i_subfr], exc2, L_SUBFR ); + mvr2r( &exc_nelp[i_subfr], exc_rf, L_SUBFR ); + } + else + { + /*-----------------------------------------------------------------* + * Gain clipping test to avoid unstable synthesis on frame erasure + * or in case of floating point encoder & fixed p. decoder + *-----------------------------------------------------------------*/ + + clip_gain = gp_clip( st->core_brate, voicing, i_subfr, coder_type, xn, st->rf_clip_var ); + + /*-----------------------------------------------------------------* + * - 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->gains_mode[i_subfr/L_SUBFR] == 0 ) + { + gain_pit = prev_gain_pit; + } + + if ( acelp_cfg->ltp_bits != 0 ) + { + prm_rf = &st->rf_indx_pitch[0][nSubfr]; + + /* Adaptive Codebook (GC and VC) */ + Mode2_pit_encode( acelp_cfg->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 */ + if( T0_res == (st->pit_res_max>>1) ) /* st->pit_res_max is 4 for 12.8kHz core */ + { + pred_lt4( &exc_rf[i_subfr], &exc_rf[i_subfr], T0, T0_frac<<1, L_SUBFR+1, inter4_2, L_INTERPOL2, PIT_UP_SAMP); + } + else + { + pred_lt4( &exc_rf[i_subfr], &exc_rf[i_subfr], T0, T0_frac, L_SUBFR+1, inter4_2, L_INTERPOL2, PIT_UP_SAMP); + } + + + /* filter adaptive codebook */ + lp_select = lp_filt_exc_enc( MODE2, st->core_brate, 0, (acelp_cfg->gains_mode[i_subfr/L_SUBFR]>0)?(acelp_cfg->gains_mode[i_subfr/L_SUBFR]):(100), + i_subfr, exc_rf, h1, xn, y1, xn2, L_SUBFR, st->L_frame, g_corr2, clip_gain, &(gain_pit), &(acelp_cfg->ltf_mode) ); + + if( acelp_cfg->ltf_mode == NORMAL_OPERATION ) + { + st->rf_indx_ltfMode[0][nSubfr] = lp_select; + } + + g_corr.y1y1 = g_corr2[0]; + g_corr.xy1 = -0.5f*(g_corr2[1]-0.01f)+0.01f; + } + else + { + gain_pit=0.f; + g_corr.xy1=0.f; + g_corr.y1y1=0.f; + set_zero( y1, L_SUBFR ); + set_zero( exc_rf+i_subfr, L_SUBFR ); + T0 = L_SUBFR; + T0_frac = 0; + T0_res = 1; + } + + /*----------------------------------------------------------------------* + * Encode the algebraic innovation * + *----------------------------------------------------------------------*/ + + if( acelp_cfg->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->fixed_cdk_index[i_subfr/L_SUBFR], + 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, + i_subfr, p_Aq, h1, xn, cn, y1, y2, + st->acelp_autocorr, &prm_rf, code + ,st->L_frame, st->last_L_frame, st->total_brate + + ); + } + else + { + set_f( code, 0.0f, L_SUBFR ); + set_f( y2, 0.0f, L_SUBFR ); + } + + if( i_subfr < (st->L_frame - L_SUBFR) ) + { + E_corr_xy2( xn, y1, y2, g_corr2, L_SUBFR ); + g_corr.y2y2 = 0.01F + g_corr2[2]; + g_corr.xy2 = 0.01F + -0.5f*g_corr2[3]; + g_corr.y1y2 = 0.01F + 0.5f*g_corr2[4]; + + g_corr.xx = 0.01F + dotp( xn, xn, L_SUBFR ); + + /*----------------------------------------------------------------------* + * Add Gaussian excitation * + *----------------------------------------------------------------------*/ + + gain_code2 = 0.f; + set_zero( code2, L_SUBFR ); + set_zero( y22, L_SUBFR ); + + /*----------------------------------------------------------* + * - Compute the fixed codebook gain * + * - quantize fixed codebook gain * + *----------------------------------------------------------*/ + + if( acelp_cfg->gains_mode[i_subfr/L_SUBFR] != 0 ) + { + prm_rf = &st->rf_indx_gain[0][nSubfr]; + encode_acelp_gains( code, acelp_cfg->gains_mode[i_subfr/L_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( st->core_brate, gain_pit, st->rf_clip_var ); + + /*----------------------------------------------------------* + * - voice factor (for codebook tilt sharpening) * + *----------------------------------------------------------*/ + + st->rf_tilt_code = est_tilt( exc_rf+i_subfr, gain_pit, code, gain_code, &voice_fac, L_SUBFR, acelp_cfg->voice_tilt ); + + /*-----------------------------------------------------------------* + * Update memory of the weighting filter + *-----------------------------------------------------------------*/ + + st->rf_mem_w0 = xn[L_SUBFR-1] - gain_pit * y1[L_SUBFR-1] - gain_code * y2[L_SUBFR-1] - gain_code2*y22[L_SUBFR-1]; + + /*-------------------------------------------------------* + * - Find the total excitation. * + *-------------------------------------------------------*/ + + for( i = 0; i < L_SUBFR; i++ ) + { + exc2[i] = gain_pit * exc_rf[i+i_subfr]; + exc2[i] += gain_code2 * code2[i]; + exc_rf[i+i_subfr] = exc2[i] + gain_code * code[i]; + } + + /*---------------------------------------------------------* + * Enhance the excitation * + *---------------------------------------------------------*/ + + enhancer( MODE2, -1, acelp_cfg->fixed_cdk_index[i_subfr/L_SUBFR], 0, coder_type, st->L_frame, voice_fac, stab_fac, + past_gcode, gain_inov, &st->rf_gc_threshold, code, exc2, gain_pit, st->rf_dispMem ); + } + } + + if( (i_subfr < (st->L_frame - L_SUBFR)) || (rf_frame_type != RF_NELP) ) + { + /*----------------------------------------------------------* + * - compute the synthesis speech * + *----------------------------------------------------------*/ + + syn_filt( p_Aq, M, exc2, &syn2[i_subfr], L_SUBFR, st->rf_mem_syn2, 1 ); + + syn_filt( p_Aq, M, &exc_rf[i_subfr], &syn_rf[i_subfr], L_SUBFR, &syn_rf[i_subfr-M], 0 ); + + /*----------------------------------------------------------* + * Updates * + *----------------------------------------------------------*/ + + p_A += (M+1); + p_Aq += (M+1); + nSubfr++; + + /* 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.c b/lib_enc/enc_higher_acelp.c new file mode 100644 index 000000000..349f09e53 --- /dev/null +++ b/lib_enc/enc_higher_acelp.c @@ -0,0 +1,332 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ + +static void find_cn( const float xn[], const float Ap[], const float *p_Aq, float cn[] ); + +/*-----------------------------------------------------------------* + * Transform domain contribution encoding + *-----------------------------------------------------------------*/ + +void transf_cdbk_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const long core_brate, /* i : core bitrate */ + const short extl, /* i : extension layer */ + const short coder_type, /* i : coding type */ + const short harm_flag_acelp,/* i : harmonic flag for higher rates ACELP */ + const short i_subfr, /* i : subframe index */ + const short tc_subfr, /* i : TC subframe index */ + float cn[], /* i/o: target vector in residual domain */ + float exc[], /* i/o: pointer to excitation signal frame */ + const float *p_Aq, /* i : 12k8 Lp coefficient */ + const float Ap[], /* i : weighted LP filter coefficients */ + const float h1[], /* i : weighted filter input response */ + float xn[], /* i/o: target vector */ + float xn2[], /* i/o: target vector for innovation search */ + float y1[], /* i/o: zero-memory filtered adaptive excitation */ + const float y2[], /* i : zero-memory filtered innovative excitation */ + const float Es_pred, /* i : predicited scaled innovation energy */ + float *gain_pit, /* i/o: adaptive excitation gain */ + const float gain_code, /* i : innovative excitation gain */ + float g_corr[], /* o : ACELP correlation values */ + const short clip_gain, /* i : adaptive gain clipping flag */ + float *mem_deemp, /* i/o: prequantizer deemhasis memory */ + float *mem_preemp, /* i/o: prequantizer preemhasis memory */ + float *gain_preQ, /* o : prequantizer excitation gain */ + float code_preQ[], /* o : prequantizer excitation */ + short *unbits /* o : number of AVQ unused bits */ +) +{ + short i, index, nBits, Nsv; + float x_in[L_SUBFR], x_tran[L_SUBFR], temp; + int x_norm[L_SUBFR+L_SUBFR/WIDTH_BAND]; + float corr, ener; + short nq[L_SUBFR/WIDTH_BAND]; + + /*--------------------------------------------------------------* + * Set bit-allocation + *--------------------------------------------------------------*/ + + Nsv = 8; + nBits = AVQ_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ(core_brate, coder_type, i_subfr, TC_SUBFR2IDX_16KHZ(tc_subfr))]; + + /* increase # of AVQ allocated bits by unused bits from the previous subframe */ + nBits += (*unbits); + + /*--------------------------------------------------------------* + * Compute/Update target + * For inactive frame, find target in residual domain + * Deemphasis + *--------------------------------------------------------------*/ + + if ( coder_type == INACTIVE ) + { + for( i=0; i ACELP_24k40 && core_brate <= ACELP_32k && !harm_flag_acelp ) + { + mvr2r( x_in, x_tran, L_SUBFR ); + } + else + { + edct2( L_SUBFR, -1, x_in, x_tran, ip_edct2_64, w_edct2_64 ); + } + + /*--------------------------------------------------------------* + * Split algebraic vector quantizer based on RE8 lattice + *--------------------------------------------------------------*/ + + AVQ_cod( x_tran, x_norm, nBits, Nsv ); + + /*--------------------------------------------------------------* + * Find prequantizer excitation gain + * Quantize the gain + *--------------------------------------------------------------*/ + + corr = 0; + ener = 1e-6f; + + for (i = 0; i < Nsv*8; i++) + { + corr += x_tran[i]*(float)x_norm[i]; + ener += (float)x_norm[i]*(float)x_norm[i]; + } + + *gain_preQ = corr/ener; + + if ( coder_type == INACTIVE ) + { + *gain_preQ /= gain_code; + + if( core_brate == ACELP_64k ) + { + index = usquant( *gain_preQ, gain_preQ, G_AVQ_MIN_INACT_64k, G_AVQ_DELTA_INACT_64k, (1 << G_AVQ_BITS) ); + } + else if( core_brate == ACELP_48k ) + { + index = usquant( *gain_preQ, gain_preQ, G_AVQ_MIN_INACT_48k, G_AVQ_DELTA_INACT_48k, (1 << G_AVQ_BITS) ); + } + else + { + index = usquant( *gain_preQ, gain_preQ, G_AVQ_MIN_INACT, G_AVQ_DELTA_INACT, (1 << G_AVQ_BITS) ); + } + + *gain_preQ *= gain_code; + } + else + { + if( Es_pred < 0 ) + { + temp = 0.25f * fabs(Es_pred); + } + else + { + temp = Es_pred; + } + *gain_preQ /= temp; + + if( core_brate > ACELP_24k40 && core_brate <= ACELP_32k ) + { + index = gain_quant( gain_preQ, 0.1f*G_AVQ_MIN, G_AVQ_MAX, G_AVQ_BITS ); + } + else + { + index = gain_quant( gain_preQ, G_AVQ_MIN, G_AVQ_MAX, G_AVQ_BITS ); + } + *gain_preQ *= temp; + } + + push_indice( st, IND_AVQ_GAIN, index, G_AVQ_BITS ); + + /*--------------------------------------------------------------* + * Encode and multiplex subvectors into bit-stream + *--------------------------------------------------------------*/ + + AVQ_encmux( st, -1, x_norm, &nBits, Nsv, nq ); + + /* save # of AVQ unused bits for next subframe */ + *unbits = nBits; + + /* at the last subframe, write AVQ unused bits */ + if( i_subfr == 4*L_SUBFR && extl != SWB_BWE_HIGHRATE && extl != FB_BWE_HIGHRATE ) + { + while( *unbits > 0 ) + { + i = min(*unbits, 16); + push_indice( st, IND_UNUSED, 0, i ); + *unbits -= i; + } + } + + /*--------------------------------------------------------------* + * DCT transform + *--------------------------------------------------------------*/ + + for( i=0; i ACELP_24k40 && core_brate <= ACELP_32k && !harm_flag_acelp ) + { + mvr2r( x_tran, code_preQ, L_SUBFR ); + } + else + { + edct2( L_SUBFR, 1, x_tran, code_preQ, ip_edct2_64, w_edct2_64 ); + } + + /*--------------------------------------------------------------* + * Preemphasise + *--------------------------------------------------------------*/ + + /* in extreme cases at subframe boundaries, lower the preemphasis memory to avoid a saturation */ + if( (nq[7] != 0) && (st->last_nq_preQ - nq[0] > 7) ) + { + *mem_preemp /= 16; + } + + st->last_nq_preQ = nq[7]; + + preemph( code_preQ, FAC_PRE_AVQ, L_SUBFR, mem_preemp ); + + /*--------------------------------------------------------------* + * For inactive segments + * - Zero-memory filtered pre-filter excitation + * - Update of targets and gain_pit + * For active segments + * - Update xn[L_subfr-1] for updating the memory of the weighting filter + *--------------------------------------------------------------*/ + + if ( coder_type == INACTIVE ) + { + temp = code_preQ[0] * h1[L_SUBFR-1]; + + for( i=1; i 0.95f ) + { + *gain_pit = 0.95f; + } + + updt_tar( xn, xn2, y1, *gain_pit, L_SUBFR ); + } + + st->use_acelp_preq = 1; + + return; + +} + +/*-------------------------------------------------------------------* + * Find target in residual domain - cn[] + *-------------------------------------------------------------------*/ + +static void find_cn( + const float xn[], /* i : target signal */ + const float Ap[], /* i : weighted LP filter coefficients */ + const float *p_Aq, /* i : 12k8 LP coefficients */ + float cn[] /* o : target signal in residual domain */ +) +{ + float tmp, tmp_fl[L_SUBFR+M]; + + set_f( tmp_fl, 0, M ); + mvr2r( xn, tmp_fl+M, L_SUBFR ); + tmp = 0.0f; + + preemph( tmp_fl+M, PREEMPH_FAC_16k, L_SUBFR, &tmp ); + syn_filt( Ap, M, tmp_fl+M, tmp_fl+M, L_SUBFR, tmp_fl, 0 ); + residu( p_Aq, M, tmp_fl+M, cn, L_SUBFR ); + + return; +} + +/*---------------------------------------------------------------* + * gain_quant() + * + * Quantization of gains between the specified range + * using the specified number of levels. + *---------------------------------------------------------------*/ + +short gain_quant( /* o: quantization index */ + float *gain, /* i/o: quantized gain */ + const float min, /* i: value of lower limit */ + const float max, /* i: value of upper limit */ + const short bits /* i: number of bits to quantize */ +) +{ + short index, levels; + float tmp, c_min, c_mult; + + levels = 1< levels-1 ) + { + index = levels-1; + } + + *gain = (float)pow( 10.0, (((float)index)/c_mult) + c_min ); + + return(index); +} diff --git a/lib_enc/enc_nelp.c b/lib_enc/enc_nelp.c new file mode 100644 index 000000000..7d7f7beab --- /dev/null +++ b/lib_enc/enc_nelp.c @@ -0,0 +1,114 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * encod_nelp() + * + * Encode Unvoiced frames in SC-VBR + *-------------------------------------------------------------------*/ + +void encod_nelp( + Encoder_State *st, /* i/o: state structure */ + LPD_state *mem, /* i/o: encoder memories */ + const float *speech, /* i : input speech */ + const float Aw[], /* i : weighted A(z) unquantized for subframes */ + const float *Aq, /* i : 12k8 Lp coefficient */ + float *res, /* o : residual signal */ + float *synth, /* o : core synthesis */ + float *tmp_noise, /* o : long-term noise energy */ + float *exc, /* i/o: current non-enhanced excitation */ + float *exc2, /* i/o: current enhanced excitation */ + float *pitch_buf, /* o : floating pitch values for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *bwe_exc /* o : excitation for SWB TBE */ +) +{ + float xn[L_SUBFR]; /* Target vector for pitch search */ + float h1[L_SUBFR]; /* Impulse response vector */ + float exc_nelp[L_FRAME]; + const float *p_Aw,*p_Aq;/* pointer to LP filter coeff. vector */ + short i_subfr, j; + + + short reduce_gains = 0; + + if ( st->bwidth == NB && st->input_Fs >= 16000) + { + if (st->last_nelp_mode == 0) + { + set_f( st->nelp_lp_fit_mem, 0, NELP_LP_ORDER*2 ); + } + polezero_filter( res, res, L_FRAME, num_nelp_lp, den_nelp_lp, NELP_LP_ORDER, st->nelp_lp_fit_mem ); /*16-Q of filter coeff*/ + } + + p_Aw = Aw; + p_Aq = Aq; + + for (i_subfr=0; i_subfrmem_syn, i_subfr, &mem->mem_w0, p_Aq,res, L_SUBFR, p_Aw, TILT_FAC, xn, NULL, h1 ); + + if (i_subfr == 0) + { + if ( (st->Local_VAD == 1 ) && ( st->bwidth == NB) ) + { + reduce_gains = 1; + } + + nelp_encoder(st, res, exc_nelp, reduce_gains); + } + *tmp_noise = 0; + + /*-----------------------------------------------------------------* + * Synthesize speech to update mem_syn[]. + * Update A(z) filters + *-----------------------------------------------------------------*/ + + syn_filt( p_Aq, M, &exc_nelp[i_subfr], &synth[i_subfr], L_SUBFR, mem->mem_syn, 1 ); + + p_Aw += (M+1); + p_Aq += (M+1); + *pitch_buf = L_SUBFR; + pitch_buf++; + } + + mvr2r( exc_nelp, exc, L_FRAME ); + + /*-----------------------------------------------------------------* + * Updates: last value of new target is stored in mem_w0 + *-----------------------------------------------------------------*/ + + mem->mem_w0 = xn[L_SUBFR-1] - (exc[L_FRAME-1]); + mem->tilt_code = 0.0f; /* purely unvoiced */ + st->prev_tilt_code = mem->tilt_code; + + mvr2r(exc, exc2, L_FRAME); + + st->prev_ppp_gain_pit = 0.0; + st->dispMem[0] = 0; + st->dispMem[2] = st->prev_ppp_gain_pit; + + for( j=3; j<7; j++ ) + { + st->dispMem[j] = st->dispMem[j-1]; + } + + interp_code_5over2( exc2, bwe_exc, L_FRAME ); + set_f( voice_factors, 0.0f, NB_SUBFR16k ); + + return; +} diff --git a/lib_enc/enc_pit_exc.c b/lib_enc/enc_pit_exc.c new file mode 100644 index 000000000..49057228c --- /dev/null +++ b/lib_enc/enc_pit_exc.c @@ -0,0 +1,278 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * enc_pit_exc() + * + * Encode pitch only contribution + *-------------------------------------------------------------------*/ + +void enc_pit_exc( + Encoder_State *st, /* i/o: State structure */ + LPD_state *mem, /* i/o: encoder memories */ + const float *speech, /* i : Input speech */ + const float Aw[], /* i : weighted A(z) unquantized for subframes */ + const float *Aq, /* i : 12k8 Lp coefficient */ + const float Es_pred, /* i : predicted scaled innov. energy */ + const short *T_op, /* i : open loop pitch */ + const float *voicing, /* i : voicing */ + const float *res, /* i : residual signal */ + float *synth, /* i/o: core synthesis */ + float *exc, /* i/o: current non-enhanced excitation */ + short *T0, /* i/o: close loop integer pitch */ + short *T0_frac, /* i/o: close-loop pitch period - fractional part */ + float *pitch_buf, /* i/o: Fractionnal per subframe pitch */ + const short nb_subfr, /* i : Number of subframe considered */ + float *gpit /* o : pitch mean gpit */ +) +{ + float xn[PIT_EXC_L_SUBFR]; /* Target vector for pitch search */ + float xn2[PIT_EXC_L_SUBFR]; /* Target vector for codebook search */ + float cn[PIT_EXC_L_SUBFR]; /* Target vector in residual domain */ + float h1[PIT_EXC_L_SUBFR+(M+1)]; /* Impulse response vector */ + float y1[PIT_EXC_L_SUBFR]; /* Filtered adaptive excitation */ + float code[L_SUBFR]; /* Fixed codebook excitation */ + float y2[L_SUBFR]; /* Filtered algebraic excitation */ + float voice_fac; /* Voicing factor */ + float gain_code; /* Gain of code */ + float gain_inov; /* inovation gain */ + float gain_pit; /* Pitch gain */ + short pit_idx, i_subfr; /* tmp variables */ + short T0_min, T0_max; /* pitch variables */ + float g_corr[10]; /* ACELP correlation values + gain pitch */ + short clip_gain, i; /* LSF clip gain and LP flag */ + const float *p_Aw, *p_Aq; /* pointer to LP filter coefficient vector */ + float *pt_pitch; /* pointer to floating pitch */ + short L_subfr; + float cum_gpit, gpit_tmp; + short Local_BR, Pitch_BR, Pitch_CT; + short unbits_PI = 0; /* saved bits for EVS_PI */ + float norm_gain_code; + short pitch_limit_flag; + short lp_select, lp_flag; + + /*------------------------------------------------------------------* + * Initialization + *------------------------------------------------------------------*/ + + pitch_limit_flag = 1; /* always extended pitch Q range */ + + if( st->GSC_noisy_speech ) + { + Local_BR = ACELP_7k20; + Pitch_CT = GENERIC; + Pitch_BR = ACELP_7k20; + } + else + { + Local_BR = ACELP_7k20; + Pitch_CT = AUDIO; + Pitch_BR = st->core_brate; + } + + gain_code = 0; + + T0_max = PIT_MAX; + T0_min = PIT_MIN; + + cum_gpit = 0.0f; + L_subfr = L_FRAME/nb_subfr; + + + /*------------------------------------------------------------------* + * ACELP subframe loop + *------------------------------------------------------------------*/ + + p_Aw = Aw; + p_Aq = Aq; + pt_pitch = pitch_buf; /* pointer to the pitch buffer */ + for( i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_subfr ) + { + + /*----------------------------------------------------------------* + * Find the the excitation search target "xn" and innovation + * target in residual domain "cn" + * Compute impulse response, h1[], of weighted synthesis filter + *----------------------------------------------------------------*/ + + mvr2r( &res[i_subfr], &exc[i_subfr], L_subfr ); + + if( L_subfr == L_SUBFR ) + { + find_targets( speech, st->mem_syn_tmp, i_subfr, &st->mem_w0_tmp, p_Aq, res, L_subfr, p_Aw, st->preemph_fac, xn, cn, h1 ); + } + else + { + find_targets( speech, st->mem_syn_tmp, i_subfr, &st->mem_w0_tmp, p_Aq, res, L_subfr, p_Aw, st->preemph_fac, xn, NULL, h1 ); + } + + /*----------------------------------------------------------------* + * Close-loop pitch search and quantization + * Adaptive exc. construction + *----------------------------------------------------------------*/ + + *pt_pitch = pit_encode( st, 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, 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( st->core_brate, voicing, i_subfr, AUDIO, xn, st->clip_var ); + + /*-----------------------------------------------------------------* + * Codebook target computation + * (No LP filtering of the adaptive excitation) + *-----------------------------------------------------------------*/ + + lp_select = lp_filt_exc_enc( MODE1, st->core_brate, 0, AUDIO, i_subfr, exc, h1, xn, y1, xn2, L_subfr, + L_FRAME, g_corr, clip_gain, &gain_pit, &lp_flag ); + + if( lp_flag == NORMAL_OPERATION ) + { + push_indice( st, IND_LP_FILT_SELECT, lp_select, 1 ); + } + + /* update long-term pitc hgain for speech/music classifier */ + st->lowrate_pitchGain = 0.9f * st->lowrate_pitchGain + 0.1f * gain_pit; + + gpit_tmp = gain_pit; + + if( st->GSC_noisy_speech == 0 || L_subfr != L_SUBFR ) + { + pit_idx = (short) vquant(&gain_pit, mean_gp, &gain_pit, dic_gp, 1, 16); + push_indice( st, IND_PIT_IDX, pit_idx, 4 ); + } + + if( st->GSC_noisy_speech && L_subfr == L_SUBFR ) + { + /*-----------------------------------------------------------------* + * Innovation & gain encoding + *-----------------------------------------------------------------*/ + + inov_encode( st, Local_BR, 0, L_FRAME, st->last_L_frame, LOCAL_CT, WB, 1, i_subfr, -1, + p_Aq, gain_pit, cn, exc, h1, mem->tilt_code, *pt_pitch, xn2, code, y2, &unbits_PI ); + + gain_enc_mless( st, Local_BR, L_FRAME, LOCAL_CT, i_subfr, -1, xn, y1, y2, code, Es_pred, + &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, clip_gain ); + } + + gp_clip_test_gain_pit( st->core_brate, gain_pit, st->clip_var ); + + if( st->GSC_noisy_speech ) + { + mem->tilt_code = est_tilt( exc+i_subfr, gain_pit, code, gain_code, &voice_fac, L_SUBFR, 0 ); + } + else + { + mem->tilt_code = 0.0f; + } + + /*-----------------------------------------------------------------* + * Update memory of the weighting filter + *-----------------------------------------------------------------*/ + + if( st->GSC_noisy_speech ) + { + st->mem_w0_tmp = xn[L_subfr-1] - (gain_pit*y1[L_subfr-1]) - (gain_code*y2[L_subfr-1]); + } + else + { + st->mem_w0_tmp = xn[L_subfr-1] - (gain_pit*y1[L_subfr-1]); + } + + /*-----------------------------------------------------------------* + * Construct adaptive part of the excitation + * Save the non-enhanced excitation for FEC_exc + *-----------------------------------------------------------------*/ + + if( st->GSC_noisy_speech ) + { + for ( i = 0; i < L_subfr; i++ ) + { + exc[i+i_subfr] = gain_pit * exc[i+i_subfr] + gain_code * code[i]; + } + } + else + { + for ( i = 0; i < L_subfr; i++ ) + { + exc[i+i_subfr] = gain_pit * exc[i+i_subfr]; + } + } + + /*-----------------------------------------------------------------* + * Synthesize speech to update mem_syn[]. + * Update A(z) filters + *-----------------------------------------------------------------*/ + + syn_filt( p_Aq, M, &exc[i_subfr], &synth[i_subfr], L_subfr, st->mem_syn_tmp, 1 ); + + if( L_subfr == 2*L_SUBFR ) + { + if( i_subfr == 0 ) + { + cum_gpit = gpit_tmp*.5f; + } + else + { + cum_gpit += gpit_tmp*.5f; + } + + p_Aw += 2*(M+1); + p_Aq += 2*(M+1); + pt_pitch++; + *pt_pitch = *(pt_pitch-1); + pt_pitch++; + } + else if( L_subfr == 4*L_SUBFR ) + { + cum_gpit = gpit_tmp; + + pt_pitch++; + *pt_pitch = *(pt_pitch-1); + pt_pitch++; + *pt_pitch = *(pt_pitch-1); + 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 = gpit_tmp*.25f; + } + else + { + cum_gpit += gpit_tmp*.25f; + } + + pt_pitch++; + p_Aw += (M+1); + p_Aq += (M+1); + } + } + + *gpit = 0.1f * *gpit + 0.9f * cum_gpit; + + return; +} diff --git a/lib_enc/enc_ppp.c b/lib_enc/enc_ppp.c new file mode 100644 index 000000000..f2c39eb7d --- /dev/null +++ b/lib_enc/enc_ppp.c @@ -0,0 +1,166 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" + +/*------------------------------------------------------------------- + * encod_ppp() + * + * Encode PPP frames in SC-VBR + *-------------------------------------------------------------------*/ + +void encod_ppp( + Encoder_State *st, /* i/o: state structure */ + LPD_state *mem, /* i/o: encoder memories */ + const float speech[], /* i : input speech */ + const float Aw[], /* i : weighted A(z) unquantized for subframes */ + const float Aq[], /* i : 12k8 Lp coefficient */ + short *coder_type, /* i/o: coding type */ + const short sharpFlag, /* i : formant sharpening flag */ + const short T_op[], /* i : open loop pitch */ + const float voicing[], /* i : voicing */ + float *res, /* i/o: residual signal */ + float *synth, /* i/o: core synthesis */ + float *exc, /* i/o: current non-enhanced excitation */ + float *exc2, /* i/o: current enhanced excitation */ + float *pitch_buf, /* i/o: floating pitch values for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *bwe_exc /* o : excitation for SWB TBE */ +) +{ + float xn[L_SUBFR]; /* Target vector for pitch search */ + float h1[L_SUBFR+(M+1)];/* Impulse response vector */ + short i_subfr; /* tmp variables */ + const float *p_Aw,*p_Aq;/* pointer to LP filter coeff. vector */ + short k; + float p_Aq_old[M+1], excQ_ppp[L_FRAME], p_Aq_curr[M], pitch[NB_SUBFR]; + float LPC_de_old[M+1], LPC_de_curr[M+1]; + short rate_ctrl; + + rate_ctrl = st->rate_control; + + /*------------------------------------------------------------------* + * ACELP subframe loop + *------------------------------------------------------------------*/ + + p_Aw = Aw; + p_Aq = Aq; + + for( i_subfr=0; i_subfrmem_syn, i_subfr, &mem->mem_w0, p_Aq,res, L_SUBFR, p_Aw, TILT_FAC,xn, NULL, h1 ); + + /* call voiced encoder at this point */ + if( i_subfr == 0 ) /* generate the L_FRAME exc */ + { + for( k=0; klsp_old, p_Aq_old, M ); + + deemph_lpc( p_Aq_curr, p_Aq_old, LPC_de_curr, LPC_de_old, 1 ); + + /* last frame-end lpc and curr frame-end lpc */ + ppp_voiced_encoder( st, res, excQ_ppp, T_op[1], LPC_de_old, LPC_de_curr, exc, pitch, st->vadsnr ); + + if( st->bump_up ) + { + i_subfr = L_FRAME; + } + } + + if( st->bump_up != 1 ) + { + /*-----------------------------------------------------------------* + * Gain clipping test to avoid unstable synthesis on frame erasure + * or in case of floating point encoder & fixed p. decoder + *-----------------------------------------------------------------*/ + + gp_clip( st->core_brate, voicing, i_subfr, *coder_type, xn, st->clip_var ); + + /* run the above to maintain gain clipping memories */ + gp_clip_test_gain_pit( st->core_brate, st->prev_ppp_gain_pit, st->clip_var ); + + /*-----------------------------------------------------------------* + * Synthesize speech to update mem_syn[]. + * Update A(z) filters + *-----------------------------------------------------------------*/ + + syn_filt( p_Aq, M, &excQ_ppp[i_subfr], &synth[i_subfr], L_SUBFR, mem->mem_syn, 1 ); + + p_Aw += (M+1); + p_Aq += (M+1); + } + + } /* end of subframe loop */ + + + if( st->bump_up ) + { + /* PPP failed, bump up */ + st->ppp_mode = 0; + st->core_brate = ACELP_7k20; + st->pppcountE = 0; + + if ( st->set_ppp_generic ) + { + *coder_type = GENERIC; + } + else + { + *coder_type = VOICED; + } + + /* delete previous indices */ + reset_indices_enc( st ); + + /* signalling matrix (writing of signalling bits) */ + signalling_enc( st, *coder_type, sharpFlag ); + } + else + { + mvr2r( excQ_ppp, exc, L_FRAME ); + + /*-----------------------------------------------------------------* + * Updates: last value of new target is stored in mem_w0 + *-----------------------------------------------------------------*/ + + mem->mem_w0 = xn[L_SUBFR-1] - (exc[L_FRAME-1]); + + mvr2r( exc, exc2, L_FRAME ); + + st->dispMem[0] = 2; + st->dispMem[2] = st->prev_ppp_gain_pit; + + for( k=3; k<7; k++ ) + { + st->dispMem[k] = st->dispMem[k-1]; + } + mem->tilt_code = st->prev_tilt_code; + mvr2r( pitch, pitch_buf, NB_SUBFR ); + pitch_buf[NB_SUBFR16k-1] = pitch[NB_SUBFR-1]; + interp_code_5over2( exc2, bwe_exc, L_FRAME ); + set_f( voice_factors, 0.0f, NB_SUBFR16k ); + } + + st->rate_control = rate_ctrl; + + return; +} diff --git a/lib_enc/enc_prm.c b/lib_enc/enc_prm.c new file mode 100644 index 000000000..198292ce6 --- /dev/null +++ b/lib_enc/enc_prm.c @@ -0,0 +1,769 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + + +/*-------------------------------------------------------------------* + * enc_prm_hm() + * + * + *-------------------------------------------------------------------*/ + +static void enc_prm_hm( + int *prm_hm, + Encoder_State *st, + int L_frame +) +{ + /* Disable HM for non-GC,VC modes */ + if( st->tcx_cfg.coder_type != VOICED && st->tcx_cfg.coder_type != GENERIC ) + { + return; + } + + /* Flag */ + push_next_indice(st, prm_hm[0], 1); + + if( prm_hm[0] ) + { + /* Periodicy index */ + EncodeIndex( L_frame >= 256, prm_hm[1], st ); + + if( st->tcx_cfg.coder_type == VOICED ) + { + /* Gain index */ + push_next_indice(st, prm_hm[2], kTcxHmNumGainBits); + } + } + + return; +} + +/*-----------------------------------------------------------------* + * Function enc_prm_rf() * + * ~~~~~~~~~~~~~~~~~~~~~~ * + * * + * encode RF parameters for ACELP and TCX partial copy * + *-----------------------------------------------------------------*/ + +void enc_prm_rf( Encoder_State *st, + const short rf_frame_type, + const short fec_offset + ) +{ + short sfr, nb_subfr, n, index; + short ltp_mode, ltf_mode, gains_mode; + + nb_subfr = st->nb_subfr; + + /* partial copy bitstream writing */ + if ( rf_frame_type >= RF_TCXFD && rf_frame_type <= RF_TCXTD2) + { + /* TCX frames partial copy write */ + if(rf_frame_type == RF_TCXFD) + { + push_next_indice(st, st->rf_indx_lsf[fec_offset][0], lsf_numbits[0]); /* VQ 1 */ + push_next_indice(st, st->rf_indx_lsf[fec_offset][1], lsf_numbits[1]); /* VQ 2 */ + push_next_indice(st, st->rf_indx_lsf[fec_offset][2], lsf_numbits[2]); /* VQ 3 */ + } + + /* classification */ + if( st->rf_clas[fec_offset] == UNVOICED_CLAS ) + { + index = 0; + } + else if( (st->rf_clas[fec_offset] == VOICED_TRANSITION) || (st->rf_clas[fec_offset] == UNVOICED_TRANSITION) ) + { + index = 1; + } + else if( st->rf_clas[fec_offset] == VOICED_CLAS ) + { + index = 2; + } + else + { + index = 3; + } + push_next_indice(st, index, 2); + + if(rf_frame_type == RF_TCXFD) + { + /* TCX global gain = 7 bits */ + push_next_indice(st, st->rf_gain_tcx[fec_offset], 7); + } + else + { + /* LTP data */ + if ( (rf_frame_type == RF_TCXTD1 || rf_frame_type == RF_TCXTD2) && st->tcxltp ) + { + push_next_indice(st, st->rf_tcxltp_param[fec_offset], 9); + } + } + } + else if( rf_frame_type == 7 ) /* NELP bitstream writing */ + { + /* LSF indices */ + push_next_indice(st, st->rf_indx_lsf[fec_offset][0], 8); /* VQ 1 */ + push_next_indice(st, st->rf_indx_lsf[fec_offset][1], 8); /* VQ 2 */ + + /* NELP gain indices */ + push_next_indice( st, st->rf_indx_nelp_iG1[fec_offset], 5 ); + push_next_indice( st, st->rf_indx_nelp_iG2[fec_offset][0], 6 ); + push_next_indice( st, st->rf_indx_nelp_iG2[fec_offset][1], 6 ); + + /* NELP filter selection index */ + push_next_indice( st, st->rf_indx_nelp_fid[fec_offset], 2 ); + + /* tbe gainFr */ + push_next_indice( st, st->rf_indx_tbeGainFr[fec_offset], 5 ); + } + else if ( rf_frame_type >= 4 ) /* rf_frame_type ALL_PRED: 4, NO_PRED: 5, GEN_PRED: 6 */ + { + /* LSF indices */ + push_next_indice(st, st->rf_indx_lsf[fec_offset][0], 8); /* VQ 1 */ + push_next_indice(st, st->rf_indx_lsf[fec_offset][1], 8); /* VQ 2 */ + + /* ES pred */ + push_next_indice(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(st, st->rf_indx_pitch[fec_offset][sfr], n); + } + + /* Adaptive codebook filtering (1 bit) */ + if( ltf_mode == 2 ) + { + push_next_indice(st, st->rf_indx_ltfMode[fec_offset][sfr], 1); + } + + /*Innovative codebook*/ + if( (rf_frame_type == RF_NOPRED) + || ( rf_frame_type == RF_GENPRED && (sfr == 0 || sfr == 2)) ) + { + push_next_indice(st, st->rf_indx_fcb[fec_offset][sfr], 7); + } + + /* Gains (5b, 6b or 7b / subfr) */ + if( sfr == 0 || sfr == 2 ) + { + n = ACELP_GAINS_BITS[gains_mode]; + push_next_indice(st, st->rf_indx_gain[fec_offset][sfr], n); + } + } + /* tbe gainFr */ + push_next_indice( 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 */ + if(fec_offset == 2 ) + { + push_next_indice(st, 0, 2); + } + else if(fec_offset == 3 || fec_offset == 5 || fec_offset == 7) + { + push_next_indice(st, (fec_offset - 1)/2, 2); + } + + /* write RF frame type last in the bitstream */ + push_next_indice(st, rf_frame_type, 3); + +} + +/*-----------------------------------------------------------------* + * Function enc_prm() * + * ~~~~~~~~~~~~~~~~~~~~~~ * + * * + * encode parameters according to selected mode including * + * the FAC parameters when transition occurs. * + *-----------------------------------------------------------------*/ + +void enc_prm( + const short coder_type, /* i : coding type */ + int param[], /* i : parameters */ + int param_lpc[], /* i : LPC parameters */ + Encoder_State *st, /* i/o: quantization Analysis values */ + const short L_frame, /* i : frame length */ + CONTEXT_HM_CONFIG hm_cfg[], + short * bits_param_lpc, + short no_param_lpc +) +{ + short j, k, n, sfr, core, last_core; + int *prm; + short nbits_start, total_nbbits, nbits_header, nbits_lpc, nbits_tcx; + short lg, nb_subfr; + int lgFB; + int nTnsParams, nTnsBits; + int ix, j_old, wordcnt, bitcnt; + short hm_size; + short numlpc, index; + short flag_ctx_hm; + + int idx; + int start_idx; + short nBits; + + /*--------------------------------------------------------------------------------* + * initialization + *--------------------------------------------------------------------------------*/ + + nbits_lpc = 0; + nbits_tcx = 0; + + flag_ctx_hm = 0; + + /* Useful parameters */ + nb_subfr = st->nb_subfr; + core = st->core; + last_core = st->last_core; + + /* Initialize pointers */ + prm = param; + + /* Init counters */ + j = 0; + nbits_start = st->nb_bits_tot; + + /*--------------------------------------------------------------------------------* + * HEADER + *--------------------------------------------------------------------------------*/ + + if (st->mdct_sw == MODE1) + { + /* Adjust st->bits_frame_core not to subtract MODE2 bandwidth signaling */ + st->bits_frame_core += FrameSizeConfig[st->frame_size_index].bandwidth_bits; + + /* Write MODE1 core mode signaling */ + signalling_mode1_tcx20_enc(st, 1); + } + + /* EVS header */ + /* Modes (ACE_GC, ACE_UC, TCX20, TCX10...) */ + if ( st->tcxonly ) + { + push_next_indice(st, core == TCX_10_CORE, 1); + { + if( st->clas == UNVOICED_CLAS ) + { + index = 0; + } + else if( (st->clas == VOICED_TRANSITION) || (st->clas == UNVOICED_TRANSITION) ) + { + index = 1; + } + else if( st->clas == VOICED_CLAS ) + { + index = 2; + } + else + { + index = 3; + } + push_next_indice(st, index, 2); + } + } + else + { + if ( core == ACELP_CORE ) + { + /* write the RF signalling information */ + if( st->rf_mode ==1 ) + { + /* find the section in the ACELP signalling table corresponding to bitrate */ + idx = 0; + while ( acelp_sig_tbl[idx] != st->total_brate ) /* total bitrate is kept at 13.2kbps */ + { + idx++; + } + + /* retrieve the number of bits for signalling */ + nBits = (short) acelp_sig_tbl[++idx]; + + /* retrieve the signalling index */ + start_idx = ++idx; + while( acelp_sig_tbl[idx] != SIG2IND(coder_type, st->bwidth, st->sharpFlag, st->rf_mode) ) + { + idx++; + } + push_next_indice( st, idx - start_idx, nBits); + push_next_indice( st, 0, 1); /* Indicate to the decoder that the core is ACELP*/ + nbits_start = 3; + } + else + { + push_next_indice( st, coder_type, 3 ); + } + } + else + { + if (st->mdct_sw == MODE1) + { + /* 2 bits instead of 3 as TCX is already signaled */ + push_next_indice(st, st->tcx_cfg.coder_type, 2 ); + } + else + { + if (st->mdct_sw_enable == MODE2) + { + push_next_indice(st, 1, 1); /* TCX */ + push_next_indice(st, 0, 1); /* not HQ_CORE */ + push_next_indice(st, st->tcx_cfg.coder_type, 2); + } + else + { + /*write the RF signalling information*/ + if( st->rf_mode ==1 ) + { + /* find the section in the ACELP signalling table corresponding to bitrate */ + idx = 0; + while ( acelp_sig_tbl[idx] != st->total_brate ) + { + idx++; + } + + /* retrieve the number of bits for signalling */ + nBits = (short) acelp_sig_tbl[++idx]; + + if(st->tcx_cfg.coder_type == VOICED || st->tcx_cfg.coder_type == GENERIC || st->tcx_cfg.coder_type == TRANSITION) + { + st->sharpFlag=1; + } + else + { + st->sharpFlag=0; + } + + /* retrieve the signalling index */ + start_idx = ++idx; + while( acelp_sig_tbl[idx] != SIG2IND(st->tcx_cfg.coder_type, st->bwidth, st->sharpFlag, st->rf_mode) ) + { + idx++; + } + push_next_indice( st, idx - start_idx, nBits); + push_next_indice( st, 1, 1); /* Indicate to the decoder that the core is TCX*/ + nbits_start = 3; + } + else + { + push_next_indice(st, ACELP_MODE_MAX + st->tcx_cfg.coder_type, 3 ); + } + } + } + } + } + + /* Encode previous mode for error concealment */ + if( !( core == ACELP_CORE && st->tcx_cfg.lfacNext<=0 ) ) + { + push_next_indice(st, ((last_core!=ACELP_CORE) || (core==TCX_10_CORE)), 1); + } + + /* write TCX overlap mode (1 bit: full, 2 bits: half or no overlap) */ + if( core != ACELP_CORE ) + { + int 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 (st->tcx_cfg.tcx_curr_overlap_mode == MIN_OVERLAP) + { + nbits_tcx = 2; + overlap_code = 2; + } + else if (st->tcx_cfg.tcx_curr_overlap_mode == HALF_OVERLAP) + { + nbits_tcx = 2; + overlap_code = 3; + } + else + { + nbits_tcx = 1; + overlap_code = 0; + } + push_next_indice(st, overlap_code, nbits_tcx); + } + + if( st->plcExt.enableGplc ) + { + /* encode side information. */ + enc_prm_side_Info( &st->plcExt, st ); + } + + if( st->glr ) + { + if( core != ACELP_CORE || coder_type == INACTIVE || + (st->last_core == ACELP_CORE && st->last_coder_type_raw == INACTIVE) || + st->glr_reset ) + { + st->glr_idx[0] = 0; + } + + if( core == ACELP_CORE ) + { + push_next_indice(st, st->glr_idx[0], G_LPC_RECOVERY_BITS); + } + } + + st->glr_reset = 0; + + nbits_header = st->nb_bits_tot - nbits_start; + + /*--------------------------------------------------------------------------------* + * LPC PARAMETERS + *--------------------------------------------------------------------------------*/ + + if( st->enableTcxLpc && core != ACELP_CORE ) + { + /* Encode the indices */ + nbits_lpc = enc_lsf_tcxlpc(¶m_lpc, st); + } + else + { + if( st->lpcQuantization == 0 ) + { + /* LPC quantizer */ + if(core == TCX_20_CORE) + { + numlpc = 1; + } + else + { + numlpc = 2; + } + + nbits_lpc = encode_lpc_avq(st, numlpc, param_lpc, core); + } + else if( st->lpcQuantization == 1 ) + { + if(st->sr_core == 16000 && coder_type == VOICED && 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); + } + } + + + /*--------------------------------------------------------------------------------* + * 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(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(st, prm[j++], n); + } + + /* Subframe parameters */ + for( sfr=0; sfracelp_cfg.ltp_mode][sfr]; + + if (n!=0) + { + push_next_indice(st, prm[j++], n); + } + + /* Adaptive codebook filtering (1 bit) */ + if( st->acelp_cfg.ltf_mode == 2 ) + { + push_next_indice(st, prm[j++], 1); + } + + /*Innovative codebook*/ + + 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 = ACELP_FIXED_CDK_BITS(st->acelp_cfg.fixed_cdk_index[sfr]) >> 4; + bitcnt = ACELP_FIXED_CDK_BITS(st->acelp_cfg.fixed_cdk_index[sfr]) & 15; + + for (ix = 0; ix < wordcnt; ix++) + { + push_next_indice(st, prm[j++], 16); + } + + if (bitcnt) + { + push_next_indice(st, prm[j++], bitcnt); + } + + j = j_old+8; + + /* Gains (5b, 6b or 7b / subfr) */ + n=ACELP_GAINS_BITS[st->acelp_cfg.gains_mode[sfr]]; + push_next_indice(st, prm[j++], n); + } + + } + + + /*--------------------------------------------------------------------------------* + * TCX20 + *--------------------------------------------------------------------------------*/ + + if( core == TCX_20_CORE ) + { + if( st->enablePlcWaveadjust ) + { + push_next_indice(st, st->Tonal_SideInfo, 1); + } + + /* TCX Gain = 7 bits */ + push_next_indice(st, prm[j++], 7); + + /* TCX Noise Filling = NBITS_NOISE_FILL_LEVEL bits */ + push_next_indice(st, prm[j++], NBITS_NOISE_FILL_LEVEL); + + /* LTP data */ + if ( st->tcxltp || (st->sr_core > 25600) ) /* PLC pitch info for HB */ + { + if ( prm[j] ) + { + push_next_indice(st, 1 , 1); + push_next_indice(st, prm[j+1], 9); + push_next_indice(st, prm[j+2], 2); + } + else + { + push_next_indice(st, 0, 1); + } + } + + j += 3; + + /* TCX spectral data */ + lg = L_frame; + lgFB = st->tcx_cfg.tcx_coded_lines; + if ( last_core == ACELP_CORE ) + { + /* ACE->TCX transition */ + lg += st->tcx_cfg.tcx_offset; + lgFB += lgFB >> 2; + if(st->tcx_cfg.lfacNext<0) + { + lg -= st->tcx_cfg.lfacNext; + } + } + + /* TNS data */ + nTnsParams = 0; + nTnsBits = 0; + + if (st->tcx_cfg.fIsTNSAllowed) + { + WriteTnsData(st->tcx_cfg.pCurrentTnsConfig, prm+j, &nTnsParams, st, &nTnsBits); + j += nTnsParams; + } + + hm_size = (int)(2.0f*st->tcx_cfg.bandwidth*(float)lg); + + if (st->tcx_lpc_shaped_ari && last_core != ACELP_CORE) + { + enc_prm_hm( &prm[j], st, hm_size ); + } + + /*Context HM flag*/ + if ( st->tcx_cfg.ctx_hm && (last_core != ACELP_CORE) ) + { + push_next_indice(st, prm[j], 1); + + if (prm[j]) + { + EncodeIndex(hm_size >= 256, prm[j+1], st); + + flag_ctx_hm=1; + } + } + j += NPRM_CTX_HM; + /* IGF data */ + if (st->igf) + { + st->hIGFEnc.infoTotalBitsPerFrameWritten = 0; + IGFEncWriteBitstream( &st->hIGFEnc, st, &st->hIGFEnc.infoTotalBitsPerFrameWritten, + (st->last_core == ACELP_CORE)? IGF_GRID_LB_TRAN: IGF_GRID_LB_NORM, 1 ); + } + + total_nbbits = st->nb_bits_tot - nbits_start; + if(st->rf_mode) + { + total_nbbits += st->rf_target_bits_write; + } + nbits_tcx = st->bits_frame_core - total_nbbits; + + if (st->tcx_lpc_shaped_ari) + { + push_next_bits(st, &prm[++j], nbits_tcx); + j += nbits_tcx; + } + else + { + ACcontextMapping_encode2_no_mem_s17_LC( st, prm+j, lgFB, prm[j-1], /* lastnz */ + nbits_tcx, NPRM_RESQ * st->tcx_cfg.resq, flag_ctx_hm? hm_cfg: NULL ); + } + + } + + + /*--------------------------------------------------------------------------------* + * TCX10 + *--------------------------------------------------------------------------------*/ + + if( core == TCX_10_CORE ) + { + int nbits_igf = 0; + if (st->igf) + { + nbits_igf = IGFEncWriteConcatenatedBitstream( &st->hIGFEnc, st ); + } + + for (k = 0; k < 2; k++) + { + flag_ctx_hm = 0; + + prm = param + (k*NPRM_DIV); + j = 0; + + nbits_tcx = total_nbbits = st->nb_bits_tot - nbits_start; + + if(st->enablePlcWaveadjust && k) + { + push_next_indice(st, st->Tonal_SideInfo, 1); + } + /* TCX Gain = 7 bits */ + push_next_indice(st, prm[j++], 7); + + /* TCX Noise Filling = NBITS_NOISE_FILL_LEVEL bits */ + push_next_indice(st, prm[j++], NBITS_NOISE_FILL_LEVEL); + + /* LTP data */ + if ( (k == 0) && (st->tcxltp || (st->sr_core > 25600) ) ) /* PLC pitch info for HB */ + { + if ( prm[j] ) + { + push_next_indice(st, 1 , 1); + push_next_indice(st, prm[j+1], 9); + push_next_indice(st, prm[j+2], 2); + } + else + { + push_next_indice(st, 0 , 1); + } + } + j += 3; + + /* TCX spectral data */ + lg = L_frame >> 1; + lgFB = st->tcx_cfg.tcx_coded_lines >> 1; + + if ( k==0 && last_core == ACELP_CORE ) + { + /* ACE->TCX transition */ + lg += st->tcx_cfg.tcx_offset; + lgFB += lgFB >> 1; + + if(st->tcx_cfg.lfacNext<0) + { + lg -= st->tcx_cfg.lfacNext; + } + } + + /* TNS data */ + 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 += nTnsParams; + } + + hm_size = (int)(2.0f*st->tcx_cfg.bandwidth*(float)lgFB); + + /*Context HM flag*/ + if ( st->tcx_cfg.ctx_hm && !(last_core == ACELP_CORE && k == 0) ) + { + push_next_indice(st, prm[j], 1); + + if (prm[j]) + { + EncodeIndex(hm_size >= 256, prm[j+1], st); + flag_ctx_hm=1; + } + } + j += NPRM_CTX_HM; + + total_nbbits = st->nb_bits_tot - nbits_start; + nbits_tcx = (( st->bits_frame_core - nbits_header - nbits_lpc - nbits_igf + 1 - k) >> 1) - (total_nbbits - nbits_tcx); + ACcontextMapping_encode2_no_mem_s17_LC( st, prm+j, lgFB, prm[j-1], /* lastnz */nbits_tcx, + NPRM_RESQ * st->tcx_cfg.resq, flag_ctx_hm?&hm_cfg[k]: NULL ); + + } /* k, window index */ + } + + + /*--------------------------------------------------------------------------------* + * END + *--------------------------------------------------------------------------------*/ + + total_nbbits = st->nb_bits_tot - nbits_start; + + + + return; +} diff --git a/lib_enc/enc_tran.c b/lib_enc/enc_tran.c new file mode 100644 index 000000000..ba8359a05 --- /dev/null +++ b/lib_enc/enc_tran.c @@ -0,0 +1,315 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "prot.h" +#include "rom_com.h" + +/*-------------------------------------------------------------------* + * encod_tran() + * + * Encode transition (TC) frames + *-------------------------------------------------------------------*/ + +short encod_tran( + Encoder_State *st, /* i/o: state structure */ + LPD_state *mem, /* i/o: encoder memories */ + const short L_frame, /* i : length of the frame */ + const float speech[], /* i : input speech */ + const float Aw[], /* i : weighted A(z) unquantized for subframes */ + const float Aq[], /* i : LP coefficients */ + const short coder_type, /* i : coding type */ + const float Es_pred, /* i : predicted scaled innov. energy */ + const short T_op[], /* i : open loop pitch */ + const float voicing[], /* i : voicing */ + const float *res, /* i : residual signal */ + float *syn, /* i/o: core synthesis */ + float *exc, /* i/o: current non-enhanced excitation */ + float *exc2, /* i/o: current enhanced excitation */ + float *pitch_buf, /* i/o: floating pitch values for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *bwe_exc, /* i/o: excitation for SWB TBE */ + const short attack_flag, /* i : Flag to indicate when an audio attack is dealt with TM */ + short *unbits, /* i/o: number of unused bits */ + const short sharpFlag /* i : formant sharpening flag */ +) +{ + float xn[L_SUBFR]; /* Target vector for pitch search */ + float xn2[L_SUBFR]; /* Target vector for codebook search */ + float cn[L_SUBFR]; /* Target vector in residual domain */ + float h1[L_SUBFR+(M+1)]; /* Impulse response vector */ + float code[L_SUBFR]; /* Fixed codebook excitation */ + float y1[L_SUBFR]; /* Filtered adaptive excitation */ + float y2[L_SUBFR]; /* Filtered algebraic excitation */ + float gain_pit; /* Pitch gain */ + float voice_fac; /* Voicing factor */ + float gain_code; /* Gain of code */ + float gain_inov; /* inovation gain */ + short i, i_subfr, tc_subfr; /* tmp variables */ + short position, T0_min, T0_max; /* pitch and TC variables */ + short T0, T0_frac; /* close loop integer pitch and fractional part */ + float *pt_pitch; /* pointer to floating pitch buffer */ + float g_corr[6]; /* ACELP correlation values and gain pitch */ + short clip_gain; /* LSF clip gain */ + const float *p_Aw, *p_Aq; /* pointer to LP filter coefficient vector */ + float gain_preQ; /* Gain of prequantizer excitation */ + float code_preQ[L_SUBFR]; /* Prequantizer excitation */ + short Jopt_flag; /* joint optimization flag */ + short unbits_PI; /* saved bits for EVS_PI */ + float norm_gain_code; + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + + gain_pit = 0; + gain_code = 0; + gain_preQ = 0; + unbits_PI = 0; + + if( L_frame == L_FRAME ) + { + T0_max = PIT_MAX; + T0_min = PIT_MIN; + } + else /* L_frame == L_FRAME16k */ + { + T0_max = PIT16k_MAX; + T0_min = PIT16k_MIN; + } + + Jopt_flag = 0; + tc_subfr = -1; + if( attack_flag ) + { + tc_subfr = 3*L_SUBFR; + } + + p_Aw = Aw; + p_Aq = Aq; + pt_pitch = pitch_buf; + gain_preQ = 0; + set_f( code_preQ, 0, L_SUBFR ); + + /*----------------------------------------------------------------* + * ACELP subframe loop + *----------------------------------------------------------------*/ + + for ( i_subfr=0; i_subfrmem_syn, i_subfr, &mem->mem_w0, p_Aq, res, L_SUBFR, p_Aw, st->preemph_fac, xn, cn, h1 ); + + /*-----------------------------------------------------------------* + * TC: subframe determination & + * adaptive/glottal part of excitation construction + *-----------------------------------------------------------------*/ + + transition_enc( st, st->core_brate, L_frame, coder_type, i_subfr, &tc_subfr, &Jopt_flag, &position, voicing, T_op, &T0, + &T0_frac, &T0_min, &T0_max, exc, y1, res, h1, xn, xn2, st->clip_var, &gain_pit, g_corr, &clip_gain, &pt_pitch, bwe_exc ); + + /*-----------------------------------------------------------------* + * Transform domain contribution encoding - active frames + *-----------------------------------------------------------------*/ + + if( st->core_brate > ACELP_24k40 ) + { + transf_cdbk_enc( st, st->core_brate, st->extl, coder_type, 0, i_subfr, tc_subfr, cn, exc, + p_Aq, p_Aw, h1, xn, xn2, y1, y2, Es_pred, &gain_pit, gain_code, g_corr, clip_gain, + &(st->mem_deemp_preQ), &(st->mem_preemp_preQ), &gain_preQ, code_preQ, unbits ); + } + + /*-----------------------------------------------------------------* + * ACELP codebook search + pitch sharpening + *-----------------------------------------------------------------*/ + + inov_encode( st, st->core_brate, 0, L_frame, st->last_L_frame, coder_type, st->bwidth, sharpFlag, i_subfr, tc_subfr, p_Aq, + gain_pit, cn, exc, h1, mem->tilt_code, *pt_pitch, xn2, code, y2, &unbits_PI ); + + if( (st->L_frame == L_FRAME16k) && (tc_subfr == 0) && (i_subfr == L_SUBFR) && (T0 == 2*L_SUBFR) ) + { + Jopt_flag = 1; + } + + /*-----------------------------------------------------------------* + * 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( st, st->core_brate, L_frame, i_subfr, tc_subfr, xn, y2, code, Es_pred, + &gain_pit, &gain_code, &gain_inov, &norm_gain_code ); + } + else + { + if( st->core_brate > ACELP_32k ) + { + /* SQ gain_pit and gain_code */ + gain_enc_SQ( st, st->core_brate, coder_type, i_subfr, tc_subfr, xn, y1, y2, code, Es_pred, + &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, clip_gain ); + } + else + { + /* VQ gain_pit and gain_code */ + gain_enc_mless( st, st->core_brate, L_frame, coder_type, i_subfr, tc_subfr, xn, y1, y2, code, Es_pred, + &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, clip_gain ); + } + } + + /*-----------------------------------------------------------------* + * update LP-filtered gains for the case of frame erasures + *-----------------------------------------------------------------*/ + + gp_clip_test_gain_pit( st->core_brate, gain_pit, st->clip_var); + mem->tilt_code = est_tilt( exc+i_subfr, gain_pit, code, gain_code, &voice_fac, L_SUBFR, 0 ); + + /*-----------------------------------------------------------------* + * Update memory of the weighting filter + *-----------------------------------------------------------------*/ + + mem->mem_w0 = xn[L_SUBFR-1] - (gain_pit*y1[L_SUBFR-1]) - (gain_code*y2[L_SUBFR-1]); + + /*-----------------------------------------------------------------* + * Construct adaptive part of the excitation + * Save the non-enhanced excitation for FEC_exc + *-----------------------------------------------------------------*/ + + for( i = 0; i < L_SUBFR; i++ ) + { + exc2[i+i_subfr] = gain_pit * exc[i+i_subfr]; + exc[i+i_subfr] = exc2[i+i_subfr] + gain_code * code[i]; + } + + /*-----------------------------------------------------------------* + * Add the ACELP pre-quantizer contribution + *-----------------------------------------------------------------*/ + + if( st->core_brate > ACELP_24k40 ) + { + for( i = 0; i < L_SUBFR; i++ ) + { + exc2[i+i_subfr] += gain_preQ * code_preQ[i]; + exc[i+i_subfr] += gain_preQ * code_preQ[i]; + } + } + + /*-----------------------------------------------------------------* + * Prepare TBE excitation + *-----------------------------------------------------------------*/ + + prep_tbe_exc( L_frame, i_subfr, gain_pit, gain_code, code, voice_fac, &voice_factors[i_subfr/L_SUBFR], + bwe_exc, gain_preQ, code_preQ, T0, coder_type, st->core_brate ); + + + /*-----------------------------------------------------------------* + * Synthesize speech to update mem_syn[]. + * Update A(z) filters + *-----------------------------------------------------------------*/ + + syn_filt( p_Aq, M, &exc[i_subfr], &syn[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 = min( unbits_PI, 16 ); + push_indice( st, IND_UNUSED, 0, i ); + unbits_PI -= i; + } + + /* write TC configuration */ + if( L_frame == L_FRAME ) + { + if( tc_subfr == TC_0_0 ) + { + push_indice( st, IND_TC_SUBFR, 1, 1 ); + } + else if( tc_subfr == TC_0_64 ) + { + push_indice( st, IND_TC_SUBFR, 0, 1 ); + push_indice( st, IND_TC_SUBFR, 1, 1 ); + push_indice( st, IND_TC_SUBFR, 0, 1 ); + push_indice( st, IND_TC_SUBFR, 1, 1 ); + } + else if( tc_subfr == TC_0_128 ) + { + push_indice( st, IND_TC_SUBFR, 0, 1 ); + push_indice( st, IND_TC_SUBFR, 1, 1 ); + push_indice( st, IND_TC_SUBFR, 0, 1 ); + push_indice( st, IND_TC_SUBFR, 0, 1 ); + } + else if( tc_subfr == TC_0_192 ) + { + push_indice( st, IND_TC_SUBFR, 0, 1 ); + push_indice( st, IND_TC_SUBFR, 1, 1 ); + push_indice( st, IND_TC_SUBFR, 1, 1 ); + } + else if( tc_subfr == L_SUBFR ) + { + push_indice( st, IND_TC_SUBFR, 0, 1 ); + push_indice( st, IND_TC_SUBFR, 0, 1 ); + push_indice( st, IND_TC_SUBFR, 1, 1 ); + } + else if( tc_subfr == 2*L_SUBFR ) + { + push_indice( st, IND_TC_SUBFR, 0, 1 ); + push_indice( st, IND_TC_SUBFR, 0, 1 ); + push_indice( st, IND_TC_SUBFR, 0, 1 ); + push_indice( st, IND_TC_SUBFR, 1, 1 ); + } + else if( tc_subfr == 3*L_SUBFR ) + { + push_indice( st, IND_TC_SUBFR, 0, 1 ); + push_indice( st, IND_TC_SUBFR, 0, 1 ); + push_indice( st, IND_TC_SUBFR, 0, 1 ); + push_indice( st, IND_TC_SUBFR, 0, 1 ); + } + } + else /* L_frame == L_FRAME16k */ + { + if( tc_subfr == 0 ) + { + push_indice( st, IND_TC_SUBFR, 0, 2 ); + } + else if( tc_subfr == L_SUBFR ) + { + push_indice( st, IND_TC_SUBFR, 1, 2 ); + } + else if( tc_subfr == 2*L_SUBFR ) + { + push_indice( st, IND_TC_SUBFR, 2, 2 ); + } + else if( tc_subfr == 3*L_SUBFR ) + { + push_indice( st, IND_TC_SUBFR, 3, 2 ); + push_indice( st, IND_TC_SUBFR, 0, 1 ); + } + else if( tc_subfr == 4*L_SUBFR ) + { + push_indice( st, IND_TC_SUBFR, 3, 2 ); + push_indice( st, IND_TC_SUBFR, 1, 1 ); + } + } + + /* SC-VBR */ + st->prev_ppp_gain_pit = gain_pit; + st->prev_tilt_code = mem->tilt_code; + + return tc_subfr; +} diff --git a/lib_enc/enc_uv.c b/lib_enc/enc_uv.c new file mode 100644 index 000000000..a0a135299 --- /dev/null +++ b/lib_enc/enc_uv.c @@ -0,0 +1,109 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * encod_unvoiced() + * + * Encode unvoiced (UC) frames + *-------------------------------------------------------------------*/ + +void encod_unvoiced( + Encoder_State *st, /* i/o: state structure */ + LPD_state *mem, /* i/o: encoder memories */ + const float *speech, /* i : input speech */ + const float Aw[], /* i : weighted A(z) unquantized for subframes */ + const float *Aq, /* i : LP coefficients */ + const short vad_flag, + const float *res, /* i : residual signal */ + float *syn, /* o : core synthesis */ + float *tmp_noise, /* o : long-term noise energy */ + float *exc, /* i/o: current non-enhanced excitation */ + float *pitch_buf, /* o : floating pitch values for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *bwe_exc /* i/o: excitation for SWB TBE */ +) +{ + float xn[L_SUBFR]; /* Target vector for pitch search */ + float h1[L_SUBFR]; /* Impulse response vector */ + float code[L_SUBFR]; /* Fixed codebook excitation */ + float y2[L_SUBFR]; /* Filtered algebraic excitation */ + float *pt_pitch; /* pointer to floating pitch buffer */ + float gain_pit; /* Pitch gain */ + float voice_fac; /* Voicing factor */ + float gain_code; /* gain of code */ + float gain_inov; /* inovative gain */ + const float *p_Aw, *p_Aq; /* pointer to LP filter coeff. vector */ + short i_subfr; + float norm_gain_code; + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + + gain_pit = 0; + + if( st->Opt_SC_VBR && vad_flag == 0 && (st->last_ppp_mode == 1 || st->last_nelp_mode == 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( st, mem, pitch_buf, voice_factors, 1 ); + + } + + p_Aw = Aw; + p_Aq = Aq; + pt_pitch = pitch_buf; + + /*----------------------------------------------------------------* + * subframe loop + *----------------------------------------------------------------*/ + + for( i_subfr=0; i_subfrmem_syn, i_subfr, &mem->mem_w0, p_Aq,res, L_SUBFR, p_Aw, st->preemph_fac, xn, NULL, h1 ); + + /*----------------------------------------------------------------* + * Unvoiced subframe processing + *----------------------------------------------------------------*/ + + *pt_pitch = gaus_encode( st, i_subfr, h1, xn, exc, &mem->mem_w0, st->clip_var, &mem->tilt_code, code, &gain_code, + y2, &gain_inov, &voice_fac, &gain_pit, &norm_gain_code, st->core_brate ); + + *tmp_noise = norm_gain_code; + + voice_factors[i_subfr/L_SUBFR] = 0.0f; + + interp_code_5over2( &exc[i_subfr], &bwe_exc[i_subfr * HIBND_ACB_L_FAC], L_SUBFR ); + + /*-----------------------------------------------------------------* + * Synthesize speech to update mem_syn[]. + * Update A(z) filters + *-----------------------------------------------------------------*/ + + syn_filt( p_Aq, M, &exc[i_subfr], &syn[i_subfr], L_SUBFR, mem->mem_syn, 1 ); + + p_Aw += (M+1); + p_Aq += (M+1); + pt_pitch++; + } + + /* SC-VBR */ + st->prev_ppp_gain_pit = gain_pit; + st->prev_tilt_code = mem->tilt_code; + + return; +} diff --git a/lib_enc/encoder.c b/lib_enc/encoder.c new file mode 100644 index 000000000..e4528ee33 --- /dev/null +++ b/lib_enc/encoder.c @@ -0,0 +1,229 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include "g192.h" +#include "wmc_auto.h" + +#define WMC_TOOL_SKIP + +/*------------------------------------------------------------------------------------------* + * Global variables + *------------------------------------------------------------------------------------------*/ +long frame = 0; /* Counter of frames */ + + +/*------------------------------------------------------------------------------------------* + * Main encoder function + *------------------------------------------------------------------------------------------*/ + +int main( int argc, char** argv ) +{ + + FILE *f_input; /* MODE1 - input signal file */ + FILE *f_stream; /* MODE1 - output bitstream file */ + FILE *f_rate = NULL; /* MODE1 - bitrate switching profile file */ + FILE *f_bwidth = NULL; /* MODE1 - bandwidth switching profile file */ + FILE *f_rf = NULL; /* Channel aware configuration file */ + long bwidth_profile_cnt = 0; /* MODE1 - counter of frames for bandwidth switching profile file */ + short tmps, input_frame, enc_delay, n_samples; + short quietMode = 0; + short noDelayCmp = 0; + short data[L_FRAME48k]; /* 'short' buffer for input signal */ + Indice ind_list[MAX_NUM_INDICES]; /* list of indices */ + Encoder_State *st; /* MODE1 - encoder state structure */ + UWord8 pFrame[(MAX_BITS_PER_FRAME + 7) >> 3]; + Word16 pFrame_size = 0; + short Opt_RF_ON_loc, rf_fec_offset_loc; + +#ifdef WMOPS + reset_wmops(); + reset_mem(USE_BYTES); +#endif + + /*------------------------------------------------------------------------------------------* + * Allocate memory for static variables + * Processing of command-line parameters + * Encoder initialization + *------------------------------------------------------------------------------------------*/ + +#undef WMC_TOOL_SKIP + if ( (st = (Encoder_State *) malloc( sizeof(Encoder_State) ) ) == NULL ) +#define WMC_TOOL_SKIP + { + fprintf(stderr, "Can not allocate memory for encoder state structure\n"); + exit(-1); + } + + io_ini_enc( argc, argv, &f_input, &f_stream, &f_rate, &f_bwidth, + &f_rf, &quietMode, &noDelayCmp, st ); + + Opt_RF_ON_loc = st->Opt_RF_ON; + rf_fec_offset_loc = st->rf_fec_offset; + + st->ind_list = ind_list; + init_encoder( st ); + + input_frame = (short)(st->input_Fs / 50); + + /*------------------------------------------------------------------------------------------* + * 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->input_Fs, get_delay(ENC, st->input_Fs) + 0.5f); + if ( noDelayCmp == 0 ) + { + /* read samples and throw them away */ + if( (tmps = (short)fread(data, sizeof(short), enc_delay, f_input)) != enc_delay ) + { + fprintf(stderr, "Can not read the data from input file\n"); + exit(-1); + } + /* the number of first output samples will be reduced by this amount */ + } + + + /*------------------------------------------------------------------------------------------* + * Loop for every frame of input data + * - Read the input data + * - Process switching files + * - Run the encoder + * - Write the parameters into output bitstream file + *------------------------------------------------------------------------------------------*/ + + 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" ); + } + + while( (n_samples = (short)fread(data, sizeof(short), input_frame, f_input)) > 0 ) + { + if(f_rf != NULL) + { + read_next_rfparam( &st->rf_fec_offset, &st->rf_fec_indicator, f_rf); + rf_fec_offset_loc = st->rf_fec_offset; + } + + if (f_rate != NULL) + { + /* read next bitrate from profile file (only if invoked on the cmd line) */ + read_next_brate( &st->total_brate, st->last_total_brate, + f_rate, st->input_Fs, &st->Opt_AMR_WB, &st->Opt_SC_VBR, &st->codec_mode); + } + + if (f_bwidth != NULL) + { + /* read next bandwidth from profile file (only if invoked on the cmd line) */ + read_next_bwidth( &st->max_bwidth, f_bwidth, &bwidth_profile_cnt, st->input_Fs ); + } + + if( ( st->Opt_RF_ON && ( st->total_brate != ACELP_13k20 || st->input_Fs == 8000 || st->max_bwidth == NB ) ) || st->rf_fec_offset == 0 ) + { + if( st->total_brate == ACELP_13k20 ) + { + st->codec_mode = MODE1; + reset_rf_indices(st); + } + st->Opt_RF_ON = 0; + st->rf_fec_offset = 0; + } + + if( Opt_RF_ON_loc && rf_fec_offset_loc != 0 && L_sub( st->total_brate, ACELP_13k20 ) == 0 && L_sub( st->input_Fs, 8000 ) != 0 && st->max_bwidth != NB ) + { + st->codec_mode = MODE2; + if(st->Opt_RF_ON == 0) + { + reset_rf_indices(st); + } + st->Opt_RF_ON = 1; + st->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 ( ((st->input_Fs == 8000)|| (st->max_bwidth == NB)) && (st->total_brate > ACELP_24k40) ) + { + st->total_brate = ACELP_24k40; + st->codec_mode = MODE2; + } + + /* run the main encoding routine */ + + if ( st->Opt_AMR_WB ) + { + amr_wb_enc( st, data, n_samples ); + } + else + { + evs_enc( st, data, n_samples ); + } + + /* pack indices into serialized payload format */ + if( st->bitstreamformat == MIME ) + { + indices_to_serial( st, pFrame, &pFrame_size ); + } + + /* write indices into bitstream file */ + write_indices( st, f_stream + , pFrame, pFrame_size + ); + + fflush( stderr ); + + frame++; + if( quietMode == 0 ) + { + fprintf( stdout, "%-8ld\b\b\b\b\b\b\b\b", frame ); + } +#ifdef WMOPS + update_wmops(); + update_mem(); +#endif + } + if( quietMode == 0 ) + { + fprintf( stdout, "\n\n" ); + fprintf( stdout, "Encoding finished\n\n" ); + } + else + { + fprintf( stdout, "Encoding of %ld frames finished\n\n", frame ); + } + + /*------------------------------------------------------------------------------------------* + * Close files and free ressources + *------------------------------------------------------------------------------------------*/ + + fclose( f_input ); + fclose( f_stream ); + if ( f_rate ) fclose ( f_rate ); + if ( f_bwidth ) fclose ( f_bwidth ); + destroy_encoder( st ); + +#undef WMC_TOOL_SKIP + free( st ); +#define WMC_TOOL_SKIP + +#ifdef WMOPS + print_wmops(); + print_mem( NULL ); +#endif + + return 0; +} diff --git a/lib_enc/energy.c b/lib_enc/energy.c new file mode 100644 index 000000000..22c14ea04 --- /dev/null +++ b/lib_enc/energy.c @@ -0,0 +1,249 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include "prot.h" +#include "cnst.h" +#include "rom_enc.h" + + + +void background_update(T_CldfbVadState *st, + float frame_energy, /*(i) current frame energy*/ + int update_flag, /*(i) current frame update flag*/ + int music_backgound_f /*(i) background music flag*/ + ,float snr + ) +{ + int i; + int SNR_sb_num; + float *sb_bg_energy = st->sb_bg_energy; + float *frame_sb_energy = st->frame_sb_energy; + float *f_tonality_rate = st->f_tonality_rate; + float *ltd_stable_rate = st->ltd_stable_rate; + int frameloop = st->frameloop; + + float t_bg_energy = st->t_bg_energy; + + + SNR_sb_num = ENERGY_BAND_NUM[st->bw_index - CLDFBVAD_NB_ID]; + + + frame_energy = frame_energy + 0.0001f; + + + if((frameloop<60)&&(frameloop>5)&&(f_tonality_rate[0]<0.56)&& + (f_tonality_rate[1]<0.5)&& ltd_stable_rate[1]<0.06&& snr<2.5f) + { + + if(frameloop < 50) + { + st->t_bg_energy_sum += frame_energy/10; + st->tbg_energy_count++; + } + else + { + st->t_bg_energy_sum += frame_energy; + st->tbg_energy_count++; + } + + for(i=0;i2&& music_backgound_f==0) + { + if(st->bg_update_count<16) + { + if(frameloop < 50) + { + st->t_bg_energy_sum += frame_energy/10; + st->tbg_energy_count++; + } + else + { + st->t_bg_energy_sum += frame_energy; + st->tbg_energy_count++; + } + for(i=0; ibg_update_count++; + } + else + { + float a = 0.94f; + if((t_bg_energyframe_energy_smootht_bg_energy_sum += frame_energy/10; + st->tbg_energy_count++; + } + else + { + st->t_bg_energy_sum += frame_energy; + st->tbg_energy_count++; + } + for(i=0; iframe_energy) + { + a = 0.95f; + if(frameloop < 50) + { + st->t_bg_energy_sum += frame_energy/10; + st->tbg_energy_count++; + } + else + { + st->t_bg_energy_sum += frame_energy; + st->tbg_energy_count++; + } + for(i=0; it_bg_energy_sum += frame_energy/10; + st->tbg_energy_count++; + } + else + { + st->t_bg_energy_sum += frame_energy; + st->tbg_energy_count++; + } + for(i=0; i500*frame_energy)&&(sb_bg_energy[0] >10*frame_sb_energy[0])) + { + for(i=0; i10*frame_energy) + { + for(i=0; it_bg_energy_sum>160*st->tbg_energy_count) + { + st->t_bg_energy_sum = 160.0f*st->tbg_energy_count; + } + + if(music_backgound_f==1&& st->lt_snr_org<3.2&& t_bg_energy>1&& update_flag==0) + { + for(i=0; itbg_energy_count==64) + { + st->tbg_energy_count = 48; + st->t_bg_energy_sum = st->t_bg_energy_sum*0.75f; + } + + st->t_bg_energy = st->t_bg_energy_sum/st->tbg_energy_count; + + + +} + +void est_energy(float sb_power[], /*(o) energy of sub-band divided uniformly*/ + float frame_sb_energy[], /*(o) energy of sub-band divided non-uniformly*/ + float *p_frame_energy, /*(o) frame energy 1*/ + float *p_frame_energy2, /*(o) frame energy 2*/ + float *p_high_energy, /*(o) high frequency energy*/ + int bw /*(i) band width*/ + ) +{ + int i, j; + float frame_energy2 = 0.0f; + float high_energy = 0.0f; + int band_num = BAND_NUM_TAB[bw]; + const float sb_power_scale[5] = {0.0f, 0.16f, 0.24f, 0.28f, 0.28f}; + + const int *Nregion_index; + int SNR_sb_num; + + + for(i=0; i0 && (i!=band_num-1)) + { + frame_energy2+=sb_power[i]; + } + if(i>5) + { + high_energy += sb_power[i]; + } + } + + high_energy /= (32768.f * 32768.f); + frame_energy2 /= (32768.f * 32768.f); + + Nregion_index = REGION_INDEX[bw-CLDFBVAD_NB_ID]; + SNR_sb_num = ENERGY_BAND_NUM[bw-CLDFBVAD_NB_ID]; + + for(i=0; i + #include "wmc_auto.h" + #include "options.h" + #include "cnst.h" + #include "rom_com.h" + #include "prot.h" + + + /*-------------------------------------------------------------------* + * Local constantes + *-------------------------------------------------------------------*/ + + #define NB_VOIC 13 + #define DIV_NB_VOIC (1.0f/NB_VOIC) + #define ALPA 0.95f + #define ALPAM1 (1.0f-ALPA) + #define BETA (ALPAM1/2.0f) + #define AFREQ_THR 2 + #define GPIT_THR 0.4f + #define HANGOVER_DELAY 2 + + /*-------------------------------------------------------------------* + * Pit_exc_contribution_len() + * + * Determine up to which band the pit contribution is significant + *-------------------------------------------------------------------*/ + + short Pit_exc_contribution_len( /* o : bin where pitch contribution is significant */ + Encoder_State *st, /* i/o: state structure */ + const float *dct_res, /* i : DCT of residual */ + float *dct_pitex, /* i/o: DCT of pitch contribution */ + float *pitch_buf, /* i/o: Pitch per subframe */ + short *hangover, /* i : hangover for the time contribution switching */ + const short coder_type /* i : coding type */ + ) + { + float corr_dct_pit[MBANDS_LOC], corr_tmp; + float av_corr, min_corr, ftmp; + short freq, i, j; + short last_pit_band, pit_contr_idx, last_pit_bin; + float ener_res; + float ener_pit; + float low_pit, F1st_harm, F8th_harm; + float corr_dct_pit_tmp[MBANDS_LOC]; + short time_flg = 0; + short Len, max_len; + short tmp_dec; + short Mbands_loc = MBANDS_LOC-2; + + if(st->L_frame == L_FRAME16k ) + { + Mbands_loc = MBANDS_LOC; + } + + minimum( pitch_buf, st->L_frame >> 6, &low_pit ); + + F1st_harm = 12800.0f/low_pit; + F8th_harm = 8.0f*F1st_harm; + + freq = 0; + for (i = 0; i core_brate < ACELP_9k60 ) + { + /* Correlation really poor at low rate, time domain still valide */ + av_corr *= 2.0; + } + + min_corr =(float)fabs(mfreq_loc[0] - av_corr); + + for (i = 1; i mfreq_loc[last_pit_band] ) + { + do + { + last_pit_band++; + {} {} } + while( F8th_harm >= mfreq_loc[last_pit_band] ); + } + + if( last_pit_band > 7+BAND1k2 && (st->core_brate < CFREQ_BITRATE || st->bwidth == NB) ) + { + last_pit_band = 7+BAND1k2; + } + else if ( last_pit_band > 10+BAND1k2 && st->core_brate >= CFREQ_BITRATE ) + { + last_pit_band = 10+BAND1k2; + } + + time_flg = 0; + if( (st->mem_last_pit_band > 0 && st->old_corr > 0.5f && st->mold_corr > 0.5f && st->lt_gpitch >= 1.5f*GPIT_THR ) + || (last_pit_band > 6) + || (last_pit_band >= 4 && st->lt_gpitch >= 1.5f*GPIT_THR && st->old_corr > 0.7f) + || (last_pit_band > BAND1k2 && st->mold_corr > 0.80f && st->lt_gpitch >= GPIT_THR) ) + { + tmp_dec = 1; + } + else + { + tmp_dec = 0; + } + + /* Different past and current decision */ + if ( (st->mem_last_pit_band == 0 && tmp_dec == 1) || (st->mem_last_pit_band > 0 && tmp_dec == 0) ) + { + if( *hangover == 0 ) + { + time_flg = tmp_dec; + *hangover = HANGOVER_DELAY; + } + else + { + time_flg = 0; + if( st->mem_last_pit_band > 0 ) + { + time_flg = 1; + } + + (*hangover) -= 1; + if( *hangover < 0 ) + { + *hangover = 0; + } + } + } + else + { + time_flg = tmp_dec; + *hangover = HANGOVER_DELAY; + } + + /* Decicison on final lenght of time contribution */ + pit_contr_idx = 0; + if( time_flg == 1 || coder_type != INACTIVE || st->GSC_noisy_speech ) + { + if( st->core_brate bwidth == NB) + { + last_pit_band = 7+BAND1k2; + } + } + else if(st->core_brate < ACELP_9k60 && low_pit < 128) + { + last_pit_band = 5+BAND1k2; + } + else if(st->core_brate < ACELP_9k60 ) + { + last_pit_band = 3+BAND1k2; + } + else if( last_pit_band < BAND1k2+1 ) + { + last_pit_band = BAND1k2+1; + } + + last_pit_bin = (short)(mfreq_loc[last_pit_band]/BIN_SIZE); + + st->bpf_off = 0; + + max_len = st->L_frame-last_pit_bin; + if( st->bwidth == NB ) + { + max_len = 160-last_pit_bin; + } + + Len = 80; + if( max_len < 80 ) + { + Len = max_len; + } + + if(st->core_brate == ACELP_8k00 && st->bwidth != NB ) + { + for (i=0; i < max_len; i++) + { + dct_pitex[i+last_pit_bin] = 0.0f; + } + } + else + { + for (i = 0; i < Len; i++) + { + dct_pitex[i+last_pit_bin] *= sm_table[i]; + } + + for (; i < max_len; i++) + { + dct_pitex[i+last_pit_bin] = 0.0f; + } + } + + st->mem_last_pit_band = last_pit_band; + pit_contr_idx = last_pit_band-BAND1k2; + } + else + { + set_f(dct_pitex, 0.0f, st->L_frame); + st->bpf_off = 1; + last_pit_bin = 0; + last_pit_band = 0; + pit_contr_idx = 0; + st->mem_last_pit_band = 0; + set_f( pitch_buf, (float)L_SUBFR, 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->ind_list[i].nb_bits != -1 ) + { + st->nb_bits_tot -= st->ind_list[i].nb_bits; + st->ind_list[i].nb_bits = -1; + } + } + + if( st->ind_list[IND_ES_PRED].nb_bits != -1 ) + { + st->nb_bits_tot -= st->ind_list[IND_ES_PRED].nb_bits; + st->ind_list[IND_ES_PRED].nb_bits = -1; + } + } + + if( st->core_brate < CFREQ_BITRATE ) + { + if( st->core_brate < ACELP_9k60 ) + { + if( pit_contr_idx > 0 ) + { + pit_contr_idx = 1; + } + + if( coder_type == INACTIVE ) + { + push_indice( st, IND_PIT_CONTR_IDX, pit_contr_idx, 1 ); + } + } + else + { + push_indice( st, IND_PIT_CONTR_IDX, pit_contr_idx, 3 ); + } + } + else + { + push_indice( st, IND_PIT_CONTR_IDX, pit_contr_idx, 4 ); + } + + return last_pit_bin; + } diff --git a/lib_enc/evs_enc.c b/lib_enc/evs_enc.c new file mode 100644 index 000000000..34df42429 --- /dev/null +++ b/lib_enc/evs_enc.c @@ -0,0 +1,704 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* +* Local functions +*-------------------------------------------------------------------*/ + +static void configure_core_coder( Encoder_State *st, short *coder_type, const short localVAD ); + +static void writeFrameHeader( Encoder_State *st ); + +static void initFrameHeader( Encoder_State *st ); + +/*-------------------------------------------------------------------* + * evs_enc() + * + * Principal encoder routine + *-------------------------------------------------------------------*/ + +void evs_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const short *data, /* i : input signal */ + const short n_samples /* i : number of input samples */ +) +{ + short i, input_frame, delay; + float old_inp_12k8[L_INP_12k8], *inp; /* buffer of input signal @ 12k8 */ + float old_inp_16k[L_INP]; /* buffer of input signal @ 16kHz */ + short sp_aud_decision1; /* 1st stage speech/music classification */ + short sp_aud_decision2; /* 2nd stage speech/music classification */ + float fr_bands[2*NB_BANDS]; /* energy in frequency bands */ + short vad_flag; + short localVAD; + float Etot; /* total energy; correlation shift */ + float ener; /* residual energy from Levinson-Durbin */ + short pitch[3]; /* open-loop pitch values for quantization */ + float voicing[3]; /* OL maximum normalized correlation */ + float A[NB_SUBFR16k*(M+1)]; /* A(z) unquantized for subframes */ + float Aw[NB_SUBFR16k*(M+1)]; /* weighted A(z) unquantized for subframes */ + float epsP[M+1]; /* LP prediction errors */ + float lsp_new[M]; /* LSPs at the end of the frame */ + float lsp_mid[M]; /* ISPs in the middle of the frame */ + short coder_type; /* coder type */ + short sharpFlag; /* formant sharpening flag */ + short vad_hover_flag; + short hq_core_type; /* HQ core type (HQ, or LR-MDCT) */ + short attack_flag; /* flag signalling attack encoded by the AC mode (GSC) */ + float new_inp_resamp16k[L_FRAME16k]; /* new input signal @16kHz, non pre-emphasised, used by the WB TBE/BWE */ + float old_syn_12k8_16k[L_FRAME16k]; /* ACELP core synthesis at 12.8kHz or 16kHz to be used by the SWB BWE */ + float shb_speech[L_FRAME16k]; + float hb_speech[L_FRAME16k/4]; + float new_swb_speech[L_FRAME48k]; + float bwe_exc_extended[L_FRAME32k+NL_BUFF_OFFSET]; + float voice_factors[NB_SUBFR16k]; + float fb_exc[L_FRAME16k]; + short Voicing_flag; + float pitch_buf[NB_SUBFR16k]; + short unbits; + short padBits; + float realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; /* real buffer */ + float imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; /* imag buffer */ + + + push_wmops("evs_enc"); + + /*------------------------------------------------------------------* + * Initializiation + *-----------------------------------------------------------------*/ + + input_frame = (short)(st->input_Fs / 50); + st->core = -1; + st->extl = -1; + st->core_brate = -1; + st->input_bwidth = st->last_input_bwidth; + st->bwidth = st->last_bwidth; + hq_core_type = -1; + unbits = 0; + + st->bits_frame_core = 0; /* For getting bit consumption in core coder */ + st->lp_cng_mode2 = 0; + st->mdct_sw_enable = 0; + st->mdct_sw = 0; + st->rate_switching_reset = 0; + + /*----------------------------------------------------------------* + * set input samples buffer + *----------------------------------------------------------------*/ + + /* get delay to synchronize ACELP and MDCT frame */ + delay = NS2SA(st->input_Fs, DELAY_FIR_RESAMPL_NS); + + mvr2r( st->input - delay, st->old_input_signal, input_frame+delay ); + + /*----------------------------------------------------------------* + * convert 'short' input data to 'float' + *----------------------------------------------------------------*/ + + for( i=0; iinput[i] = (float)data[i]; + } + + if( n_samples < input_frame ) + { + set_f( st->input + n_samples, 0.0f, input_frame - n_samples ); + } + + /*----------------------------------------------------------------* + * HP filtering + *----------------------------------------------------------------*/ + + hp20( st->input, input_frame, st->mem_hp20_in, st->input_Fs ); + + /*----------------------------------------------------------------* + * Updates in case of AMR-WB IO mode -> EVS primary mode switching + *----------------------------------------------------------------*/ + + if( st->last_core == AMR_WB_CORE ) + { + updt_IO_switch_enc( st, input_frame ); + set_f( st->old_speech_shb, 0, L_LOOK_16k + L_SUBFR16k ); + cldfb_reset_memory( st->cldfbAnaEnc ); + cldfb_reset_memory( st->cldfbSynTd ); + } + + /*---------------------------------------------------------------------* + * Pre-processing + *---------------------------------------------------------------------*/ + + pre_proc( 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, lsp_new, lsp_mid, &coder_type, &sharpFlag, &vad_hover_flag, + &attack_flag, new_inp_resamp16k, &Voicing_flag, realBuffer, imagBuffer, &hq_core_type ); + + st->sharpFlag = sharpFlag; + + if( st->mdct_sw == MODE2 ) + { + + st->bits_frame_nominal = st->total_brate / 50; + initFrameHeader( st ); + + writeFrameHeader( st ); + + if( (st->total_brate > ACELP_24k40 && st->total_brate < HQ_96k) || (st->total_brate == ACELP_24k40 && st->bwidth >= WB) ) + { + st->L_frame = L_FRAME16k; + st->gamma = GAMMA16k; + st->preemph_fac = PREEMPH_FAC_16k; + + weight_a_subfr( NB_SUBFR16k, A, Aw, GAMMA16k, M ); + + if( st->last_L_frame == L_FRAME && st->ini_frame != 0 ) + { + /* this is just an approximation, but it is sufficient */ + mvr2r( st->lsp_old1, st->lspold_enc, M ); + } + } + else + { + st->L_frame = L_FRAME; + st->gamma = GAMMA1; + st->preemph_fac = PREEMPH_FAC; + } + + st->sr_core = 50*st->L_frame; + st->core_brate = st->total_brate; + + st->igf = 0; + hq_core_type = NORMAL_HQ_CORE; + + if( (st->bwidth == SWB || st->bwidth == WB) && st->total_brate <= LRMDCT_CROSSOVER_POINT ) + { + /* note that FB (bit-rate >= 24400bps) is always coded with NORMAL_HQ_CORE */ + hq_core_type = LOW_RATE_HQ_CORE; + } + else if( st->bwidth == NB ) + { + hq_core_type = LOW_RATE_HQ_CORE; + } + } + + /*---------------------------------------------------------------------* + * Encoding + *---------------------------------------------------------------------*/ + + if( st->codec_mode == MODE1 ) + { + /* write signalling info into the bitstream */ + signalling_enc( st, coder_type, sharpFlag ); + + /*---------------------------------------------------------------------* + * Preprocessing (preparing) for ACELP/HQ core switching + *---------------------------------------------------------------------*/ + + core_switching_pre_enc( st, &(st->LPDmem), old_inp_12k8, old_inp_16k ); + + /*---------------------------------------------------------------------* + * ACELP core encoding + *---------------------------------------------------------------------*/ + + if( st->core == ACELP_CORE ) + { + acelp_core_enc( st, &st->LPDmem, inp, vad_flag, ener, pitch, voicing, + A, Aw, epsP, lsp_new, lsp_mid, coder_type, sharpFlag, vad_hover_flag, attack_flag, + bwe_exc_extended, voice_factors, old_syn_12k8_16k, pitch_buf, &unbits ); + } + + /*---------------------------------------------------------------------* + * HQ core encoding + *---------------------------------------------------------------------*/ + + if( st->core == HQ_CORE ) + { + hq_core_enc( st, st->input - delay, input_frame, hq_core_type, Voicing_flag ); + } + + /*---------------------------------------------------------------------* + * Postprocessing for ACELP/HQ core switching + *---------------------------------------------------------------------*/ + + core_switching_post_enc( st, old_inp_12k8, old_inp_16k, pitch, voicing, A ); + } + + else /* MODE2 */ + { + + /*----------------------------------------------------------------* + * Configuration of core coder/SID + * Write Frame Header + *----------------------------------------------------------------*/ + + configure_core_coder( st, &coder_type, localVAD ); + + if( st->mdct_sw != MODE1 ) + { + writeFrameHeader( 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, bwe_exc_extended, voice_factors, pitch_buf, + vad_hover_flag, vad_flag ); + + /*---------------------------------------------------------------------* + * Postprocessing for Mode 1/2 switching + *---------------------------------------------------------------------*/ + /* TBE for Mode 2 interface */ + if( st->igf && st->core_brate > SID_2k40 ) + { + if( st->core == ACELP_CORE ) + { + switch (st->bwidth) + { + case WB: + st->extl = WB_TBE; + st->extl_brate = WB_TBE_0k35; + break; + + case SWB: + st->extl = SWB_TBE; + st->extl_brate = SWB_TBE_1k6; + break; + + case FB: + st->extl = FB_TBE; + st->extl_brate = FB_TBE_1k8; + break; + } + } + else + { + coder_type = -1; + st->extl = IGF_BWE; + st->extl_brate = 0; + } + + st->core_brate = st->total_brate - st->extl_brate; + + if( st->tec_tfa == 1 ) + { + st->core_brate -= BITS_TEC; + st->core_brate -= BITS_TFA; + } + } + + /*----------------------------------------------------------------* + * Complete Bitstream Writing + *----------------------------------------------------------------*/ + + /* Pad the bitstream with zeros and byte-alignment*/ + if( st->igf && st->core == ACELP_CORE && st->core_brate > SID_2k40 ) + { + padBits = ((st->bits_frame+7)/8)*8 - (st->nb_bits_tot + (st->rf_target_bits_write - ((st->rf_mode==1)? 1: 0) ) + get_tbe_bits(st->total_brate, st->bwidth, st->rf_mode )); + } + else + { + padBits = ((st->bits_frame+7)/8)*8 - (st->nb_bits_tot + (st->rf_target_bits_write - ((st->rf_mode==1)? 1: 0) )); + } + + for( i = 0; iinput_Fs >= 16000 && st->bwidth < SWB ) + { + /* Common pre-processing for WB TBE and WB BWE */ + wb_pre_proc( st, new_inp_resamp16k, hb_speech ); + } + + if ( st->extl == WB_TBE ) + { + /* WB TBE encoder */ + wb_tbe_enc( st, coder_type, hb_speech, bwe_exc_extended, voice_factors, pitch_buf, voicing ); + + if( st->codec_mode == MODE2 ) + { + tbe_write_bitstream( st ); + } + } + else if ( st->extl == WB_BWE ) + { + /* WB BWE encoder */ + wb_bwe_enc( st, new_inp_resamp16k, coder_type ); + } + + /*---------------------------------------------------------------------* + * SWB(FB) TBE encoding + * SWB(FB) BWE encoding + *---------------------------------------------------------------------*/ + + if( !st->Opt_SC_VBR && st->input_Fs >= 32000 ) + { + /* Common pre-processing for SWB(FB) TBE and SWB(FB) BWE */ + swb_pre_proc( st, st->input, new_swb_speech, shb_speech, realBuffer, imagBuffer ); + } + else if( st->input_Fs >= 32000 ) + { + set_f( st->old_speech_shb, 0.0f, L_LOOK_16k + L_SUBFR16k ); + set_f( shb_speech, 0.0f, L_FRAME16k ); + } + + /* SWB TBE encoder */ + if ( st->extl == SWB_TBE || st->extl == FB_TBE || (st->igf && st->core == ACELP_CORE && st->extl != WB_TBE) ) + { + if( st->core_brate != FRAME_NO_DATA && st->core_brate != SID_2k40 ) + { + swb_tbe_enc( st, coder_type, shb_speech, bwe_exc_extended, voice_factors, fb_exc, voicing, pitch_buf ); + + if ( st->extl == FB_TBE ) + { + /* FB TBE encoder */ + fb_tbe_enc( st, st->input, fb_exc ); + } + + if( st->codec_mode == MODE2 ) + { + if( st->tec_tfa == 1 ) + { + tecEnc_TBE( &(st->tecEnc.corrFlag), voicing, coder_type); + + if( coder_type == INACTIVE ) + { + st->tec_flag = 0; + st->tecEnc.corrFlag = 0; + } + st->tfa_flag = tfaEnc_TBE( st->tfa_enr, st->last_core, voicing, pitch_buf ); + set_TEC_TFA_code( st->tecEnc.corrFlag, &st->tec_flag, &st->tfa_flag ); + } + else + { + st->tec_flag = 0; + st->tecEnc.corrFlag = 0; + st->tfa_flag = 0; + } + + tbe_write_bitstream( st ); + } + } + } + else if( st->extl == SWB_BWE || st->extl == FB_BWE ) + { + /* SWB(FB) BWE encoder */ + swb_bwe_enc( st, old_inp_12k8, old_inp_16k, old_syn_12k8_16k, new_swb_speech, shb_speech, coder_type ); + } + else if( st->extl == SWB_BWE_HIGHRATE || st->extl == FB_BWE_HIGHRATE ) + { + swb_bwe_enc_hr( st, st->input - delay, input_frame, coder_type, unbits ); + } + + + /*---------------------------------------------------------------------* + * SWB DTX/CNG encoding + *---------------------------------------------------------------------*/ + + if ( st->Opt_DTX_ON && input_frame >= L_FRAME32k ) + { + /* SHB DTX/CNG encoder */ + swb_CNG_enc( 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; + st->last_codec_mode = st->codec_mode; + st->last_L_frame = st->L_frame; + st->last_core = st->core; + + st->last_total_brate = st->total_brate; + st->last_core_brate = st->core_brate; + st->last_extl = st->extl; + st->last_input_bwidth = st->input_bwidth; + st->last_bwidth = st->bwidth; + st->Etot_last = Etot; + st->last_coder_type_raw = st->coder_type_raw; + + if( st->core_brate > SID_2k40 ) + { + st->last_active_brate = st->total_brate; + } + + if ( st->core == HQ_CORE ) + { + /* in the HQ core, coder_type is not used so it could have been set to anything */ + st->prev_coder_type = GENERIC; + } + else + { + st->prev_coder_type = coder_type; + } + + if( st->core_brate > SID_2k40 && st->first_CNG == 1 ) + { + if( st->act_cnt >= BUF_DEC_RATE ) + { + st->act_cnt = 0; + } + + st->act_cnt++; + + if( st->act_cnt == BUF_DEC_RATE && st->ho_hist_size > 0 ) + { + st->ho_hist_size--; + } + + if( ++(st->act_cnt2) >= MIN_ACT_CNG_UPD ) + { + st->act_cnt2 = MIN_ACT_CNG_UPD; + } + } + + if ( st->core_brate <= SID_2k40 && st->first_CNG == 0 && st->cng_type == LP_CNG ) + { + st->first_CNG = 1; + } + + /*-----------------------------------------------------------------* + * Increase the counter of initialization frames + * Limit the max number of init. frames + *-----------------------------------------------------------------*/ + + if( st->ini_frame < MAX_FRAME_COUNTER ) + { + (st->ini_frame)++; + } + + /* synchronisation of CNG seeds */ + if( st->core_brate != FRAME_NO_DATA && st->core_brate != SID_2k40 ) + { + own_random( &(st->cng_seed) ); + own_random( &(st->cng_ener_seed) ); + } + + + /*---------------------------------------------------------------------* + * Updates - MODE2 + *---------------------------------------------------------------------*/ + + if( st->mdct_sw == MODE2 ) + { + st->codec_mode = MODE2; + st->sr_core = getCoreSamplerateMode2( st->total_brate, st->bwidth, st->rf_mode ); + st->L_frame = st->sr_core / 50; + if ( st->sr_core == 12800 ) + { + st->preemph_fac = PREEMPH_FAC; + st->gamma = GAMMA1; + } + else + { + st->preemph_fac = PREEMPH_FAC_16k; + st->gamma = GAMMA16k; + } + + st->igf = getIgfPresent( st->total_brate, st->bwidth, st->rf_mode ); + } + + /* update FER clas */ + st->last_clas = st->clas; + + /* Update Core */ + core_encode_update( st ); + + if( st->mdct_sw == MODE1 ) + { + st->codec_mode = MODE1; + } + + if( st->lp_cng_mode2 ) + { + st->codec_mode = MODE2; + } + + /* RF mode updates */ + if( st->rf_mode ) + { + if (st->rf_frame_type == RF_NELP ) + { + st->last_nelp_mode = 1; + } + else + { + st->last_nelp_mode = 0; + } + } + st->rf_mode_last = st->rf_mode; + if( st->Opt_RF_ON ) + { + st->L_frame = L_FRAME; + st->rf_mode = 1; + } + + + pop_wmops(); + + return; +} + + +/*-------------------------------------------------------------------* + * initFrameHeader() + * + * Init Mode 2 frame header + *-------------------------------------------------------------------*/ + +static void initFrameHeader( + Encoder_State *st /* i/o: encoder state structure */ +) +{ + + int n; + + if( st->core_brate == SID_2k40 ) + { + /*Get size of frame*/ + st->bits_frame = FRAME_2_4; + st->bits_frame_core += FRAME_2_4-4; /*1 bit for SID on/off + 2 bits for bandwith in case of SID + 1 bit CNG type */ + st->frame_size_index = 2; + } + else if( st->core_brate == FRAME_NO_DATA ) + { + st->bits_frame = FRAME_0; + st->bits_frame_core += st->bits_frame; + st->frame_size_index = 0; + } + else + { + for( n=0; nbits_frame_nominal ) + { + st->frame_size_index = n; + st->bits_frame = FrameSizeConfig[n].frame_bits; + st->bits_frame_core = FrameSizeConfig[n].frame_net_bits; + break; + } + } + } + + return; +} + +/*-------------------------------------------------------------------* + * writeFrameHeader() + * + * Write Mode 2 frame header + *-------------------------------------------------------------------*/ + +static void writeFrameHeader( + Encoder_State *st /* i/o: encoder state structure */ +) +{ + + if( st->core_brate != FRAME_NO_DATA ) + { + /* SID flag at 2.4kbps */ + if( st->core_brate == SID_2k40 ) + { + if ( st->cng_type == FD_CNG ) + { + /* write SID/CNG type flag */ + push_next_indice( st, 1, 1 ); + + /* write bandwidth mode */ + push_next_indice( st, st->bwidth, 2 ); + + /* write L_frame */ + if( st->L_frame == L_FRAME ) + { + push_next_indice( st, 0, 1 ); + } + else + { + push_next_indice( st, 1, 1 ); + } + } + } + else /* active frames */ + { + if( st->rf_mode == 0 ) + { + push_next_indice( st, st->bwidth-FrameSizeConfig[st->frame_size_index].bandwidth_min, FrameSizeConfig[st->frame_size_index].bandwidth_bits); + } + } + + /* Write reserved bit */ + if( FrameSizeConfig[st->frame_size_index].reserved_bits && st->rf_mode == 0) + { + push_next_indice( st, 0, FrameSizeConfig[st->frame_size_index].reserved_bits ); + } + } + + return; +} + + +/*------------------------------------------------------------------------* + * Configuration of core coder/SID + *------------------------------------------------------------------------*/ + +static void configure_core_coder( + Encoder_State *st, /* i/o: encoder state structure */ + short *coder_type, /* i : coder type */ + const short localVAD +) +{ + initFrameHeader( st ); + + if( st->core_brate != SID_2k40 && st->core_brate != FRAME_NO_DATA ) + { + if( st->tcxonly ) + { + *coder_type = GENERIC; + } + + st->tcx_cfg.coder_type = *coder_type; + + + if( !st->tcxonly && !localVAD && st->tcx_cfg.coder_type == GENERIC ) + { + st->tcx_cfg.coder_type = UNVOICED; + } + } + + st->igf = getIgfPresent( st->total_brate, st->bwidth, st->rf_mode ); + + if( st->core_brate != SID_2k40 && st->core_brate != FRAME_NO_DATA ) + { + st->core_brate = st->total_brate; + } + + return; +} diff --git a/lib_enc/ext_sig_ana.c b/lib_enc/ext_sig_ana.c new file mode 100644 index 000000000..903c5aa47 --- /dev/null +++ b/lib_enc/ext_sig_ana.c @@ -0,0 +1,255 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include "options.h" +#include "prot.h" +#include "rom_com.h" + + +/*-------------------------------------------------------------------* +* core_signal_analysis_high_bitrate() +* +* +*-------------------------------------------------------------------*/ + +void core_signal_analysis_high_bitrate( + const float *new_samples, + const short T_op[3], /* i : open-loop pitch values for quantiz. */ + const float voicing[3], /* i : open-loop pitch gains */ + const short pitch[2], /* i : open-loop pitch @12.8kHz for adapt. lag windowing */ + float lsp_new[], + float lsp_mid[], + Encoder_State *st, + int pTnsSize[], + int pTnsBits[], + int param_core[], + int *ltpBits, + int L_frame, + int L_frameTCX +) +{ + const int last_overlap = st->tcx_cfg.tcx_last_overlap_mode; + const int curr_overlap = st->tcx_cfg.tcx_curr_overlap_mode; + int i, frameno; + int L_subframe; + int left_overlap=-1, right_overlap=-1, folding_offset; + float buf[N_MAX+L_MDCT_OVLP_MAX]; /* Buffer for TCX20/TCX10 windowing */ + float mdstWin[N_MAX+L_MDCT_OVLP_MAX]; /* Buffer for MDST windowing */ + float * powerSpec; + float * tcx20Win; + float tcx5Win[N_TCX10_MAX/2+L_MDCT_OVLP_MAX]; /* Buffer for TCX5 windowing and interleaving. */ + float * interleaveBuf = tcx5Win; + int nSubframes; + short overlap_mode[3]; + short transform_type[2]; + float r[M+1]; + float A[M+1]; + float * lsp[2]; + const int tcx10SizeFB = 2*st->tcx_cfg.tcx5SizeFB; + const int tcx5SizeFB = st->tcx_cfg.tcx5SizeFB; + const int tcx10Size = 2*st->tcx_cfg.tcx5Size; + short alw_pitch_lag_12k8[2], alw_pitch_lag_12k8_wc; + float alw_voicing[2], alw_voicing_wc; + + powerSpec = tcx20Win = buf; /* Share memory for windowed TD signal and for the power spectrum */ + + /*--------------------------------------------------------------* + * Input Signal Processing: copy, HP filter, pre-emphasis + *---------------------------------------------------------------*/ + + /* Copy Samples */ + mvr2r( new_samples, st->new_speech_enc, L_frame ); + + /*--------------------------------------------------------------* + * TCX-LTP + *---------------------------------------------------------------*/ + + 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, st->pit_min, st->pit_fr1, st->pit_fr2, st->pit_max, + st->pit_res_max, &st->transientDetection, (st->sr_core > 25600), NULL, M ); + + mvr2r( st->speech_enc+st->encoderLookahead_enc, st->new_speech_enc_pe, L_frame ); + + preemph( st->new_speech_enc_pe, st->preemph_fac, L_frame, &(st->mem_preemph_enc) ); + + if( st->tcxMode == TCX_10 ) + { + mvi2i( ¶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]; + alw_pitch_lag_12k8[1] = pitch[1]; + alw_voicing[0] = voicing[0]; + alw_voicing[1] = voicing[1]; + alw_pitch_lag_12k8_wc = min(alw_pitch_lag_12k8[0], alw_pitch_lag_12k8[1]); + alw_voicing_wc = max(alw_voicing[0], alw_voicing[1]); + overlap_mode[0] = last_overlap; /* Overlap between the last and the current frame */ + + if (st->tcxMode == TCX_20) + { + nSubframes = 1; + transform_type[0] = TCX_20; + overlap_mode[1] = curr_overlap; /* Overlap between the current and the next frame */ + alw_pitch_lag_12k8[0] = alw_pitch_lag_12k8_wc; + alw_voicing[0] = alw_voicing_wc; + } + else + { + nSubframes = 2; + if (curr_overlap == FULL_OVERLAP) + { + transform_type[0] = TCX_5; + transform_type[1] = TCX_10; + overlap_mode[1] = (last_overlap == HALF_OVERLAP) ? HALF_OVERLAP : MIN_OVERLAP; /* Overlap between 2nd and 3rd sub-frame */ + } + else if (last_overlap == FULL_OVERLAP) + { + transform_type[0] = TCX_10; + transform_type[1] = TCX_5; + overlap_mode[1] = (curr_overlap == HALF_OVERLAP) ? HALF_OVERLAP : MIN_OVERLAP; /* Overlap between 1st and 2nd sub-frame */ + } + else + { + transform_type[0] = transform_type[1] = TCX_5; + overlap_mode[1] = (last_overlap == HALF_OVERLAP && curr_overlap == HALF_OVERLAP) ? HALF_OVERLAP : MIN_OVERLAP; /* Overlap between 2nd and 3rd sub-frame */ + } + overlap_mode[2] = curr_overlap; /* Overlap between the current and the next frame */ + } + + if (transform_type[0] != TCX_20) + { + IGFEncResetTCX10BitCounter(&st->hIGFEnc); + } + + for (frameno = 0; frameno < nSubframes; frameno++) + { + /*-------------------------------------------------------------------------* + * Get MDCT output and TNS parameters. Apply TNS in the spectrum if needed + *--------------------------------------------------------------------------*/ + + L_subframe = L_frameTCX/nSubframes; + + if( (transform_type[frameno] == TCX_20) && (st->tcx_cfg.tcx_last_overlap_mode != TRANSITION_OVERLAP) ) + { + wtda( st->new_speech_TCX, tcx20Win, NULL, overlap_mode[frameno], overlap_mode[frameno+1], L_frameTCX ); + + /* Windowing of the 2xTCX5 subframes or 1xTCX10 or 1xTCX20 */ + WindowSignal( &st->tcx_cfg, st->tcx_cfg.tcx_offsetFB, overlap_mode[frameno] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno], + overlap_mode[frameno+1] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno+1], &left_overlap, &right_overlap, + &st->speech_TCX[frameno*tcx10SizeFB], &L_subframe, mdstWin, 1 ); + } + else + { + /* 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( transform_type[frameno] == TCX_5 ) + { + /* Outter left folding */ + for (i = 0; i < left_overlap/2; i++) + { + tcx20Win[left_overlap/2+i] -= tcx20Win[left_overlap/2-1-i]; + } + + /* Outter right folding */ + for (i = 0; i < right_overlap/2; i++) + { + tcx20Win[L_subframe+left_overlap/2-1-i] += tcx20Win[L_subframe+left_overlap/2+i]; + } + + /* 2xTCX5 */ + L_subframe = tcx5SizeFB; + folding_offset = left_overlap/2; + + for (i = 0; i < 2; i++) + { + WindowSignal( &st->tcx_cfg, folding_offset, i == 0 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, i == 1 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, + &left_overlap, &right_overlap, tcx20Win+i*tcx5SizeFB, &L_subframe, tcx5Win, 1 ); + + TCX_MDCT( tcx5Win, st->spectrum[frameno]+i*tcx5SizeFB, left_overlap, L_subframe-(left_overlap+right_overlap)/2, right_overlap ); + } + } + else /* transform_type[frameno] != TCX_5 */ + { + assert(transform_type[frameno] == TCX_10 || transform_type[frameno] == TCX_20); + + if( transform_type[frameno] == TCX_20 && st->tcx_cfg.tcx_last_overlap_mode != TRANSITION_OVERLAP ) + { + edct(tcx20Win, st->spectrum[frameno], L_subframe); + v_multc(st->spectrum[frameno], (float)sqrt((float)NORM_MDCT_FACTOR / L_subframe), st->spectrum[frameno], L_subframe); + } + else + { + /* TCX20/TCX10 */ + TCX_MDCT( tcx20Win, st->spectrum[frameno], left_overlap, L_subframe-(left_overlap+right_overlap)/2, right_overlap ); + } + + /* For TCX20 at bitrates up to 64 kbps we need the power spectrum */ + if ((st->tcxMode == TCX_20) && ((st->total_brate < HQ_96k) || st->igf)) + { + /* Compute noise-measure flags for spectrum filling and quantization */ + AnalyzePowerSpectrum( st, L_subframe*st->L_frame/st->L_frameTCX, L_subframe, left_overlap, right_overlap, st->spectrum[frameno], + ((st->tcxMode == TCX_20) && (st->tcx_cfg.tcx_last_overlap_mode != TRANSITION_OVERLAP)) ? mdstWin : tcx20Win, powerSpec ); + } + } + + TNSAnalysis( &st->tcx_cfg, L_frameTCX, st->tcx_cfg.tcx_coded_lines, transform_type[frameno], (frameno == 0) && (st->last_core == 0), + st->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( transform_type[frameno] == TCX_5 ) + { + /* group sub-windows: interleave bins according to their frequencies */ + for( i = 0; i < tcx5SizeFB; i++ ) + { + interleaveBuf[2*i] = st->spectrum[frameno][i]; + interleaveBuf[2*i+1] = st->spectrum[frameno][tcx5SizeFB+i]; + } + + mvr2r( interleaveBuf, st->spectrum[frameno], tcx10SizeFB ); + } + + /*--------------------------------------------------------------* + * LPC analysis + *---------------------------------------------------------------*/ + + HBAutocorrelation( &st->tcx_cfg, overlap_mode[frameno]==ALDO_WINDOW? FULL_OVERLAP: overlap_mode[frameno], + overlap_mode[frameno+1]==ALDO_WINDOW? FULL_OVERLAP: overlap_mode[frameno+1], + &st->speech_enc_pe[frameno*tcx10Size], L_frame/nSubframes, r, M ); + + adapt_lag_wind( r, M, alw_pitch_lag_12k8[frameno], alw_voicing[frameno], st->sr_core ); + + lev_dur( A, r, M, NULL ); + + a2lsp_stab( A, lsp[nSubframes-1-frameno], st->lspold_enc ); + + if( st->igf ) + { + ProcessIGF(&st->hIGFEnc, st, st->spectrum[frameno], powerSpec, transform_type[frameno] == TCX_20, st->fUseTns[frameno], (st->last_core == ACELP_CORE), frameno ); + } + } + + /* Copy memory */ + mvr2r( lsp_new, st->lspold_enc, M ); + + return; +} diff --git a/lib_enc/fd_cng_enc.c b/lib_enc/fd_cng_enc.c new file mode 100644 index 000000000..c3fccfd21 --- /dev/null +++ b/lib_enc/fd_cng_enc.c @@ -0,0 +1,749 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "rom_enc.h" +#include "rom_com.h" +#include "prot.h" +#include "stat_enc.h" +#include "options.h" + +/*-------------------------------------------------------------------* +* createFdCngEnc() +* +* +*-------------------------------------------------------------------*/ + +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)); + + createFdCngCom(&(hs->hFdCngCom)); + + *hFdCngEnc = hs; + + return; +} + +/*-------------------------------------------------------------------* +* initFdCngEnc() +* +* Initialize FD_CNG +*-------------------------------------------------------------------*/ + +void initFdCngEnc( + HANDLE_FD_CNG_ENC hsEnc, /* i/o: Contains the variables related to the FD-based CNG process */ + int input_Fs, /* i: input signal sampling frequency in Hz */ + float scale /* i: scaling factor */ +) +{ + int j; + HANDLE_FD_CNG_COM hsCom = hsEnc->hFdCngCom; + + /* Initialize common */ + + initFdCngCom( hsCom, scale ); + + /* Configure the Noise Estimator */ + + hsCom->numSlots = 16; + hsCom->numCoreBands = 16; + hsCom->regularStopBand = input_Fs/800; + if ( hsCom->regularStopBand > 40 ) + { + hsCom->regularStopBand = 40; + } + + hsCom->startBand = 2; + if ( hsCom->regularStopBand == 10 ) + { + hsCom->stopFFTbin = 160; + hsCom->stopBand = 160; + hsCom->nFFTpart = 17; + } + else + { + hsCom->stopFFTbin = 256; + hsCom->stopBand = hsCom->regularStopBand - hsCom->numCoreBands + hsCom->stopFFTbin; + hsCom->nFFTpart = 20; + } + + initPartitions( sidparts_encoder_noise_est, sizeof(sidparts_encoder_noise_est)/sizeof(int), hsCom->startBand, hsCom->stopBand, hsCom->part, &hsCom->npart, hsCom->midband, hsCom->psize, hsCom->psize_inv, 0); + + hsCom->nCLDFBpart = hsCom->npart - hsCom->nFFTpart; + for(j=0; jnCLDFBpart; j++) + { + hsCom->CLDFBpart[j] = hsCom->part[j+hsCom->nFFTpart] - (256-hsCom->startBand); + hsCom->CLDFBpsize_inv[j] = hsCom->psize_inv[j+hsCom->nFFTpart]; + } + + /* Initialize the Noise Estimator */ + + set_f( hsEnc->msPeriodog, 0.0f, NPART ); + set_f( hsEnc->msAlpha, 0.0f, NPART ); + set_f( hsEnc->msBminWin, 0.0f, NPART ); + set_f( hsEnc->msBminSubWin, 0.0f, NPART ); + set_f( hsEnc->msPsd, 0.0f, NPART ); + set_f( hsEnc->msNoiseFloor, 0.0f, NPART ); + set_f( hsEnc->msNoiseEst, 0.0f, NPART ); + set_f( hsEnc->energy_ho, 0.0f, NPART ); + set_f( hsEnc->msNoiseEst_old, 0.0f, NPART ); + set_f( hsEnc->msMinBuf, FLT_MAX, MSNUMSUBFR*NPART ); + set_f( hsEnc->msCurrentMin, FLT_MAX, NPART ); + set_f( hsEnc->msCurrentMinOut, FLT_MAX, NPART ); + set_f( hsEnc->msCurrentMinSubWindow, FLT_MAX, NPART ); + set_i( hsEnc->msLocalMinFlag, 0, NPART ); + set_i( hsEnc->msNewMinFlag, 0, NPART ); + set_f( hsEnc->msPsdFirstMoment, 0.0f, NPART ); + set_f( hsEnc->msPsdSecondMoment, 0.0f, NPART ); + hsEnc->msPeriodogBufPtr = 0; + set_f( hsEnc->msPeriodogBuf, 0.0f, MSBUFLEN*NPART ); + set_f( hsEnc->msLogPeriodog, 0.0f, NPART ); + set_f( hsEnc->msLogNoiseEst, 0.0f, NPART ); + + return; +} + +/*-------------------------------------------------------------------* +* configureFdCngEnc() +* +* Configure FD_CNG +*-------------------------------------------------------------------*/ + +void configureFdCngEnc( + HANDLE_FD_CNG_ENC hsEnc, /* i/o: Contains the variables related to the FD-based CNG process */ + short bandwidth, + int bitrate +) +{ + HANDLE_FD_CNG_COM hsCom = hsEnc->hFdCngCom; + float psizeDec[NPART]; + float psize_invDec[NPART]; + + hsCom->CngBandwidth = bandwidth; + if ( hsCom->CngBandwidth == FB ) + { + hsCom->CngBandwidth = SWB; + } + hsCom->CngBitrate = bitrate; + + /* NB configuration */ + if ( bandwidth == NB ) + { + hsCom->FdCngSetup = FdCngSetup_nb; + } + + /* WB configuration */ + else if ( bandwidth == WB ) + { + /* FFT 6.4kHz, no CLDFB */ + if ( bitrate <= ACELP_8k00 ) + { + hsCom->FdCngSetup = FdCngSetup_wb1; + } + /* FFT 6.4kHz, CLDFB 8.0kHz */ + else if ( 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 ( bitrate <= ACELP_13k20 ) + { + hsCom->FdCngSetup = FdCngSetup_swb1; + } + /* FFT 8.0kHz, CLDFB 16kHz */ + else + { + hsCom->FdCngSetup = FdCngSetup_swb2; + } + } + hsCom->fftlen = hsCom->FdCngSetup.fftlen; + hsEnc->stopFFTbinDec = hsCom->FdCngSetup.stopFFTbin; + + /* Configure the SID quantizer and the Confort Noise Generator */ + + hsEnc->startBandDec = hsCom->startBand; + hsEnc->stopBandDec = hsCom->FdCngSetup.sidPartitions[hsCom->FdCngSetup.numPartitions-1] + 1; + initPartitions( hsCom->FdCngSetup.sidPartitions, hsCom->FdCngSetup.numPartitions, hsEnc->startBandDec, hsEnc->stopBandDec, + hsEnc->partDec, &hsEnc->npartDec, hsEnc->midbandDec, psizeDec, psize_invDec, 0 ); + + if ( hsEnc->stopFFTbinDec == 160 ) + { + hsEnc->nFFTpartDec = 17; + } + else if ( hsEnc->stopFFTbinDec == 256 ) + { + hsEnc->nFFTpartDec = 20; + } + else + { + hsEnc->nFFTpartDec = 21; + } + + switch (hsCom->fftlen) + { + case 512: + hsCom->fftSineTab = NULL; + hsCom->olapWinAna = olapWinAna512; + hsCom->olapWinSyn = olapWinSyn256; + break; + case 640: + hsCom->fftSineTab = fftSineTab640; + hsCom->olapWinAna = olapWinAna640; + hsCom->olapWinSyn = olapWinSyn320; + break; + default: + assert(!"Unsupported FFT length for FD-based CNG"); + break; + } + hsCom->frameSize = hsCom->fftlen >> 1; + + return; +} + + +/*-------------------------------------------------------------------* +* deleteFdCngEnc() +* +* Delete the instance of type FD_CNG +*-------------------------------------------------------------------*/ + +void deleteFdCngEnc( + HANDLE_FD_CNG_ENC *hFdCngEnc +) +{ + + HANDLE_FD_CNG_ENC hsEnc = *hFdCngEnc; + if (hsEnc != NULL) + { + deleteFdCngCom(&(hsEnc->hFdCngCom)); + free(hsEnc); + *hFdCngEnc = NULL; + } + + return; +} + +/*-------------------------------------------------------------------* +* resetFdCngEnc() +* +* Reset the instance of type FD_CNG +*-------------------------------------------------------------------*/ + +void resetFdCngEnc( + Encoder_State * st +) +{ + int n; + float totalNoiseIncrease; + + /* Detect fast increase of totalNoise */ + totalNoiseIncrease = st->totalNoise - st->last_totalNoise; + st->last_totalNoise = st->totalNoise; + if ( totalNoiseIncrease > 0 ) + { + if ( st->totalNoise_increase_len == TOTALNOISE_HIST_SIZE ) + { + for ( n = 0; n < TOTALNOISE_HIST_SIZE - 1; n++ ) + { + st->totalNoise_increase_hist[n] = st->totalNoise_increase_hist[n+1]; + } + st->totalNoise_increase_hist[TOTALNOISE_HIST_SIZE-1] = totalNoiseIncrease; + } + else + { + st->totalNoise_increase_hist[st->totalNoise_increase_len] = totalNoiseIncrease; + st->totalNoise_increase_len++; + } + } + else + { + st->totalNoise_increase_len = 0; + } + totalNoiseIncrease = 0.f; + for ( n = 0; n < st->totalNoise_increase_len; n++ ) + { + totalNoiseIncrease += st->totalNoise_increase_hist[n]; + } + if ( + (totalNoiseIncrease > 5 && st->totalNoise_increase_len == TOTALNOISE_HIST_SIZE && st->ini_frame > 150 ) + || + ( st->input_bwidth > st->last_input_bwidth ) + || + ( st->last_core == AMR_WB_CORE ) + ) + { + st->fd_cng_reset_flag = 1; + st->hFdCngEnc->hFdCngCom->msFrCnt_init_counter = 0; + st->hFdCngEnc->hFdCngCom->init_old = FLT_MAX; + } + else if ( st->fd_cng_reset_flag > 0 && st->fd_cng_reset_flag < 10 ) + { + st->fd_cng_reset_flag++; + } + else + { + st->fd_cng_reset_flag = 0; + } + + return; +} + + +/*-------------------------------------------------------------------* +* perform_noise_estimation_enc() +* +* Perform noise estimation +*-------------------------------------------------------------------*/ + +void perform_noise_estimation_enc( + float *band_energies, /* i: energy in critical bands without minimum noise floor E_MIN */ + float *enerBuffer, + HANDLE_FD_CNG_ENC st /* i/o: CNG structure containing all buffers and variables */ +) +{ + short i, j; + int numCoreBands = st->hFdCngCom->numCoreBands; + int regularStopBand = st->hFdCngCom->regularStopBand; + int numSlots = st->hFdCngCom->numSlots; + float numSlots_inv = 1.f/(float)numSlots; /*enough if done only once*/ + float * periodog = st->hFdCngCom->periodog; + float * ptr_per = periodog; + int npart = st->hFdCngCom->npart; + int nFFTpart = st->hFdCngCom->nFFTpart; + float * psize = st->hFdCngCom->psize; + float * msPeriodog = st->msPeriodog; + float * msNoiseEst = st->msNoiseEst; + + float * msLogPeriodog = st->msLogPeriodog; + float * msLogNoiseEst = st->msLogNoiseEst; + + + /* preemphasis compensation and grouping of per bin energies into msPeriodog */ + for(i=0; ihFdCngCom->scalingFactor); + ptr_per++; + } + + /* Adjust filterbank to the desired frequency resolution by averaging over spectral partitions for SID transmission */ + if (numCoreBands < regularStopBand) + { + bandcombinepow(periodog, regularStopBand-numCoreBands, st->hFdCngCom->CLDFBpart, st->hFdCngCom->nCLDFBpart, st->hFdCngCom->CLDFBpsize_inv, &msPeriodog[nFFTpart]); + } + + /* Compress MS inputs */ + compress_range(msPeriodog, msLogPeriodog, npart); + + /* Call the minimum statistics routine for noise estimation */ + minimum_statistics( npart, nFFTpart, psize, msLogPeriodog, st->msNoiseFloor, 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( msLogNoiseEst, msNoiseEst, npart ); + + + return; +} + + +/*-------------------------------------------------------------------* +* AdjustFirstSID() +* +* Adjust the noise estimator at the beginning of each CNG phase (encoder-side) +*-------------------------------------------------------------------*/ + +void AdjustFirstSID( + int npart, + float * msPeriodog, + float * energy_ho, + float * msNoiseEst, + float * msNoiseEst_old, + short * active_frame_counter, + Encoder_State *stcod +) +{ + + float lambda; + int i; + + if ( stcod->cnt_SID == 1 && stcod->last_core_brate > SID_2k40 ) + { + /* Detect the hangover period and the first SID frame at the beginning of each CNG phase */ + + /* Average input energy over hangover period */ + mvr2r(msPeriodog, energy_ho, npart); /*First hangover frame*/ + /* Set first SID to current input level but add some smoothing */ + lambda = (float)pow( 0.96f, (float)(*active_frame_counter+1) ); + v_multc( msNoiseEst_old, lambda, msNoiseEst_old, npart ); + v_multc( energy_ho, 1-lambda, energy_ho, npart ); + + v_add( msNoiseEst_old, energy_ho, energy_ho, npart ); + for (i=0; ienergy_ho[i]) + { + msNoiseEst[i] = energy_ho[i]; + } + } + *active_frame_counter = 0; + } + + if ( stcod->core_brate != SID_2k40 && stcod->core_brate != FRAME_NO_DATA ) + { + (*active_frame_counter)++; /* Count the number of active frames in a row */ + } + else + { + mvr2r( msNoiseEst, msNoiseEst_old, npart); /* Store the noise estimate obtained in the CNG phases */ + } + + return; +} + +/*-------------------------------------------------------------------* +* FdCng_encodeSID() +* +* Generate a bitstream out of the partition levels +*-------------------------------------------------------------------*/ + +void FdCng_encodeSID( + HANDLE_FD_CNG_ENC stenc, /* i/o: CNG structure containing all buffers and variables */ + Encoder_State *corest, + float preemph_fac +) +{ + int N; + HANDLE_FD_CNG_COM st = stenc->hFdCngCom; + float* E = stenc->msNoiseEst; + float gain; + int i, index; + float v[32], e; + int indices[32]; + float w[32]; + (void)preemph_fac; + + + /* Init */ + N = stenc->npartDec; + + /* Convert to LOG */ + e = 0.f; + for ( i=0; iCngBandwidth, st->CngBitrate ); + + /* Quantize gain */ + index = (short) floor( gain*1.5f + 60.f + 0.5f ); + + if (index < 0) + { + index = 0; + } + + if (index > 127) + { + index = 127; + } + + gain = ((float)index-60.f)/1.5f; + + /* Apply gain and undo log */ + for ( i=0; isidNoiseEst[i] = (float)pow( 10.f, (v[i]+gain)/10.f ); + } + + /* NB last band energy compensation */ + if (st->CngBandwidth == NB) + { + st->sidNoiseEst[N-1] *= NB_LAST_BAND_SCALE; + } + + if ( st->CngBandwidth == SWB && st->CngBitrate <= ACELP_13k20 ) + { + st->sidNoiseEst[N-1] *= SWB_13k2_LAST_BAND_SCALE; + } + + /* Write bitstream */ + if ( corest->codec_mode == MODE2 ) + { + for ( i=0; ibwidth, 2 ); + push_indice( corest, IND_ACELP_16KHZ, corest->L_frame == L_FRAME16k ? 1 : 0, 1 ); + + for ( i=0; isidNoiseEst, stenc->partDec, stenc->npartDec, stenc->midbandDec, stenc->nFFTpartDec, stenc->stopBandDec-stenc->startBandDec, st->cngNoiseLevel, 1); + + lpc_from_spectrum(st->cngNoiseLevel, stenc->startBandDec, stenc->stopFFTbinDec, st->fftlen, st->fftSineTab, st->A_cng, preemph_fac ); + + return; +} + + +void generate_comfort_noise_enc( Encoder_State *stcod ) +{ + short i; + float * ptr_r; + float * ptr_i; + HANDLE_FD_CNG_ENC stenc = stcod->hFdCngEnc; + HANDLE_FD_CNG_COM st = stenc->hFdCngCom; + float * cngNoiseLevel = st->cngNoiseLevel; + float * ptr_level = cngNoiseLevel; + short * seed = &(st->seed); + float scale = 1.f; + float * fftBuffer = st->fftBuffer; + float * timeDomainOutput = st->timeDomainBuffer; + float preemph_fac = stcod->preemph_fac; + int tcx_transition = 0; + float enr, att; + short bwidth = stcod->bwidth; + short CNG_mode = stcod->CNG_mode; + + /* + 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 (stenc->startBandDec==0) + { + rand_gauss(&fftBuffer[0], seed); + fftBuffer[0] *= (float)sqrt(scale **ptr_level); /* DC component in FFT */ + ptr_level++; + ptr_r = fftBuffer + 2; + } + else + { + fftBuffer[0] = 0.f; + set_f( fftBuffer+2, 0.0f, 2*(stenc->startBandDec-1) ); + ptr_r = fftBuffer + 2*stenc->startBandDec; + } + ptr_i = ptr_r + 1; + for( ; ptr_level < cngNoiseLevel+stenc->stopFFTbinDec-stenc->startBandDec ; ptr_level++) + { + /* Real part in FFT bins */ + rand_gauss(ptr_r, seed); + (*ptr_r) *= (float)sqrt((scale **ptr_level)*0.5f); + ptr_r += 2; + /* Imaginary part in FFT bins */ + rand_gauss(ptr_i, seed); + (*ptr_i) *= (float)sqrt((scale **ptr_level)*0.5f); + ptr_i += 2; + } + /* Remaining FFT bins are set to zero */ + set_f( fftBuffer+2*stenc->stopFFTbinDec, 0.0f, st->fftlen-2*stenc->stopFFTbinDec); + /* Nyquist frequency is discarded */ + fftBuffer[1] = 0.f; + + /* If previous frame is active, reset the overlap-add buffer */ + if( stcod->last_core_brate > SID_2k40 ) + { + set_f( st->olapBufferSynth, 0.0f, st->fftlen); + if( (stcod->last_core>0 && stcod->codec_mode == MODE2)|| stcod->codec_mode == MODE1 ) + { + tcx_transition = 1; + } + } + + /* Perform STFT synthesis */ + SynthesisSTFT(fftBuffer, timeDomainOutput, st->olapBufferSynth, st->olapWinSyn, tcx_transition, st ); + /* update CNG excitation energy for LP_CNG */ + + /* calculate the residual signal energy */ + enr = dotp( st->exc_cng, st->exc_cng, st->frameSize ) / st->frameSize; + + /* convert log2 of residual signal energy */ + enr = (float)log10( enr + 0.1f ) / (float)log10( 2.0f ); + + /* decrease the energy in case of WB input */ + if( bwidth != NB ) + { + if( bwidth == WB ) + { + if( CNG_mode >= 0 ) + { + /* Bitrate adapted attenuation */ + att = ENR_ATT[CNG_mode]; + } + else + { + /* Use least attenuation for higher bitrates */ + att = ENR_ATT[4]; + } + } + else + { + att = 1.5f; + } + + enr -= att; + } + + stcod->lp_ener = 0.8f * stcod->lp_ener + 0.2f * pow( 2.0f, enr ); + + + /* Overlap-add when previous frame is active */ + if( stcod->last_core_brate > SID_2k40 && stcod->codec_mode == MODE2 ) + { + float noise[2048], old_exc_ener = 0.f, gain = 0.f, tmp; + int N = st->frameSize; + short seed_loc = st->seed; + float *old_exc, old_Aq[M+1], *old_syn_pe, old_syn; + + if( stcod->last_core > 0 ) + { + 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, + stcod->tcx_cfg.tcx_last_overlap_mode==ALDO_WINDOW? FULL_OVERLAP: stcod->tcx_cfg.tcx_last_overlap_mode, + NULL, NULL, NULL, NULL, NULL, N/2, stcod->tcx_cfg.tcx_offset<0?-stcod->tcx_cfg.tcx_offset: 0, + 1, 0, 0 ); + + if(stcod->tcx_cfg.last_aldo) + { + for (i=0; iframeSize; i++) + { + timeDomainOutput[i] += stcod->old_out[i+NS2SA(stcod->sr_core, N_ZERO_MDCT_NS)]; + } + } + 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; itcx_cfg.tcx_mdct_window_length; i++) + { + timeDomainOutput[i] += stcod->LPDmem.Txnq[i]; + } + } + } + else + { + lsp2a_stab( stcod->lsp_old, old_Aq, M ); + old_exc = stcod->LPDmem.old_exc+L_EXC_MEM-(N/2); + old_syn_pe = stcod->LPDmem.mem_syn2; + old_syn = stcod->LPDmem.syn[M]; + for ( i=0; iolapWinSyn[N/2+i]; + } + } + } + + return; +} diff --git a/lib_enc/find_tar.c b/lib_enc/find_tar.c new file mode 100644 index 000000000..99bdb9928 --- /dev/null +++ b/lib_enc/find_tar.c @@ -0,0 +1,87 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * find_targets() + * + * Find the target vectors for excitaiton search: + *-------------------------------------------------------------------*/ + +void find_targets( + const float *speech, /* i : pointer to the speech frame */ + const float *mem_syn, /* i : memory of the synthesis filter */ + const short i_subfr, /* i : subframe index */ + float *mem_w0, /* i/o: weighting filter denominator memory */ + const float *p_Aq, /* i : interpolated quantized A(z) filter */ + const float *res, /* i : residual signal */ + const short L_subfr, /* i : length of vectors for gain quantization */ + const float *Ap, /* i : unquantized A(z) filter with bandwidth expansion */ + const float tilt_fac, /* i : tilt factor */ + float *xn, /* o : Close-loop Pitch search target vector */ + float *cn, /* o : target vector in residual domain */ + float *h1 /* o : impulse response of weighted synthesis filter */ +) +{ + short i; + float error[M+5*L_SUBFR]; /* error of quantization */ + float tmp_fl[L_SUBFR+M], tmp; + + /*------------------------------------------------------------------------* + * 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[] */ + set_f( tmp_fl, 0, M ); + mvr2r( xn, tmp_fl+M, L_subfr/2 ); + tmp = 0.0f; + + preemph( tmp_fl+M, tilt_fac, L_subfr/2, &tmp ); + syn_filt( Ap, M, tmp_fl+M, tmp_fl+M, L_subfr/2, tmp_fl, 0 ); + residu( p_Aq, M, tmp_fl+M, cn, L_subfr/2 ); + + /* second half: res[] --> cn[] (approximated and faster) */ + mvr2r( &res[i_subfr+(L_subfr/2)], cn+(L_subfr/2), L_subfr/2 ); + } + + /*-----------------------------------------------------------------* + * Compute impulse response h1[] of the weighted synthesis filter + *-----------------------------------------------------------------*/ + + set_f( h1, 0, L_subfr ); + mvr2r( Ap, h1, M+1 ); + syn_filt( p_Aq, M, h1, h1, L_subfr, h1+(M+1), 0 ); + tmp = 0.0f; + deemph( h1, tilt_fac, L_subfr, &tmp ); + + return; +} diff --git a/lib_enc/find_tilt.c b/lib_enc/find_tilt.c new file mode 100644 index 000000000..bc8dabff3 --- /dev/null +++ b/lib_enc/find_tilt.c @@ -0,0 +1,184 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ + +#define FACT 3.0f /* background noise energy estimation adjusting factor - to maintain the ADR about the same */ +#define TH_COR 0.6f /* Minimum correlation for per bin processing */ +#define TH_D 50.0f /* Difference limit between nearest harmonic and a frequency bin */ +#define TH_PIT (INT_FS_12k8 / (2.0f * TH_D)) /* Maximum pitch for per bin processing */ + +/*-------------------------------------------------------------------* + * find_tilt() + * + * Find LF/HF energy ratio + *-------------------------------------------------------------------*/ + +void find_tilt( + const float fr_bands[], /* i : energy in frequency bands */ + const float bckr[], /* i : per band background noise energy estimate */ + float ee[2], /* o : lf/hf E ration for present frame */ + const short pitch[3], /* i : open loop pitch values for 3 half-frames */ + const float voicing[3], /* i : normalized correlation for 3 half-frames */ + const float *lf_E, /* i : per bin energy for low frequencies */ + const float corr_shift, /* i : normalized correlation correction */ + const short bwidth, /* i : input signal bandwidth */ + const short max_band, /* i : maximum critical band */ + float hp_E[], /* o : energy in HF */ + const short codec_mode, /* i : Mode 1 or 2 */ + float *bckr_tilt_lt, /* i/o: lf/hf E ratio of background noise */ + short Opt_vbr_mode +) +{ + float lp_bckr, hp_bckr, lp_E, freq, f0, f1, f2, mean_voi, bin; + const float *pt_bands, *pt_bckr, *tmp_E, *hf_bands, *pt_E; + short cnt, i, nb_bands; + float th_pit; + + /*-----------------------------------------------------------------* + * Initializations + *-----------------------------------------------------------------*/ + + th_pit = TH_PIT; + + if( bwidth != NB ) + { + /* WB processing */ + bin = BIN; /* First useful frequency bin ~ 50 Hz */ + pt_bands = fr_bands; + tmp_E = lf_E; + pt_bckr = bckr; + nb_bands = 10; + } + else + { + /* NB processing */ + bin = 3.0f*BIN; /* 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; /* exclude 1st critical band */ + nb_bands = 9; /* nb. of "low" frequency bands taken into account in NB processing */ + } + + /*-----------------------------------------------------------------* + * Find spectrum tilt + *-----------------------------------------------------------------*/ + + pt_E = tmp_E; /* pointer 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 */ + hp_bckr = 0.5f * (bckr[max_band-1] + bckr[max_band]); /* estimated noise E in last 2 critical bands */ + *bckr_tilt_lt = 0.9f * *bckr_tilt_lt + 0.1f * lp_bckr / hp_bckr; + + if ( codec_mode == MODE2 + || Opt_vbr_mode + ) + { + lp_bckr *= FACT; + hp_bckr *= FACT; + } + + mean_voi = 0.5f * (voicing[1] + voicing[2]) + corr_shift; + f0 = ((float)INT_FS_12k8) / pitch[2]; + + for( i=0; i<2; i++ ) + { + hp_E[i] = 0.5f * (hf_bands[max_band-1] + hf_bands[max_band]) - hp_bckr; /* average E in last 2 critical bands */ + + if ( !Opt_vbr_mode) + { + if( hp_E[i] < E_MIN ) + { + /* to avoid division by 0 */ + hp_E[i] = E_MIN; + } + + } + else + { + if( hp_E[i] < 1.0f ) + { + /* to avoid division by 0 */ + hp_E[i] = 1.0f; + } + } + + + if( (mean_voi > TH_COR) && (pitch[2] < th_pit) ) + { + /* high-pitched voiced frames */ + freq = bin; /* 1st useful frequency bin */ + cnt = 0; + lp_E = 0.0f; + f1 = 1.5f * f0; /* middle between 2 harmonics */ + f2 = f0; + + while( freq <= 1270.0f ) /* end frequency of 10th critical band */ + { + /*pt_E*/ + while( freq <= f1 ) + { + if( fabs(freq-f2) < TH_D ) /* include only bins sufficiently close to harmonics */ + { + lp_E += *pt_E; + cnt++; + } + freq += BIN; + pt_E++; + } + f1 += f0; + f2 += f0; /* next harmonic */ + } + + lp_E = lp_E / (float)cnt - 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; /* average E in first critical bands, up to 1270 Hz */ + } + + if ( !Opt_vbr_mode) + { + if( lp_E < E_MIN ) + { + /* avoid negative E due to noise subtraction */ + lp_E = E_MIN; + } + } + else + { + + if( lp_E < 0.0f ) + { + /* avoid negative E due to noise subtraction */ + lp_E = 0.0f; + } + } + + /* calculate the tilt (LF/HF ratio) */ + ee[i] = lp_E / hp_E[i]; + + if( bwidth == NB ) /* for NB input, compensate for the missing bands */ + { + ee[i] *= 6.0f; + } + + pt_bands += NB_BANDS; /* update pointers for the 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 000000000..0a4029ae1 --- /dev/null +++ b/lib_enc/find_uv.c @@ -0,0 +1,414 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define L_ENR (NB_SSF+2) +#define VOI_THRLD 0.2f + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static float find_ener_decrease( const short ind_deltaMax, const float *pt_enr_ssf ); + +/*-------------------------------------------------------------------* + * find_ener_decrease() + * + * Find maximum energy ratio between short sub-subframes in case + * energy is trailing off after a spike + *-------------------------------------------------------------------*/ + +static float find_ener_decrease( /* o : maximum energy ratio */ + const short ind_deltaMax, /* i : index of the beginning of maximum energy search */ + const float *pt_enr_ssf /* i : Pointer to the energy buffer */ +) +{ + short i, j, end, flag; + float maxEnr, minEnr, dE2; + + dE2 = 0.0f; + j = ind_deltaMax+2; + end = j+L_ENR; + maxEnr = pt_enr_ssf[j]; + j++; + flag = 0; + for( i=j; i maxEnr && flag == 0 ) + { + maxEnr = pt_enr_ssf[i]; + j++; + } + else + { + flag = 1; + } + } + + minEnr = maxEnr; + for( i=j; i dE1 ) + { + dE1 = fac; + ind_deltaMax = i; + } + + pt_enr_ssf++; + pt_enr_ssf1++; + } + + /*-----------------------------------------------------------------* + * Average spectral tilt + * Average voicing (normalized correlation) + *-----------------------------------------------------------------*/ + + mean_ee = 1.0f/3.0f * (st->ee_old + ee[0] + ee[1]); + mean_voi3 = 1.0f/3.0f * (voicing[0] + voicing[1] + voicing[2]); + + /*-----------------------------------------------------------------* + * Total frame energy difference (dE3) + *-----------------------------------------------------------------*/ + + dE3 = Etot - st->Etot_last; + + /*-----------------------------------------------------------------* + * Energy decrease after spike (dE2) + *-----------------------------------------------------------------*/ + + /* set different thresholds and conditions for NB and WB input */ + if ( st->input_bwidth == NB ) + { + dE2_th = 21.0f; + nb_cond = ( mean_voi3 + corr_shift ) < 0.68f; + } + else + { + dE2_th = 30.0f; + nb_cond = 1; /* no additional condition for WB input */ + } + + /* calcualte maximum energy decrease */ + dE2 = 0.0f; + pt_enr_ssf = enr_ssf + 2*NB_SSF; + + if( dE1 > 30.0f && nb_cond ) + { + if( 2 * NB_SSF - ind_deltaMax < L_ENR ) + { + st->old_ind_deltaMax = ind_deltaMax; + mvr2r( pt_enr_ssf, st->old_enr_ssf, 2*NB_SSF ); + } + else + { + st->old_ind_deltaMax = -1; + dE2 = find_ener_decrease( ind_deltaMax, pt_enr_ssf ); + if( dE2 > dE2_th ) + { + st->spike_hyst = 0; + } + } + } + else + { + if( st->old_ind_deltaMax >= 0 ) + { + mvr2r( st->old_enr_ssf, enr_ssf, 2*NB_SSF ); + dE2 = find_ener_decrease( st->old_ind_deltaMax, enr_ssf ); + if( dE2 > dE2_th ) + { + st->spike_hyst = 1; + } + } + st->old_ind_deltaMax = -1; + } + + /*-----------------------------------------------------------------* + * Detection of voiced offsets (tmp_offset_flag) + *-----------------------------------------------------------------*/ + + tmp_offset_flag = 1; + + if ( st->input_bwidth != NB ) + { + ee0_th = 2.4f; + voi_th = 0.74f; + } + else + { + ee0_th = 9.8f; + voi_th = 0.76f; + } + + if( ( st->last_coder_type_raw == UNVOICED ) || /* previous frame was unvoiced */ + ( ( ee[0] < ee0_th ) && ( hp_E[0] > (float)E_MIN ) && /* energy is concentrated in high frequencies provided that some energy is present in HF. The cast to (float) is needed for Linux i686 (gcc version 4.7.2), otherwise the criterion hp_E[0] > E_MIN holds true if E_MIN was assigned to hp_E[0] before */ + ( voicing[0] + corr_shift < voi_th ) ) ) /* normalized correlation is low */ + { + tmp_offset_flag = 0; + } + + /*-----------------------------------------------------------------* + * Decision about UC + *-----------------------------------------------------------------*/ + + /* SC-VBR - set additional parameters and thresholds for SC-VBR */ + mean_voi3_offset = 0.0f; + flag_low_relE = 0; + ee1_th = 9.5f; + if ( st->Opt_SC_VBR ) + { + ee1_th = 8.5f; + + /* SC-VBR - determine the threshold on relative energy as a function of lp_noise */ + if ( st->input_bwidth != NB ) + { + if ( st->Last_Resort == 0 ) + { + relE_thres = 0.650f * st->lp_noise - 33.5f; + } + else + { + relE_thres = 0.700f * st->lp_noise - 33.5f; + } + } + else + { + relE_thres = 0.60f * st->lp_noise - 28.2f; + + } + + if( relE_thres < -25.0f ) + { + relE_thres = -25.0f; + } + + /* SC-VBR = set flag on low relative energy */ + if ( relE < relE_thres ) + { + flag_low_relE = 1; + } + + /* SC-VBR - correction of voicing threshold for NB inputs (important only in noisy conditions) */ + if ( st->input_bwidth == NB && st->vadnoise < 20.0f ) + { + mean_voi3_offset = 0.05f; + } + } + + /* make decision whether frame is unvoiced */ + coder_type = GENERIC; + if ( st->input_bwidth == NB ) + { + if( ( ( mean_voi3 + corr_shift < 0.68f + mean_voi3_offset ) && /* normalized correlation low */ + ( ( voicing[2] + corr_shift ) < 0.79f ) && /* normalized correlation low on look-ahead - onset detection */ + ( ee[0] < 10.0f ) && ( hp_E[0] > (float)E_MIN ) && /* energy concentrated in high frequencies provided that some energy is present in HF... */ + ( ee[1] < ee1_th ) && ( hp_E[1] > (float)E_MIN ) && /* ... biased towards look-ahead to detect onsets. The cast to (float) is needed for Linux i686 (gcc version 4.7.2), otherwise the criterion hp_E[0] > E_MIN holds true if E_MIN was assigned to hp_E[] before */ + ( tmp_offset_flag == 0 ) && /* take care of voiced offsets */ + ( st->music_hysteresis == 0 ) && /* ... and in segment after AUDIO frames */ + ( dE1 <= 29.0f ) && /* avoid on sharp energy spikes */ + ( st->old_dE1 <= 29.0f ) && /* + one frame hysteresis */ + ( st->spike_hyst < 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; + } + } + else + { + if( ( ( mean_voi3 + corr_shift < 0.695f + mean_voi3_offset ) && /* normalized correlation low */ + ( ee[0] < 6.2f ) && ( hp_E[0] > (float)E_MIN ) && /* energy concentrated in high frequencies provided that some energy is present in HF */ + ( ee[1] < 6.2f ) && ( hp_E[1] > (float)E_MIN ) && /* ... biased towards look-ahead to detect onsets. The cast to (float) is needed for Linux i686 (gcc version 4.7.2), otherwise the criterion hp_E[0] > E_MIN holds true if E_MIN was assigned to hp_E[] before */ + ( tmp_offset_flag == 0 ) && /* take care of voiced offsets */ + ( st->music_hysteresis == 0 ) && /* ... and in segment after AUDIO frames */ + ( dE1 <= 30.0f ) && /* avoid on sharp energy spikes */ + ( st->old_dE1 <= 30.0f ) && /* + one frame hysteresis */ + ( st->spike_hyst < 0 ) ) || /* avoid after sharp energy spikes followed by decay (e.g. castanets) */ + ( flag_low_relE + && st->old_dE1 <= 30.0f + )) /* low relative frame energy (only for SC-VBR) */ + { + coder_type = UNVOICED; + } + } + + /*-----------------------------------------------------------------* + * Decision about VC + *-----------------------------------------------------------------*/ + + st->set_ppp_generic = 0; + + if( localVAD == 1 && coder_type == GENERIC && last_core_orig != AMR_WB_CORE) + { + if( ( voicing_fr[0] > 0.605f ) && /* normalized correlation high in 1st sf. */ + ( voicing_fr[1] > 0.605f ) && /* normalized correlation high in 2st sf. */ + ( voicing_fr[2] > 0.605f ) && /* normalized correlation high in 3st sf. */ + ( voicing_fr[3] > 0.605f ) && /* normalized correlation high in 4st sf. */ + ( mean_ee > 4.0f ) && /* energy concentrated in low frequencies */ + ( fabs( pitch_fr[1] - pitch_fr[0] ) < 3.0f ) && /* small OL pitch difference in 1st sf. */ + ( fabs( pitch_fr[2] - pitch_fr[1] ) < 3.0f ) && /* small OL pitch difference in 2nd sf. */ + ( fabs( pitch_fr[3] - pitch_fr[2] ) < 3.0f ) ) /* small OL pitch difference in 3rd sf. */ + { + coder_type = VOICED; + } + else if ( st->Opt_SC_VBR && st->input_bwidth == NB && st->vadnoise < 20 ) + { + if( ( voicing_fr[0] > 0.25f) && /* normalized correlation high in 1st sf. */ + ( voicing_fr[1] > 0.25f ) && /* normalized correlation high in 2st sf. */ + ( voicing_fr[2] > 0.25f ) && /* normalized correlation high in 3st sf. */ + ( voicing_fr[3] > 0.25f ) && /* normalized correlation high in 4st sf. */ + ( mean_ee > 1.0f ) && /* energy concentrated in low frequencies (used 1.0 for WB) */ + ( fabs( pitch_fr[1] - pitch_fr[0] ) < 5.0f ) && /* small OL pitch difference in 1st sf. */ + ( fabs( pitch_fr[2] - pitch_fr[1] ) < 5.0f ) && /* small OL pitch difference in 2nd sf. */ + ( fabs( pitch_fr[3] - pitch_fr[2] ) < 5.0f ) ) /* small OL pitch difference in 3rd sf. */ + { + st->set_ppp_generic = 1; + coder_type = VOICED; + } + } + /* set VOICED mode for frames with very stable pitch and high correlation + and avoid to switch to AUDIO/MUSIC later */ + voicing_m = mean( voicing_fr, NB_SUBFR ); + + dpit1 = (float)fabs( pitch_fr[0] - pitch_fr[1] ); + dpit2 = (float)fabs( pitch_fr[1] - pitch_fr[2] ); + dpit3 = (float)fabs( pitch_fr[2] - pitch_fr[3] ); + + if( *flag_spitch || ( dpit1 <= 3.0f && dpit2 <= 3.0f && dpit3 <= 3.0f && + voicing_m > 0.95f && voicing_sm > 0.97f ) ) + { + coder_type = VOICED; + *flag_spitch = 1; /*to avoid switch to AUDIO/MUSIC later*/ + } + } + + /*-----------------------------------------------------------------* + * Channel-aware mode - set RF mode and total bitrate + *-----------------------------------------------------------------*/ + + st->rf_mode = st->Opt_RF_ON; + + if ( coder_type == GENERIC ) + { + if( ( voicing_fr[0] < VOI_THRLD ) && /* normalized correlation high in 1st sf. */ + ( voicing_fr[1] < VOI_THRLD ) && /* normalized correlation high in 2st sf. */ + ( voicing_fr[2] < VOI_THRLD ) && /* normalized correlation high in 3st sf. */ + ( voicing_fr[3] < VOI_THRLD ) && /* normalized correlation high in 4st sf. */ + ( st->vadnoise > 25.0f ) ) /* when speech is clean */ + { + st->rf_mode = 0; + /* Current frame cannot be compressed to pack the partial redundancy;*/ + + if( st->rf_mode != st->Opt_RF_ON ) + { + core_coder_mode_switch( st, st->bwidth, st->total_brate ); + } + } + } + + /*-----------------------------------------------------------------* + * Updates + *-----------------------------------------------------------------*/ + + /* update spike hysteresis parameters */ + if( st->spike_hyst >= 0 && st->spike_hyst < 2 ) + { + st->spike_hyst++; + } + + /* reset spike hysteresis */ + if( ( st->spike_hyst > 1 ) && + ( dE3 > 5.0f || /* energy increases */ + ( relE > -13.0f && ( mean_voi3 + corr_shift > 0.695f) ) ) ) /* normalized correlation is high */ + { + st->spike_hyst = -1; + } + + /* update tilt parameters */ + st->ee_old = ee[1]; + st->old_dE1 = dE1; + + /* save the raw coder_type for various modules later in the codec (the reason is that e.g. UNVOICED is not used (rewritten) at higher rates) */ + st->coder_type_raw = coder_type; + + return coder_type; +} diff --git a/lib_enc/find_wsp.c b/lib_enc/find_wsp.c new file mode 100644 index 000000000..5a7046546 --- /dev/null +++ b/lib_enc/find_wsp.c @@ -0,0 +1,62 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * find_wsp() + * + * Compute weighted speech used in open-loop pitch search + *-------------------------------------------------------------------*/ + +void find_wsp( + const short L_frame, /* i : length of the frame */ + const short L_subfr, /* i : length of subframe */ + const short nb_subfr, /* i : number of subframes */ + const float *A, /* i : A(z) filter coefficients */ + float *Aw, /* o : weighted A(z) filter coefficients */ + const float *speech, /* i : pointer to the denoised speech frame */ + const float tilt_fact, /* i : tilt factor */ + float *wsp, /* o : poitnter to the weighted speech frame */ + float *mem_wsp, /* i/o: W(Z) denominator memory */ + const float gamma, /* i : weighting factor */ + const short L_look /* i : look-ahead */ +) +{ + float *p_Aw, tmp; + short i_subfr; + + + /*-----------------------------------------------------------------* + * Compute weighted A(z) unquantized for subframes + *-----------------------------------------------------------------*/ + + weight_a_subfr( nb_subfr, A, Aw, gamma, M ); + + /*-----------------------------------------------------------------* + * Compute weighted speech for all subframes + *-----------------------------------------------------------------*/ + + p_Aw = Aw; + for (i_subfr=0; i_subfr +#include "wmc_auto.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * frame_spec_dif_cor_rate() + * + * + *-------------------------------------------------------------------*/ + +void frame_spec_dif_cor_rate( + float spec_amp[], /*(i) spectral amplitude*/ + float pre_spec_low_dif[], /*(io) low spectrum different*/ + float f_tonality_rate[] /*(o) tonality rate*/ +) +{ + int i; + float spec_low_dif[59]; + float tmp,spec_low_dif_cor_rate,spec_dif_cor_rate; + float m,dx,dy; + + + for(i=0; i +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define RANGE 64 + +/*---------------------------------------------------------------------* + * Es_pred_enc() + * + * Calculation and quantization of average predicted innovation energy to be + *---------------------------------------------------------------------*/ + +void Es_pred_enc( + float *Es_pred, /* o : predicited scaled innovation energy */ + int *Es_pred_indice, /* o : indice corresponding to above parameter */ + const short L_frame, /* i : length of the frame */ + const short L_subfr, /* i : length of the subframe */ + const float *res, /* i : residual signal */ + const float *voicing, /* i : normalized correlation in three 1/2frames */ + const short nb_bits, /* i : allocated number of bits */ + const short no_ltp /* i : no_ltp flag */ +) +{ + short i, i_subfr, size; + float tmp, dist, mean_ener_code, ener; + float weight; + const float *qua_table; + + /*----------------------------------------------------------* + * calculate the average residual signal energy + *----------------------------------------------------------*/ + if( L_frame == L_FRAME ) + { + weight = 0.25f; + } + else /* L_frame == L_FRAME16k */ + { + weight = 0.2f; + } + + mean_ener_code = 0.0f; + for (i_subfr = 0; i_subfr < L_frame; i_subfr += L_subfr) + { + /* calculate the energy of residual signal */ + ener = sum2_f(&res[i_subfr], L_subfr) + 0.01f; + ener = 10 * (float)log10( ener / ((float) L_subfr)); + if ((ener < 0) && !(no_ltp)) + { + ener = 0; + } + + /* update the average energy of residual signal */ + mean_ener_code += weight * ener; + } + + if( !no_ltp ) + { + /*----------------------------------------------------------* + * subtract an estimate of adaptive codebook contribution + *----------------------------------------------------------*/ + + mean_ener_code -= 10.0f * (0.5f * voicing[0] + 0.5f * voicing[1]); + + /*----------------------------------------------------------* + * quantize the average predicted innovation energy + *----------------------------------------------------------*/ + switch ( nb_bits ) + { + case 5: + { + qua_table = Es_pred_qua_5b; + break; + } + case 4: + { + qua_table = Es_pred_qua_4b; + break; + } + case 3: + { + qua_table = Es_pred_qua_3b; + break; + } + default: + { + qua_table = Es_pred_qua_5b; + break; + } + } + } + else + { + qua_table = Es_pred_qua_4b_no_ltp; + } + + /* select codebook, size and number of bits */ + size = (short)pow2[nb_bits]; + + /* find the nearest neighbour (codevector) */ + tmp = 1e30f; + *Es_pred_indice=0; + for (i=0; i, -2,, -2 and 2 */ + const short clip_gain, /* i : gain pitch clipping flag (1 = clipping) */ + float *past_qua_en /* i/o: gain quantization memory (4 words) */ +) +{ + short index, i, j, min_ind, size, nBits; + float dist, dist_min, g_pitch, g_code, qua_en, gcode0; + const float *p, *t_qua_gain; + + /*-----------------------------------------------------------------* + * gain computation correlations + * find raw innovation energy + *-----------------------------------------------------------------*/ + + E_corr_xy2( xn, y1, y2, g_corr,L_SUBFR); + g_corr[2] += 0.01F; + g_corr[3] -= 0.02F; + g_corr[4] += 0.02F; + *gain_inov = 1.0f / (float)sqrt( ( dotp( code, code, L_SUBFR ) + 0.01f ) / L_SUBFR ); + + /*-----------------------------------------------------------------* + * find the initial quantization pitch index + * set gains search range + *-----------------------------------------------------------------*/ + + if ( core_brate < ACELP_12k65 ) + { + t_qua_gain = t_qua_gain6b; + nBits = 6; + min_ind = 0; + size = RANGE; + if (clip_gain == 1) + { + size -= 16; /* limit pitch gain to 1.0 */ + } + } + else + { + t_qua_gain = t_qua_gain7b; + nBits = 7; + p = t_qua_gain7b + RANGE; /* pt at 1/4th of table */ + j = NB_QUA_GAIN7B - RANGE; + if (clip_gain == 1) + { + j -= 27; /* limit pitch gain to 1.0 */ + } + + min_ind = 0; + g_pitch = *gain_pit; + + + for (i=0; i *p) + { + min_ind++; + } + } + size = RANGE; + } + + /*-----------------------------------------------------------------* + * predicted code gain + *-----------------------------------------------------------------*/ + + /* start with predicting code energy in dB */ + gcode0 = MEAN_ENER; + for (i=0; i0; i--) + { + past_qua_en[i] = past_qua_en[i-1]; + } + past_qua_en[0] = (float)(20.0*log10(qua_en)); + + push_indice( st, IND_GAIN, index, nBits ); + + *norm_gain_code = *gain_code / *gain_inov; + + return; +} + +/*---------------------------------------------------------------------* + * gain_enc_mless() + * + * Quantization of pitch and codebook gains without prediction (memory-less) + * - an initial predicted gain, gcode0, is first determined based on + * the predicted average 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_mless( + Encoder_State *st, /* i/o: encoder state structure */ + const long core_brate, /* i : core bitrate */ + const short L_frame, /* i : length of the frame */ + const short coder_type, /* i : coding type */ + const short i_subfr, /* i : subframe index */ + const short tc_subfr, /* i : TC subframe index */ + const float *xn, /* i : target vector */ + const float *y1, /* i : zero-memory filtered adaptive excitation */ + const float *y2, /* i : zero-memory filtered algebraic codebook excitation */ + const float *code, /* i : algebraic excitation */ + const float Es_pred, /* i : predicted scaled innovation energy */ + float *gain_pit, /* o : quantized pitch gain */ + float *gain_code, /* o : quantized codebook gain */ + float *gain_inov, /* o : gain of the innovation (used for normalization) */ + float *norm_gain_code, /* o : norm. gain of the codebook excitation */ + float *g_corr, /* i/o: correlations , -2,, -2 and 2 */ + const short clip_gain /* i : gain pitch clipping flag (1 = clipping) */ +) +{ + short index, i, size, nBits; + float dist, dist_min, g_pitch, g_code, gcode0, Ei, Ecode; + short nBits2; + float tmp1, tmp2; + const float *p, *qua_table; + + /*-----------------------------------------------------------------* + * calculate the rest of the correlation coefficients + * c2 = , c3 = -2, c4 = 2 + *-----------------------------------------------------------------*/ + + E_corr_xy2( xn, y1, y2, g_corr,L_SUBFR); + g_corr[2] += 0.01F; + g_corr[3] -= 0.02F; + g_corr[4] += 0.02F; + + /*-----------------------------------------------------------------* + * calculate the unscaled innovation energy + * calculate the predicted gain code + *-----------------------------------------------------------------*/ + + Ecode = (dotp( code, code, L_SUBFR) + 0.01f) / L_SUBFR; + *gain_inov = 1.0f / (float)sqrt( Ecode ); + Ei = 10 * (float)log10( Ecode ); + gcode0 = (float) pow(10, 0.05 * (Es_pred - Ei)); + + /*-----------------------------------------------------------------* + * select the codebook, size and number of bits + * set the gains searching range + *-----------------------------------------------------------------*/ + + if( L_frame == L_FRAME ) + { + nBits = gain_bits_tbl[BIT_ALLOC_IDX(core_brate, coder_type, i_subfr, TC_SUBFR2IDX(tc_subfr))]; + } + else /* L_frame == L_FRAME16k */ + { + nBits = gain_bits_16kHz_tbl[ BIT_ALLOC_IDX_16KHZ(core_brate, coder_type, i_subfr, TC_SUBFR2IDX_16KHZ(tc_subfr)) ]; + } + + if( (tc_subfr == 3*L_SUBFR && i_subfr == 3*L_SUBFR && L_frame == L_FRAME) || + (tc_subfr == 4*L_SUBFR && i_subfr == 4*L_SUBFR && L_frame == L_FRAME16k) ) + { + /* in case of attack at the end of the frame, use scalar gain quantizers */ + tmp1 = (g_corr[0]*g_corr[2]) - (0.25f*g_corr[4]*g_corr[4]); + tmp2 = -0.5f*g_corr[1]/tmp1; + tmp1 = -0.5f*g_corr[3]/tmp1; + + *gain_pit = (g_corr[2]*tmp2) - (0.5f*g_corr[4]*tmp1); + *gain_code = (g_corr[0]*tmp1) - (0.5f*g_corr[4]*tmp2); + + *gain_pit = max(G_PITCH_MIN_TC192,min(*gain_pit,G_PITCH_MAX_TC192)); + + /* set number of bits for two SQs */ + nBits2 = (nBits+1)>>1; + nBits = nBits>>1; + + /* gain_pit Q */ + tmp1 = (G_PITCH_MAX_TC192 - G_PITCH_MIN_TC192) / ((1 << nBits) - 1); /* set quantization step */ + index = usquant( *gain_pit, gain_pit, G_PITCH_MIN_TC192, tmp1, (1 << nBits) ); + push_indice( st, IND_GAIN_PIT, index, nBits ); + + /* gain_code Q */ + *gain_code /= gcode0; + index = gain_quant( gain_code, G_CODE_MIN_TC192, G_CODE_MAX_TC192, nBits2 ); + push_indice( st, IND_GAIN_CODE, index, nBits2 ); + *gain_code *= gcode0; + } + else + { + size = (short)pow2[nBits]; + + switch ( nBits ) + { + case 7: + { + qua_table = gain_qua_mless_7b; + if (clip_gain == 1) + { + size -= 30; + } + break; + } + case 6: + { + qua_table = gain_qua_mless_6b; + if (clip_gain == 1) + { + size -= 14; + } + break; + } + case 5: + { + qua_table = gain_qua_mless_5b; + if (clip_gain == 1) + { + size -= 6; + } + break; + } + default: + { + qua_table = gain_qua_mless_6b; + if (clip_gain == 1) + { + size -= 14; + } + break; + } + } + + /* in case of AVQ inactive, limit the gain_pit to 0.65 */ + if( clip_gain == 2 && nBits == 6 ) + { + size -= 36; + nBits--; + } + + /*-----------------------------------------------------------------* + * search for the best quantizer + *-----------------------------------------------------------------*/ + + p = qua_table; + dist_min = 3.402823466e+38F; + index = 0; + for (i = 0; i, -2,, -2 and 2 */ + const short clip_gain /* i : gain pitch clipping flag (1 = clipping) */ +) +{ + short index, nBits_pitch, nBits_code; + float g_code, gcode0, Ei, Ecode, tmp1, tmp2; + short tmp16; + /*-----------------------------------------------------------------* + * 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; + + /*-----------------------------------------------------------------* + * 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 ); + Ei = 10 * (float)log10( Ecode ); + gcode0 = (float) pow(10, 0.05 * (Es_pred - Ei)); + + 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 = max(G_PITCH_MIN,min(*gain_pit,G_PITCH_MAX)); + + /*-----------------------------------------------------------------* + * limit the pitch gain searching range (if indicated by clip_gain) + *-----------------------------------------------------------------*/ + + if( clip_gain == 1 && *gain_pit > 0.95f ) + { + *gain_pit = 0.95f; + } + else if( clip_gain == 2 && *gain_pit > 0.65f ) + { + *gain_pit = 0.65f; + } + + /*-----------------------------------------------------------------* + * search for the best quantized values + *-----------------------------------------------------------------*/ + + nBits_pitch = gain_bits_16kHz_tbl[ BIT_ALLOC_IDX_16KHZ(core_brate, coder_type, i_subfr, TC_SUBFR2IDX_16KHZ(tc_subfr)) ]; + nBits_code = (nBits_pitch+1)>>1; + nBits_pitch = nBits_pitch>>1; + + tmp16 = div_s(1,((1 << (nBits_pitch)) - 1) ); /* Q15*/ + tmp1 = (float)mult_r((short)(G_PITCH_MAX*8192.0f+0.5f),tmp16)/8192.0f; + index = usquant( *gain_pit, gain_pit, G_PITCH_MIN, tmp1, (1 << nBits_pitch) ); + push_indice( st, IND_GAIN_PIT, index, nBits_pitch ); + + g_code = *gain_code / gcode0; + index = gain_quant( &g_code, G_CODE_MIN, G_CODE_MAX, nBits_code ); + *gain_code = g_code * gcode0; + push_indice( st, IND_GAIN_CODE, index, nBits_code); + + *norm_gain_code = *gain_code / *gain_inov; + + return; +} + +/*-------------------------------------------------------------------* + * gain_enc_gaus() + * + * Quantization of gain for Gaussian codebook + *-------------------------------------------------------------------*/ + +short gain_enc_gaus( /* o : Return index of quantization */ + float *gain, /* i/o: Code gain to quantize */ + const short bits, /* i : number of bits to quantize */ + const float lowBound, /* i : lower bound of quantizer (dB) */ + const float topBound /* i : upper bound of quantizer (dB) */ +) +{ + short index; + float enr, stepSize; + + + enr = (float)( 20.0 * log10( *gain + 0.001f ) ); /* codebook gain in dB */ + + /*-----------------------------------------------------------------* + * quantize linearly the log E + *-----------------------------------------------------------------*/ + + stepSize = (topBound-lowBound)/((float)(1<= (1< 3 ) + { + g_code = *gain_code / gcode0; + index = gain_quant( &g_code, G_CODE_MIN, G_CODE_MAX, nBits ); + *gain_code = g_code * gcode0; + push_indice( st, IND_GAIN_CODE, index, nBits ); + } + else + { + index = N_GAIN_CODE_TC-1; + for( i=0; i < N_GAIN_CODE_TC-1; i++ ) + { + if( *gain_code < ((tbl_gain_code_tc[i]+(tbl_gain_code_tc[i+1]-tbl_gain_code_tc[i])/2) * gcode0) ) + { + index = i; + break; + } + } + + /*----------------------------------------------------------------* + * 3-bit -> 2-bit encoding + *----------------------------------------------------------------*/ + + if( nBits == 2 ) + { + index /= 2; + *gain_code = tbl_gain_code_tc[index*2] * gcode0; + push_indice( st, IND_GAIN_CODE, index, nBits ); + } + else + { + *gain_code = tbl_gain_code_tc[index] * gcode0; + push_indice( st, IND_GAIN_CODE, index, nBits ); + } + } + + *norm_gain_code = *gain_code / *gain_inov; + + return; +} + +/*---------------------------------------------------------------------* + * E_corr_xy2() + * + * Find the correlations between the target xn[], the filtered adaptive + * codebook exc. y1[], and the filtered fixed codebook innovation y2[]. + * ( , -2 and 2 ) (stored in g_corr[2..4]) + *---------------------------------------------------------------------*/ + +void E_corr_xy2( + const float xn[], /* i : target vector */ + const float y1[], /* i : filtered excitation components 1 */ + const float y2[], /* i : filtered excitation components 2 */ + float g_corr[],/* o : correlations between x, y1, y2, y3, y4 */ + const short L_subfr /* i : subframe size */ +) +{ + + + g_corr[2] = dotp(y2, y2, L_subfr); + g_corr[3] = -2.0f * dotp(xn, y2, L_subfr); + g_corr[4] = 2.0f * dotp(y1, y2, L_subfr); + + return; +} + + +/*---------------------------------------------------------------------* + * gain_enc_lbr() + * + * Quantization of pitch and codebook gains without prediction (memory-less) + * in ACELP at 7.2 and 8.0 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( + Encoder_State *st, /* i/o: encoder state structure */ + const long core_brate, /* i : core bitrate */ + const short coder_type, /* i : coding type */ + const short i_subfr, /* i : subframe index */ + const float *xn, /* i : target vector */ + const float *y1, /* i : zero-memory filtered adaptive excitation */ + const float *y2, /* i : zero-memory filtered algebraic codebook excitation */ + const float *code, /* i : algebraic excitation */ + float *gain_pit, /* o : quantized pitch gain */ + float *gain_code, /* o : quantized codebook gain */ + float *gain_inov, /* o : gain of the innovation (used for normalization) */ + float *norm_gain_code, /* o : norm. gain of the codebook excitation */ + float *g_corr, /* i/o: correlations , -2,, -2 and 2 */ + float gains_mem[], /* i/o: pitch gain and code gain from previous subframes */ + const short clip_gain /* i : gain pitch clipping flag (1 = clipping) */ +) +{ + short index = 0, i, size, nBits, n_pred, ctype; + float dist, dist_min, g_pitch, g_code, gcode0, aux[10], Ecode; + short rf_flag = 0; + const float *p, *b, *cdbk = 0; + + /*-----------------------------------------------------------------* + * calculate the rest of the correlation coefficients + * c2 = , c3 = -2, c4 = 2, c5* = + * c5* - not necessary to calculate + *-----------------------------------------------------------------*/ + + E_corr_xy2( xn, y1, y2, g_corr,L_SUBFR); + 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); + + /*-----------------------------------------------------------------* + * select the codebook, size and number of bits + * set the gains searching range + *-----------------------------------------------------------------*/ + + nBits = gain_bits_tbl[BIT_ALLOC_IDX(core_brate, coder_type, i_subfr, 0)]; + size = (short)pow2[nBits]; + + /*-----------------------------------------------------------------* + * calculate prediction of gcode + * search for the best codeword + *-----------------------------------------------------------------*/ + + ctype = 2*(coder_type - 1); + if (i_subfr == 0) + { + b = b_1sfr; + n_pred = 2; + + switch ( nBits ) + { + case 8: + { + cdbk = gp_gamma_1sfr_8b; + if (clip_gain == 1) + { + size -= 60; + } + break; + } + case 7: + { + cdbk = gp_gamma_1sfr_7b; + if (clip_gain == 1) + { + size -= 27; + } + break; + } + case 6: + { + cdbk = gp_gamma_1sfr_6b; + if (clip_gain == 1) + { + size -= 10; + } + break; + } + } + + /* calculate predicted gain */ + aux[0] = 1.0f; + aux[1] = ctype; + gcode0 = (float)pow(10, dotp(b, aux, n_pred) - 0.5f * (float)log10(Ecode)); + + /* searching of codebook */ + p = cdbk; + dist_min = 3.402823466e+38F; + index = 0; + for (i = 0; i +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define NMAX 8 /* Control of the routine's complexity */ +#define FAC_DELTA 16.0f + +/*---------------------------------------------------------------------* + * Prototypes + *---------------------------------------------------------------------*/ + +static short cod_2pos( const short ind1,const short ind2,const float sign1, + const float sign2,const short n ); + +static void gauss2v( Encoder_State *st, const float h[], const float xn[], const float dn[], float code[], + float y1[], float *gain, const short lg, const short nb_bits ); + +/*-------------------------------------------------------------------* + * Gaus_encode + * + * Encoder UnVoiced excitation coding using Gaussian codebooks + * - ACELP quantized Gaussian excitation + * - gain quantization + * - Total excitation for UnVoiced coders + * - Updates + *-------------------------------------------------------------------*/ + +float gaus_encode( + Encoder_State *st, /* i/o: encoder state structure */ + const short i_subfr, /* i : subframe index */ + const float *h1, /* i : weighted filter input response */ + const float *xn, /* i : target vector */ + float *exc, /* o : pointer to excitation signal frame */ + float *mem_w0, /* o : weighting filter denominator memory */ + float *gp_clip_mem, /* o : memory of gain of pitch clipping algorithm */ + float *tilt_code, /* o : synthesis excitation spectrum tilt */ + float *code, /* o : algebraic excitation */ + float *gain_code, /* o : Code gain. */ + float *y2, /* o : zero-memory filtered adaptive excitation */ + float *gain_inov, /* o : innovation gain */ + float *voice_fac, /* o : voicing factor */ + float *gain_pit, /* o : adaptive excitation gain */ + float *norm_gain_code, /* o : normalized innovative cb. gain */ + const long core_brate /* i : core bitrate */ +) +{ + short i = 0, nb_bits, idx; + float dn[L_SUBFR]; /* Correlation between xn and h1 */ + + /*----------------------------------------------------------------* + * Encode gaussian excitation + *----------------------------------------------------------------*/ + + corr_xh( xn, dn, h1, L_SUBFR ); /* Correlation between target xn[] and impulse response h1[] */ + + nb_bits = FCB_bits_tbl[BIT_ALLOC_IDX(core_brate, UNVOICED, i_subfr, TC_SUBFR2IDX(-1))]; + + gauss2v( st, h1, xn, dn, code, y2, gain_code, L_SUBFR, nb_bits>>1 ); + + /*----------------------------------------------------------------* + * Encode gaussian gain + *----------------------------------------------------------------*/ + + /* codeword energy computation */ + *gain_inov = 1.0f / (float)sqrt( ( dotp( code, code, L_SUBFR ) + 0.01f ) / L_SUBFR ); + + nb_bits = gain_bits_tbl[BIT_ALLOC_IDX(core_brate, UNVOICED, i_subfr, TC_SUBFR2IDX(-1))]; + + idx = gain_enc_gaus( gain_code, nb_bits, -30.0f, 190.0f ); + push_indice( st, IND_GAIN, idx, nb_bits ); + + /*-----------------------------------------------------------------* + * Total excitation for Unvoiced coders + *-----------------------------------------------------------------*/ + + for (i = 0; i < L_SUBFR; i++) + { + exc[i+i_subfr] = *gain_code * code[i]; + } + + /*-----------------------------------------------------------------* + * Updates: last value of new target is stored in mem_w0 + *-----------------------------------------------------------------*/ + + *mem_w0 = xn[L_SUBFR-1] - *gain_code * y2[L_SUBFR-1]; + + init_gp_clip(gp_clip_mem); /* reset pitch clipping parameters */ + *gain_pit = 0.0f; + *tilt_code = 0.0f; /* purely unvoiced */ + *voice_fac = -1.0f; /* purely unvoiced */ + + *norm_gain_code = *gain_code / *gain_inov; + + return L_SUBFR; +} + +/*-------------------------------------------------------------------* + * gauss2v() + * + * encoder of Gaussian Codebook for unvoiced + * consisting of addition of 2 Gaussian vectors + * + * One Gaussian vector of 192 values vectors delayed by 2 + *-------------------------------------------------------------------*/ + +static void gauss2v( + Encoder_State *st, /* i/o: encoder state structure */ + const float h[], /* i : weighted LP filter impulse response */ + const float xn[], /* i : target signal */ + const float dn[], /* i : backward filtered target */ + float code[], /* o : gaussian excitation */ + float y11[], /* o : zero-memory filtered gauss. excitation */ + float *gain, /* o : excitation gain */ + const short lg, /* i : subframe size */ + const short nb_bits /* i : nb ob bits per track (max 6) */ +) +{ + short i, j, ind1, ind2, idx; + short nvec, step; + float cor, cora, cor2, cor2w, eneri, enerw; + float *pt1, *pt2; + float max[NMAX+1], *pos[NMAX+1], sign[NMAX+1]; + float ener[NMAX+1], corr[NMAX+1], ener1; + float dico2[L_SUBFR*NMAX]; + float c1, c0; + float gxx, gcc; + float gaus_dico2[190]; + float hg[190]; + float delta; + short index_delta; + + + /*-----------------------------------------------------------------* + * Encode the tilt of gaussian excitation + *-----------------------------------------------------------------*/ + + c0=0.0f; /* Compute spectral tilt of target */ + c1=0.0f; + for (i=1; i 7) + { + index_delta = 7; + } + + delta = STEP_DELTA * (float)index_delta; + if( delta > 0.0f ) /* Adapt spectral tilt of initial codebook */ + { + gaus_dico2[0] = gaus_dico[0]; + for (i=1; i<190; i++) + { + gaus_dico2[i] = (gaus_dico[i] - delta*gaus_dico[i-1])/(1+delta*delta); + } + } + else + { + for (i=0; i<190; i++) + { + gaus_dico2[i] = gaus_dico[i]; + } + } + + /*-----------------------------------------------------------------* + * Codebook search initializations + *-----------------------------------------------------------------*/ + + ind1 = 0; + ind2 = 0; + + nvec = 1 << nb_bits; + step = 0x80 >> nb_bits; + + /*-----------------------------------------------------------------* + * dot product between dn and gaussian codevectors, + * keep NMAX best vectors + *-----------------------------------------------------------------*/ + + set_f(max, 0, NMAX+1); + set_f(sign, 0, NMAX+1); + + for (i = 0; i < NMAX+1; i++) + { + pos[i] = (float *)gaus_dico2; + } + + pt1 = (float *)gaus_dico2; + + for (i=0; i < nvec; i++, pt1+=step) + { + cor = dotp(pt1, dn, lg); + cora = (float)fabs(cor); + j = NMAX-1; + do + { + if(cora >= max[j]) + { + max[j+1] = max[j]; + pos[j+1] = pos[j]; + sign[j+1] = sign[j]; + max[j] = cora; + pos[j] = pt1; + sign[j] = cor; + } + + j--; + } + while (j >= 0); + } + + /*-----------------------------------------------------------------* + * filter selected vectors + * put sign + * compute energy + *-----------------------------------------------------------------*/ + + pt1 = dico2; + for (i=0; i cor2w * eneri) + { + cor2w = cor2; + enerw = eneri; + ind1 = i; + ind2 = j; + } + } + } + + /*-----------------------------------------------------------------* + * Compute zero-memory filtered gauss. excitation y + *-----------------------------------------------------------------*/ + + pt1 = dico2 + ind1*L_SUBFR; + pt2 = dico2 + ind2*L_SUBFR; + for(i=0; i= 0.0f) + { + sign[ind1] = 1.0f; + } + else + { + sign[ind1] = -1.0f; + } + + if(sign[ind2] >= 0.0f) + { + sign[ind2] = 1.0f; + } + else + { + sign[ind2] = -1.0f; + } + + /*-----------------------------------------------------------------* + * Compute code + *-----------------------------------------------------------------*/ + + pt1 = pos[ind1]; + pt2 = pos[ind2]; + for(i=0; i 0.0f) + { + s1=0; + } + + s2=1; + if(sign2 > 0.0f) + { + s2=0; + } + + if(s1 == s2) + { + if (ind1<=ind2) + { + i1 = ind1; + i2 = ind2; + } + else + { + i1 = ind2; + i2 = ind1; + } + } + else + { + if (ind1>ind2) + { + i1 = ind1; + i2 = ind2; + } + else + { + i1 = ind2; + i2 = ind1; + s1 = s2; + } + } + index = i1*n + i2; + index = (index<<1) + s1; + + return index; +} diff --git a/lib_enc/gp_clip.c b/lib_enc/gp_clip.c new file mode 100644 index 000000000..cf47a5b34 --- /dev/null +++ b/lib_enc/gp_clip.c @@ -0,0 +1,214 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "prot.h" +#include "options.h" +#include "prot.h" +#include "cnst.h" + +/*-------------------------------------------------------------------* +* Local constants +*-------------------------------------------------------------------*/ + +#define DIST_ISF_MAX_IO 150.0f + +#define DIST_ISF_MAX 120.0f +#define DIST_ISF_THRES 60 +#define GAIN_PIT_THRES 0.9f +#define GAIN_PIT_MIN 0.6f + +#define ALPHA1 0.98f +#define ALPHA4 0.99f +#define WINDOW_SIZE 50 +#define THRESH_TYPE 0.85f +#define THRESH_VOICING 0.86f + +/*-------------------------------------------------------------------* +* init_gp_clip +* +* Pitch Gain clipping initializations +*-------------------------------------------------------------------*/ +void init_gp_clip( + float mem[] /* o: memory of gain of pitch clipping algorithm */ +) +{ + mem[0] = DIST_ISF_MAX; + mem[1] = GAIN_PIT_MIN; + mem[2] = 0.0f; /* old energy of target (dB) */ + mem[3] = 0.0f; + mem[4] = 0.0f; + mem[5] = 0.8f; + + 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) + *-------------------------------------------------------------------*/ + +short gp_clip( + const long core_brate, /* i : core bitrate */ + const float *voicing, /* i : normalized correlations (from OL pitch) */ + const short i_subfr, /* i : subframe index */ + const short coder_type, /* i : type of coder */ + const float xn[], /* i : target vector */ + float mem[] /* i/o: memory of gain of pitch clipping algorithm */ +) +{ + short clip; + short i; + float wener, tmp; + + clip = 0; + if( (core_brate == ACELP_6k60) || (core_brate == ACELP_8k85) ) + { + tmp = 0.9f + (0.1f * mem[0]/DIST_ISF_MAX_IO); /* clipping is activated when filtered pitch gain > threshold (0.94 to 1) */ + if (mem[1] > tmp) + { + clip = 1; + } + } + else if( (mem[0] < DIST_ISF_THRES) && (mem[1] > GAIN_PIT_THRES) ) + { + clip = 1; + } + + wener = 0.01f; + for (i=0; i 1.0f)) + { + clip = 1; + } + + mem[2] = wener; + tmp = ALPHA1 * mem[4]; + + if( coder_type == GENERIC || coder_type == TRANSITION || coder_type == INACTIVE ) + { + tmp += (1-ALPHA1); + } + + mem[4] = tmp; + tmp = ALPHA4 * mem[5]; + if( i_subfr == 0 ) + { + mem[5] = (1-ALPHA4) * voicing[0] + tmp; + } + else if( i_subfr == 2*L_SUBFR ) + { + mem[5] = (1-ALPHA4) * voicing[1] + tmp; + } + if( mem[3] > WINDOW_SIZE ) + { + if( ( mem[4] > THRESH_TYPE ) && ( mem[5] > THRESH_VOICING ) ) + { + clip = 1; + } + } + else + { + mem[3]++; + } + + return (clip); +} + +/*-------------------------------------------------------------------* + * gp_clip_test_lsf() + * + * check the minimum distance of LSFs for pitch gain clipping flag + *-------------------------------------------------------------------*/ + +void gp_clip_test_lsf( + const long core_brate, /* i : core bitrate */ + const float lsf[], /* i : LSF vector */ + float mem[], /* i/o: memory of gain of pitch clipping algorithm */ + const short Opt_AMR_WB /* i : flag indicating AMR-WB IO mode */ +) +{ + short i; + short m; + float dist, dist_min; + + dist_min = lsf[1] - lsf[0]; + + if ( Opt_AMR_WB ) + { + m = M-1; + } + else + { + m = M; + } + + for (i=2; i DIST_ISF_MAX_IO) + { + dist = DIST_ISF_MAX_IO; + } + } + else if (dist > DIST_ISF_MAX) + { + dist = DIST_ISF_MAX; + } + + mem[0] = dist; + + return; +} + +/*-------------------------------------------------------------------* + * gp_clip_test_gain_pit() + * + * low-pass filtering of the pitch gain for pitch gain clipping flag + *-------------------------------------------------------------------*/ + +void gp_clip_test_gain_pit( + const long core_brate, /* i : core bitrate */ + const float gain_pit, /* i : gain of quantized pitch */ + float mem[] /* i/o: memory of gain of pitch clipping algorithm */ +) +{ + float gain; + + if( (core_brate == ACELP_6k60) || (core_brate == ACELP_8k85) ) + { + gain = 0.98f*mem[1] + 0.02f*gain_pit; /* long term LTP gain average (>250ms) */ + } + else + { + gain = 0.9f*mem[1] + 0.1f*gain_pit; + } + if (gain < GAIN_PIT_MIN) + { + gain = GAIN_PIT_MIN; + } + mem[1] = gain; + + return; +} diff --git a/lib_enc/gs_enc.c b/lib_enc/gs_enc.c new file mode 100644 index 000000000..2f21691f7 --- /dev/null +++ b/lib_enc/gs_enc.c @@ -0,0 +1,470 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static float edyn( const float *vec, const short lvec ); + +static void gsc_enc( Encoder_State *st, float res_dct_in[], float exc_dct_in[], const short Diff_len, + const short bits_used, const short nb_subfr, const short coder_type, + float *lsf_new, float* exc_wo_nf, float *tmp_noise ); + +/*-------------------------------------------------------------------* + * encod_audio() + * + * Encode audio (AC) frames + *-------------------------------------------------------------------*/ + +void encod_audio( + Encoder_State *st, /* i/o: State structure */ + LPD_state *mem, /* i/o: encoder memories */ + const float speech[], /* i : input speech */ + const float Aw[], /* i : weighted A(z) unquantized for subframes */ + const float Aq[], /* i : 12k8 Lp coefficient */ + const short T_op[], /* i : open loop pitch */ + const float voicing[], /* i : voicing */ + const float *res, /* i : residual signal */ + float *synth, /* i/o: core synthesis */ + float *exc, /* i/o: current non-enhanced excitation */ + float *pitch_buf, /* i/o: floating pitch values for each subframe */ + float *voice_factors, /* o : voicing factors */ + float *bwe_exc, /* o : excitation for SWB TBE */ + const short attack_flag, /* i : Flag that point to an attack coded with AC mode (GSC) */ + const short coder_type, /* i : coding type */ + float *lsf_new, /* i : current frame ISF vector */ + float *tmp_noise /* o : long-term noise energy */ +) +{ + const float *p_Aq; + short i, i_subfr, nb_subfr, last_pit_bin; + short T0_tmp, T0_frac_tmp, nb_subfr_flag; + short tmp_nb_bits_tot; + float Es_pred; + float dct_res[L_FRAME], dct_epit[L_FRAME]; + float m_mean; + float exc_wo_nf[L_FRAME]; + short nb_bits; /*number of bits*/ + int indice; /*parameter indices to write*/ + + m_mean = 0.0f; + tmp_nb_bits_tot = 0; + + T0_tmp = 64; + T0_frac_tmp = 0; + mvr2r( mem->mem_syn, st->mem_syn_tmp, M ); + st->mem_w0_tmp = mem->mem_w0; + Es_pred = 0; + + /*---------------------------------------------------------------* + * Encode GSC attack flag (used to reduce possible pre-echo) + * Encode GSC SWB speech flag + *---------------------------------------------------------------*/ + + push_indice( st, IND_GSC_ATTACK, attack_flag, 1 ); + + if( coder_type != INACTIVE && st->total_brate >= ACELP_13k20 ) + { + push_indice( st,IND_GSC_SWB_SPEECH, st->GSC_noisy_speech, 1); + } + + /*---------------------------------------------------------------* + * Find and encode the number of subframes + *---------------------------------------------------------------*/ + + if ( st->core_brate >= ACELP_9k60 && st->core_brate <= ACELP_13k20 ) + { + for( i = 0; i < 5; i++ ) + { + if( fabs(st->gsc_lt_diff_etot[MAX_LT-i-1]) > 6.0f && st->cor_strong_limit == 1 ) + { + st->cor_strong_limit = 0; + } + } + } + + if( st->GSC_noisy_speech ) + { + nb_subfr = NB_SUBFR; + st->cor_strong_limit = 0; + nb_subfr_flag = 1; + } + else + { + if( (st->cor_strong_limit == 0 || coder_type == INACTIVE) && st->core_brate >= ACELP_9k60 ) + { + nb_subfr = 2; + nb_subfr_flag = 0; + st->cor_strong_limit = 0; + } + else + { + nb_subfr = SWNB_SUBFR; + nb_subfr_flag = 1; + } + + if( st->core_brate >= ACELP_9k60 ) + { + /* nb_subfr_flag can only have the value 0 or 1 */ + push_indice( st, IND_HF_NOISE, nb_subfr_flag, 1); + } + } + + /*---------------------------------------------------------------* + * Compute adaptive (pitch) excitation contribution + *---------------------------------------------------------------*/ + + if( st->GSC_noisy_speech && nb_subfr == NB_SUBFR ) + { + nb_bits = Es_pred_bits_tbl[BIT_ALLOC_IDX(st->core_brate, GENERIC, -1, -1)]; + Es_pred_enc( &Es_pred, &indice, L_FRAME, L_SUBFR, res, voicing, nb_bits, 0 ); + push_indice( st, IND_ES_PRED, indice, nb_bits ); + } + + enc_pit_exc( st, mem, speech, Aw, Aq, Es_pred, T_op, voicing, res, synth, exc, &T0_tmp, &T0_frac_tmp, pitch_buf, nb_subfr, &st->lt_gpitch ); + + /*---------------------------------------------------------------* + * DCT transform + *---------------------------------------------------------------*/ + + edct( exc, dct_epit, L_FRAME ); + edct( res, dct_res, L_FRAME ); + + /*---------------------------------------------------------------* + * Calculate energy dynamics + *---------------------------------------------------------------*/ + + for( i = 7; i < 15; i++ ) + { + m_mean += edyn( dct_res+i*16, 16 ); + } + m_mean *= 0.125f; + + if( m_mean > st->mid_dyn ) + { + st->mid_dyn = 0.2f * st->mid_dyn + 0.8f * m_mean; + } + else + { + st->mid_dyn = 0.6f * st->mid_dyn + 0.4f * m_mean; + } + + if( coder_type != INACTIVE ) + { + st->noise_lev = (NOISE_LEVEL_SP3+1) - usquant(st->mid_dyn, &m_mean, MIN_DYNAMIC, DYNAMIC_RANGE/GSC_NF_STEPS, GSC_NF_STEPS); + if( st->noise_lev > NOISE_LEVEL_SP3) + { + st->noise_lev = NOISE_LEVEL_SP3; + } + } + + st->past_dyn_dec = st->noise_lev; + + if( st->core_brate <= ACELP_8k00 ) + { + if( st->noise_lev <= NOISE_LEVEL_SP2 ) + { + st->noise_lev = NOISE_LEVEL_SP2; + } + + push_indice( st, IND_NOISE_LEVEL, st->noise_lev - NOISE_LEVEL_SP2, 2 ); + } + else if( st->GSC_noisy_speech ) + { + st->noise_lev = NOISE_LEVEL_SP3; + } + else + { + push_indice( st, IND_NOISE_LEVEL, st->noise_lev - NOISE_LEVEL_SP0, 3 ); + } + + /*---------------------------------------------------------------* + * Find and encode the last band where the adaptive (pitch) contribution is significant + *---------------------------------------------------------------*/ + + last_pit_bin = Pit_exc_contribution_len( st, dct_res, dct_epit, pitch_buf, &st->pit_exc_hangover, coder_type ); + + if( last_pit_bin == 0 ) + { + mem->tilt_code = 0.0f; + } + else + { + last_pit_bin++; + } + + /*--------------------------------------------------------------------------------------* + * GSC encoder + *--------------------------------------------------------------------------------------*/ + + /* Find the current total number of bits used */ + tmp_nb_bits_tot = st->nb_bits_tot; + + if( st->extl_brate > 0 ) + { + /* subtract 1 bit for TBE/BWE BWE flag (bit counted in extl_brate) */ + tmp_nb_bits_tot--; + } + + if( coder_type == INACTIVE && st->core_brate <= ACELP_9k60 ) + { + /* add 5 bits for noisiness */ + tmp_nb_bits_tot += 5; + } + + gsc_enc( st, dct_res, dct_epit, last_pit_bin, tmp_nb_bits_tot, nb_subfr, coder_type, lsf_new, exc_wo_nf, tmp_noise ); + + /*--------------------------------------------------------------------------------------* + * iDCT transform + *--------------------------------------------------------------------------------------*/ + + edct( dct_epit, exc, L_FRAME ); + edct( exc_wo_nf, exc_wo_nf, L_FRAME ); + + + /*--------------------------------------------------------------------------------------* + * Remove potential pre-echo in case an onset has been detected + *--------------------------------------------------------------------------------------*/ + + pre_echo_att( &st->Last_frame_ener, exc, attack_flag, st->last_coder_type ); + + /*--------------------------------------------------------------------------------------* + * Update BWE excitation + *--------------------------------------------------------------------------------------*/ + + set_f( voice_factors, 0.0f, NB_SUBFR); + interp_code_5over2( 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->mem_w0_tmp; + mvr2r( exc_wo_nf, exc, L_FRAME ); + + return; +} + +/*-------------------------------------------------------------------* + * gsc_enc() + * + * Generic audio signal encoder + *-------------------------------------------------------------------*/ + +static void gsc_enc( + Encoder_State *st, /* i/o: State structure */ + float res_dct_in[], /* i : dct of residual signal */ + float exc_dct_in[], /* i/o: dct of pitch-only excitation / total excitation */ + const short Diff_len, /* i : Lenght of the difference signal (before pure spectral)*/ + const short bits_used, /* i : Number of bit used before frequency Q */ + const short nb_subfr, /* i : Number of subframe considered */ + const short coder_type, /* i : coding type */ + float *lsf_new, /* i : ISFs at the end of the frame */ + float *exc_wo_nf, /* o : excitation (in f domain) without noisefill */ + float *tmp_noise /* o : long-term noise energy */ +) +{ + short i; + float exc_diffQ[L_FRAME]; + float exc_diff[L_FRAME]; + short bit; + short nb_subbands; + short pvq_len; + short bits_per_bands[MBANDS_GN]; /*Q3*/ + short tmp_band; + float concat_in[L_FRAME]; + float concat_out[L_FRAME]; + short max_ener_band[MBANDS_GN], j; + float Ener_per_bd_iQ[MBANDS_GN]; + short last_bin; + short bitallocation_band[MBANDS_GN]; + short bitallocation_exc[2]; + short npulses[NB_SFM]; + short maxpulse[NB_SFM]; + float mean_gain; + short seed_init; + + /*--------------------------------------------------------------------------------------* + * Initialization + *--------------------------------------------------------------------------------------*/ + + bit = bits_used; + set_f( exc_diffQ, 0.0f, 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) + *--------------------------------------------------------------------------------------*/ + + v_sub( res_dct_in, exc_dct_in, exc_diff, L_FRAME ); + exc_diff[0] = 0; + + /*--------------------------------------------------------------------------------------* + * 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; + } + else + { + tmp_band = st->mem_last_pit_band; + } + + Ener_per_band_comp( exc_diff, Ener_per_bd_iQ, MBANDS_GN, 1 ); + + /*--------------------------------------------------------------------------------------* + * Gain quantizaion + *--------------------------------------------------------------------------------------*/ + + mean_gain = gsc_gainQ( st, Ener_per_bd_iQ, Ener_per_bd_iQ, st->core_brate, coder_type, st->bwidth ); + *tmp_noise = 10.0f * mean_gain; + + /*--------------------------------------------------------------------------------------* + * PVQ encoder + *--------------------------------------------------------------------------------------*/ + + bands_and_bit_alloc( st->cor_strong_limit, st->noise_lev, st->core_brate, 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->bwidth, st->GSC_noisy_speech ); + + set_s( npulses, 0, NB_SFM ); + bit -= pvq_core_enc(st, concat_in, concat_out, bit, nb_subbands, gsc_sfm_start, gsc_sfm_end, gsc_sfm_size, bits_per_bands, NULL, npulses, maxpulse, ACELP_CORE ); + + /* write unused bits */ + while( bit > 0 ) + { + i = min( bit, 16 ); + push_indice( st, IND_UNUSED, 0, i ); + bit -= i; + } + + /* Reorder Q bands */ + last_bin = 0; + set_s( bitallocation_band, 0, MBANDS_GN ); + seed_init = 0; + + for( j = 0; j < nb_subbands; j++ ) + { + mvr2r( concat_out+j*16, exc_diffQ + max_ener_band[j]*16, 16 ); + + if( max_ener_band[j] > last_bin ) + { + last_bin = max_ener_band[j]; + } + + bitallocation_band[max_ener_band[j]] = 1; + + seed_init += npulses[j]; + } + if( st->last_coder_type != AUDIO /* First audio frame */ + && st->last_coder_type != UNVOICED ) /* last_coder_type == INACTIVE is overwritten in update_enc to UNVOICED */ + { + for( j = 0; j < nb_subbands*16; j++ ) + { + if( concat_out[j] > 0 ) + { + seed_init = (short)((int)seed_init<<3); + } + if( concat_out[j] < 0 ) + { + seed_init += 3; + } + } + + st->seed_tcx = seed_init; + } + + if( st->core_brate == ACELP_8k00 && st->bwidth != NB ) + { + bitallocation_exc[0] = 0; + bitallocation_exc[1] = 0; + + if( exc_diffQ[L_FRAME8k - 2] != 0 ) + { + bitallocation_exc[0] = 1; + } + + if( exc_diffQ[L_FRAME8k - 1] != 0 ) + { + bitallocation_exc[1] = 1; + } + } + + /*--------------------------------------------------------------------------------------* + * 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( st->cor_strong_limit, coder_type, st->noise_lev, st->core_brate, exc_diffQ ); + + /*--------------------------------------------------------------------------------------* + * Estimate noise level + *--------------------------------------------------------------------------------------*/ + + highband_exc_dct_in( st->core_brate, mfreq_bindiv_loc, last_bin, Diff_len, st->noise_lev, tmp_band, exc_diffQ, + &st->seed_tcx, Ener_per_bd_iQ, nb_subfr, exc_dct_in, st->last_coder_type, bitallocation_band, lsf_new, + st->last_exc_dct_in, &st->last_ener, st->last_bitallocation_band, bitallocation_exc, 0, coder_type, + st->bwidth, exc_wo_nf, st->GSC_noisy_speech, NULL ); + + exc_dct_in[0] = 0; + + return; +} + +/*---------------------------------------------------------------------* + * edyn() + * + * Calculate energy dynamics in a vector (ratio of energy maximum to energy mean) + *---------------------------------------------------------------------*/ + +static float edyn( /* o : ratio of max to mean */ + const float *vec, /* i : input vector */ + const short lvec /* i : length of input vector */ +) +{ + short j; + float temp, ener_max, ener_mean, dyn; + + ener_mean = 1.0f; + ener_max = 1.0f; + + for( j=0; j ener_max ) + { + ener_max = temp; + } + ener_mean += temp; + } + ener_mean /= lvec; + dyn = 10.0f * (ener_max / ener_mean); + + return dyn; +} diff --git a/lib_enc/guided_plc_enc.c b/lib_enc/guided_plc_enc.c new file mode 100644 index 000000000..1aba33764 --- /dev/null +++ b/lib_enc/guided_plc_enc.c @@ -0,0 +1,368 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "stat_enc.h" +#include "wmc_auto.h" +#include "prot.h" + + +/*-------------------------------------------------------------------* +* coderLookAheadInnovation() +* +* +*-------------------------------------------------------------------*/ + +void coderLookAheadInnovation( + const float A[], /* input: coefficients NxAz[M+1] */ + int *pT, /* out: pitch */ + HANDLE_PLC_ENC_EVS st, /* i/o: coder memory state */ + float *speechLookAhead, + float *old_exc, + int L_subfr, + int L_frame +) +{ + int i; + float *exc, exc_buf[L_EXC_MEM+2*L_SUBFR+8] = { 0.0f }; + int T0=0; + short prev_pitch; + float ps, alp, max_ps; + short subfr_len; + short search_range; + + search_range = 9; + + /* Framing parameters */ + if( L_frame < L_FRAME16k ) + { + subfr_len = (short)(1.75*L_subfr); + } + else + { + subfr_len = (short)(2*L_subfr); + } + + /*------------------------------------------------------------------------* + * Initialize buffers * + *------------------------------------------------------------------------*/ + + /* set excitation memory */ + exc = exc_buf + L_EXC_MEM + 8; + mvr2r( old_exc, exc_buf, L_EXC_MEM+8); + + /*------------------------------------------------------------------------* + * - Get residual signal and target at lookahead part. * + *------------------------------------------------------------------------*/ + + /* find LP residual signal for look-ahead part */ + getLookAheadResSig( speechLookAhead, A, exc, L_frame, L_subfr, M, 2 ); + + /* Initialize excitation buffer */ + prev_pitch = st->T0_4th; + /* find target signals */ + /* find best candidate of pitch lag */ + { + max_ps = -1.0e10; + T0 = st->T0_4th; + for( i=-search_range; ist->pit_max || prev_pitch+ipit_min ) + { + continue; + } + ps = dotp( exc, &exc[-(prev_pitch+i)], subfr_len ); + alp = dotp( &exc[-(prev_pitch+i)], &exc[-(prev_pitch+i)], subfr_len ); + ps /= (float)sqrt( alp + 1.0e-10 ); + if( max_ps < ps ) + { + max_ps = ps; + T0 = prev_pitch + i; + } + } + if( max_ps < 0.0 ) + { + T0 = st->T0_4th; + } + } + + pT[0] = T0; + + return; +} + + +/*-------------------------------------------------------------------* +* enc_prm_side_Info() +* +* +*-------------------------------------------------------------------*/ + +void enc_prm_side_Info( + HANDLE_PLC_ENC_EVS hPlc_Ext, + Encoder_State *st +) +{ + int diff_pitch; + short bits_per_subfr, search_range; + + bits_per_subfr = 4; + search_range = 8; + + if( hPlc_Ext->nBits > 1 ) + { + push_next_indice(st, 1, 1); + + diff_pitch = hPlc_Ext->T0 - hPlc_Ext->T0_4th; + + if( ( diff_pitch > search_range-1 ) || ( diff_pitch < -search_range+1 ) ) + { + diff_pitch = -8; + } + + push_next_indice(st, (diff_pitch+search_range), bits_per_subfr); + } + else + { + push_next_indice(st, 0, 1); + } + + return; +} + +/*-------------------------------------------------------------------* +* encoderSideLossSimulation() +* +* Encoder side loss simulation +*-------------------------------------------------------------------*/ + +void encoderSideLossSimulation( + Encoder_State *st, + HANDLE_PLC_ENC_EVS hPlc_Ext, + float *lsf_q, + float stab_fac, + int calcOnlylsf, + int L_frame +) +{ + float lspLocal[M]; + float const* lsfBase; /* base for differential lsf coding */ + + /************************************************************* + * Decoder state could be stored with memcpy, + * since Decoder_State does not contain pointer member. + *************************************************************/ + + /* Decoder State Update */ + lsf2lsp( lsf_q, lspLocal, M, st->sr_core ); + + lsfBase = PlcGetlsfBase( st->lpcQuantization, st->narrowBand, st->sr_core ); + + mvr2r( st->mem_MA, hPlc_Ext->mem_MA, M ); + + /* lsf parameter processing for concealment */ + updatelsfForConcealment( hPlc_Ext, lsf_q); + hPlc_Ext->stab_fac = stab_fac; + + /* Update Decoder State for the loss simulation at the next frame */ + mvr2r( lsf_q, hPlc_Ext->lsfold, M ); + mvr2r( lspLocal, hPlc_Ext->lspold, M ); + + if (calcOnlylsf) + { + /* lsf concealment simulation */ + getConcealedlsf( hPlc_Ext, lsfBase, L_frame, st->clas); + hPlc_Ext->T0 = hPlc_Ext->T0_4th; + } + else + { + float AqCon[(NB_SUBFR16k+1)*(M+1)]; + float *speechLookAhead; + float old_exc[L_EXC_MEM+8]; + + /* Initialize pointers here */ + mvr2r( hPlc_Ext->old_exc, old_exc, 8 ); + mvr2r( hPlc_Ext->LPDmem->old_exc, &old_exc[8], L_EXC_MEM ); + speechLookAhead = &( st->speech_enc_pe[L_frame] ); + + /* lsf concealment simulation */ + getConcealedLP( hPlc_Ext, AqCon, lsfBase, st->sr_core, st->clas, L_frame); + + /* apply encoder side PLC simulation */ + hPlc_Ext->pit_min = st->pit_min; + hPlc_Ext->pit_max = st->pit_max; + coderLookAheadInnovation( AqCon, &(hPlc_Ext->T0), hPlc_Ext, speechLookAhead, old_exc, L_SUBFR, st->L_frame ); + + } + + return; +} + +/*-------------------------------------------------------------------* +* GplcTcxEncSetup() +* +* +*-------------------------------------------------------------------*/ + +void GplcTcxEncSetup( + Encoder_State *st, + HANDLE_PLC_ENC_EVS hPlc_Ext) +{ + hPlc_Ext->T0_4th = st->tcxltp_pitch_int; + + return; +} + +/*-------------------------------------------------------------------* +* encSideSpecPowDiffuseDetector() +* +* +*-------------------------------------------------------------------*/ + +short encSideSpecPowDiffuseDetector( + float *lsf_ref, + float *lsf_con, + int sr_core, + float *prev_lsf4_mean, + short sw + ,short coder_type +) +{ + float lsf_mod[M]; + float dist1, dist2, cum_dist1, cum_dist2; + float lsf4_mean; + float th; + float th_dif_lsf4_mean; + short idx; + int cnt_imprv, i; + + /* calculate the mean of the lowest 4 lsfs */ + lsf4_mean = 0; + + for(i = 0; i < 4; i++) + { + lsf4_mean += lsf_ref[i]; + } + lsf4_mean /= 4.0f; + + if(sw) + { + mvr2r( lsf_con, lsf_mod, M ); + + modify_lsf( lsf_mod, M, sr_core + , 1 + ); + + cum_dist1 = 0; + cum_dist2 = 0; + + cnt_imprv = 0; + + + for(i = 0; i < M; i++) + { + dist1 = (lsf_con[i] - lsf_ref[i]) * (lsf_con[i] - lsf_ref[i]); + dist2 = (lsf_mod[i] - lsf_ref[i]) * (lsf_mod[i] - lsf_ref[i]); + cum_dist1 += dist1; + cum_dist2 += dist2; + + if(dist1 > dist2) + { + cnt_imprv++; + } + } + + th = 800; + th_dif_lsf4_mean = 90; + + if(sr_core == 16000) + { + th *= 1.25; + th_dif_lsf4_mean *= 1.25; + } + + + if(cum_dist1 > cum_dist2 * 1.15 + && lsf4_mean - *prev_lsf4_mean > th_dif_lsf4_mean + && *prev_lsf4_mean < th + && cnt_imprv > 2 + && coder_type == GENERIC + ) + { + idx = 1; + } + else + { + idx = 0; + } + } + else + { + idx = 0; + } + + /* update parameters */ + *prev_lsf4_mean = lsf4_mean; + + return idx; +} + +/*-------------------------------------------------------------------* +* updateSpecPowDiffuseIdx() +* +* +*-------------------------------------------------------------------*/ + +void updateSpecPowDiffuseIdx( + Encoder_State *st, + const float gain_pitch_buf[], /* i : gain pitch values */ + const float gain_code_buf[] /* i : gain pitch values */ +) +{ + float min_gp; + int k; + + st->mean_gc[1] = gain_code_buf[0]; + min_gp = gain_pitch_buf[0]; + + for(k = 1; k < 4; k++) + { + st->mean_gc[1] += gain_code_buf[k]; + + if( gain_pitch_buf[k] < min_gp ) + { + min_gp = gain_pitch_buf[k]; + } + } + + if(st->mean_gc[1] / (st->mean_gc[0] + 1e-6) < 1.098 || min_gp > 0.82) + { + st->glr_idx [0]= 0; + } + st->mean_gc[0] = st->mean_gc[1]; + + return; +} + + +/*-------------------------------------------------------------------* +* getConcealedlsf() +* +* +*-------------------------------------------------------------------*/ + +void getConcealedlsf( + HANDLE_PLC_ENC_EVS memDecState, + const float lsfBase[], + int L_frame, + int last_good +) +{ + float *lsf = memDecState->lsf_con; + + dlpc_bfi( L_frame, &lsf[0], memDecState->lsfold, last_good, + 1 /*assumes packet loss */, memDecState->mem_MA, memDecState->mem_AR, &(memDecState->stab_fac), memDecState->lsf_adaptive_mean, + 1, NULL, 0, NULL, NULL, lsfBase); + + return; +} diff --git a/lib_enc/hf_cod_amrwb.c b/lib_enc/hf_cod_amrwb.c new file mode 100644 index 000000000..dbe7b8e6f --- /dev/null +++ b/lib_enc/hf_cod_amrwb.c @@ -0,0 +1,306 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ + +static void hp400_12k8(float signal[], const short lg, float mem[]); +static void filt_6k_8k(float signal[], const short lg, float mem[]); + +/*---------------------------------------------------------------------* + * hf_cod_init() + * + * + *---------------------------------------------------------------------*/ + +void hf_cod_init( + float *mem_hp400_enc, /* o: memory of hp 400 Hz filter */ + float *mem_hf1_enc, /* o: HF band-pass filter memory */ + float *mem_syn_hf_enc, /* o: HF synthesis memory */ + float *mem_hf2_enc, /* o: HF band-pass filter memory */ + float *gain_alpha /* o: smoothing gain for transitions between active and inactive frames */ +) +{ + set_f( mem_hp400_enc, 0, 4 ); + set_f( mem_hf1_enc, 0, L_FIR-1 ); + set_f( mem_syn_hf_enc, 0, M ); + set_f( mem_hf2_enc, 0, L_FIR-1 ); + *gain_alpha = 1.0; + + return; +} + + +/*---------------------------------------------------------------------* + * hf_cod() + * + * + *---------------------------------------------------------------------*/ + +void hf_cod( + const long core_brate, /* i : core bitrate */ + const float *speech16k, /* i : original speech at 16 kHz */ + const float Aq[], /* i : quantized Aq */ + const float exc[], /* i : excitation at 12.8 kHz */ + float synth[], /* i : 12.8kHz synthesis signal */ + short *seed2_enc, /* i/o: random seed for HF noise gen */ + float *mem_hp400_enc, /* i/o: memory of hp 400 Hz filter */ + float *mem_syn_hf_enc, /* i/o: HF synthesis memory */ + float *mem_hf1_enc, /* i/o: HF band-pass filter memory */ + float *mem_hf2_enc, /* i/o: HF band-pass filter memory */ + const short *dtxHangoverCount, + float *gain_alpha, /* i/o: smoothing gain for transitions between active and inactive frames */ + short *hf_gain /* o : HF gain to be transmitted to decoder */ +) +{ + short i; + float ener_hf, ener_exc, ener_input, fac, HF_syn[L_SUBFR16k], tmp, ener, scale; + float Ap[M16k+1]; + float HF_SP[L_SUBFR16k]; + float HF_est_gain; + float HF_calc_gain; + float HF_corr_gain; + short HF_gain_ind; + float dist_min, dist; + float HF[L_SUBFR16k]; /* o : HF excitation */ + + /* Original speech signal as reference for high band gain quantisation */ + for (i = 0; i < L_SUBFR16k; i++) + { + HF_SP[i] = speech16k[i]; + } + + /*-----------------------------------------------------------------* + * generate white noise vector + *-----------------------------------------------------------------*/ + + for (i=0; i 1.0f) /* this condition is not in G.722.2, but in AMR-WB!*/ + { + HF_est_gain = 1.0f; + } + + /*-----------------------------------------------------------------* + * synthesis of noise: 4.8kHz..5.6kHz --> 6kHz..7kHz + *-----------------------------------------------------------------*/ + + weight_a( Aq, Ap, 0.6f, M ); + syn_filt( Ap, M, HF, HF_syn, L_SUBFR16k, mem_syn_hf_enc, 1 ); + + /*-----------------------------------------------------------------* + * high pass filtering (0.9375ms of delay = 15 samples@16k) + *-----------------------------------------------------------------*/ + + filt_6k_8k( HF_syn, L_SUBFR16k, mem_hf1_enc ); + + /* filtering of the original signal */ + filt_6k_8k( HF_SP, L_SUBFR16k, mem_hf2_enc ); + + /* check the gain difference */ + ener_input = 0.01f; + ener_hf = 0.01f; + for ( i=0; i 6) + { + *gain_alpha = 1.0f; + } + + HF_corr_gain = (*gain_alpha)*HF_calc_gain + (1.0f-(*gain_alpha))*HF_est_gain; + HF_corr_gain /= 2.0f; /* to stay in alignlent with AMR-WB legacy decoder where decoded gain is multiplied by 2 */ + + /* Quantize the correction gain */ + dist_min = 100000.0f; + HF_gain_ind = 0; + for ( i = 0; i < 16; i++ ) + { + dist = (HF_corr_gain-HP_gain[i])*(HF_corr_gain-HP_gain[i]); + if (dist_min > dist) + { + dist_min = dist; + HF_gain_ind = i; + } + } + + *hf_gain = HF_gain_ind; + + return; +} + +/*-----------------------------------------------------------------------* + * Function hp400_12k8() * + * * + * 2nd order Cheb2 high pass filter with cut off frequency at 400 Hz. * + * Optimized for fixed-point to get the following frequency response : * + * * + * frequency : 0Hz 100Hz 200Hz 300Hz 400Hz 630Hz 1.5kHz 3kHz * + * dB loss : -infdB -30dB -20dB -10dB -3dB +6dB +1dB 0dB * + * * + * Algorithm : * + * * + * y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] * + * + a[1]*y[i-1] + a[2]*y[i-2]; * + * * + * short b[3] = {3660, -7320, 3660}; in Q12 * + * short a[3] = {4096, 7320, -3540}; in Q12 * + * * + * float --> b[3] = {0.893554687, -1.787109375, 0.893554687}; * + * a[3] = {1.000000000, 1.787109375, -0.864257812}; * + *-----------------------------------------------------------------------*/ + +static void hp400_12k8( + float signal[], /* i/o: signal */ + const short lg, /* i : lenght of signal */ + float mem[] /* i/o: filter memory [4] */ +) +{ + short i; + float x0, x1, x2; + float yy0, yy1, y2; + + yy1 = mem[0]; + y2 = mem[1]; + x0 = mem[2]; + x1 = mem[3]; + for(i=0; i +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*-----------------------------------------------------------------* + * Local constants + *-----------------------------------------------------------------*/ + +#define SHARP_DIST_THRES 22.2f + +/*-----------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------*/ + +static void hvq_classifier( const float *input, short *prev_Npeaks, short *prev_peaks, + short *hqswb_clas, short *Npeaks, short *peaks, const long core_brate, + const short last_core, float *nf_gains, short *hvq_hangover, float *pe_gains ); + +/*--------------------------------------------------------------------------* + * hq_classifier_enc() + * + * HQ mode selector (decision_matrix) + *--------------------------------------------------------------------------*/ + +short hq_classifier_enc( /* o : Consumed bits */ + Encoder_State *st, /* i/o: encoder state structure */ + const short length, /* i : Frame length */ + const float *coefs, /* i : Spectral coefficients */ + const short is_transient, /* i : Transient flag */ + short *Npeaks, /* o : Number of identified peaks */ + short *peaks, /* o : Peak indices */ + float *pe_gains, /* o : Peak gains */ + float *nf_gains, /* o : Noise-fill gains */ + short *hqswb_clas /* o : HQ class */ +) +{ + short bits; + + *hqswb_clas = HQ_NORMAL; + if( is_transient ) + { + *hqswb_clas = HQ_TRANSIENT; + } + else if( length == L_FRAME32k && st->core_brate <= HQ_32k && st->bwidth == st->last_bwidth ) + { + /* Detect HQ_HARMONIC mode */ + *hqswb_clas = peak_avrg_ratio( st->total_brate, coefs, NUMC_N+96, &st->mode_count, &st->mode_count1 ); + + /* Detect HQ_HVQ mode */ + hvq_classifier( coefs, &st->prev_Npeaks, st->prev_peaks, hqswb_clas, Npeaks, peaks, st->core_brate, st->last_core, + nf_gains, &st->hvq_hangover, pe_gains ); + } + else if ( length == L_FRAME48k && st->core_brate <= HQ_32k && st->bwidth == st->last_bwidth ) + { + /* Detect HQ_HARMONIC mode */ + *hqswb_clas = peak_avrg_ratio( st->total_brate, coefs, NUMC_N+96, &st->mode_count, &st->mode_count1 ); + /* Detect HQ_HVQ mode */ + hvq_classifier( coefs, &st->prev_Npeaks, st->prev_peaks, hqswb_clas, Npeaks, peaks, st->core_brate, st->last_core, + nf_gains, &st->hvq_hangover, pe_gains ); + } + if( length == L_FRAME48k && st->core_brate <= HQ_32k && *hqswb_clas == HQ_NORMAL) + { + *hqswb_clas = HQ_GEN_FB; + } + /* set the required number of bits for signalling */ + if( length >= L_FRAME32k && st->core_brate <= HQ_32k ) + { + bits = 2; + } + else + { + bits = 1; + } + + /* write signalling info to the bitstream */ + if ( length == L_FRAME48k && st->core_brate <= HQ_32k ) + { + if ( *hqswb_clas >= HQ_GEN_SWB) + { + push_indice( st, IND_HQ_SWB_CLAS, *hqswb_clas - 5, bits ); + } + else + { + push_indice( st, IND_HQ_SWB_CLAS, *hqswb_clas, bits ); + } + } + else + { + push_indice( st, IND_HQ_SWB_CLAS, *hqswb_clas, bits ); + } + + if ( *hqswb_clas == HQ_NORMAL && length == L_FRAME32k && st->core_brate <= HQ_32k ) + { + *hqswb_clas = HQ_GEN_SWB; + } + + return bits; +} + +/*--------------------------------------------------------------------------* + * peak_avrg_ratio() + * + * Classify the input signal and decide if it has a harmonic structure + *--------------------------------------------------------------------------*/ +short peak_avrg_ratio( + const long total_brate, + const float *input_hi, /* i : input signal */ + const short N, /* i : number of coefficients */ + short *mode_count, /* i/o: HQ_HARMONIC mode count */ + short *mode_count1 /* i/o: HQ_NORMAL mode count */ +) +{ + float mean, peak, sharp; + short i, j, q, k, k1, hqswb_clas; + float input_abs[L_FRAME32k]; + + for ( i = 96; i < N; i++) + { + input_abs[i] = (float) fabs(input_hi[i]); + } + + hqswb_clas = HQ_NORMAL; + + k = 0; + k1 = 0; + q = 96; + for( i = 3; i < 17; i++ ) + { + peak = 0.0f; + mean = EPSILON; + for(j = 0; j < 32; j++, q++) + { + mean += input_abs[q]; + + if ( input_abs[q] > peak ) + { + peak = input_abs[q]; + } + } + + sharp = 32 * peak / mean; + + if( i < 8 ) + { + if( sharp > 4.5 ) + { + k += 1; + } + } + else + { + if( sharp > 3.6 && peak > 10 ) + { + k1 += 1; + } + } + } + + if( k + k1 >= 10 && k1 > 5 ) + { + if( *mode_count < 8 ) + { + (*mode_count)++; + } + + if( *mode_count1 > 0 ) + { + (*mode_count1)--; + } + } + else + { + if( *mode_count > 0 ) + { + (*mode_count)--; + } + + if( *mode_count1 < 8 ) + { + (*mode_count1)++; + } + } + if( (k + k1 >= 5 && k1 > 2 && total_brate == HQ_24k40) || (((k + k1 >= 10 && k1 > 5) || *mode_count >= 5) && *mode_count1 < 5) ) + { + hqswb_clas = HQ_HARMONIC; + } + + return hqswb_clas; +} + + +/*--------------------------------------------------------------------------* + * hvq_classifier() + * + * Classification of spectral content for HQ_HVQ mode + *--------------------------------------------------------------------------*/ + +static void hvq_classifier( + const float *input, /* i : input signal */ + short *prev_Npeaks, /* i/o: Peak number memory */ + short *prev_peaks, /* i/o: Peak indices memory */ + short *hqswb_clas, /* i/o: HQ class */ + short *Npeaks, /* o : Number of peaks */ + short *peaks, /* o : Peak indices */ + const long core_brate, /* i : Core bit-rate */ + const short last_core, /* i : Last core used */ + float *nf_gains, /* o : Noisefloor gains */ + short *hvq_hangover, /* i/o: Mode-switch hangover */ + float *pe_gains /* o : peak gains */ +) +{ + const float *p_adj; + float sharp_dist; + float nf, pe, d, peak, thr_tmp, m; + float input_abs[L_FRAME32k], thr[L_FRAME16k]; + float pe_mean[HVQ_NSUB_32k], nf_mean[HVQ_NSUB_32k]; + float sharp[HVQ_NSUB_32k]; + + short num_sharp_bands, i, j, k, q, peak_th, nsub, pindx, N, offset; + short num_peak_cands, high, low; + short peak_cand_idx[HVQ_THRES_BIN_32k], avail_peaks[HVQ_NSUB_32k]; + + if( *hqswb_clas == HQ_HARMONIC && last_core != ACELP_CORE && last_core != AMR_WB_CORE ) + { + set_f(thr, 0.0f, L_FRAME16k); + if( core_brate == HQ_24k40 ) + { + nsub = HVQ_NSUB_24k; + } + else + { + nsub = HVQ_NSUB_32k; + } + + N = nsub * HVQ_BW; + + for( i = 0; i < N; i++ ) + { + input_abs[i] = (float) fabs(input[i]); + } + + *Npeaks = 0; + nf = 800; + pe = 800; + num_sharp_bands = 0; + k = 0; + q = 0; + sharp_dist = 0; + + /* Find peak threshold */ + for( i = 0; i < nsub; i++ ) + { + peak = 0.0f; + nf_mean[i] = EPSILON; + pe_mean[i] = EPSILON; + for( j = 0; j < HVQ_BW; j++, q++ ) + { + d = input_abs[q]; + + if( d > nf ) + { + nf = HVQ_NF_WEIGHT1 * nf + (1 - HVQ_NF_WEIGHT1) * d; + } + else + { + nf = HVQ_NF_WEIGHT2 * nf + (1 - HVQ_NF_WEIGHT2) * d; + } + + if( d > pe ) + { + pe = HVQ_PE_WEIGHT1 * pe + (1 - HVQ_PE_WEIGHT1) * d; + } + else + { + pe = HVQ_PE_WEIGHT2 * pe + (1 - HVQ_PE_WEIGHT2) * d; + } + + nf_mean[i] += nf; + pe_mean[i] += pe; + + if( d > peak ) + { + peak = d; + } + } + + nf_mean[i] /= HVQ_BW; + pe_mean[i] /= HVQ_BW; + + + thr_tmp = (float)pow( pe_mean[i]/nf_mean[i], HVQ_THR_POW ) * nf_mean[i]; + set_f( &thr[k], thr_tmp, HVQ_BW ); + k += HVQ_BW; + + sharp[i] = peak / nf_mean[i]; + sharp_dist += sharp[i] - HVQ_SHARP_THRES; + + if( sharp[i] > HVQ_SHARP_THRES ) + { + num_sharp_bands++; + } + } + + /* Estimate noise floor gains */ + offset = nsub % 2; + for( i = 0; i < 2*(nsub/2); i++ ) + { + nf_gains[(2*i+1)/nsub] += nf_mean[i+offset]; + pe_gains[(2*i+1)/nsub] += pe_mean[i+offset]; + } + + for( i = 0; i < HVQ_NF_GROUPS; i++ ) + { + nf_gains[i] /= nsub/HVQ_NF_GROUPS; + pe_gains[i] /= nsub/HVQ_NF_GROUPS; + } + + /* Allocate available peaks */ + for( i = 0; i < nsub; i++ ) + { + avail_peaks[i] = HVQ_PA_PEAKS_SHARP1; + if( nf_mean[i] < nf_gains[(2*i+1)/nsub] * HVQ_PA_FAC ) + { + if( sharp[i] < HVQ_PA_SHARP_THRES3 ) + { + avail_peaks[i] = HVQ_PA_PEAKS_SHARP3; + } + else if( sharp[i] < HVQ_PA_SHARP_THRES2 ) + { + avail_peaks[i] = HVQ_PA_PEAKS_SHARP2; + } + } + } + + /* Adjust threshold around previous peaks */ + for( i = 0; i < *prev_Npeaks; i++ ) + { + j = prev_peaks[i] - 2; + k = prev_peaks[i] + 2; + p_adj = hvq_thr_adj; + + for( q = j; q < k; q++ ) + { + thr[q] *= *p_adj++; + } + } + + num_peak_cands = 0; + + /* Remove everything below threshold for peak search */ + input_abs[0] = 0; + input_abs[1] = 0; + input_abs[N-2] = 0; + input_abs[N-1] = 0; + for( i = 0; i < N-2; i++ ) + { + if( input_abs[i] < thr[i] ) + { + input_abs[i] = 0; + } + else + { + input_abs[num_peak_cands] = input_abs[i]; + peak_cand_idx[num_peak_cands] = i; + num_peak_cands++; + } + } + + if( core_brate == HQ_24k40 ) + { + peak_th = HVQ_MAX_PEAKS_24k_CLAS; + } + else + { + peak_th = HVQ_MAX_PEAKS_32k; + } + + /* Find peaks */ + pindx = maximum( input_abs, num_peak_cands, &m ); + i = 0; + + while( m > 0 && i < peak_th+1) + { + if( avail_peaks[peak_cand_idx[pindx]/HVQ_BW] > 0 ) + { + peaks[i++] = peak_cand_idx[pindx]; + avail_peaks[peak_cand_idx[pindx]/HVQ_BW]--; + } + + j = pindx - 2; + k = pindx + 2; + + if( j < 0 ) + { + j = 0; + } + + if( k > num_peak_cands-1 ) + { + k = num_peak_cands-1; + } + + low = peak_cand_idx[pindx] - 2; + high = peak_cand_idx[pindx] + 2; + + if( low < 0 ) + { + low = 0; + } + + if( high > N-1 ) + { + high = N-1; + } + + for( q = j; q <= pindx; q++ ) + { + if( peak_cand_idx[q] >= low ) + { + peak_cand_idx[q] = 0; + input_abs[q] = 0; + } + } + + for( q = pindx + 1; q <= k; q++ ) + { + if( peak_cand_idx[q] <= high ) + { + peak_cand_idx[q] = 0; + input_abs[q] = 0; + } + } + + pindx = maximum(input_abs, num_peak_cands, &m); + } + + *Npeaks = i; + + /* decision about HQ_HVQ mode */ + if (*Npeaks > HVQ_MIN_PEAKS) + { + if( num_sharp_bands > nsub - 3 && *Npeaks <= peak_th ) + { + sharp_dist /= nsub; + if( sharp_dist <= SHARP_DIST_THRES && *hvq_hangover < 0 ) + { + (*hvq_hangover)++; + } + else + { + *hqswb_clas = HQ_HVQ; + *hvq_hangover = 2; + } + + /* update memory */ + *prev_Npeaks = *Npeaks; + mvs2s( peaks, prev_peaks, *Npeaks ); + } + else + { + if( *hvq_hangover > 0 ) + { + *hqswb_clas = HQ_HVQ; + (*hvq_hangover)--; + } + else + { + *hvq_hangover = -1; + } + } + } + else + { + *hvq_hangover = -1; + } + + + if( core_brate == HQ_24k40 ) + { + *Npeaks = min( HVQ_MAX_PEAKS_24k, *Npeaks ); + } + else + { + *Npeaks = min( HVQ_MAX_PEAKS_32k, *Npeaks ); + } + } + else + { + *prev_Npeaks = 0; + *hvq_hangover = 0; + } + + return; +} diff --git a/lib_enc/hq_core_enc.c b/lib_enc/hq_core_enc.c new file mode 100644 index 000000000..0c367b0b8 --- /dev/null +++ b/lib_enc/hq_core_enc.c @@ -0,0 +1,158 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*-------------------------------------------------------------------------- + * hq_core_enc() + * + * HQ core encoder + *--------------------------------------------------------------------------*/ + +void hq_core_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const float *audio, /* i : input audio signal */ + const short input_frame_orig,/* i : frame length */ + const short hq_core_type, /* i : HQ core type */ + const short Voicing_flag /* i : HQ core voicing flag */ +) +{ + short i, is_transient, num_bits, extra_unused; + float wtda_audio[2 * L_FRAME48k]; + float t_audio[L_FRAME48k]; + short inner_frame, input_frame; + float ener_match; + + + set_f( t_audio, 0, L_FRAME48k ); + st->Nb_ACELP_frames = 0; + + /* set input_frame length */ + input_frame = input_frame_orig; + + st->tcx_cfg.tcx_last_overlap_mode = st->tcx_cfg.tcx_curr_overlap_mode; + st->tcx_cfg.tcx_curr_overlap_mode = ALDO_WINDOW; + + /*-------------------------------------------------------------------------- + * 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); + extra_unused = 0; + + /*-------------------------------------------------------------------------- + * Detect signal transition + *--------------------------------------------------------------------------*/ + + is_transient = detect_transient( audio, st, input_frame, HQ_CORE ); + + /*-------------------------------------------------------------------------- + * Windowing and time-domain aliasing + * DCT transform + *--------------------------------------------------------------------------*/ + + wtda( audio, wtda_audio, NULL, st->tcx_cfg.tcx_last_overlap_mode, st->tcx_cfg.tcx_curr_overlap_mode, input_frame ); + + if ( st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE ) + { + /* Preprocessing in the first HQ frame after ACELP frame */ + core_switching_hq_prepare_enc( st, &num_bits, input_frame, wtda_audio, audio ); + + /* During ACELP->HQ core switching, limit the HQ core bitrate to 48kbps */ + if( num_bits > HQ_48k / 50 ) + { + extra_unused = num_bits - (short)(HQ_48k / 50); + num_bits = (short)(HQ_48k / 50); + } + } + /* subtract signalling bits */ + num_bits -= st->nb_bits_tot; + direct_transform( wtda_audio, t_audio, is_transient, input_frame ); + + /* scale coefficients to their nominal level (8kHz) */ + if( input_frame != NORM_MDCT_FACTOR ) + { + ener_match = (float)sqrt((float)NORM_MDCT_FACTOR/(float)input_frame); + + for( i=0; ibwidth]; + + if( input_frame > inner_frame ) + { + if( is_transient ) + { + for( i = 1; i < NUM_TIME_SWITCHING_BLOCKS; i++ ) + { + mvr2r( t_audio + i*input_frame/NUM_TIME_SWITCHING_BLOCKS, t_audio + i*inner_frame/NUM_TIME_SWITCHING_BLOCKS, inner_frame/NUM_TIME_SWITCHING_BLOCKS ); + } + } + + set_f( t_audio + inner_frame, 0.0f, input_frame - inner_frame ); + } + + /*-------------------------------------------------------------------------- + * Classify whether to put extra bits for FER mitigation + *--------------------------------------------------------------------------*/ + + if( st->last_core == HQ_CORE && st->core_brate > MINIMUM_RATE_TO_ENCODE_VOICING_FLAG ) + { + if ( Voicing_flag > 0 ) + { + push_indice( st, IND_HQ_VOICING_FLAG, 1, 1 ); + num_bits -= 1; + } + else + { + push_indice( st, IND_HQ_VOICING_FLAG, 0, 1 ); + num_bits -= 1; + } + } + + /*-------------------------------------------------------------------------- + * Transform-domain encoding + *--------------------------------------------------------------------------*/ + + if( hq_core_type == LOW_RATE_HQ_CORE ) + { + /* HQ low rate encoder */ + hq_lr_enc( st, t_audio, inner_frame, &num_bits, is_transient ); + } + else + { + /* HQ high rate encoder */ + hq_hr_enc( st, t_audio, inner_frame, &num_bits, is_transient ); + } + + /* write all unused bits to the bitstream */ + num_bits += extra_unused; + + while( num_bits >= 16 ) + { + push_indice( st, IND_UNUSED, 0, 16 ); + num_bits -= 16; + } + + if( num_bits != 0 ) + { + push_indice( st, IND_UNUSED, 0, num_bits ); + } + + + + + return; +} diff --git a/lib_enc/hq_env_enc.c b/lib_enc/hq_env_enc.c new file mode 100644 index 000000000..cbaa2ecb2 --- /dev/null +++ b/lib_enc/hq_env_enc.c @@ -0,0 +1,529 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "prot.h" +#include "rom_com.h" +#include "rom_enc.h" + +/*--------------------------------------------------------------------------------------* + * encode_envelope_indices() + * + * Encode envelope indices + *--------------------------------------------------------------------------------------*/ + +short encode_envelope_indices( /* o : Number of bits if flag_pack=0,0 if flag_pack=1 */ + Encoder_State *st, /* i/o: encoder state structure */ + const short num_sfm, /* i : Number of subbands */ + const short numnrmibits, /* i : Bitrate of fall-back coding mode */ + short *difidx, /* i/o: Diff indices/encoded diff indices */ + short *LCmode, /* o : Coding mode if flag_pack=0, i : if flag_pack=1 */ + const short flag_pack, /* i : indicator of packing or estimating bits */ + const short flag_HQ2, /* i : indicator of HQ2 core */ + const short is_transient /* i : transient flag */ +) +{ + short bits; + short prevj; + short hcode_l; + short i,j; + short difidx_flag; + short index_max, index_min, index_rad; + short difidx_org[NB_SFM]; /* lenght of this buffer is max(BANDS_MAX,NB_SFM) */ + short m, r; + short v, k; + + set_s( difidx_org, 0, NB_SFM ); + difidx_flag = 0; + + /*------------------------------------------------------------------* + * 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 ) + { + if(is_transient && flag_HQ2 == LOW_RATE_HQ_CORE_TRAN) + { + bits = 0; + index_max = 0; + index_min = 31; + for( i = 0; i< num_sfm; i++ ) + { + if( difidx[i] > index_max ) + { + index_max = difidx[i]; + } + if( difidx[i] < index_min ) + { + index_min = difidx[i]; + } + } + if(index_min > 10 && index_max < 22) + { + for( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + bits += huffsizn_tran[j]; + } + } + hcode_l= 0; + *LCmode = 0; + prevj = difidx[0] + OFFSET_NORM; + /* LC mode 0 = Context based coding */ + for( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + if( prevj>HTH_NORM ) + { + /* above */ + hcode_l += huffsizn_n[31-j]; + } + else + { + if( prevj= bits && bits !=0) + { + /* LC mode 1 Transient Huffman Coding */ + *LCmode = 1; + hcode_l = bits; + } + } + else + { + /* Check bits if LC mode == 3 -> Check bits if LC mode == 0 */ + hcode_l= 0; + prevj = difidx[0] + OFFSET_NORM; + for( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + if( prevj>HTH_NORM ) + { + /* above */ + hcode_l += huffsizn_n[31-j]; + } + else + { + if( prevj Check bits if LC mode == 2 */ + bits = 0; + for( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + bits += huffsizn[j]; + } + + /*------------------------------------------------------------------------------* + * comparing bit expenses of coding mode 2 with that of the optimal coding mode + *------------------------------------------------------------------------------*/ + + if( hcode_l > bits ) + { + *LCmode = 2; + hcode_l = bits; + } + } + + /* Check bits if LC mode == 2 -> Check bits if LC mode == 1 */ + bits = 0; + index_max = 0; + index_min = 31; + for( i = 1; i < num_sfm; i++ ) + { + difidx_org[i] = difidx[i]; + } + + difidx_flag = 0; + for( i = 2; i < num_sfm; i++ ) + { + if( difidx_org[i-1] > 17 ) + { + difidx[i] = difidx_org[i] + min((difidx_org[i-1]-17),3); + if( difidx[i] > 31 ) + { + difidx_flag = 1; + break; + } + } + + if( difidx_org[i-1] < 13 ) + { + difidx[i] = difidx_org[i] + max((difidx_org[i-1]-13),-3); + if( difidx[i] < 0 ) + { + difidx_flag = 1; + break; + } + } + } + + index_rad = 0; + if( difidx_flag != 1 ) + { + for( i = 1; i< num_sfm; i++ ) + { + if( difidx[i] > index_max ) + { + index_max = difidx[i]; + } + + if( difidx[i] < index_min ) + { + index_min = difidx[i]; + } + } + + index_rad = max((15 - index_min),(index_max - 15)); + + if( index_rad <= HUFF_THR ) + { + for( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + bits += resize_huffsizn[j]; + } + + /*------------------------------------------------------------------* + * comparing bit expenses of coding mode 1 with that of coding mode 0 + *------------------------------------------------------------------*/ + + if( hcode_l > bits ) + { + hcode_l = bits; + *LCmode = 1; + } + } + } + + /* 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( hcode_l >= numnrmibits ) + { + hcode_l = numnrmibits; + *LCmode = 3; + } + } + + if( (*LCmode != 1 && flag_HQ2 == NORMAL_HQ_CORE ) || flag_HQ2 == LOW_RATE_HQ_CORE ) + { + for(i = 2; i< num_sfm; i++) + { + difidx[i] = difidx_org[i]; + } + } + } + } + else + { + if(flag_HQ2 == LOW_RATE_HQ_CORE_TRAN || flag_HQ2 == LOW_RATE_HQ_CORE) + { + push_indice( st, IND_HQ2_DENG_HMODE, *LCmode, BITS_DE_HMODE); + push_indice( st, IND_HQ2_DIFF_ENERGY, difidx[0], BITS_DE_FCOMP); + } + else + { + push_indice( st, IND_LC_MODE, *LCmode, 2 ); + push_indice( st, IND_YNRM, difidx[0], NORM0_BITS ); + } + + if(is_transient && flag_HQ2 == LOW_RATE_HQ_CORE_TRAN) + { + hcode_l = 0; + if ( *LCmode == 1 ) + { + /* LC mode 0 Transient Huffman Coding */ + for( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + m = huffnorm_tran[j]; + r = huffsizn_tran[j]; + v = 0; + + /* Bit reverse */ + for( k = 0; k < r; k++ ) + { + v <<= 1; + v |= m & 1; + m >>= 1; + } + + push_indice(st,IND_HQ2_DIFF_ENERGY, v, r); + } + } + else + { + /* LC mode 1 context based Coding */ + prevj = difidx[0] + OFFSET_NORM; + for( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + + if( prevj > HTH_NORM ) + { + /* above */ + r = huffsizn_n[31-j]; + m = huffnorm_n[31-j]; + } + else + { + if( prevj LC mode 0 */ + prevj = difidx[0] + OFFSET_NORM; + for( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + + if( prevj > HTH_NORM ) + { + /* above */ + r = huffsizn_n[31-j]; + m = huffnorm_n[31-j]; + } + else + { + if( prevj 17) + { + difidx[i] = difidx_org[i] + min((difidx_org[i-1]-17),3); + if(difidx[i] > 31) + { + difidx_flag = 1; + break; + } + } + + if(difidx_org[i-1] < 13) + { + difidx[i] = difidx_org[i] + max((difidx_org[i-1]-13),-3); + if(difidx[i] < 0) + { + difidx_flag = 1; + break; + } + } + } + + if( difidx_flag != 1 ) + { + for(i = 1; i< num_sfm; i++) + { + if(difidx[i]>index_max) + { + index_max = difidx[i]; + } + + if(difidx[i] LC mode 1 */ + for( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + + m = resize_huffnorm[j]; + r = resize_huffsizn[j]; + v = 0; + + /* Bit reverse */ + for( k = 0; k < r; k++ ) + { + v <<= 1; + v |= m & 1; + m >>= 1; + } + + if ( flag_HQ2 ) + { + push_indice( st,IND_HQ2_DIFF_ENERGY, v, r); + } + else + { + push_indice( st, IND_YNRM, v, r ); + } + } + } + else if( *LCmode == 2 ) + { + /* LC mode 1 -> LC mode 2 */ + for( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + + m = huffnorm[j]; + r = huffsizn[j]; + + push_indice( st, IND_YNRM, m, r ); + } + } + else + { + for( i = 1; i < num_sfm; i++ ) + { + push_indice( st, IND_YNRM, difidx[i], NORMI_BITS ); + } + } + } + } + + return hcode_l; +} + +/*--------------------------------------------------------------------------* + * diff_envelope_coding() + * + * Create differential code of norm indices + *--------------------------------------------------------------------------*/ + +void diff_envelope_coding( + const short is_transient, /* i : transient indicator */ + const short num_env_bands, /* i : number of envelope bands to code */ + const short start_norm, /* i : start of envelope coding */ + short *ynrm, /* i/o: quantization indices for norms */ + short *normqlg2, /* i/o: quantized norms */ + short *difidx /* o : differential code */ +) +{ + short i; + short idxbuf[NB_SFM]; + short normbuf[NB_SFM]; + + /* Differential coding for indices of quantized norms */ + if( is_transient ) + { + /* Reorder quantization indices and quantized norms */ + reordernorm( ynrm, normqlg2, idxbuf, normbuf, num_env_bands ); + diffcod( num_env_bands, idxbuf, &difidx[1] ); + difidx[0] = idxbuf[0]; + recovernorm( idxbuf, ynrm, normqlg2, num_env_bands ); + } + else + { + diffcod( num_env_bands, &ynrm[start_norm], &difidx[1] ); + difidx[0] = ynrm[start_norm]; + + for( i = start_norm; i < start_norm + num_env_bands; i++ ) + { + normqlg2[i] = dicnlg2[ynrm[i]]; + } + } + + return; +} diff --git a/lib_enc/hq_hr_enc.c b/lib_enc/hq_hr_enc.c new file mode 100644 index 000000000..f077d8701 --- /dev/null +++ b/lib_enc/hq_hr_enc.c @@ -0,0 +1,197 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_enc.h" +#include "rom_com.h" + +/*--------------------------------------------------------------------------* + * hq_hr_enc() + * + * HQ high rate encoding routine + *--------------------------------------------------------------------------*/ + +void hq_hr_enc( + Encoder_State *st, /* i/o: encoder state structure */ + float *t_audio, /* i/o: transform-domain coefficients */ + const short length, /* i : length of spectrum */ + short *num_bits, /* i : number of available bits */ + const short is_transient /* i : transient flag */ +) +{ + short nb_sfm; + short sum, hcode_l; + short difidx[NB_SFM]; + short normqlg2[NB_SFM], ynrm[NB_SFM]; + short nf_idx; + short LCmode; + short shape_bits, num_sfm, numnrmibits; + short hqswb_clas; + short num_env_bands; + short Npeaks, start_norm; + short difidx_org[NB_SFM]; + short R[NB_SFM]; + short peaks[HVQ_MAX_PEAKS]; + const short *sfmsize, *sfm_start, *sfm_end; + short npulses[NB_SFM], maxpulse[NB_SFM]; + short Rsubband[NB_SFM]; /* Q3 */ + float t_audio_q[L_FRAME48k]; + float nf_gains[HVQ_NF_GROUPS], pe_gains[HVQ_NF_GROUPS]; + float noise_level[HVQ_BWE_NOISE_BANDS]; + short hq_generic_offset; + float hq_generic_fenv[HQ_FB_FENV]; + short hq_generic_exc_clas = 0; + short core_sfm; + short har_freq_est1 = 0, har_freq_est2 = 0; + short flag_dis = 1; + const short *subband_search_offset; + short wBands[2]; + short b_delta_env; + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + + Npeaks = 0; + set_s( npulses, 0, NB_SFM ); + set_s( maxpulse, 0, NB_SFM ); + set_s( difidx_org, 0, NB_SFM ); + set_f( t_audio_q, 0.0f, L_FRAME48k ); + set_f( nf_gains, 0.0f, HVQ_NF_GROUPS ); + set_f( pe_gains, 0.0f, HVQ_NF_GROUPS ); + + /*------------------------------------------------------------------* + * Classification + *------------------------------------------------------------------*/ + + *num_bits -= hq_classifier_enc( st, length, t_audio, is_transient, &Npeaks, peaks, pe_gains, nf_gains, &hqswb_clas ); + + /*------------------------------------------------------------------* + * Set quantization parameters + *------------------------------------------------------------------*/ + + hq_configure( length, hqswb_clas, st->core_brate, &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 frame */ + if( is_transient ) + { + interleave_spectrum( t_audio, length ); + } + + /*------------------------------------------------------------------* + * Scalar quantization of norms + * Encode norm indices + *------------------------------------------------------------------*/ + + /* calculate and quantize norms */ + calc_norm( t_audio, ynrm, normqlg2, start_norm, num_env_bands, sfmsize, sfm_start ); + + /* create differential code of quantized norm indices */ + diff_envelope_coding( is_transient, num_env_bands, start_norm, ynrm, normqlg2, difidx ); + + /* Find norm coding mode and calculate number of bits */ + hcode_l = encode_envelope_indices( st, num_env_bands, numnrmibits, difidx, &LCmode, 0, NORMAL_HQ_CORE, is_transient ); + *num_bits -= hcode_l + NORM0_BITS + FLAGS_BITS; + + /* Encode norm indices */ + encode_envelope_indices( st, num_env_bands, numnrmibits, difidx, &LCmode, 1, NORMAL_HQ_CORE, is_transient ); + + /*------------------------------------------------------------------* + * HQ GENERIC BWE encoding + *------------------------------------------------------------------*/ + + if ( hqswb_clas == HQ_GEN_SWB || hqswb_clas == HQ_GEN_FB ) + { + hq_generic_hf_encoding( t_audio, hq_generic_fenv, hq_generic_offset, st, &hq_generic_exc_clas ); + if (hq_generic_exc_clas == HQ_GENERIC_SP_EXC) + { + (*num_bits)++; /* conditional 1 bit saving for representing FD3 BWE excitation class */ + } + map_hq_generic_fenv_norm(hqswb_clas, hq_generic_fenv, ynrm, normqlg2, num_env_bands, nb_sfm, hq_generic_offset); + } + + /*------------------------------------------------------------------* + * Bit allocation + *------------------------------------------------------------------*/ + + hq_bit_allocation( st->core_brate, 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 ) + { + if (hqswb_clas == HQ_GEN_SWB || hqswb_clas == HQ_GEN_FB) + { + b_delta_env = calc_nor_delta_hf( st, t_audio, ynrm, Rsubband, num_env_bands, nb_sfm, sfmsize, sfm_start, core_sfm ); + sum -= b_delta_env; + } + normalizecoefs( t_audio, ynrm, nb_sfm, sfm_start, sfm_end ); + } + + /*------------------------------------------------------------------* + * Quantize/code spectral fine structure using PVQ or HVQ + *------------------------------------------------------------------*/ + + if( hqswb_clas == HQ_HVQ ) + { + sum = hvq_enc( st, st->core_brate, *num_bits, Npeaks, ynrm, R, peaks, nf_gains, + noise_level, pe_gains, t_audio, t_audio_q ); + *num_bits -= sum; + } + else + { + shape_bits = pvq_core_enc( st, t_audio, t_audio_q, sum, nb_sfm, sfm_start, sfm_end, sfmsize, Rsubband, R, npulses, maxpulse, HQ_CORE ); + *num_bits += (sum - shape_bits); + } + + if( hqswb_clas == HQ_HVQ || hqswb_clas == HQ_HARMONIC ) + { + subband_search_offset = subband_search_offsets_13p2kbps_Har; + wBands[0] = SWB_SB_BW_LEN0_16KBPS_HAR; + wBands[1] = SWB_SB_BW_LEN1_16KBPS_HAR; + + har_est( t_audio_q, 300, &har_freq_est1, &har_freq_est2, &flag_dis, &st->prev_frm_hfe2, subband_search_offset, wBands, &st->prev_stab_hfe2 ); + + st->prev_frm_hfe2 = har_freq_est2; + } + + if( hqswb_clas != HQ_HARMONIC || hqswb_clas != HQ_HVQ || flag_dis == 0) + { + st->prev_frm_hfe2 = 0; /*reset*/ + st->prev_stab_hfe2 = 0; /*reset*/ + } + + nf_idx = 0; + if ( !is_transient && hqswb_clas != HQ_HVQ && !(length == L_FRAME16k && st->core_brate == HQ_32k) ) + { + if (hqswb_clas == HQ_GEN_SWB || hqswb_clas == HQ_GEN_FB) + { + nf_idx = noise_adjust( t_audio, R, sfm_start, sfm_end, max(core_sfm,num_env_bands-1)); + push_indice( st, IND_NF_IDX, nf_idx, 2 ); + } + else + { + nf_idx = noise_adjust( t_audio, R, sfm_start, sfm_end, core_sfm ); + push_indice( st, IND_NF_IDX, nf_idx, 2 ); + } + } + + + /* updates */ + st->prev_hqswb_clas = hqswb_clas; + + return; +} diff --git a/lib_enc/hq_lr_enc.c b/lib_enc/hq_lr_enc.c new file mode 100644 index 000000000..d0e2c8649 --- /dev/null +++ b/lib_enc/hq_lr_enc.c @@ -0,0 +1,1688 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_enc.h" +#include "rom_com.h" +#include "prot.h" +#include "stl.h" +#include "basop_util.h" + +/*--------------------------------------------------------------------------* + * Local functions + *--------------------------------------------------------------------------*/ + +static short small_symbol_enc( Encoder_State *st, const int *qbidx, const short bands, short *hLCmode, const short flag_pack, const short is_transient ); + +static short small_symbol_enc_tran( Encoder_State *st, const int *qbidx, const short bands, short *hLCmode, const short flag_pack ,const short is_transient ); + +static float band_energy_quant( Encoder_State *st, const float *t_audio, const short band_start[], const short band_end[], float band_energy[], + const short bands, const Word32 L_qint, const Word16 eref_fx, const short is_transient ); + +static short p2a_threshold_quant( Encoder_State *st, const float *t_audio, const short band_start[], const short band_end[], const short band_width[], + const short bands, const short p2a_bands, const float p2a_th, short *p2a_flags ); + +static void mdct_spectrum_fine_gain_enc( Encoder_State *st, const float ybuf[], float y2[], const short band_start[], const short band_end[], + const short k_sort[], const short bands, const Word32 L_qint, const short Ngq, const short gqlevs, const short gqbits ); + +/*--------------------------------------------------------------------------* + * spt_shorten_domain_set() + * + * Track the spectral peak based on peak -avg analysis + *--------------------------------------------------------------------------*/ + +static void spt_shorten_domain_set( + Encoder_State *st, /* i: encoder state structure */ + const float t_audio[], /* i: input spectrum */ + const short p2a_flags[], /* i: p2a anlysis information */ + const short new_band_start[], /* i: new band start position */ + const short new_band_end[], /* i: new band end position */ + const short new_band_width[], /* i: new subband band width */ + const short bands, /* i: total number of subbands */ + short band_start[], /* i/o: band start position */ + short band_end[], /* i/o: band end position */ + short band_width[], /* i: sub band band width */ + short *bit_budget /* i/o: bit budget */ +) +{ + short i, j, k; + short kpos; + float max_y2; + short max_y2_pos; + short spt_shorten_flag[SPT_SHORTEN_SBNUM]; + + kpos = 0; + j = 0; + for( k=bands-SPT_SHORTEN_SBNUM; kprev_SWB_peak_pos[kpos] != 0) + { + max_y2 = 0.0f; + max_y2_pos = 0; + for( i=band_start[k]; i<=band_end[k]; i++ ) + { + if( max_y2 < fabs(t_audio[i]) ) + { + max_y2 =(float) fabs(t_audio[i]); + max_y2_pos = i; + } + } + if( max_y2_pos >= new_band_start[j] && max_y2_pos <= new_band_end[j] ) + { + band_start[k] = new_band_start[j]; + band_end[k] = new_band_end[j]; + band_width[k] = new_band_width[j]; + spt_shorten_flag[j] = 1; + } + } + push_indice( st, IND_HQ2_SPT_SHORTEN, spt_shorten_flag[j], 1 ); + *bit_budget -= 1; + } + + kpos++; + j++; + } + + return; +} + +/*--------------------------------------------------------------------------* + * hq_lr_enc() + * + * HQ low rate encoding routine + *--------------------------------------------------------------------------*/ + +void hq_lr_enc( + Encoder_State *st, /* i/o: encoder state structure */ + float t_audio[], /* i/o: transform-domain coefs. */ + const short inner_frame, /* i : inner frame length */ + short *num_bits, /* i/o: number of available bits */ + const short is_transient /* i : transient flag */ +) +{ + short i, k1, k2; + short bit_budget, pbits; + short bands, length, ni_seed, gqlevs, gqbits, Ngq, p2a_bands; + short p2a_flags[BANDS_MAX]; + short band_start[BANDS_MAX], band_end[BANDS_MAX], band_width[BANDS_MAX]; + float band_energy[BANDS_MAX], Rk[BANDS_MAX]; + Word32 Rk_fx[BANDS_MAX]; + float ebits; + float p2a_th, ni_coef, ni_pd_th, pd_thresh, ld_slope; + Word32 L_qint; /* Q29 */ + Word16 eref_fx; /* Q10 */ + Word16 bit_alloc_weight_fx; /* Q13 */ + short k_sort[BANDS_MAX]; + int npulses[BANDS_MAX]; + int inp_vector[L_FRAME48k]; + float y2[L_FRAME48k]; + float y2_ni[L_FRAME48k]; + short hqswb_clas; + short lowlength; + short highlength; + float m[L_FRAME32k]; + short har_bands; + float Ep[BANDS_MAX], enerH = 0.0f, enerL = 0.0f; + short lowband, highband, bw_low = 0, bw_high = 20; + float band_energy_tmp[BANDS_MAX]; + long bwe_br; + short trans_bit, p2a_flags_tmp[BANDS_MAX]; + short adjustFlag = 0; + short prev_SWB_peak_pos_tmp[SPT_SHORTEN_SBNUM]; + int k,j; + short flag_spt; + short org_band_start[SPT_SHORTEN_SBNUM]; + short org_band_end[SPT_SHORTEN_SBNUM]; + short org_band_width[SPT_SHORTEN_SBNUM]; + short new_band_start[SPT_SHORTEN_SBNUM]; + short new_band_end[SPT_SHORTEN_SBNUM]; + short new_band_width[SPT_SHORTEN_SBNUM]; + short bws_cnt=0; + Word32 L_tmp,L_tmp2,L_tmp3; + Word16 exp,tmp,exp2,tmp1,tmp2,tmp3,alpha_fx,frac1; + 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; */ + Word32 L_band_energy[BANDS_MAX],L_band_energy_tmp[BANDS_MAX]; + UWord16 lo; + Word16 Q_band_energy; + set_f( y2, 0.0f, L_FRAME48k ); + set_i( inp_vector, 0, inner_frame ); + flag_spt = 0; + set_s(prev_SWB_peak_pos_tmp, 0, SPT_SHORTEN_SBNUM); + + bwe_br = st->core_brate; + hqswb_clas = HQ_NORMAL; + if( st->bwidth == SWB && (bwe_br == HQ_16k40 || bwe_br == HQ_13k20) ) + { + if ( is_transient == 1 ) + { + hqswb_clas = HQ_TRANSIENT; + } + else + { + /* classification of HQ_HARMONIC and HQ_NORMAL frames for SWB BWE */ + hqswb_clas = peak_avrg_ratio( st->total_brate, t_audio, NUMC_N, &st->mode_count, &st->mode_count1); + } + + /* write the classification information into the bitstream */ + push_indice( st, IND_HQ2_SWB_CLAS, hqswb_clas, 2 ); + (*num_bits) -= 2; + + if( hqswb_clas == HQ_NORMAL ) + { + flag_spt = 1; + } + } + else + { + /* write the transient bit into the bitstream */ + push_indice( st, IND_HQ2_SWB_CLAS, is_transient, 1 ); + + /* subtract one bit for the transient flag */ + (*num_bits)--; + } + + /* Configure encoder for different bandwidths, bit rates, etc. */ + hq2_core_configure( inner_frame, *num_bits, is_transient, &bands, &length, band_width, band_start, band_end, &L_qint, &eref_fx, + &bit_alloc_weight_fx, &gqlevs, &Ngq, &p2a_bands, &p2a_th, &pd_thresh, &ld_slope, &ni_coef, &ni_pd_th, bwe_br ); + + highlength = band_end[bands-1]; + har_bands = bands; + + if( st->bwidth == SWB && is_transient == 0 && (bwe_br == HQ_16k40 || bwe_br == HQ_13k20) ) + { + /* reserve bits for HQ_NORMAL and HQ_HARMONIC modes */ + if( hqswb_clas == HQ_NORMAL || hqswb_clas == HQ_HARMONIC ) + { + (*num_bits) -= (short)get_usebit_npswb(hqswb_clas); + } + } + + if( (bwe_br == HQ_16k40 || bwe_br == HQ_13k20) && st->bwidth == SWB ) + { + if( st->prev_hqswb_clas != HQ_NORMAL ) + { + j = 0; + for( k=bands-SPT_SHORTEN_SBNUM; kprev_SWB_peak_pos[j] = 0; + j++; + } + } + } + + /* Check if input frame is larger than coded bandwidth */ + if( inner_frame > length && is_transient ) + { + /* If so, collapse transient frame (4 short transforms) to remove uncoded coefficients */ + for( i = 1; i < NUM_TIME_SWITCHING_BLOCKS; i++ ) + { + k1 = i*length/NUM_TIME_SWITCHING_BLOCKS; + k2 = i*inner_frame/NUM_TIME_SWITCHING_BLOCKS; + + mvr2r( &t_audio[k2], &t_audio[k1], length/NUM_TIME_SWITCHING_BLOCKS ); + } + } + + /* Spectral energy calculation/quantization */ + ebits = band_energy_quant( st, t_audio, band_start, band_end, band_energy, bands, L_qint, eref_fx, is_transient ); + + for( i = 0; i < bands; i++) + { + L_band_energy[i] = (Word32)(band_energy[i] * pow(2.0f, SWB_BWE_LR_Qbe)); + } + + /* First pass bit budget for TCQ of spectral band information */ + gqbits = (short int) log2_f ((float) gqlevs); + bit_budget = (*num_bits) - (short) ceil (ebits) - Ngq * gqbits; + + pbits = 0; + if( st->bwidth == SWB && (bwe_br == HQ_16k40 || bwe_br == HQ_13k20) ) + { + if( hqswb_clas == HQ_HARMONIC ) + { + set_s( p2a_flags, 1, har_bands ); + } + else + { + /* High band tonality detector based on per band peak-to-average ratio */ + pbits = p2a_threshold_quant( st, t_audio, band_start, band_end, band_width, bands, p2a_bands, p2a_th, p2a_flags ); + bit_budget -= pbits; + + if( hqswb_clas == HQ_NORMAL ) + { + return_bits_normal2( &bit_budget, p2a_flags, bands, bits_lagIndices_modeNormal ); + } + } + } + else + { + /* High band tonality detector based on per band peak-to-average ratio */ + pbits = p2a_threshold_quant( st, t_audio, band_start, band_end, band_width, bands, p2a_bands, p2a_th, p2a_flags ); + bit_budget -= pbits; + } + + if( flag_spt == 1 ) + { + /* initalize the desired parameters for SPT */ + spt_shorten_domain_band_save( bands, band_start, band_end, band_width, org_band_start, org_band_end, org_band_width ); + spt_shorten_domain_pre( band_start, band_end, st->prev_SWB_peak_pos, bands, bwe_br, new_band_start, new_band_end, new_band_width ); + spt_shorten_domain_set( st, t_audio, p2a_flags, new_band_start, new_band_end, new_band_width, bands, band_start, band_end, band_width, &bit_budget ); + } + + /* Estimate number of bits per band */ +#define WMC_TOOL_SKIP + + Q_band_energy = SWB_BWE_LR_Qbe; + FOR(i = 0; i < bands; 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 , sub(exp,6)); /* Q -6 */ + Ep[i] = (float)(Ep_fx[i]/pow(2.0,-6)); + } + + FOR( i = 0; i < bands; 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_lc1(L_tmp, &exp2); + move32();/*Q(31-exp2) */ + Ep_tmp_fx[i] = L_shr(L_tmp,sub(15,exp2));/*Q13 */ + } + +#undef WMC_TOOL_SKIP + + if ( is_transient == 0 && inner_frame == L_FRAME8k && st->core_brate <= ACELP_13k20 ) + { +#define WMC_TOOL_SKIP + lowband = 6; + move16(); + trans_bit = 2; + move16(); + bit_budget =sub(bit_budget,trans_bit); + gama_fx = 27852; /*Q15 0.85f; */ + beta_fx = 17203; + move16();/*Q14 1.05f; */ + set_s( &p2a_flags_tmp[bands-trans_bit], 0, 2 ); + + IF( st->core_brate == ACELP_13k20 ) + { + beta_fx = 13107; + move16();/*14 1.25f; */ + gama_fx = 31130; + move16();/*0.95f; */ + mvs2s(&p2a_flags[sub(bands,trans_bit)], &p2a_flags_tmp[sub(bands,trans_bit)], trans_bit); + } + + /* calculate the the low band/high band energy and the variance/avrage of the envelopes */ + Ep_vari_fx = 0; + move32(); + Ep_avrg_fx = 0; + move32(); + Ep_avrgL_fx = 0; + move32(); + Ep_peak_fx = 0; + move32(); + FOR( i = 0; i < bands; i++ ) + { + IF( sub(i,lowband) >= 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 */ + + } + ELSE + { + Ep_avrgL_fx = L_add(Ep_avrgL_fx,Ep_tmp_fx[i]);/*Q15 */ + IF(L_sub(Ep_tmp_fx[i],Ep_peak_fx) > 0) + { + Ep_peak_fx = Ep_tmp_fx[i]; + move32();/*Q15 */ + } + } + } + /* modify the last p2a_bands subbands band_energies */ + k = (int)bands; + mvi2i( L_band_energy,L_band_energy_tmp,k); /*Q_band_energy */ + Mpy_32_16_ss(Ep_peak_fx,24576,&L_tmp,&lo); + Mpy_32_16_ss(Ep_peak_fx,shl(sub(bands,lowband),9),&L_tmp2,&lo); + Mpy_32_16_ss(Ep_avrg_fx,1126,&L_tmp3,&lo); + + IF(( (L_sub(L_tmp, L_shr(Ep_avrgL_fx,1)) < 0 && st->core_brate == ACELP_13k20 ) || st->core_brate < ACELP_13k20 )&& + L_sub(L_tmp2, L_tmp3) < 0 && L_sub(L_tmp2, L_shr(Ep_avrg_fx,7)) > 0) + { + FOR(i = lowband; i < bands; i++) + { + Mpy_32_16_ss(Ep_avrg_fx,24576,&L_tmp,&lo); + IF(L_sub(L_shr(Ep_tmp_fx[i],1), L_tmp) < 0) + { + Mpy_32_16_ss(Ep_peak_fx,sub(bands,lowband),&L_tmp,&lo); + 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(); + } + Mpy_32_16_ss(Ep_avrg_fx,tmp,&L_tmp,&lo); + L_tmp = L_shl(L_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 */ + Mpy_32_16_ss(L_band_energy_tmp[i],tmp2,&L_band_energy_tmp[i],&lo); + } + } + } + ELSE + { + j = 0; + FOR(i = sub(bands,trans_bit); i < bands; i++) + { + alpha_fx = 16384; + move16();/*Q14 */ + IF( sub(p2a_flags_tmp[i],1) == 0) + { + Mpy_32_16_ss(Ep_tmp_fx[i],sub(bands,lowband),&L_tmp,&lo); + 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(); + } + Mpy_32_16_ss(Ep_vari_fx,3277,&L_tmp,&lo); + Mpy_32_16_ss(L_tmp,tmp,&L_tmp,&lo); + L_tmp = L_shl(L_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(); + } + Mpy_32_16_ss(Ep_vari_fx,6554,&L_tmp2,&lo); + Mpy_32_16_ss(L_tmp2,tmp2,&L_tmp2,&lo); + L_tmp2 = L_shl(L_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(sub(st->last_bitalloc_max_band[j++], 1) == 0) + { + Mpy_32_16_ss(Ep_tmp_fx[i],sub(bands,lowband),&L_tmp,&lo); + 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(); + } + Mpy_32_16_ss(Ep_avrg_fx,tmp,&L_tmp,&lo); + L_tmp = L_shl(L_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(); + } + Mpy_32_16_ss(Ep_tmp_fx[i],tmp2,&L_tmp,&lo); + L_tmp = L_shl(L_tmp,sub(19,exp));/*Q(13+exp-15 +19-exp +3 = 20) */ + Mpy_32_16_ss(L_tmp,shl(sub(bands,lowband),9),&L_tmp,&lo); + 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 */ + } + Mpy_32_16_ss(L_band_energy_tmp[i],alpha_fx,&L_tmp,&lo); + L_band_energy_tmp[i] = L_shl(L_tmp,1);/*Q(Q_band_energy+14-15 +1= Q_band_energy) */ + } + } + lowband = 3; + move16(); + Ep_avrg_fx = 0; + move32(); + Ep_avrgL_fx = 0; + move32(); + Ep_peak_fx = 0; + move32(); + FOR(i = 0; i < bands; i++) + { + IF(sub(i,lowband) >=0 ) + { + 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(L_sub(Ep_tmp_fx[i],Ep_peak_fx) > 0) + { + Ep_peak_fx = Ep_tmp_fx[i]; + move32();/*Q13 */ + } + } + } + Mpy_32_16_ss(Ep_peak_fx,28262,&L_tmp,&lo); + Mpy_32_16_ss(Ep_avrgL_fx,24576,&L_tmp2,&lo); + IF( L_sub(L_shr(Ep_avrg_fx,2), L_tmp2) > 0 && L_sub(L_shr(Ep_avrg_fx,4), L_tmp2) < 0 && L_sub(L_tmp, Ep_avrgL_fx)>0) + { + 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(); + } + Mpy_32_16_ss(Ep_peak_fx,tmp,&L_tmp,&lo); + Mpy_32_16_ss(L_tmp,lowband,&L_tmp,&lo); + Mpy_32_16_ss(L_tmp,18842,&L_tmp,&lo); + L_tmp = L_shl(L_tmp,sub(27,exp));/*Q14 0.5 */ + tmp2=extract_l(L_min(L_tmp,19661));/*14 */ + Mpy_32_16_ss(L_band_energy_tmp[i],tmp2,&L_tmp,&lo); + L_band_energy_tmp[i] = L_shl(L_tmp,1); /*Q_band_energy */ + } + } + for (i = 0; i < bands; i++) + { + band_energy_tmp[i] = (float)(L_band_energy_tmp[i]/pow(2.0f, SWB_BWE_LR_Qbe)); + } +#undef WMC_TOOL_SKIP + + hq2_bit_alloc( band_energy_tmp, bands, Rk_fx, &bit_budget, p2a_flags, bit_alloc_weight_fx, band_width, + *num_bits, hqswb_clas, st->bwidth, is_transient ); + + /* encode the last p2a_bands-1 subbands bit-allocation index of the previous frame */ + for(i = 0; i < 2; i++) + { + push_indice ( st, IND_HQ2_LAST_BA_MAX_BAND, st->last_bitalloc_max_band[i], 1 ); + } + } + else if( is_transient == 0 && inner_frame == L_FRAME16k ) + { +#define WMC_TOOL_SKIP + bit_budget = sub(bit_budget,2);/* bits in high bands to indicate the last 2 subbands is allocated bits or not */ + FOR( i = 0; i < bands; i++ ) + { + Ep_tmp_fx[i] = L_shl(Ep_tmp_fx[i],2); + } + IF( st->core_brate == 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,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,1)],1),band_start[highband]); + } + /* calculate the the low band/high band energy and the variance/avrage of the envelopes */ + enerL_fx = 0; + move32(); + enerH_fx = 0; + move32(); + Ep_vari_fx = 0; + move32(); + Ep_avrg_fx = 0; + move32(); + FOR( i = 0; i < bands; i++ ) + { + IF( sub(i,lowband) >= 0 && add(sub(i,bands),p2a_bands) < 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(sub(i,highband) >= 0) + { + enerH_fx = L_add(enerH_fx,L_shl(Ep_fx[i],2));/*Q0 */ + } + ELSE IF(sub(i,lowband) >= 0) + { + enerL_fx = L_add(enerL_fx,L_shl(Ep_fx[i],2));/*Q0 */ + } + } + enerL = (float)(enerL_fx/pow(2.0,-4)); + enerH = (float)(enerH_fx/pow(2.0,-4)); + /* modify the last p2a_bands subbands band_energies */ + k = (int)bands; + mvi2i( L_band_energy,L_band_energy_tmp,k); /*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); + Mpy_32_16_ss(L_shl(enerH_fx,i),shl(bw_low,j),&L_tmp,&lo); + Mpy_32_16_ss(L_shl(enerL_fx,i),shl(bw_high,j),&L_tmp2,&lo); + L_tmp2 = L_sub(L_tmp,L_tmp2); + + FOR( i = sub(bands,p2a_bands); i < bands; i++ ) + { + IF( sub(p2a_flags[i],1) == 0 || L_tmp2 > 0 ) + { + tmp = sub(bands,p2a_bands); + 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(); + } + Mpy_32_16_ss(Ep_tmp_fx[i],tmp1,&L_tmp,&lo); + Mpy_32_16_ss(L_tmp,tmp,&L_tmp,&lo); + Mpy_32_16_ss(L_tmp,16384,&L_tmp,&lo); + L_tmp = L_shl(L_tmp,sub(32,exp));/*Q15 */ + tmp = extract_l(L_min(L_tmp,6554));/*Q15 */ + Mpy_32_16_ss(Ep_vari_fx,tmp1,&L_tmp,&lo); + Mpy_32_16_ss(L_tmp,tmp,&L_tmp,&lo); + 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),p2a_bands) > 0) + { + tmp = sub(bands, p2a_bands); + IF(sub(st->last_bitalloc_max_band[sub(i, add(tmp, 1))], 1) == 0) + { + tmp = sub(tmp,lowband); + Mpy_32_16_ss(Ep_tmp_fx[i],tmp,&L_tmp,&lo); + 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(); + } + Mpy_32_16_ss(Ep_avrg_fx,tmp,&L_tmp,&lo); + 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(); + } + Mpy_32_16_ss(Ep_tmp_fx[i],tmp1,&L_tmp,&lo); + Mpy_32_16_ss(L_tmp,tmp,&L_tmp,&lo); + 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 */ + } + } + Mpy_32_16_ss(L_band_energy_tmp[i],alpha_fx,&L_tmp,&lo); + L_band_energy_tmp[i] = L_shl(L_tmp,1);/*Q Q_band_energy */ + } + lowband = 6; + move16(); + Ep_avrg_fx = 0; + move32(); + Ep_avrgL_fx = 0; + move32(); + Ep_peak_fx = 0; + move32(); + FOR(i = 0; i < bands; i++) + { + IF(sub(i,lowband) >= 0) + { + 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(L_sub(Ep_tmp_fx[i],Ep_peak_fx) > 0) + { + Ep_peak_fx = Ep_tmp_fx[i]; + move32();/*Q15 */ + } + } + } + + Mpy_32_16_ss(Ep_peak_fx,24576,&L_tmp,&lo); + Mpy_32_16_ss(Ep_peak_fx,19661,&L_tmp2,&lo); + Mpy_32_16_ss(Ep_avrgL_fx,24576,&L_tmp3,&lo); + + IF( (L_sub(L_shr(Ep_avrgL_fx,1), Ep_avrg_fx)>0 && L_sub(L_tmp,L_shr(Ep_avrgL_fx,2)) > 0 && L_sub(L_shr(Ep_avrgL_fx,1),L_tmp2) < 0 ) || + (L_sub(L_shr(Ep_avrg_fx,1), Ep_avrgL_fx)>0 && L_sub(L_shr(Ep_avrg_fx,3),L_tmp3) < 0 && L_sub(L_tmp,L_shr(Ep_avrgL_fx,2)) > 0 ) ) + { + 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(); + } + Mpy_32_16_ss(Ep_peak_fx,tmp,&L_tmp,&lo); + Mpy_32_16_ss(L_tmp,lowband,&L_tmp,&lo); + L_tmp = L_shl(L_tmp,sub(28,exp));/*Q14 0.5 */ + tmp = extract_l(L_min(L_tmp,19661));/*Q14 */ + Mpy_32_16_ss(L_band_energy_tmp[i],tmp,&L_tmp,&lo); + L_band_energy_tmp[i] = L_shl(L_tmp,1); /*Q_band_energy */ + } + } + for (i = 0; i < bands; i++) + { + band_energy_tmp[i] = (float)(L_band_energy_tmp[i]/pow(2.0f, SWB_BWE_LR_Qbe)); + } +#undef WMC_TOOL_SKIP + + hq2_bit_alloc( band_energy_tmp, bands, Rk_fx, &bit_budget, p2a_flags, bit_alloc_weight_fx, band_width, + *num_bits, hqswb_clas, st->bwidth, is_transient ); + + /* encode the last p2a_bands-1 subbands bit-allocation index of the previous frame */ + for(i = 0; i < 2; i++) + { + push_indice( st, IND_HQ2_LAST_BA_MAX_BAND, st->last_bitalloc_max_band[i], 1 ); + } + } + else if( st->bwidth == SWB && hqswb_clas == HQ_HARMONIC && (bwe_br == HQ_16k40 || bwe_br == HQ_13k20) ) + { + /* bit allocation for harmonic mode */ + hq2_bit_alloc_har( band_energy, bit_budget, bands, Rk_fx, p2a_bands,bwe_br, p2a_flags, band_width); + } + else + { + + /* estimate number of bits per band */ + hq2_bit_alloc( band_energy, bands, Rk_fx, &bit_budget, p2a_flags, bit_alloc_weight_fx, band_width, + *num_bits, hqswb_clas, st->bwidth, is_transient ); + } + + tcq_core_LR_enc( st, inp_vector, t_audio, y2, bit_budget, bands, band_start, band_end, band_width, Rk_fx, + npulses, k_sort, p2a_flags, p2a_bands, st->last_bitalloc_max_band, inner_frame, adjustFlag, is_transient ); + + if((inner_frame == L_FRAME8k && st->core_brate <= ACELP_13k20) || inner_frame == L_FRAME16k) + { + j = 0; + for(i = 2; i > 0; i--) + { + if(npulses[bands-i] > 0) + { + st->last_bitalloc_max_band[j] = 1; + } + else + { + st->last_bitalloc_max_band[j] = 0; + } + j++; + } + } + + /* Prepare floating Rk for next modules */ + for( k = 0; k < bands; k++) + { + Rk[k] = WORD322FL_SCALE( Rk_fx[k], SWB_BWE_LR_QRk - 1); + } + + /* Denormalize the coded MDCT spectrum */ + mdct_spectrum_denorm( inp_vector, y2, band_start, band_end, band_width, band_energy, npulses, bands, ld_slope, pd_thresh ); + + /* Apply fine gain quantization to denormalized coded spectrum */ + mdct_spectrum_fine_gain_enc( st, t_audio, y2, band_start, band_end, k_sort, bands, L_qint, Ngq, gqlevs, gqbits ); + + /* reStore the subband information*/ + if(flag_spt == 1) + { + spt_shorten_domain_band_restore(bands, 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 = npulses[0] + npulses[1] + npulses[2] + npulses[3]; + + for(i=0; ilast_ni_gain, st->last_env, &st->last_max_pos_pulse, p2a_flags, p2a_bands, hqswb_clas, st->bwidth, bwe_br ); + + if( st->bwidth == SWB && (bwe_br == HQ_16k40 || bwe_br == HQ_13k20) ) + { + if( hqswb_clas == HQ_NORMAL || hqswb_clas == HQ_HARMONIC ) + { + preset_hq2_swb( hqswb_clas, band_end, &har_bands, p2a_bands,length, bands, &lowlength, &highlength, m ); + + swb_bwe_enc_lr( st, y2, t_audio, m , bwe_br, bands, band_start, band_end, band_energy, p2a_flags, + hqswb_clas, lowlength, highlength, st->prev_frm_index, har_bands, &st->prev_frm_hfe2, &st->prev_stab_hfe2,band_width, y2_ni, &ni_seed ); + + post_hq2_swb( m, lowlength, highlength, hqswb_clas, har_bands, bands, p2a_flags, band_start, band_end, y2, npulses ); + + if( hqswb_clas == HQ_NORMAL ) + { + spt_swb_peakpos_tmp_save(y2, bands, band_start, band_end, prev_SWB_peak_pos_tmp); + for( k=0; kbwidth, is_transient, hqswb_clas, &st->prev_hqswb_clas, + st->prev_SWB_peak_pos, prev_SWB_peak_pos_tmp, &st->prev_frm_hfe2, &st->prev_stab_hfe2, bws_cnt ); + + if( st->bwidth != SWB ) + { + /* reset HQ classifier memories */ + st->mode_count = 0; + st->mode_count1 = 0; + } + if( hqswb_clas != HQ_HARMONIC && (bwe_br == HQ_16k40 || bwe_br == HQ_13k20) && st->bwidth == SWB ) + { + st->prev_frm_index[0] = -1; + st->prev_frm_index[1] = -1; + } + /* update number of unused bits */ + *num_bits = 0; + + st->hvq_hangover = 0; + + 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 short small_symbol_enc_tran( /* o : bits */ + Encoder_State *st, /* i/o: encoder state structure */ + const int *qbidx, /* i : input of dequantized differential energy */ + const short BANDS, /* i : number of bands */ + short *hLCmode, /* i/o: LC mode info */ + const short flag_pack, /* i : indicator of packing or estimating bits */ + const short is_transient +) +{ + short i, bits; + short difidx[BANDS_MAX]; + + for( i=0; iLRMDCT_BE_LIMIT || difidx[i]<0) + { + /* Huffman cannot encode this vector */ + return -1; + } + } + + /* Preparing lossless coding input */ + if ( flag_pack == 0 ) + { + /* estimating # of bits */ + bits = encode_envelope_indices(st, BANDS, -1, difidx, hLCmode, flag_pack, LOW_RATE_HQ_CORE_TRAN , is_transient ); + bits += BITS_DE_FCOMP; /* xx bits for diff. energies + BITS_DE_FCOMP bits for first energies */ + } + else + { + bits = 0; + encode_envelope_indices(st, BANDS, -1, difidx, hLCmode, flag_pack, LOW_RATE_HQ_CORE_TRAN ,is_transient ); + } + + return bits + BITS_DE_HMODE; /* xx bits for diff. energies + 1 bit for LC coding mode */ +} + + +/*--------------------------------------------------------------------------* + * small_symbol_enc() + * + * 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 short small_symbol_enc( /* o : bits */ + Encoder_State *st, /* i/o: encoder state structure */ + const int *qbidx, /* i : input of dequantized differential energy */ + const short BANDS, /* i : number of bands */ + short *hLCmode, /* i/o: LC mode info */ + const short flag_pack, /* i : indicator of packing or estimating bits */ + const short is_transient +) +{ + short i, bits; + short difidx[BANDS_MAX], LSB[BANDS_MAX]; + + /* Preparing lossless coding input */ + difidx[0] = (short)(qbidx[0]+DE_OFFSET0); + + for( i=1; i=DE_LIMIT || difidx[i]<0) + { + /* Huffman cannot encode this vector */ + return -1; + } + } + + /* splitting MSB and LSB */ + for( i=0; i>= 1; + } + + /* Preparing lossless coding input */ + if ( flag_pack == 0 ) + { + /* estimating # of bits */ + /* Encoding MSB bits */ + bits = encode_envelope_indices( st, BANDS, -1, difidx, hLCmode, flag_pack, LOW_RATE_HQ_CORE, is_transient ); + bits += BITS_DE_FCOMP; /* xx bits for diff. energies + BITS_DE_FCOMP bits for first energies */ + + /* Encoding LSB bit packing */ + bits += BANDS; + } + else + { + /* Encoding MSB bits */ + bits = 0; + encode_envelope_indices( st, BANDS, -1, difidx, hLCmode, flag_pack, LOW_RATE_HQ_CORE, is_transient ); + + /* Encoding LSB bit packing */ + for( i=0; iABS_ENG_OFFSET-1 || qbidx[0]<-ABS_ENG_OFFSET) + { + cnt_outlyer0 = 2; + } + else if (qbidx[0]>3 || qbidx[0]<-4) + { + cnt_outlyer0 = 1; + } + else + { + cnt_outlyer0 = 0; + } + + cnt_outlyer=0; + pos_outlyer = -1; + for( i=1; i3 || qbidx[i]<-4) + { + cnt_outlyer++; + pos_outlyer = i; + } + + if (qbidx[i]>ABS_ENG_OFFSET-1 || qbidx[i]<-ABS_ENG_OFFSET) + { + cnt_outlyer++; + } + } + + if (cnt_outlyer0 == 0 && cnt_outlyer<=1) + { + bitsmode0 = BITS_DE_8SMODE + BITS_DE_8SMODE_N0 + BITS_DE_8SMODE_N1; + if (cnt_outlyer == 1) + { + /* 01 */ + bitsmode0 += BITS_DE_8SPOS + BITS_ABS_ENG; + } + + for( i=0; imax_q) + { + max_q = (short)qbidx[i]; + } + + if (qbidx[i]= -(2<<(i+1))) + { + break; + } + } + basic_shift = i; + + min_bits=1000; + min_bits_pos = basic_shift; + for(offset0=basic_shift; offset0>offset0)+4]+(offset0)); + } + + if (min_bits>bitsmode1) + { + min_bits_pos = offset0; + min_bits = bitsmode1; + } + } + + bitsmode1 = min_bits; + lsbdepth1 = min_bits_pos; + + for( i=0; i>lsbdepth1; + } + } + + /* Preparing lossless coding input */ + if ( flag_pack == 0 ) + { + /* estimating # of bits */ + /* Encoding MSB bits */ + if (bitsmode0 0) + { + for(i=0; iMAXIMUM_ENERGY_LOWBRATE) + { + bq2[i] = MAXIMUM_ENERGY_LOWBRATE; + } + if (bq2[i] Qbe(Q14) */ + band_energy[k] = (float)(L_band_energy[k]/pow(2.0f, SWB_BWE_LR_Qbe)); +#undef WMC_TOOL_SKIP + } + + if( is_transient ) + { + reverse_transient_frame_energies( band_energy, bands ); + } + + return( deng_bits ); +} + + +/*-------------------------------------------------------------------* + * p2a_threshold_quant() + * + * + *-------------------------------------------------------------------*/ + +static short p2a_threshold_quant( + Encoder_State *st, /* i/o: encoder state structure */ + const float *t_audio, + const short band_start[], + const short band_end[], + const short band_width[], + const short bands, + const short p2a_bands, + const float p2a_th, + short *p2a_flags +) +{ + short i, j, k; + float p, a, e; + float p2a; + + set_s( p2a_flags, 1, bands ); + + j = 0; + for (k = bands - p2a_bands; k < bands; k++) + { + a = 0.0f; + p = 0.0f; + for (i = band_start[k]; i <= band_end[k]; i++) + { + e = t_audio[i] * t_audio[i]; + if (e > p) + { + p = e; + } + a += e; + } + + if (a > 0.0f) + { + a /= band_width[k]; + p2a = 10.0f * (float) log10 (p / a); + + if (p2a <= p2a_th) + { + p2a_flags[k] = 0; + } + } + + push_indice( st, IND_HQ2_P2A_FLAGS, p2a_flags[k], 1 ); + j++; + } + + return( j ); +} + + +/*-------------------------------------------------------------------* + * mdct_spectrum_fine_gain_enc() + * + * + *-------------------------------------------------------------------*/ + +static void mdct_spectrum_fine_gain_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const float ybuf[], + float y2[], + const short band_start[], + const short band_end[], + const short k_sort[], + const short bands, + const Word32 L_qint, + const short Ngq, + const short gqlevs, + const short gqbits +) +{ + short i, k, imin; + float Eyy, Exy, gamma; + float dmin, d; + float gain_table[MAX_GQLEVS]; + Word16 exp_normn, exp_normd; + Word16 delta_fx, Qdelta; + Word32 L_delta, L_q; + Word32 L_temp; + Word16 gain_table_fx[MAX_GQLEVS]; + Word16 Qgt; + Word16 temp_lo_fx, temp_hi_fx; + + /* Fine gain quantization on only the most significant energy bands */ + +#define WMC_TOOL_SKIP + /*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 */ + gain_table[i] = (float)(gain_table_fx[i]/pow(2.0f, 14)); + } +#undef WMC_TOOL_SKIP + + for (k = 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]; + } + + if (Eyy > 0.0f && Exy > 0.0f) + { + gamma = Exy / Eyy; + dmin = FLT_MAX; + imin = -1; + for (i = 0; i < gqlevs; i++) + { + d = (float) fabs (gamma - gain_table[i]); + if (d < dmin) + { + dmin = d; + imin = i; + } + } + + gamma = gain_table[imin]; + + for (i = band_start[k_sort[k]]; i <= band_end[k_sort[k]]; i++) + { + y2[i] *= gamma; + } + } + else + { + imin = 0; + } + + push_indice( st, IND_HQ2_SUBBAND_GAIN, imin, gqbits ); + } + + return; +} diff --git a/lib_enc/hvq_enc.c b/lib_enc/hvq_enc.c new file mode 100644 index 000000000..003e11413 --- /dev/null +++ b/lib_enc/hvq_enc.c @@ -0,0 +1,118 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_enc.h" +#include "rom_com.h" + +/*--------------------------------------------------------------------------* + * hvq_enc() + * + * Harmonic VQ encoder + *--------------------------------------------------------------------------*/ + +short hvq_enc( /* o : Consumed bits */ + Encoder_State *st, /* i/o: encoder state structure */ + const long brate, /* i : Total bit rate */ + const short hvq_bits, /* i : HVQ bit budget */ + const short Npeaks, /* i : Number of peaks */ + const short *ynrm, /* i : Envelope coefficients */ + short *R, /* i/o: Bit allocation/updated bit allocation */ + short *peaks, /* i : Peak pos. / Encoded peak pos. */ + float *nf_gains, /* i/o: Noise fill gains / Quant. nf gains */ + float *noise_level, /* o : Quantized noise level */ + const float *pe_gains, /* i : Peak gains */ + const float *coefs, /* i : spectrum coefficients */ + float *coefs_out /* o : encoded spectrum coefficients */ +) +{ + short bin_th,q,j,i; + short nf_cnt; + short q_noise_level_idx[HVQ_BWE_NOISE_BANDS]; + float q_noise_level[HVQ_BWE_NOISE_BANDS]; + float d, nf, nf_mean, pe, pe_mean, nfpe; + short bits_used; + float lb_nfpe; + + bits_used = 0; + + bin_th = HVQ_THRES_BIN_32k; + if( brate == HQ_24k40 ) + { + bin_th = HVQ_THRES_BIN_24k; + } + + nf = 800; + pe = 800; + q = bin_th; + + /* Find HB noise level */ + for( i = 0; i < HVQ_BWE_NOISE_BANDS; i++ ) + { + nf_cnt = 0; + nf_mean = EPSILON; + pe_mean = EPSILON; + for( j = 0; j < (L_FRAME32k-bin_th)/HVQ_BWE_NOISE_BANDS; j++, q++ ) + { + d = (float)fabs(coefs[q]); + + if( d > pe ) + { + pe = HVQ_BWE_WEIGHT2 * pe + (1 - HVQ_BWE_WEIGHT2) * d; + } + else + { + pe = HVQ_BWE_WEIGHT1 * pe + (1 - HVQ_BWE_WEIGHT1) * d; + if( d > nf ) + { + nf = HVQ_BWE_WEIGHT1 * nf + (1 - HVQ_BWE_WEIGHT1) * d; + } + else + { + nf = HVQ_BWE_WEIGHT2 * nf + (1 - HVQ_BWE_WEIGHT2) * d; + } + nf_mean += nf; + nf_cnt++; + } + + pe_mean += pe; + } + + if( nf_cnt > 0 ) + { + nf_mean /= nf_cnt; + } + pe_mean /= (L_FRAME32k-bin_th)/HVQ_BWE_NOISE_BANDS; + + nfpe = HVQ_NFPE_FACTOR*nf_mean/pe_mean; + noise_level[i] = nfpe * nfpe * nfpe; + + q_noise_level_idx[i] = usquant( noise_level[i], &q_noise_level[i], 0.0f, 0.1f, 4 ); + push_indice( st, IND_HVQ_BWE_NL, q_noise_level_idx[i], 2 ); + bits_used += 2; + + noise_level[i] = q_noise_level[i]; + } + + for( i = 0; i < HVQ_NF_GROUPS; i ++ ) + { + lb_nfpe = HVQ_LB_NFPE_FACTOR*nf_gains[i]/pe_gains[i]; + lb_nfpe = lb_nfpe * lb_nfpe * lb_nfpe; + + if( lb_nfpe > 0.5f ) + { + lb_nfpe = 0.5f; + } + nf_gains[i] *= 2*lb_nfpe; + } + + bits_used += peak_vq_enc( st, coefs, coefs_out, (short)brate, hvq_bits - bits_used, + Npeaks, ynrm, R, peaks, &nf_gains[0] ); + + return bits_used; +} diff --git a/lib_enc/igf_enc.c b/lib_enc/igf_enc.c new file mode 100644 index 000000000..dfd3bd53d --- /dev/null +++ b/lib_enc/igf_enc.c @@ -0,0 +1,868 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include +#include "options.h" +#include "prot.h" +#include "cnst.h" +#include "stat_enc.h" + +/**********************************************************************/ /* +write single bit to stream +**************************************************************************/ +static void IGF_write_bit(Encoder_State *st, /**< in: | encoder state structure */ + int *bitCount, /**< in/out: | bit counter */ + int bit /**< in/out: | bit counter */ + ) +{ + IGFCommonFuncsWriteSerialBit(st, bitCount, bit); + + return; +} + +/**********************************************************************/ /* +write bits to stream +**************************************************************************/ +static void IGF_write_bits(Encoder_State *st, /**< in: | encoder state structure */ + int *bitCount, /**< in/out: | bit counter */ + int value, /**< in/out: | bit counter */ + int bits /**< in: | number of bits */ + ) +{ + while (bits--) + { + IGF_write_bit(st, bitCount, ((value & (1 << bits)) == 0) ? 0 : 1); + } + + return; +} + + +/**********************************************************************/ /* +envelope estimation +**************************************************************************/ +static void IGF_CalculateEnvelope(const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + float *pMDCTSpectrum, /**< in: | MDCT spectrum */ + float *pPowerSpectrum, /**< in: | MDCT^2 + MDST^2 spectrum, or estimate */ + const int igfGridIdx /**< in: | IGF grid index */ + ) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + int *swb_offset; + int sfb; /* this is the actual scalefactor band */ + int width; /* this is width in subbands of the actual scalefactor band */ + int tile_idx; + int strt_cpy; + float gain; /* the gain which has to be applied to the source tile to get the destination energy */ + int sb; + float sfbEnergyR; + float sfbEnergyC; /* the energy of the destination region of the tile */ + float sfbEnergyTileR; + float sfbEnergyTileC; /* the energy of the destination region of the tile */ + + mvr2r(pMDCTSpectrum + IGF_START_MN, hInstance->spec_be_igf, hInstance->infoStopLine-IGF_START_MN); + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[(int)igfGridIdx]; + swb_offset = hGrid->swb_offset; + + + for (tile_idx = 0; tile_idx < hGrid->nTiles; tile_idx++) + { + strt_cpy = hGrid->sbWrap[tile_idx]; + + for (sfb = hGrid->sfbWrap[tile_idx]; sfb < hGrid->sfbWrap[tile_idx + 1]; sfb++) + { + + + width = swb_offset[sfb + 1] - swb_offset[sfb]; + sfbEnergyTileR = EPSILON; + sfbEnergyTileC = EPSILON; + sfbEnergyC = EPSILON; + + if (pPowerSpectrum) + { + + for (sb = swb_offset[sfb]; sb < swb_offset[sfb + 1]; sb++) + { + sfbEnergyC += pPowerSpectrum[sb]; + sfbEnergyTileR += pMDCTSpectrum[strt_cpy] * pMDCTSpectrum[strt_cpy]; + sfbEnergyTileC += pPowerSpectrum[strt_cpy]; + + + strt_cpy++; + } + + sfbEnergyTileR /= width; + gain = (float)(sfbEnergyTileR * (sfbEnergyC / sfbEnergyTileC)); + + } + else + { + sfbEnergyR = EPSILON + sum2_f(pMDCTSpectrum + swb_offset[ sfb ], width) / width; + gain = (float)(sfbEnergyR); + + } + + gain = 0.5f + (float) ((2.885390081777927f * logf(gain) + 16.f)); + gain = min(gain, 91.f); /* 13+15+63, see arithocde encode residual */ + gain = max(gain, 0.f); + + hPrivateData->igfScfQuantized[sfb] = (int)(gain); + } + } + + return; +} + +/**********************************************************************/ /* +writes IGF SCF values +**************************************************************************/ +static int IGF_WriteEnvelope( /**< out: | number of bits writen */ + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + Encoder_State *st, /**< in: | encoder state */ + int *pBitOffset, /**< in: | ptr to bitOffset counter */ + const int igfGridIdx, /**< in: | igf grid index see declaration of IGF_GRID_IDX for details */ + const int isIndepFlag, /**< in: | if 1 frame is independent, 0 = frame is coded with data from previous frame */ + int *igfAllZero /**< in: | returns 1 if all IGF scfs are zero, else 0 */ +) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + int totBitCount; + int startBitCount; + int sfb; + + startBitCount = *pBitOffset; + totBitCount = 0; + *igfAllZero = 1; + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + + for (sfb = hGrid->startSfb; sfb < hGrid->stopSfb; sfb++) + { + if (hPrivateData->igfScfQuantized[sfb]!=0) + { + *igfAllZero = 0; + break; + } + } + + if (*igfAllZero) + { + 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) ); + if (NULL == st) + { + IGFSCFEncoderRestoreContextState(&hPrivateData->hIGFSCFArithEnc); + } + } + totBitCount = *pBitOffset - startBitCount; + + return totBitCount; +} + +/**********************************************************************/ /* +identifies significant spectral content +**************************************************************************/ +static float IGF_ErodeSpectrum( /**< out: | highPassEnergy */ + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + float *pSpectrum, /**< in/out: | MDCT spectrum */ + float *pPowerSpectrum, /**< in/out: | power spectrum */ + const int igfGridIdx /**< in: Q0 | IGF grid index */ +) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + int i; + int igfBgn; + int igfEnd; + float highPassEner; + float lastLine; + float nextLine; + float factor; + int *igfScaleF; + int startSfb; + int stopSfb; + int *swb_offset; + int tmp; + int sfb; + int line; + + highPassEner = 0.f; + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[(int)igfGridIdx]; + igfBgn = hGrid->startLine; + igfEnd = hGrid->stopLine; + startSfb = hGrid->startSfb; + stopSfb = hGrid->stopSfb; + swb_offset = hGrid->swb_offset; + igfScaleF = hPrivateData->igfScfQuantized; + + if (NULL == pPowerSpectrum) + { + for (i = igfBgn; i< hGrid->infoGranuleLen; i++) + { + pSpectrum[i] = 0.f; + } + return 0; + } + + if (igfBgn > 0) + { + for (i = 0; i < igfBgn; i++) + { + highPassEner += (float)i * pPowerSpectrum[i]; + } + + if ( hPrivateData->igfInfo.bitRateIndex == IGF_BITRATE_SWB_9600 || + hPrivateData->igfInfo.bitRateIndex == IGF_BITRATE_RF_SWB_13200 || + hPrivateData->igfInfo.bitRateIndex == IGF_BITRATE_SWB_13200 ) + { + factor = 1.f; + } + else + { + factor = 2.f; + } + highPassEner /= igfBgn * factor; /* for 9.6kbs use 1.f */ + lastLine = pSpectrum[i-1]; + nextLine = (pPowerSpectrum[i-1] < highPassEner) ? 0.0f : pSpectrum[i]; + + for (/*i*/; i < igfEnd - 1; i++) + { + if (pPowerSpectrum[i] < highPassEner) + { + lastLine = pSpectrum[i]; + pSpectrum[i] = nextLine; + nextLine = 0.0f; + } + else + { + pSpectrum[i-1] = lastLine; + lastLine = pSpectrum[i]; + nextLine = pSpectrum[i+1]; + } + } + + /* i == igfEnd - 1 */ + if (pPowerSpectrum[i] < highPassEner) + { + pSpectrum[i] = 0.f; + } + } + + /* delete spectrum above igfEnd: */ + for (i = igfEnd; i < hGrid->infoGranuleLen; i++) + { + pSpectrum[i] = 0.f; + pPowerSpectrum[i] = 0.f; + } + + if (NULL != pPowerSpectrum) + { + for (sfb = startSfb; sfb < stopSfb; sfb++) + { + tmp = 0; + for (line = swb_offset[sfb]; line < swb_offset[sfb+1]; line++) + { + if (pSpectrum[line] != 0.f) tmp++; + } + if (tmp && igfScaleF[sfb]) + { + igfScaleF[sfb]--; + } + } + } + + return highPassEner; +} + +/**********************************************************************/ /* +crest factor calculation +**************************************************************************/ +static float IGF_getCrest( /**< out: | crest factor */ + const float *powerSpectrum, /**< in: | power spectrum */ + const int start, /**< in: | start subband index */ + const int stop /**< in: | stop subband index */ +) +{ + int i; + int x; + int x_eff = 0; + int x_max = 0; + float crest = 1.f; + + for (i = start; i < stop; i++) + { + x = max(0, (int)(log(max(FLT_MIN, powerSpectrum[i])) * INV_LOG_2)); + x_eff += x * x; + + if (x > x_max) + { + x_max = x; + } + } + + x_eff /= (stop - start); + + if (x_eff > 0 && x_max > 0) + { + crest = max(1.f, (float)x_max/sqrt(x_eff)); + } + + return crest; +} + +/************************************************************************* +calculates spectral flatness measurment +**************************************************************************/ +static float IGF_getSFM( /**< out: | SFM value */ + const float *powerSpectrum, /**< in: | energies */ + const int start, /**< in: | start subband index */ + const int stop /**< in: | stop subband index */ +) +{ + int n; + int i; + int num; + float denom; + float numf; + float tmp; + float sfm; + + num = 0.f; + denom = 1.f; + sfm = 1.f; + + for (i = start; i < stop; i++) + { + tmp = powerSpectrum[i]; + n = max(0, (int)(log(max(FLT_MIN, tmp)) * INV_LOG_2)); + num += n; + denom += tmp; + } + + numf = (float)num / (float)(stop - start); + denom /= (float)(stop - start); + + if (denom != 0) + { + sfm = min(((float)pow(2.0, numf + 0.5f) / denom), 1.0f); + } + + return sfm; +} + +/**********************************************************************/ /* +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 */ + float *powerSpectrum, /**< in: Q31 | MDCT/MDST power spectrum */ + const int igfGridIdx, /**< in: Q0 | IGF grid index */ + int isTransient, /**< in: Q0 | boolean, indicating if transient is detected */ + int last_core_acelp /**< in: Q0 | indictaor if last frame was acelp coded */ + ) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + int p; + float tmp; + float SFM; + + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[(int)igfGridIdx]; + + if (igfGridIdx != IGF_GRID_LB_NORM) + { + for (p = 0; p < hGrid->nTiles; p++) + { + /* reset filter */ + hPrivateData->prevSFM_FIR[p] = 0.f; + hPrivateData->prevSFM_IIR[p] = 0.f; + + /* preset values: */ + hPrivateData->igfCurrWhiteningLevel[p] = IGF_WHITENING_OFF; + } + } + + for (p = 0; p < IGF_MAX_TILES; p++) + { + /* update prev data: */ + hPrivateData->igfPrevWhiteningLevel[p] = hPrivateData->igfCurrWhiteningLevel[p]; + /* preset values: */ + hPrivateData->igfCurrWhiteningLevel[p] = IGF_WHITENING_OFF; + } + + if (!(isTransient || hPrivateData->wasTransient)) + { + if (powerSpectrum) + { + for (p = 0; p < hGrid->nTiles; p++) + { + tmp = IGF_getSFM(powerSpectrum, hGrid->tile[p], hGrid->tile[p + 1]) / IGF_getCrest(powerSpectrum, hGrid->tile[p], hGrid->tile[p + 1]); + + if(last_core_acelp || hPrivateData->wasTransient) + { + hPrivateData->prevSFM_FIR[p] = hPrivateData->prevSFM_IIR[p] = tmp; + } + + SFM = tmp + hPrivateData->prevSFM_FIR[p] + 0.5f * hPrivateData->prevSFM_IIR[p]; + SFM = min(2.7f, SFM); + + hPrivateData->prevSFM_FIR[p] = tmp; + hPrivateData->prevSFM_IIR[p] = SFM; + + if (SFM > hGrid->whiteningThreshold[1][p]) + { + hPrivateData->igfCurrWhiteningLevel[p] = IGF_WHITENING_STRONG; + } + else if (SFM > hGrid->whiteningThreshold[0][p]) + { + hPrivateData->igfCurrWhiteningLevel[p] = IGF_WHITENING_MID; + } + else + { + hPrivateData->igfCurrWhiteningLevel[p] = IGF_WHITENING_OFF; + } + } + + 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: + 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; + } + } + } + else + { + /* reset filter */ + for (p = 0; p < IGF_MAX_TILES; p++) + { + hPrivateData->prevSFM_FIR[p] = 0.f; + hPrivateData->prevSFM_IIR[p] = 0.f; + } + } + + hPrivateData->wasTransient = isTransient; + + return; +} + + +/**********************************************************************/ /* +write whitening levels into bitstream +**************************************************************************/ +static int IGF_WriteWhiteningTile( /**< out: | number of bits written */ + Encoder_State *st, /**< in: | encoder state handle */ + int *pBitOffset, /**< in: | ptr to bitOffset counter */ + int whiteningLevel /**< in: Q0 | whitening levels to write */ +) +{ + int totBitCount; + int startBitCount; + + totBitCount = 0; + startBitCount = *pBitOffset; + + if (whiteningLevel == IGF_WHITENING_MID) + { + IGF_write_bits(st, pBitOffset, 0, 1); + } + else + { + IGF_write_bits(st, pBitOffset, 1, 1); + if(whiteningLevel == IGF_WHITENING_OFF) + { + IGF_write_bits(st, pBitOffset, 0, 1); + } + else + { + IGF_write_bits(st, pBitOffset, 1, 1); + } + } + totBitCount = *pBitOffset - startBitCount; + + return totBitCount; +} + +/**********************************************************************/ /* +writes the whitening levels +**************************************************************************/ +static int IGF_WriteWhiteningLevels( /**< out: Q0 | total number of bits written */ + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF encoder */ + Encoder_State *st, /**< in: | encoder state */ + int *pBitOffset, /**< in: | ptr to bitOffset counter */ + const int igfGridIdx, /**< in: Q0 | igf grid index see declaration of IGF_GRID_IDX for details */ + const int 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; + int p; + int nTiles; + int totBitCount; + int isSame; + int startBitCount; + + totBitCount = 0; + isSame = 1; + startBitCount = *pBitOffset; + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + nTiles = hGrid->nTiles; + + if (isIndepFlag) + { + isSame = 0; + } + else + { + for (p = 0; p < nTiles ; p++) + { + if (hPrivateData->igfCurrWhiteningLevel[p] != hPrivateData->igfPrevWhiteningLevel[p]) + { + isSame = 0; + break; + } + } + } + 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]); + for (p = 1; p < nTiles ; p++) + { + isSame = 1; + if (hPrivateData->igfCurrWhiteningLevel[p] != hPrivateData->igfCurrWhiteningLevel[p-1]) + { + isSame = 0; + break; + } + } + 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); + } + } + totBitCount = *pBitOffset - startBitCount; + + return totBitCount; +} + +/**********************************************************************/ /* +write flattening trigger +**************************************************************************/ +static int IGF_WriteFlatteningTrigger( /**< out: | number of bits written */ + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + Encoder_State *st, /**< in: | encoder state */ + int *pBitOffset /**< in: | ptr to bitOffset counter */ +) +{ + int totBitCount; + int startBitCount; + int flatteningTrigger; + + totBitCount = 0; + startBitCount = *pBitOffset; + flatteningTrigger = hInstance->flatteningTrigger; + + IGF_write_bits(st, pBitOffset, flatteningTrigger, 1); + + totBitCount = *pBitOffset - startBitCount; + + return totBitCount; +} + +/**********************************************************************/ /* +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 int igfGridIdx /**< in: | 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; + hInstance->infoStopFrequency = hGrid->stopFrequency; + hInstance->infoStartLine = hGrid->startLine; + hInstance->infoStopLine = hGrid->stopLine; + + return; +} + +/**********************************************************************/ /* +IGF bitsream writer +**************************************************************************/ +int IGFEncWriteBitstream( /**< out: | number of bits written per frame */ + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + void *st, /**< in: | encoder state */ + int *pBitOffset, /**< in: | ptr to bitOffset counter */ + const int igfGridIdx, /**< in: | igf grid index see declaration of IGF_GRID_IDX for details */ + const int isIndepFlag /**< in: | if 1 frame is independent, 0 = frame is coded with data from previous frame */ +) +{ + int igfAllZero; + int startBitCount = *pBitOffset; + + hInstance->infoTotalBitsPerFrameWritten = 0; + hInstance->infoFrameCount++; + if (isIndepFlag) + { + hInstance->infoTotalBitsWritten = 0; + } + + 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 = (*pBitOffset - startBitCount); + 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 int bitRate, /**< in: | encoder bitrate */ + const int mode, /**< in: | encoder bandwidth mode */ + int const rf_mode /**< in: flag to signal the RF mode */ +) +{ + short i; + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + + hPrivateData = &hInstance->igfData; + hPrivateData->igfBitstreamBits = 0; + set_i(hPrivateData->igfScfQuantized, 0, IGF_MAX_SFB); + set_i(hPrivateData->igfCurrWhiteningLevel, 0, IGF_MAX_TILES); + set_i(hPrivateData->igfPrevWhiteningLevel, 0, IGF_MAX_TILES); + for( i=0; iigfBitstream[i] = 0; + } + hPrivateData->wasTransient = 0; + set_f(hPrivateData->prevSFM_FIR, 0, IGF_MAX_TILES); + set_f(hPrivateData->prevSFM_IIR, 0, IGF_MAX_TILES); + + + if (IGFCommonFuncsIGFConfiguration(bitRate, mode, &hPrivateData->igfInfo, rf_mode)) + { + IGFSCFEncoderOpen( &hPrivateData->hIGFSCFArithEnc, hPrivateData->igfInfo.grid[0].stopSfb - hPrivateData->igfInfo.grid[0].startSfb, bitRate, mode, rf_mode ); + + hInstance->infoSamplingRate = hPrivateData->igfInfo.sampleRate; + hInstance->infoStartFrequency = hPrivateData->igfInfo.grid[0].startFrequency; + hInstance->infoStopFrequency = hPrivateData->igfInfo.grid[0].stopFrequency; + hInstance->infoStartLine = hPrivateData->igfInfo.grid[0].startLine; + hInstance->infoStopLine = hPrivateData->igfInfo.grid[0].stopLine; + } + else + { + /* IGF configuration failed -> error! */ + hInstance->infoSamplingRate = 0; + hInstance->infoStartFrequency = -1; + hInstance->infoStopFrequency = -1; + hInstance->infoStartLine = -1; + hInstance->infoStopLine = -1; + fprintf(stderr,"IGFEncSetMode: initialization error!\n"); + } + + /* reset remaining variables */ + hInstance->infoTotalBitsWritten = 0; + hInstance->infoTotalBitsPerFrameWritten = 0; + hInstance->flatteningTrigger = 0; + hInstance->tns_predictionGain = 0; + set_f(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 */ + short bsBits, /**< in: | number of IGF bits written to list of indices */ + short *next_ind, /**< in/out: | pointer to actual bit indice */ + short *nb_bits, /**< in/out: | total number of bits already written */ + Indice *ind_list /**< in: | pointer to list of indices */ + ) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + + hPrivateData = &hInstance->igfData; + *next_ind -= bsBits; + + indices_to_serial_generic( + &ind_list[*next_ind], + bsBits, + hPrivateData->igfBitstream, + &hPrivateData->igfBitstreamBits + ); + + *nb_bits -= hInstance->infoTotalBitsPerFrameWritten; + + 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; + hInstance->infoTotalBitsWritten = 0; +} + +/**********************************************************************/ /* +IGF write concatenated bitsream for TCX10 modes +**************************************************************************/ +int IGFEncWriteConcatenatedBitstream( /**< out: | 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; + int i; + int bitsLeft; + UWord8 *pBitstream; + + hPrivateData = &hInstance->igfData; + pBitstream = hPrivateData->igfBitstream; + + for (i = 0; i < hPrivateData->igfBitstreamBits >> 3; i++) + { + push_next_indice(st, pBitstream[i], 8); + } + + bitsLeft = hPrivateData->igfBitstreamBits & 0x7; + if(bitsLeft > 0) + { + push_next_indice(st, pBitstream[i] >> (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 int igfGridIdx, /**< in: | IGF grid index */ + Encoder_State *st, /**< in: | Encoder state */ + float *pMDCTSpectrum, /**< in: | MDCT spectrum */ + float *pPowerSpectrum, /**< in: | MDCT^2 + MDST^2 spectrum, or estimate */ + int isTCX20, /**< in: | flag indicating if the input is TCX20 or TCX10/2xTCX5 */ + int isTNSActive, /**< in: | flag indicating if the TNS is active */ + int last_core_acelp /**< in: | indictaor if last frame was acelp coded */ + ) +{ + float *pPowerSpectrumParameter; /* If it is NULL it informs a function that specific handling is needed */ + + pPowerSpectrumParameter = !isTNSActive && isTCX20 ? pPowerSpectrum : NULL; + + 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 */ + pPowerSpectrumParameter, /* i: MDCT^2 + MDST^2 spectrum, or estimate */ + igfGridIdx /* i: IGF grid index */ + ); + + + IGF_Whitening(hInstance, /* i: instance handle of IGF Encoder */ + isTCX20 ? pPowerSpectrum : NULL, /* i: MDCT^2 + MDST^2 spectrum, or estimate */ + igfGridIdx, /* i: IGF grid index */ + (st->transientDetection.transientDetector.bIsAttackPresent == 1), + last_core_acelp /* i: last frame was acelp indicator */ + ); + + pPowerSpectrumParameter = isTCX20 ? pPowerSpectrum : NULL; + + IGF_ErodeSpectrum( /* o: highpass energy */ + hInstance, /* i: instance handle of IGF Encoder */ + pMDCTSpectrum, /* i: MDCT spectrum */ + pPowerSpectrumParameter, /* i: MDCT^2 + MDST^2 spectrum, or estimate */ + 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 000000000..60377b27e --- /dev/null +++ b/lib_enc/igf_scf_enc.c @@ -0,0 +1,363 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "prot.h" +#include "options.h" +#include "stat_enc.h" +#include "stat_com.h" +#include "cnst.h" + +/*---------------------------------------------------------------------* + * IGFSCFEncoderOpen() + * + * initialization of an instance of this module, pass a ptr to a hPublicData + *---------------------------------------------------------------------*/ + +void IGFSCFEncoderOpen( + IGFSCFENC_INSTANCE_HANDLE hPublicData, /**< inout: handle to public data */ + int scfCountLongBlock, + int bitRate, + int mode, + int rf_mode /**< in: flag to signal the RF mode */ +) +{ + + hPublicData->ptrBitIndex = 0; + hPublicData->bitCount = 0; + hPublicData->Tsave = 0; + hPublicData->contex_saved = 0; + hPublicData->acState.low = 0; + hPublicData->acState.high = 0; + hPublicData->acState.vobf = 0; + set_i(hPublicData->prev, 0, 64); + set_i(hPublicData->prevSave, 0, 64); + + hPublicData->scfCountLongBlock = scfCountLongBlock; + hPublicData->t = 0; /* 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 ); + + return; +} + + +/*---------------------------------------------------------------------* + * quant_ctx() + * + * + *---------------------------------------------------------------------*/ + +static int quant_ctx( + int ctx +) +{ + /* + 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 ... + */ + if (abs(ctx) <= 3) + { + return ctx; + } + else if (ctx > 3) + { + return 3; + } + else /* ctx < -3 */ + { + return -3; + } +} + + +/*---------------------------------------------------------------------* + * arith_encode_bits() + * + * + *---------------------------------------------------------------------*/ + +static void arith_encode_bits( + IGFSCFENC_INSTANCE_HANDLE hPrivateData, /**< instance handle */ + int *ptr, /**< pointer to expanded bit buffer, one bit in each int */ + int x, /**< value to encode */ + int nBits /**< number of bits to encode */ +) +{ + int i; + int bit; + + for (i = nBits - 1; i >= 0; --i) + { + bit = (x >> i) & 1; + hPrivateData->ptrBitIndex = ari_encode_14bits_sign(ptr, hPrivateData->ptrBitIndex, 32767, /* disable the bit count limitation */ &hPrivateData->acState, bit ); + } + + return; +} + + +/*---------------------------------------------------------------------* + * arith_encode_residual() + * + * + *---------------------------------------------------------------------*/ + +static void arith_encode_residual( + IGFSCFENC_INSTANCE_HANDLE hPrivateData, /**< instance handle */ + int *ptr, /**< pointer to expanded bit buffer, one bit in each int */ + int x, /**< prediction residual to encode */ + const unsigned short *cumulativeFrequencyTable, /**< cumulative frequency table to be used */ + int tableOffset /**< offset used to align the table */ +) +{ + int extra; + + x += tableOffset; + if ((x >= IGF_MIN_ENC_SEPARATE) && (x <= IGF_MAX_ENC_SEPARATE)) + { + /* 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 - IGF_MIN_ENC_SEPARATE) + 1, cumulativeFrequencyTable ); + + return; + } + else if (x < IGF_MIN_ENC_SEPARATE) + { + /* send escape code 0 to indicate x <= IGF_MIN_ENC_SEPARATE - 1 */ + extra = (IGF_MIN_ENC_SEPARATE - 1) - x; + hPrivateData->ptrBitIndex = ari_encode_14bits_ext( ptr, hPrivateData->ptrBitIndex, &hPrivateData->acState, 0, cumulativeFrequencyTable ); + } + else + { + /* x > IGF_MAX_ENC_SEPARATE */ + /* send escape code (IGF_SYMBOLS_IN_TABLE - 1) to indicate x >= IGF_MAX_ENC_SEPARATE + 1 */ + extra = x - (IGF_MAX_ENC_SEPARATE + 1); + hPrivateData->ptrBitIndex = ari_encode_14bits_ext( ptr, hPrivateData->ptrBitIndex, &hPrivateData->acState, IGF_SYMBOLS_IN_TABLE - 1, cumulativeFrequencyTable ); + } + + /* encode one of the tails of the distribution */ + if (extra < 15) + { + /* 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 -= 15; + + if (extra < 63) + { + /* encode additional extra with 6 bits */ + arith_encode_bits(hPrivateData, ptr, extra, 6); + } + else /* extra >= 63 */ + { + arith_encode_bits(hPrivateData, ptr, 63, 6); + extra -= 63; + /* encode safety extra with 7 bits */ + arith_encode_bits(hPrivateData, ptr, extra, 7); + } + } + + return; +} + + +/*---------------------------------------------------------------------* + * encode_sfe_vector() + * + * + *---------------------------------------------------------------------*/ + +static void encode_sfe_vector( + IGFSCFENC_INSTANCE_HANDLE hPrivateData, /**< instance handle */ + int *ptr, /**< pointer to expanded bit buffer, one bit in each int */ + int t, /**< frame counter reset to 0 at each independent frame */ + int *prev_x, /**< previous vector */ + int *x, /**< current vector to encode */ + int length, /**< number of elements to encode */ + int do_real_encoding /**< whether the real encoding is needed, otherwise only the number of bits is used */ +) +{ + /* + f + ^ + | d a x + | c b + | e --> t + */ + int f; + int pred; + int ctx; + int ctx_f; + int ctx_t; + + + (void) do_real_encoding; /* avoid compiler warning: unreferenced formal parameter */ + + for (f = 0; f < length; f++) + { + if (t == 0) + { + if (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, x[f] >> 2, hPrivateData->cf_se00 ); + arith_encode_bits(hPrivateData, ptr, x[f] & 3, 2); /* LSBs as 2 bit raw */ + } + else if (f == 1) + { + pred = x[f - 1]; /* pred = b */ + arith_encode_residual( hPrivateData, ptr, x[f] - pred, hPrivateData->cf_se01, hPrivateData->cf_off_se01 ); + } + else + { + /* f >= 2 */ + pred = x[f - 1]; /* pred = b */ + ctx = quant_ctx(x[f - 1] - x[f - 2]); /* Q(b - e) */ + arith_encode_residual( hPrivateData, ptr, x[f] - pred, &hPrivateData->cf_se02[(IGF_SYMBOLS_IN_TABLE + 1) * (IGF_CTX_OFFSET + ctx)], + hPrivateData->cf_off_se02[IGF_CTX_OFFSET + ctx] ); + } + } + else + { + /* t == 1 */ + if (f == 0) + { + pred = prev_x[f]; /* pred = a */ + arith_encode_residual( hPrivateData, ptr, x[f] - pred, hPrivateData->cf_se10, hPrivateData->cf_off_se10 ); + } + else + { + /* (t == 1) && (f >= 1) */ + pred = prev_x[f] + x[f - 1] - prev_x[f - 1]; /* pred = a + b - c */ + ctx_f = quant_ctx(prev_x[f] - prev_x[f - 1]); /* Q(a - c) */ + ctx_t = quant_ctx(x[f - 1] - prev_x[f - 1]); /* Q(b - c) */ + arith_encode_residual( hPrivateData, ptr, x[f] - pred, + &hPrivateData->cf_se11[(IGF_SYMBOLS_IN_TABLE + 1) * IGF_CTX_COUNT * (IGF_CTX_OFFSET + ctx_t) + (IGF_SYMBOLS_IN_TABLE + 1) * (IGF_CTX_OFFSET + ctx_f)], + hPrivateData->cf_off_se11[IGF_CTX_COUNT * (IGF_CTX_OFFSET + ctx_t) + (IGF_CTX_OFFSET + ctx_f)]); + } + } + } + + return; +} + + +/*---------------------------------------------------------------------* + * IGFSCFEncoderReset() + * + * Reset of Arith enc context memory + *---------------------------------------------------------------------*/ + +int IGFSCFEncoderReset( + IGFSCFENC_INSTANCE_HANDLE hPublicData +) +{ + + + hPublicData->t = 0; + /* we do not need to fill hPublicData->prev with zeros, because when t = 0 no previous information is used */ + + return 0; +} + + +/*---------------------------------------------------------------------* + * IGFSCFEncoderEncode() + * + * main IGF encoder function + *---------------------------------------------------------------------*/ + +int IGFSCFEncoderEncode( + IGFSCFENC_INSTANCE_HANDLE hPublicData, /**< inout: handle to public data or NULL in case there was no instance created */ + Encoder_State *st, /**< inout: pointer to decoder state */ + int bitCount, /**< in: offset to the first bit in bitbuffer which should be readed by iisArithDecoderDecode function */ + int *sfe, /**< in: ptr to an array which contain quantized scalefactor energies */ + int indepFlag, /**< in: if 1 on input the encoder will be forced to reset, + if 0 on input the encodder will be forced to encode without a reset */ + int doRealEncoding /**< in: whether the real encoding is needed, otherwise only the number of bits is used */ +) +{ + int ptr[BITBUFSIZE]; /* temporary expanded bit buffer, one bit in each int */ + int i; + + + /* insert data: */ + hPublicData->ptrBitIndex = 0; + hPublicData->bitCount = bitCount; + ari_start_encoding_14bits(&hPublicData->acState); /* start AC encoding */ + + /* check if coder needs a reset and do it if necessary */ + if (indepFlag) + { + IGFSCFEncoderReset( hPublicData ); + } + + encode_sfe_vector( hPublicData, ptr, hPublicData->t, hPublicData->prev, sfe, hPublicData->scfCountLongBlock, doRealEncoding ); + + hPublicData->ptrBitIndex = ari_done_encoding_14bits( ptr, hPublicData->ptrBitIndex, &hPublicData->acState ); /* finish AC encoding */ + hPublicData->bitCount = hPublicData->bitCount + hPublicData->ptrBitIndex; + + /* advancing history: */ + mvi2i(sfe, hPublicData->prev, hPublicData->scfCountLongBlock); + hPublicData->t++; + + /* 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(st, ptr[i], 1); + } + } + + /* return next bit offset in the stream */ + return hPublicData->bitCount; +} + + +/*---------------------------------------------------------------------* + * IGFSCFEncoderSaveContextState() + * + * for a closed loop enc, the ArithEncoder needs to memorize the context + *---------------------------------------------------------------------*/ + +void IGFSCFEncoderSaveContextState( + IGFSCFENC_INSTANCE_HANDLE hPublicData /**< inout: handle to public data or NULL in case there was no instance created */ +) +{ + + hPublicData->Tsave = hPublicData->t; + + mvi2i(hPublicData->prev, hPublicData->prevSave, hPublicData->scfCountLongBlock); + + + return; +} + +/*---------------------------------------------------------------------* + * IGFSCFEncoderRestoreContextState() + * + * for a closed loop enc, the ArithEncoder needs to memorize the context + *---------------------------------------------------------------------*/ +void IGFSCFEncoderRestoreContextState( + IGFSCFENC_INSTANCE_HANDLE hPublicData /**< inout: handle to public data or NULL in case there was no instance created */ +) +{ + + + hPublicData->t = hPublicData->Tsave; + + mvi2i(hPublicData->prevSave, hPublicData->prev, hPublicData->scfCountLongBlock); + + + return; +} diff --git a/lib_enc/init_enc.c b/lib_enc/init_enc.c new file mode 100644 index 000000000..f618d84d7 --- /dev/null +++ b/lib_enc/init_enc.c @@ -0,0 +1,732 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_com.h" +#include "rom_enc.h" +#include "prot.h" + + +/*-----------------------------------------------------------------------* + * init_encoder() + * + * Initialization of state variables + *-----------------------------------------------------------------------*/ + +void init_encoder( + Encoder_State *st /* i/o: Encoder static variables structure */ +) +{ + short i; + + st->nb_bits_tot = 0; + /*-----------------------------------------------------------------* + * ACELP core parameters + *-----------------------------------------------------------------*/ + + if ( st->Opt_AMR_WB ) + { + st->last_core = AMR_WB_CORE; + } + else + { + st->last_core = -1; + } + + st->L_frame = L_FRAME; + st->last_coder_type = GENERIC; + st->last_7k2_coder_type = GENERIC; + st->last_total_brate = st->total_brate; + st->last_total_brate_cng = -1; + st->last_core_brate = st->total_brate; + st->extl = -1; + st->last_extl = -1; + st->last_L_frame = L_FRAME; + st->rate_switching_reset = 0; + st->rate_switching_reset_16kHz = 0; + + mvr2r( GEWB_Ave, st->mem_AR, M ); + mvr2r( GEWB_Ave, st->lsfoldbfi0, M ); + mvr2r( GEWB_Ave, st->lsfoldbfi1, M ); + mvr2r( GEWB_Ave, st->lsf_adaptive_mean, M ); + init_lvq( st->offset_scale1, st->offset_scale2, st->offset_scale1_p, st->offset_scale2_p, st->no_scales, st->no_scales_p ); + st->next_force_safety_net = 0; + + st->pstreaklen = 0; + st->streaklimit = 1.0f; + set_f(st->mem_MA, 0, M ); + + init_gp_clip(st->clip_var); + pitch_ol_init( &st->old_thres, &st->old_pitch, &st->delta_pit, &st->old_corr) ; + + hf_cod_init( st->mem_hp400_enc, st->mem_hf_enc, st->mem_syn_hf_enc, st->mem_hf2_enc, &st->gain_alpha ); + + st->LPDmem.tilt_code = 0.0f; + st->LPDmem.gc_threshold = 0.0f; + + st->clas = UNVOICED_CLAS; + set_f( st->old_inp_12k8, 0, L_INP_MEM ); + set_f( st->old_wsp, 0, L_WSP_MEM ); + set_f( st->LPDmem.old_exc, 0, L_EXC_MEM ); + set_f( st->old_wsp2, 0, (L_WSP_MEM - L_INTERPOL)/OPL_DECIM ); + set_f( st->old_inp_16k, 0, L_INP_MEM ); + + st->mem_deemph = 0.0f; + st->mem_preemph = 0.0f; + st->mem_preemph16k = 0.0f; + st->mem_preemph_enc = 0.0; + + /* AVQ pre-quantizer memory */ + st->mem_preemp_preQ = 0.0f; + st->mem_deemp_preQ = 0.0f; + st->last_nq_preQ = 0; + st->use_acelp_preq = 0; + + /* (Decimated) Weighted Speech Memory */ + st->mem_wsp_enc = 0.0; + + set_f( st->mem_decim16k, 0, 2*L_FILT_MAX ); + st->mem_wsp = 0.0f; + st->LPDmem.mem_w0 = 0.0f; + set_f( st->LPDmem.mem_syn, 0, M ); + set_f( st->mem_syn1, 0, M ); + st->mem_deemph_old_syn = 0.0f; + set_f( st->LPDmem.mem_syn2, 0, M ); + set_f( st->mem_decim, 0, 2*L_FILT_MAX ); + set_f( st->mem_decim2, 0, 3 ); + set_f( st->Bin_E, 0, L_FFT ); + set_f( st->Bin_E_old, 0, L_FFT/2 ); + set_f( st->LPDmem.mem_syn3, 0, M ); + + st->ini_frame = 0; + st->ee_old = 10.0f; + st->Nb_ACELP_frames = 0; + st->audio_frame_cnt = AUDIO_COUNTER_INI; /* Initializatin of the audio frame counter mildly into the audio mode */ + + /* adaptive lag window memory */ + st->old_pitch_la = 0; + st->old_voicing_la = 0; + + set_f( st->mem_hp20_in, 0.0f, 4 ); + + set_f( st->dispMem, 0, 8 ); + + /* HF (6-7kHz) BWE */ + st->seed2_enc = RANDOM_INITSEED; + + for (i=0; ipast_qua_en[i] = -14.0f; /* gain quantization memory (used in AMR-WB IO mode) */ + } + + if( st->input_Fs == 8000 ) + { + st->min_band = 1; + st->max_band = 16; + } + else + { + st->min_band = 0; + st->max_band = 19; + } + + for( i=0; ifr_bands1[i] = 1e-5f; + st->fr_bands2[i] = 1e-5f; + st->ave_enr2[i] = E_MIN; + } + + if ( st->Opt_AMR_WB ) + { + mvr2r( mean_isf_amr_wb, st->lsf_old, M ); + isf2isp( st->lsf_old, st->lsp_old1, M, INT_FS_12k8 ); + } + else + { + mvr2r( GEWB_Ave, st->lsf_old, M ); + lsf2lsp( st->lsf_old, st->lsp_old1, M, INT_FS_12k8 ); + } + + mvr2r( st->lsf_old, st->lsf_old1, M ); + mvr2r( st->lsp_old1, st->lsp_old, M ); + mvr2r( st->lsp_old, st->lsp_old16k, M ); + mvr2r( st->lsp_old, st->lspold_enc, M ); + + st->stab_fac = 0.0f; + + MDCT_selector_reset( st ); + + /* Bass post-filter memories - enceder side of MODE2 */ + st->bpf_off = 0; + st->pst_mem_deemp_err = 0.0f; + st->pst_lp_ener = 0.0f; + + /* TC mode */ + st->tc_cnt = 0; + st->mCb1 = 0; + + /* AC mode */ + st->seed_tcx = 15687; + st->cor_strong_limit = 1; + set_f( st->last_exc_dct_in, 0, L_FRAME ); + st->last_ener = 0.0f; + set_s( st->last_bitallocation_band, 0, 6 ); + + st->mem_last_pit_band = BAND1k2+1; + + st->old_dE1 = 0.0f; + st->old_ind_deltaMax = 0; + set_f( st->old_enr_ssf, 0.0f, 2*NB_SSF ); + st->spike_hyst = -1; + st->music_hysteresis = 0; /* Counter of frames after AUDIO frame to prevent UC */ + st->last_harm_flag_acelp = 0; + st->GSC_noisy_speech = 0; + + /*-----------------------------------------------------------------* + * speech/music classifier + *-----------------------------------------------------------------*/ + + st->inact_cnt = 0; + set_s( st->past_dec, 0, HANG_LEN-1 ); + set_f( st->past_dlp, 0, HANG_LEN-1 ); + + for( i=0; ipast_log_enr[i] = (float)log(E_MIN); + } + + st->sp_mus_state = -8; + st->wdrop = 0.0f; + st->wdlp_0_95_sp = 0.0f; + set_f( st->last_lsp, 0.0f, M_LSP_SPMUS ); + st->last_cor_map_sum = 0.0f; + st->last_non_sta = 0.0f; + set_f( st->past_PS, 0.0f, HIGHEST_FBIN-LOWEST_FBIN ); + st->past_ps_diff = 0; + st->past_epsP2 = 01; + + st->gsc_thres[0] = TH_0_MIN; + st->gsc_thres[1] = TH_1_MIN; + st->gsc_thres[2] = TH_2_MIN; + st->gsc_thres[3] = TH_3_MIN; + set_f( st->gsc_lt_diff_etot, 0.0f, MAX_LT ); + st->gsc_mem_etot = 0.0f; + st->gsc_last_music_flag = 0; + st->gsc_nb_thr_1 = 0; + st->gsc_nb_thr_3 = 0; + st->mold_corr = 0.9f; + st->lt_gpitch = 0.0f; + st->mean_avr_dyn = 0.5f; + st->last_sw_dyn = 10.0f; + st->pit_exc_hangover = 0; + st->Last_pulse_pos = 0; + + /* speech/music classifier improvement */ + for ( i=0; ibuf_flux[i] = -100; + st->buf_pkh[i] = 0; + st->buf_epsP_tilt[i] = 0; + st->buf_cor_map_sum[i] = 0; + st->buf_Ntonal[i] = 0; + st->buf_Ntonal2[i] = 0; + st->buf_Ntonal_lf[i] = 0; + } + + set_f( st->lpe_buf, 0, HANG_LEN_INIT ); + set_f( st->voicing_buf, 0, HANG_LEN_INIT ); + st->gsc_hangover = 0; + set_f( st->sparse_buf, 0, HANG_LEN_INIT ); + set_f( st->hf_spar_buf, 0, HANG_LEN_INIT ); + st->LT_sparse = 0.0f; + st->gsc_cnt = 0; + st->last_vad_spa = 0; + + set_f( st->old_Bin_E, 0.0f, 3*N_OLD_BIN_E ); + set_f( st->buf_etot, 0, 4 ); + set_f( st->buf_dlp, 0, 10 ); + + st->UV_cnt1 = 300; + st->LT_UV_cnt1 = 250.0f; + st->onset_cnt = 0; + st->attack_hangover = 0; + st->dec_mov = 0.0f; + st->dec_mov1 = 0.0f; + st->mov_log_max_spl = 200.0f; + st->old_lt_diff[0] = 0.0f; + st->old_lt_diff[1] = 0.0f; + + st->Etot_h = 0.0f; + st->Etot_l = 0.0f; + st->Etot_l_lp = 0.0f; + st->Etot_last = 0.0f; + st->Etot_v_h2 = 0.0f; + st->sign_dyn_lp = 0.0f; + + /*-----------------------------------------------------------------* + * GSC + *-----------------------------------------------------------------*/ + + /* GSC - pitch excitation parameters */ + st->mem_w0_tmp = 0.0f; + set_f(st->mem_syn_tmp, 0.0f, M); + st->high_stable_cor = 0; + set_f(st->var_cor_t, 0.0f, VAR_COR_LEN); + + st->lps = 0.0f; + st->lpm = 0.0f; + st->Last_frame_ener = (float)MAX_32; + st->lt_dec_thres = 10.0f; + st->ener_RAT = 0.0f; + st->mid_dyn = 40.0f; + st->noise_lev = NOISE_LEVEL_SP0; + st->past_dyn_dec = 0; + + /*-----------------------------------------------------------------* + * VAD & noise estimator + *-----------------------------------------------------------------*/ + + wb_vad_init( &st->nb_active_frames, &st->hangover_cnt, &st->lp_speech, &st->nb_active_frames_he, &st->hangover_cnt_he, + &st->bcg_flux, &st->soft_hangover, &st->voiced_burst, &st->bcg_flux_init, &st->nb_active_frames_he1, &st->hangover_cnt_he1, + &st->vad_flag_reg_H, &st->vad_flag_reg_L, &st->vad_prim_reg, &st->vad_flag_cnt_50, &st->vad_prim_cnt_16, + &st->hangover_cnt_dtx, &st->flag_noisy_speech_snr, &st->hangover_cnt_music ); + + st->Pos_relE_cnt = 20; + + st->nb_active_frames_HE_SAD = 0; + + /* Noise estimator */ + noise_est_init( &st->totalNoise, &st->first_noise_updt, st->bckr, st->enrO, st->ave_enr, &st->pitO, &st->aEn, + &st->harm_cor_cnt, &st->bg_cnt, &st->lt_tn_track, &st->lt_tn_dist, + &st->lt_Ellp_dist,&st->lt_haco_ev,&st->low_tn_track_cnt, &st->Etot_st_est,&st->Etot_sq_st_est ); + + st->epsP_0_2_lp = 1.0f; + st->epsP_0_2_ad_lp = 0.0f; + st->epsP_2_16_lp = 1.0f; + st->epsP_2_16_lp2 = 1.0f; + st->epsP_2_16_dlp_lp = 0.0f; + st->epsP_2_16_dlp_lp2 = 0.0f; + st->lt_aEn_zero = 0.0f; + st->prim_act_quick = 0.0f; + st->prim_act_slow = 0.0f; + st->prim_act = 0.0f; + st->prim_act_quick_he = 0.0f; + st->prim_act_slow_he = 0.0f; + st->prim_act_he = 0.0f; + st->bckr_tilt_lt = 0.f; + + /*-----------------------------------------------------------------* + * WB, SWB and FB bandwidth detector + *-----------------------------------------------------------------*/ + + st->lt_mean_NB = 0; + st->lt_mean_WB = 0; + st->lt_mean_SWB = 0; + st->count_WB = BWD_COUNT_MAX; + st->count_SWB = BWD_COUNT_MAX; + st->count_FB = BWD_COUNT_MAX; + st->bwidth = st->max_bwidth; + st->last_input_bwidth = st->bwidth; + st->last_bwidth = st->bwidth; + st->last_bwidth_cng = st->bwidth; + + /*-----------------------------------------------------------------* + * + *-----------------------------------------------------------------*/ + + /* Tonal detector */ + for ( i=0; iold_S[i] = 1; + } + set_f(st->cor_map, 0, L_FFT/2 ); + st->act_pred = 1; + st->noise_char = 0; + st->multi_harm_limit = THR_CORR; + st->coder_type_raw = VOICED; + st->last_coder_type_raw = st->coder_type_raw; + + /* Stationary noise UV modification */ + st->ge_sm = 10; + st->uv_count = 0; + st->act_count = 3; + mvr2r(st->lsp_old, st->lspold_s, M); + st->noimix_seed = RANDOM_INITSEED; + st->min_alpha = 1; + st->exc_pe = 0; + + /*-----------------------------------------------------------------* + * CNG and DTX + *-----------------------------------------------------------------*/ + + st->lp_noise = 0.0f; + mvr2r( st->lsp_old1, st->lspCNG, M ); + st->cng_seed = RANDOM_INITSEED; + st->cng_ener_seed = RANDOM_INITSEED; + st->cng_ener_seed1 = RANDOM_INITSEED; + st->lp_ener = 0.0f; + st->first_CNG = 0; + st->cnt_SID = 0; + st->max_SID = 2; + st->old_enr_index = -1; + st->Enew = 0.0f; + st->VarDTX_cnt_voiced = 0; + st->lt_ener_voiced = 0.0f; + st->VarDTX_cnt_noise = 0; + st->lt_ener_noise = 0.0f; + st->lt_ener_last_SID = 0.0f; + if( st->var_SID_rate_flag ) + { + st->interval_SID = 12; + } + st->lp_sp_enr = 0.0f; + st->last_allow_cn_step = 0; + + st->fd_cng_reset_flag = 0; + + if( st->Opt_DTX_ON ) + { + st->cng_hist_ptr = -1; + set_f( st->cng_lsp_hist, 0, DTX_HIST_SIZE*M ); + set_f( st->cng_ener_hist, 0, DTX_HIST_SIZE ); + st->cng_cnt = 0; + st->ho_hist_ptr = -1; + st->ho_sid_bw = 0; + set_f( st->ho_lsp_hist, 0, HO_HIST_SIZE*M ); + set_f( st->ho_ener_hist, 0, HO_HIST_SIZE ); + set_f( st->ho_env_hist, 0, HO_HIST_SIZE*NUM_ENV_CNG ); + st->ho_hist_size = 0; + st->act_cnt = 0; + } + + st->active_cnt = 0; + st->cng_type = -1; + + st->CNG_mode = -1; + st->last_active_brate = ACELP_7k20; + st->last_CNG_L_frame = L_FRAME; + set_s( st->ho_16k_lsp, 0, HO_HIST_SIZE ); + st->act_cnt2 = 0; + st->num_ho = 0; + st->hangover_terminate_flag = 0; + + st->ho_circ_ptr = -1; + set_f( st->ho_lsp_circ, 0, HO_HIST_SIZE*M ); + set_f( st->ho_ener_circ, 0, HO_HIST_SIZE ); + set_f( st->ho_env_circ, 0, HO_HIST_SIZE*NUM_ENV_CNG ); + st->ho_circ_size = 0; + st->burst_ho_cnt = 0; + st->cng_buf_cnt = 0; + + if( st->var_SID_rate_flag || ((!st->var_SID_rate_flag) && (st->interval_SID >= DTX_HIST_SIZE)) ) + { + st->cng_hist_size = DTX_HIST_SIZE; + } + else + { + st->cng_hist_size = st->interval_SID; + } + set_f(st->lp_env, 0.0f, 20); + set_f(st->cng_res_env, 0.0f, 20*8); + set_f(st->exc_mem, 0.0f, 24); + set_f(st->exc_mem1, 0.0f, 30); + set_f(st->exc_mem2, 0.0f, 30); + set_f(st->old_env, 0.0f, NUM_ENV_CNG); + /* SWB CNG/DTX */ + st->last_wb_cng_ener = -6.02f; + st->last_shb_cng_ener = -6.02f; + st->mov_wb_cng_ener = -6.02f; + st->mov_shb_cng_ener = -6.02f; + st->shb_cng_ini_cnt = 1; + st->shb_NO_DATA_cnt = 0; + st->last_SID_bwidth = min( st->max_bwidth, SWB ); + st->last_vad = 0; + /* FEC */ + st->last_clas = UNVOICED_CLAS; + + for (i=0; i<2*NB_SUBFR16k; i++) + { + st->old_pitch_buf[i] = L_SUBFR; + } + + st->old_Es_pred = 0; + set_f( st->old_Aq_12_8 + 1, 0, M ); + st->old_Aq_12_8[0] = 1; + + /*-----------------------------------------------------------------* + * CLDFB & resampling tools parameters + *-----------------------------------------------------------------*/ + + openCldfb( &st->cldfbAnaEnc, CLDFB_ANALYSIS, st->input_Fs ); + + st->currEnergyLookAhead = 6.1e-5f; + + /*-----------------------------------------------------------------* + * SC-VBR parameters + *-----------------------------------------------------------------*/ + + st->nelp_enc_seed = 0; + st->last_nelp_mode = 0; + st->pppcountE = 0; + st->last_ppp_mode = 0; + st->last_last_ppp_mode = 0; + st->firstTime_voicedenc = 1; + st->prev_ppp_gain_pit = 0.0; + st->prev_tilt_code = 0.0; + + st->ppp_mode = 0; + st->nelp_mode = 0; + + /* stable short pitch detection */ + st->voicing0_sm = 0; + st->voicing_sm = 0; + st->LF_EnergyRatio_sm = 1; + st->predecision_flag = 0; + st->diff_sm = 0; + st->energy_sm = 0; + + st->pattern_m = 0; + st->Last_Resort = 0; + st->set_ppp_generic = 0; + st->Q_to_F = 0; + + st->numactive = 0; /* keep the count of the frames inside current 600 frame bloack.*/ + st->sum_of_rates = 0.0f; /* sum of the rates of past 600 active frames*/ + st->global_avr_rate = 0.0f; /* global rate upto current time. recorded a (rate in kbps) *6000*/ + st->global_frame_cnt = 0; /* 600 active frame block count. Used to update the global rate*/ + + st->rate_control = 0; + st->SNR_THLD = 67.0f; + st->mode_QQF = 1; + st->last_Opt_SC_VBR = 0; + + set_f(st->shape1_filt_mem, 0, 20); + set_f(st->shape2_filt_mem, 0, 20); + set_f(st->shape3_filt_mem, 0, 20); + set_f(st->txlpf1_filt1_mem, 0, 20); + set_f(st->txlpf1_filt2_mem, 0, 20); + set_f(st->txhpf1_filt1_mem, 0, 20); + set_f(st->txhpf1_filt2_mem, 0, 20); + + /*-----------------------------------------------------------------* + * SWB BWE parameters + *-----------------------------------------------------------------*/ + + set_f( st->new_input_hp, 0, NS2SA(16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS)); + set_f( st->old_input, 0, NS2SA(48000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS) ); + set_f( st->old_input_wb, 0, NS2SA(16000, DELAY_FD_BWE_ENC_12k8_NS) ); + set_f( st->old_input_lp, 0, NS2SA(16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS) ); + set_f( st->old_syn_12k8_16k, 0, NS2SA(16000, DELAY_FD_BWE_ENC_NS) ); + + st->prev_mode = NORMAL; + set_f( st->old_wtda_swb, 0, L_FRAME48k ); + st->prev_L_swb_norm1 = 8; + st->prev_global_gain = 0.0f; + st->modeCount = 0; + st->EnergyLF = 0.0f; + + + /*-----------------------------------------------------------------* + * TBE parameters + *-----------------------------------------------------------------*/ + + InitSWBencBuffer(st); + ResetSHBbuffer_Enc(st); + set_f( st->old_speech_shb, 0.0f, L_LOOK_16k + L_SUBFR16k ); + set_f( st->old_speech_wb, 0.0f, (L_LOOK_12k8 + L_SUBFR) * 5/16 ); + set_f( st->old_input_fhb, 0.0f, NS2SA(48000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS) - L_FRAME48k/2); + + for( i=0; i < LPC_SHB_ORDER; i++ ) + { + st->prev_lsp_shb[i] = i/20.0f; + } + + st->cldfbHBLT = 1.0f; + st->prev_gainFr_SHB = 0; + set_f( st->lsp_shb_slow_interpl, 0, LPC_SHB_ORDER ); + set_f( st->lsp_shb_fast_interpl, 0, LPC_SHB_ORDER ); + set_f( st->shb_inv_filt_mem, 0, LPC_SHB_ORDER ); + set_f( st->lsp_shb_spacing, 0.1f, 3); + st->prev_swb_GainShape = 0; + st->prev_frGainAtten = 0; + st->prev_wb_GainShape = 0; + set_f(st->fb_state_lpc_syn, 0, LPC_SHB_ORDER); + st->fb_tbe_demph = 0.0f; + st->tilt_mem = 0.0f; + + openCldfb( &st->cldfbSynTd, CLDFB_SYNTHESIS, 16000); + + st->prev_coder_type = GENERIC; + set_f( st->prev_lsf_diff, 0.5f, LPC_SHB_ORDER-2 ); + st->prev_tilt_para = 0.0f; + set_f( st->cur_sub_Aq, 0.0f, M+1 ); + + /* TD BWE post-processing */ + st->ptr_mem_stp_swb = st->mem_stp_swb + LPC_SHB_ORDER - 1; + set_f( st->mem_zero_swb, 0, LPC_SHB_ORDER ); + + for( i=0; iswb_lsp_prev_interp[i] = (float)cos( (float)i * EVS_PI / (float)10.0f ); + } + + set_f( st->dec_2_over_3_mem, 0.0f, 12 ); + set_f( st->dec_2_over_3_mem_lp, 0.0f, 6 ); + set_f( st->old_fdbwe_speech, 0.0f, L_FRAME48k ); + + /*-----------------------------------------------------------------* + * HQ core parameters + *-----------------------------------------------------------------*/ + + st->input = st->input_buff+L_FRAME48k+NS2SA(48000, DELAY_FIR_RESAMPL_NS); + set_zero( st->input_buff+L_FRAME48k, L_FRAME48k+NS2SA(48000, DELAY_FIR_RESAMPL_NS) ); + st->old_input_signal = st->input - NS2SA(st->input_Fs, DELAY_FIR_RESAMPL_NS) - (short)(st->input_Fs / 50); + + st->old_hpfilt_in = 0.0f; + st->old_hpfilt_out = 0.0f; + st->EnergyLT = 0.0f; + st->Energy_Old = 0; + st->TransientHangOver = 0; + + set_f( st->old_out, 0, L_FRAME32k ); + + st->mode_count = 0; + st->mode_count1 = 0; + + st->hq_generic_speech_class = 0; + st->prev_Npeaks = 0; + set_s( st->prev_peaks, 0, HVQ_MAX_PEAKS ); + st->hvq_hangover = 0; + st->prev_hqswb_clas = HQ_NORMAL; + set_s( st->prev_SWB_peak_pos, 0, SPT_SHORTEN_SBNUM ); + st->clas_sec_old = 1.0f; + st->clas_final_old = 1; + st->last_gain1 = 0.0f; + st->last_gain2 = 0.0f; + + /* speech/music classification */ + set_s( st->lt_old_mode, 1, 3 ); + st->lt_voicing = 0.5f; + st->lt_corr = 0.5f; + st->lt_tonality = 0; + set_s( st->lt_corr_pitch, 0, 3 ); + st->lt_hangover = 0; + st->lowrate_pitchGain = 0; + + st->lt_music_hangover = 0; + set_f( st->tonality2_buf, 0, HANG_LEN_INIT ); + set_f( st->tonality3_buf, 0, HANG_LEN_INIT ); + set_f( st->LPCErr_buf, 0,HANG_LEN_INIT ); + st->lt_music_state = 0; + st->lt_speech_state = 0; + st->lt_speech_hangover = 0; + st->consec_inactive = 0; + st->spectral_tilt_reset = 1; + st->running_avg = 0; + st->ra_deltasum = 0; + st->trigger_SID = 0; + st->snr_sum_vad = 0; + + set_s( st->prev_frm_index, -1, NB_SWB_SUBBANDS_HAR_SEARCH_SB ); + st->prev_frm_hfe2 = 0; + st->prev_stab_hfe2 = 0; + st->prev_ni_ratio = 0.5f; + set_f( st->prev_En_sb, 0.0f, NB_SWB_SUBBANDS ); + set_s( st->last_bitalloc_max_band, 0, 2 ); + set_f( st->last_ni_gain, 0, BANDS_MAX ); + set_f( st->last_env, 0, BANDS_MAX ); + st->last_max_pos_pulse = 0; + + + /*-----------------------------------------------------------------* + * Channel-aware mode + *-----------------------------------------------------------------*/ + + if( !st->Opt_RF_ON || (st->bwidth != WB && st->bwidth != SWB) || st->total_brate != ACELP_13k20 ) + { + if ( st->Opt_RF_ON ) + { + printf("\nWarning: Channel-aware mode only available for 13.2 kbps WB/SWB\n"); + printf(" Switched to normal mode!\n"); + st->Opt_RF_ON = 0; + st->rf_fec_offset = 0; + } + st->rf_mode = 0; + } + else + { + st->rf_mode = st->Opt_RF_ON; + } + + st->rf_mode_last = st->rf_mode; + + /* initialize RF indice buffers */ + reset_rf_indices( st ); + + /*-----------------------------------------------------------------* + * Mode 2 initialization + *-----------------------------------------------------------------*/ + + st->last_sr_core = st->last_L_frame * 50; + + if( st->codec_mode == MODE2 ) + { + st->igf = getIgfPresent( st->total_brate, st->bwidth, st->rf_mode ); + } + else + { + st->igf = 0; + } + + /* FD-CNG encoder */ + createFdCngEnc( &st->hFdCngEnc ); + initFdCngEnc( st->hFdCngEnc, st->input_Fs, st->cldfbAnaEnc->scale ); + configureFdCngEnc( st->hFdCngEnc, st->bwidth, st->rf_mode&& st->total_brate==13200? 9600: st->total_brate ); + + /* INIT CORE CODER */ + + st->last_totalNoise = 0.f; + set_f( st->totalNoise_increase_hist, 0.f, TOTALNOISE_HIST_SIZE ); + st->totalNoise_increase_len = 0; + + init_coder_ace_plus( st ); + + InitTransientDetection( (int)(st->input_Fs / 50), NS2SA(st->input_Fs, DELAY_FIR_RESAMPL_NS), &st->transientDetection ); + + reset_indices_enc( st ); + + + st->vbr_generic_ho = 0; + + st->sharpFlag = 0; + + st->Local_VAD = 0; + set_f( st->nelp_lp_fit_mem, 0, NELP_LP_ORDER*2 ); + + return; +} + + + +/*-----------------------------------------------------------------------* + * destroy_encoder() + * + * Free memory which was allocated in init_encoder() + *-----------------------------------------------------------------------*/ + +void destroy_encoder( + Encoder_State *st /* i/o: Encoder static variables structure */ +) +{ + deleteCldfb( &st->cldfbSynTd ); + deleteCldfb( &st->cldfbAnaEnc ); + deleteFdCngEnc( &st->hFdCngEnc ); + + /* Close Core */ + + return; +} diff --git a/lib_enc/inov_enc.c b/lib_enc/inov_enc.c new file mode 100644 index 000000000..a339055f4 --- /dev/null +++ b/lib_enc/inov_enc.c @@ -0,0 +1,267 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + + +/*---------------------------------------------------------------------* + * inov_encode() + * + * Encode the algebraic innovation + *---------------------------------------------------------------------*/ + +void inov_encode( + Encoder_State *st, /* i/o: encoder state structure */ + const long core_brate, /* i : core bitrate */ + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short L_frame, /* i : length of the frame */ + const short last_L_frame, /* i : length of the last frame */ + const short coder_type, /* i : coding type */ + const short bwidth, /* i : input signal bandwidth */ + const short sharpFlag, /* i : formant sharpening flag */ + const short i_subfr, /* i : subframe index */ + const short tc_subfr, /* i : TC subframe index */ + const float *p_Aq, /* i : LP filter coefficients */ + const float gain_pit, /* i : adaptive excitation gain */ + float *cn, /* i/o: target vector in residual domain */ + const float *exc, /* i : pointer to excitation signal frame */ + float *h1, /* i/o: weighted filter input response */ + const float tilt_code, /* i : tilt of the excitation of previous subframe */ + const float pt_pitch, /* i : pointer to current subframe fractional pitch */ + const float *xn2, /* i : target vector for innovation search */ + float *code, /* o : algebraic excitation */ + float *y2, /* o : zero-memory filtered algebraic excitation */ + short *unbits /* o : number of unused bits for EVS_PI */ +) +{ + float dn[L_SUBFR]; /* Correlation between xn2 and h1 */ + short nBits, cmpl_flag; + short k; + float g1, g2; + float cn2[L_SUBFR]; + float Rw[L_SUBFR]; + short i, acelpautoc; + + if( L_frame == L_FRAME ) + { + g1 = FORMANT_SHARPENING_G1; + g2 = FORMANT_SHARPENING_G2; + } + else + { + g1 = FORMANT_SHARPENING_G1_16k; + g2 = FORMANT_SHARPENING_G2_16k; + } + + /*----------------------------------------------------------------* + * 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[] + *----------------------------------------------------------------*/ + + if( core_brate > ACELP_13k20 && !Opt_AMR_WB ) + { + acelpautoc = 1; + + cb_shape( 1, 1, 0, sharpFlag, 0, g1, g2, p_Aq, h1, tilt_code, pt_pitch ); + + corr_xh( h1, Rw, h1, L_SUBFR ); + + for( k=0; k WB ) + { + if( i_subfr <= L_SUBFR ) + { + cmpl_flag -= 1; + } + else + { + cmpl_flag -= 2; + } + } + } + else if( core_brate <= ACELP_48k ) + { + cmpl_flag = 3; + + if( coder_type == TRANSITION ) + { + if( i_subfr <= L_SUBFR ) + { + cmpl_flag -= 1; + } + else + { + cmpl_flag -= 2; + } + } + } + else + { + cmpl_flag = 4; + + if( coder_type == TRANSITION ) + { + if( i_subfr <= L_SUBFR ) + { + cmpl_flag -= 1; + } + else + { + cmpl_flag -= 2; + } + } + } + + if( coder_type == INACTIVE ) + { + cmpl_flag = 4; + } + } + + /* reduce number of iterations in a frame where there is an internal sampling rate switch in order not to increase the WC complexity */ + if( L_frame != last_L_frame && core_brate > ACELP_13k20 && (core_brate < ACELP_32k || bwidth == WB) ) + { + if( cmpl_flag > 1 ) + { + cmpl_flag--; + } + } + + /*-----------------------------------------------------------------* + * Find and encode the algebraic innovation + *-----------------------------------------------------------------*/ + + set_f( y2, 0, L_SUBFR ); + + if( !Opt_AMR_WB ) + { + if( L_frame == L_FRAME ) + { + nBits = FCB_bits_tbl[BIT_ALLOC_IDX(core_brate, coder_type, i_subfr, TC_SUBFR2IDX(tc_subfr))]; + } + else /* L_frame == L_FRAME16k */ + { + nBits = FCB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ(core_brate, coder_type, i_subfr, TC_SUBFR2IDX_16KHZ(tc_subfr))]; + } + + if( nBits == 7 ) + { + acelp_1t64( st, dn, h1, code, y2 ); + } + else if( nBits == 12 ) + { + acelp_2t32( st, dn, h1, code, y2 ); + } + else + { + *unbits += acelp_4t64( st, dn, cn, h1, Rw, acelpautoc, code, y2, nBits, cmpl_flag, Opt_AMR_WB ); + } + } + else + { + if (core_brate == ACELP_6k60 ) + { + acelp_2t32( st, dn, h1, code, y2 ); + } + else if( (core_brate == ACELP_8k85) ) + { + acelp_4t64( st, dn, cn, h1, Rw, acelpautoc, code, y2, 20, cmpl_flag, Opt_AMR_WB ); + } + else if( core_brate == ACELP_12k65 ) + { + acelp_4t64( st, dn, cn, h1, Rw, acelpautoc, code, y2, 36, cmpl_flag, Opt_AMR_WB ); + } + else if( core_brate == ACELP_14k25 ) + { + acelp_4t64( st, dn, cn, h1, Rw, acelpautoc, code, y2, 44, cmpl_flag, Opt_AMR_WB ); + } + else if( core_brate == ACELP_15k85 ) + { + acelp_4t64( st, dn, cn, h1, Rw, acelpautoc, code, y2, 52, cmpl_flag, Opt_AMR_WB ); + } + else if( core_brate == ACELP_18k25 ) + { + acelp_4t64( st, dn, cn, h1, Rw, acelpautoc, code, y2, 64, cmpl_flag, Opt_AMR_WB ); + } + else if( core_brate == ACELP_19k85 ) + { + acelp_4t64( st, dn, cn, h1, Rw, acelpautoc, code, y2, 72, cmpl_flag, Opt_AMR_WB ); + } + else if( core_brate == ACELP_23k05 ) + { + acelp_4t64( st, dn, cn, h1, Rw, acelpautoc, code, y2, 88, cmpl_flag, Opt_AMR_WB ); + } + else if( core_brate == ACELP_23k85 ) + { + acelp_4t64( st, dn, cn, h1, Rw, acelpautoc, code, y2, 88, cmpl_flag, Opt_AMR_WB ); + } + } + + /*----------------------------------------------------------------* + * Pitch sharpening + *----------------------------------------------------------------*/ + + cb_shape( 1, 1, 0, sharpFlag, 0, g1, g2, p_Aq, code, tilt_code, pt_pitch ); + + return; +} diff --git a/lib_enc/io_enc.c b/lib_enc/io_enc.c new file mode 100644 index 000000000..927f5d86d --- /dev/null +++ b/lib_enc/io_enc.c @@ -0,0 +1,1008 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include "mime.h" + + +#define WMC_TOOL_SKIP + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static void usage_enc(void); +static char *to_upper( char *str ); + +/*---------------------------------------------------------------------* + * io_ini_enc() + * + * Processing of command line parameters + *---------------------------------------------------------------------*/ + +void io_ini_enc( + 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 */ + short *quietMode, /* o : limit printouts */ + short *noDelayCmp, /* o : turn off delay compensation */ + Encoder_State *st /* o : state structure */ +) +{ + short i = 1, j; + int tmp; + short max_bwidth_user = -1; + char max_bwidth_string[4]; + char stmp[FILENAME_MAX]; + + short rf_file_attempt = 1; + char first_char; + char rf_file_name[300]; + + print_disclaimer( stderr ); + + /*-----------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + + *f_input = NULL; + *f_stream = NULL; + *quietMode = 0; + *noDelayCmp = 0; + + st->input_Fs = 16000; + st->total_brate = ACELP_12k65; + + st->Opt_AMR_WB = 0; + st->Opt_DTX_ON = 0; + st->Opt_RF_ON = 0; + st->rf_fec_offset = 0; + st->rf_fec_indicator = 1; + st->max_bwidth = SWB; + st->interval_SID = FIXED_SID_RATE; + st->var_SID_rate_flag = 1; + st->Opt_SC_VBR = 0; + st->last_Opt_SC_VBR =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 = max_bwidth_user = NB; + } + else if (strcmp( to_upper(stmp), "-WB") == 0 || strcmp( to_upper(stmp), "WB") == 0) + { + st->max_bwidth = max_bwidth_user = WB; + } + else if (strcmp( to_upper(stmp), "-SWB") == 0 || strcmp( to_upper(stmp), "SWB") == 0) + { + st->max_bwidth = max_bwidth_user = SWB; + } + else if (strcmp( to_upper(stmp), "-FB") == 0 || strcmp( to_upper(stmp), "FB") == 0) + { + st->max_bwidth = 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 = 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 = 1; + + if( tmp == 0 ) + { + st->var_SID_rate_flag = 1; + st->interval_SID = 0; + } + else if (tmp >= 3 && tmp <= 100) + { + st->var_SID_rate_flag = 0; + st->interval_SID = (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 = tmp; + i += 1; + 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, 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 = tmp; + + /* channel-aware mode is supported only at 13.20 */ + if( st->Opt_RF_ON && st->total_brate != ACELP_13k20 ) + { + st->Opt_RF_ON = 0; + } + } + + /* SC-VBR at 5.90 kbps */ + if ( st->total_brate == ACELP_5k90 ) + { + st->Opt_SC_VBR = 1; + st->last_Opt_SC_VBR = st->Opt_SC_VBR; + st->total_brate = ACELP_7k20; + if ( st->max_bwidth != NB ) + { + st->max_bwidth = WB; + } + } + + /* check if the entered bitrate is supported */ + j = 0; + while ( j < SIZE_BRATE_TBL && st->total_brate != brate_tbl[j] ) + { + j++; + } + + /* AMR-WB IO mode/EVS primary mode determination */ + if ( j >= SIZE_BRATE_TBL ) + { + switch ( st->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: %ld\n\n", st->total_brate ); + usage_enc(); + } + break; + } + + st->Opt_AMR_WB = 1; + } + else + { + st->Opt_AMR_WB = 0; + } + + i++; + } + else + { + fprintf(stderr, "Error: no bitrate specified\n\n"); + usage_enc(); + } + + /*-----------------------------------------------------------------* + * Input sampling frequency + *-----------------------------------------------------------------*/ + + if( i < argc-2 ) + { + st->input_Fs = (int) atoi( argv[i] ) * 1000; + if( st->Opt_RF_ON && st->input_Fs == 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 != 8000) && ( st->input_Fs != 16000) && (st->input_Fs != 32000) && (st->input_Fs != 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; /* one channel */ + 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 == 8000 && st->max_bwidth > NB ) + { + st->max_bwidth = NB; + } + else if ( st->input_Fs == 16000 && st->max_bwidth > WB ) + { + st->max_bwidth = WB; + } + else if ( st->input_Fs == 32000 && st->max_bwidth > SWB ) + { + st->max_bwidth = SWB; + } + + if ( st->Opt_AMR_WB ) + { + st->codec_mode = MODE1; + } + else + { + switch ( st->total_brate ) + { + case 5900: + st->codec_mode = MODE1; + break; + case 7200: + st->codec_mode = MODE1; + break; + case 8000: + st->codec_mode = MODE1; + break; + case 9600: + st->codec_mode = MODE2; + break; + case 13200: + st->codec_mode = MODE1; + break; + case 16400: + st->codec_mode = MODE2; + break; + case 24400: + st->codec_mode = MODE2; + break; + case 32000: + st->codec_mode = MODE1; + break; + case 48000: + st->codec_mode = MODE2; + break; + case 64000: + st->codec_mode = MODE1; + break; + case 96000: + st->codec_mode = MODE2; + break; + case 128000: + st->codec_mode = MODE2; + break; + } + } + + if( st->total_brate == 13200 && st->Opt_RF_ON == 1) + { + st->codec_mode = MODE2; + } + + st->last_codec_mode = st->codec_mode; + + /*-----------------------------------------------------------------* + * Print info on screen + *-----------------------------------------------------------------*/ + /*-----------------------------------------------------------------* + * Print input signal sampling frequency + *-----------------------------------------------------------------*/ + + fprintf(stdout, "Input sampling rate: %d Hz\n", st->input_Fs); + + /*-----------------------------------------------------------------* + * Print bitrate + *-----------------------------------------------------------------*/ + + if ( st->Opt_SC_VBR ) + { + fprintf(stdout, "Average bitrate: %.2f kbps\n", (float)ACELP_5k90/1000); + } + else + { + fprintf(stdout, "Bitrate: %.2f kbps\n", (float)st->total_brate/1000); + } + + /*-----------------------------------------------------------------* + * Print CNG update interval, if DTX is activated + *-----------------------------------------------------------------*/ + + if ( st->Opt_DTX_ON ) + { + if( st->var_SID_rate_flag ) + { + fprintf(stdout, "DTX: ON, variable CNG update interval\n"); + } + else + { + fprintf(stdout, "DTX: ON, CNG update interval = %d frames\n", st->interval_SID); + } + } + + /*-----------------------------------------------------------------* + * 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 ) + { + 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 && !st->Opt_DTX_ON) + { + fprintf(stderr, "\nError: SC-VBR 5900 bit/s not supported without DTX\n\n"); + exit(-1); + } + + if ( (max_bwidth_user != -1) && (st->max_bwidth != max_bwidth_user) ) + { + fprintf(stdout, "\nBandwidth limited to %s.\n", max_bwidth_string); + } + if( (max_bwidth_user == -1) && (st->max_bwidth < FB) && (st->input_Fs == 48000) ) + { + fprintf(stdout, "\nBandwidth limited to %s. To enable FB coding, please use -max_band FB.\n", max_bwidth_string); + } + if( (st->max_bwidth == FB) && (st->total_brate < ACELP_16k40) ) + { + fprintf(stdout, "\nFB coding not supported below %.2f kbps. ", ACELP_16k40 / 1000.f); + if( st->total_brate < ACELP_9k60 ) + { + fprintf(stdout, "Switching to WB.\n"); + } + else + { + fprintf(stdout, "Switching to SWB.\n"); + } + } + if( (st->max_bwidth == SWB) && (st->total_brate < ACELP_9k60) ) + { + fprintf(stdout, "\nSWB coding not supported below %.2f kbps. Switching to WB.", ACELP_9k60 / 1000.f); + } + /* in case of 8kHz input sampling or "-max_band NB", require the total bitrate to be below 24.40 kbps */ + if ( ((st->max_bwidth == NB) || (st->input_Fs == 8000)) && (st->total_brate > ACELP_24k40) ) + { + fprintf(stderr, "\nError: Unsupported mode NB %ld bit/s, NB mode supports rates 5900-24400 bit/s\n\n", st->total_brate); + usage_enc(); + } + + + fprintf(stdout, "\n"); + return; +} + +/*---------------------------------------------------------------------* + * read_next_rfparam() + * + * 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(short *rf_fec_offset, /* o: rf offset */ + short *rf_fec_indicator, /* o: rf FEC indicator */ + FILE *f_rf /* i: file pointer to read parameters */ + ) +{ + char rline[10], str[4]; + short 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 %hd",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 = 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( + long *total_brate, /* i/o: total bitrate */ + const int last_total_brate, /* i : last total bitrate */ + FILE *f_rate, /* i : bitrate switching profile (0 if N/A) */ + int input_Fs, /* i : input sampling frequency */ + short *Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + short *Opt_SC_VBR, /* i/o: SC-VBR flag */ + short *codec_mode /* i/o: Mode 1 or 2 */ +) +{ + short j; + + /* 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 mode/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: %ld\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; + break; + case 5900: + *codec_mode = MODE1; + break; + case 7200: + *codec_mode = MODE1; + break; + case 8000: + *codec_mode = MODE1; + break; + case 9600: + *codec_mode = MODE2; + break; + case 13200: + *codec_mode = MODE1; + break; + case 16400: + *codec_mode = MODE2; + break; + case 24400: + *codec_mode = MODE2; + break; + case 32000: + *codec_mode = MODE1; + break; + case 48000: + *codec_mode = MODE2; + break; + case 64000: + *codec_mode = MODE1; + break; + case 96000: + *codec_mode = MODE2; + break; + case 128000: + *codec_mode = MODE2; + break; + } + } + + + return; +} + + +/*---------------------------------------------------------------------* + * read_next_bwidth() + * + * Read next bandwidth from profile file (only if invoked on cmd line) + *---------------------------------------------------------------------*/ + +void read_next_bwidth( + short *max_bwidth, /* i/o: maximum encoded bandwidth */ + FILE *f_bwidth, /* i : bandwidth switching profile (0 if N/A) */ + long *bwidth_profile_cnt, /* i/o: counter of frames for bandwidth switching profile file */ + int input_Fs /* i : input sampling rate */ +) +{ + 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, "%ld %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 st->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.c b/lib_enc/isf_enc_amr_wb.c new file mode 100644 index 000000000..471d78d3b --- /dev/null +++ b/lib_enc/isf_enc_amr_wb.c @@ -0,0 +1,488 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_enc.h" +#include "rom_com.h" +#include "prot.h" + + +/*-----------------------------------------------------------------* + * 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( Encoder_State *st, float *isf ); +static void qisf_2s_46b( Encoder_State *st, float *isf, short nb_surv, float *mem_AR, float *mem_MA ); +static void qisf_2s_36b( Encoder_State *st, float *isf, short nb_surv, float *mem_AR, float *mem_MA ); +static void VQ_stage1(const float *x, const float *dico, const short dim, const short dico_size, short *index, const short surv); +static short sub_VQ(float *x, const float *dico, const short dim, const short dico_size, float *distance); + +/*-------------------------------------------------------------------* + * isf_enc_amr_wb() + * + * Quantization of ISF parameters in AMR-WB IO mode + *-------------------------------------------------------------------*/ + +void isf_enc_amr_wb( + Encoder_State *st, /* i/o: state structure */ + float *isf_new, /* i/o : quantized ISF vector */ + float *isp_new, /* i/o: ISP vector to quantize/quantized */ + float *Aq, /* o : quantized A(z) for 4 subframes */ + float *stab_fac /* o : ISF stability factor */ +) +{ + + /*---------------------------------* + * ISF quantization of SID frames + *---------------------------------*/ + + if ( st->core_brate == SID_1k75 ) + { + qisf_ns_28b( st, isf_new ); + + reorder_isf( isf_new, ISF_GAP, M, INT_FS_12k8 ); + + isf2isp( isf_new, isp_new, M, INT_FS_12k8 ); + + /* return if SID frame (conversion to A(z) done in the calling function) */ + return; + } + + /* check resonance for pitch clipping algorithm */ + gp_clip_test_lsf( st->core_brate, isf_new, st->clip_var, 1 ); + + /*---------------------------------------* + * ISF quantization of all other frames + *---------------------------------------*/ + + if ( st->core_brate == ACELP_6k60 ) + { + qisf_2s_36b( st, isf_new, 4, st->mem_AR, st->mem_MA); + } + else if( st->core_brate >= ACELP_8k85 ) + { + qisf_2s_46b( st, isf_new, 4, st->mem_AR, st->mem_MA); + } + + reorder_isf( isf_new, ISF_GAP, M, INT_FS_12k8 ); + + /* convert quantized ISFs back to ISPs */ + isf2isp( isf_new, isp_new, M, INT_FS_12k8 ); + + /*------------------------------------------------------------------* + * ISP interpolation + * A(z) calculation + *------------------------------------------------------------------*/ + + if( st->rate_switching_reset ) + { + mvr2r( isf_new, st->lsf_old, M ); + mvr2r( isp_new, st->lsp_old, M ); + } + + int_lsp( L_FRAME, st->lsp_old, isp_new, Aq, M, interpol_isp_amr_wb, 1 ); + + /*------------------------------------------------------------------* + * Calculate ISF stability (distance between old ISF and current ISF) + *------------------------------------------------------------------*/ + + *stab_fac = lsf_stab( isf_new, st->lsf_old, 1, st->L_frame ); + + + return; +} + +/*-------------------------------------------------------------------* +* qisf_ns_28b() +* +* ISF quantizer for SID frames (only in AMR-WB IO mode) +*-------------------------------------------------------------------*/ + +static void qisf_ns_28b( + Encoder_State *st, /* i/o: encoder state structure */ + float *isf /* i/o: unquantized/quantized ISF vector */ +) +{ + short i, indice[5]; + float tmp; + + for (i=0; i do not allow */ + + /* write indices to array */ + push_indice( st, IND_ISF_0_0, indice[0], 6 ); + push_indice( st, IND_ISF_0_1, indice[1], 6 ); + push_indice( st, IND_ISF_0_2, indice[2], 6 ); + push_indice( st, IND_ISF_0_3, indice[3], 5 ); + push_indice( st, IND_ISF_0_4, indice[4], 5 ); + + /* decoding the ISFs */ + disf_ns_28b( 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( + Encoder_State *st, /* i/o: encoder state structure */ + float *isf, /* i/o: unquantized/quantized ISF vector */ + short nb_surv, /* i : number of survivors (1, 2, 3 or 4) */ + float *mem_AR, /* o : quantizer memory for AR model */ + float *mem_MA /* i/o: quantizer memory for MA model */ +) +{ + short i, k, indice[5], tmp_ind[2]; + short surv1[N_SURV_MAX]; /* indices of survivors from 1st stage */ + float temp, min_err, distance, isf2[M]; + + /*------------------------------------------------------------------------* + * Subtract mean + *------------------------------------------------------------------------*/ + + for (i=0; i N_SURV_MAX) + { + nb_surv = N_SURV_MAX; + } + + for (k=0; k N_SURV_MAX) + { + nb_surv = N_SURV_MAX; + } + + for (k=0; kk; l--) + { + dist_min[l] = dist_min[l-1]; + index[l] = index[l-1]; + } + dist_min[k] = dist; + index[k] = i; + break; + } + } + } + return; +} + +/*-------------------------------------------------------------------* + * sub_VQ() + * + * Quantization of a subvector in Split-VQ of ISFs + *-------------------------------------------------------------------*/ + +static short sub_VQ( /* o : selected codebook vector index */ + float *x, /* i/o: ISF vector */ + const float *dico, /* i : ISF codebook */ + const short dim, /* i : codebook dimension */ + const short dico_size, /* i : codebook size */ + float *distance /* o : quantization error (min. distance) */ +) +{ + float dist_min, dist, temp; + const float *p_dico; + short i, j, index; + + + dist_min = 1.0e30f; + p_dico = dico; + + index = 0; + for (i = 0; i < dico_size; i++) + { + dist = 0.0f; + for (j = 0; j < dim; j++) + { + temp = x[j] - *p_dico++; + dist += temp * temp; + } + if (dist < dist_min) + { + dist_min = dist; + index = i; + } + } + + *distance = dist_min; + + /* Reading the selected vector */ + p_dico = &dico[index * dim]; + for (j = 0; j < dim; j++) + { + x[j] = *p_dico++; + } + return index; +} diff --git a/lib_enc/lead_indexing.c b/lib_enc/lead_indexing.c new file mode 100644 index 000000000..a4152e704 --- /dev/null +++ b/lib_enc/lead_indexing.c @@ -0,0 +1,177 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "rom_com.h" +#include "prot.h" + + +/*-------------------------------------------------------------------* + * Local function prototypes + *-------------------------------------------------------------------*/ +static int fcb_encode_pos(int pos_vector[], int pulse_num, int pos_num); + +/*-------------------------------------------------------------------* + * re8_compute_base_index: + * + * Compute base index for RE8 + *-------------------------------------------------------------------*/ + +void re8_compute_base_index( + const int *x, /* i : Elemen of Q2, Q3 or Q4 */ + const int ka, /* i : Identifier of the absolute leader related to x */ + long *I /* o : index */ +) +{ + int i, j, k1,m; + int setor_8p[8], setor_8p_temp[8]; + int sign_8p; + int code_index, code_level, code_area; + int offset; + const int *a1,*a2; + + + a1 = vals_a[ka]; + a2 = vals_q[ka]; + + /* the sign process */ + + sign_8p = 0; + m = 0; + code_index = 0; + k1 = a2[0]; + + if ((a2[1]==2) && (a1[0] ^ 1) && (ka != 5)) + { + for (i=0; i<8; i++) + { + if (x[i] != 0) + { + sign_8p = sign_8p * 2; + setor_8p_temp[m] = i; + m++; + } + if (x[i] < 0) + { + sign_8p += 1; + } + } + + code_index = fcb_encode_pos(setor_8p_temp,8,m); + code_index = (code_index << k1) + sign_8p; + + offset = Is[ka]; + + + *I = offset + code_index; + } + else + { + for (i=0; i<8; i++) + { + setor_8p[i] = abs(x[i]); + + if (x[i] < 0) + { + sign_8p = sign_8p * 2 + 1; + m++; + } + if (x[i] > 0) + { + sign_8p = sign_8p * 2; + m++; + } + } + + if ( k1 != m ) + { + sign_8p = sign_8p >> 1; + } + + /* code level by level */ + + code_level = a2[1]; + code_area = 8; + + if ( a2[2] != 1 ) + { + for (j=0; jini_frame < 4 ) + { + st->lp_noise = st->totalNoise; + tmp = st->lp_noise + 10.0f; + + if( st->lp_speech < tmp ) + { + st->lp_speech = 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; + } + + if ( localVAD_HE_SAD && !high_lpn_flag ) + { + if ( ( st->lp_speech - Etot ) < 10.0f ) + { + st->lp_speech = 0.98f * st->lp_speech + 0.02f * Etot; + } + else + { + st->lp_speech = st->lp_speech - 0.05f; + } + } + } + + /*-----------------------------------------------------------------* + * Initialize parameters for energy tracking and signal dynamics + *-----------------------------------------------------------------*/ + return; +} diff --git a/lib_enc/lp_exc_e.c b/lib_enc/lp_exc_e.c new file mode 100644 index 000000000..4b33bb62b --- /dev/null +++ b/lib_enc/lp_exc_e.c @@ -0,0 +1,286 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define GAIN_PIT_MAX 1.2f +#define ACELP_GAINS_CONST 0.8f /* adaptive codebook gain constraint */ + + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static float adpt_enr( const short codec_mode, const float *exc, const float *h1, float *y1, const short L_subfr, float *gain, float *g_corr, + const short clip_gain, const float *xn, float *xn2, short use_prev_sf_pit_gain ); + +/*-------------------------------------------------------------------* + * lp_filt_exc_enc() + * + * Low-pass filtering of the adaptive excitation + * Innovation target construction + * Gain quantization limitation + *-------------------------------------------------------------------*/ + +short lp_filt_exc_enc( + const short codec_mode, /* i : codec mode */ + const long core_brate, /* i : core bitrate */ + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short coder_type, /* i : coding type */ + const short i_subfr, /* i : subframe index */ + float *exc, /* i/o: pointer to excitation signal frame */ + const float *h1, /* i : weighted filter input response */ + const float *xn, /* i : target vector */ + float *y1, /* o : zero-memory filtered adaptive excitation */ + float *xn2, /* o : target vector for innovation search */ + const short L_subfr, /* i : length of vectors for gain quantization */ + const short L_frame, /* i : frame size */ + float *g_corr, /* o : ACELP correlation values */ + const short clip_gain, /* i : adaptive gain clipping flag */ + float *gain_pit, /* o : adaptive excitation gain */ + short *lp_flag /* i/o : mode selection */ +) +{ + float ener, ener_tmp, gain1, gain2, g_corr2[2], exc_tmp[L_FRAME16k], xn2_tmp[L_FRAME16k]; + float y1_tmp[L_FRAME16k]; + short select, i; + short use_prev_sf_pit_gain; + + gain1 = 0.0f; + gain2 = 0.0f; + ener = 0.0f; + ener_tmp = 0.0f; + use_prev_sf_pit_gain = 0; + + /*-----------------------------------------------------------------* + * Select LP filtering flag + *-----------------------------------------------------------------*/ + + if( codec_mode == MODE1 ) + { + if ( ( Opt_AMR_WB || coder_type == GENERIC || coder_type == TRANSITION ) && core_brate < ACELP_11k60 ) + { + *lp_flag = LOW_PASS; + } + else if ( core_brate >= ACELP_11k60 && coder_type != AUDIO ) + { + *lp_flag = NORMAL_OPERATION; + } + else + { + *lp_flag = FULL_BAND; + } + } + + /*----------------------------------------------------------------* + * Find energy of the fixed cb. target with respect to adaptive + * exc. filtering + * Find flag about splitting the gain quantizer in half + * - find the target energy if adaptive exc. is not filtered + * - filter the adaptive excitation and find the target energy + * if the exc. is filtered. + *----------------------------------------------------------------*/ + + if( codec_mode == MODE2 && coder_type == 100 ) + { + use_prev_sf_pit_gain = 1; + } + + if( *lp_flag == FULL_BAND || *lp_flag == NORMAL_OPERATION ) + { + if( use_prev_sf_pit_gain == 1 ) + { + ener = adpt_enr( codec_mode, &exc[i_subfr], h1, y1, L_subfr, gain_pit, g_corr, clip_gain, xn, xn2, use_prev_sf_pit_gain ); + } + else + { + ener = adpt_enr( codec_mode, &exc[i_subfr], h1, y1, L_subfr, &gain1, g_corr, clip_gain, xn, xn2, use_prev_sf_pit_gain ); + } + } + + /*----------------------------------------------------------------* + * Find energy of the fixed cb. target with respect to adaptive + * exc. filtering + * filter the adaptive excitation and find the target energy + * if the exc. is filtered. + *----------------------------------------------------------------*/ + + if( *lp_flag == LOW_PASS || *lp_flag == NORMAL_OPERATION ) + { + if( codec_mode == MODE2 && L_frame == L_FRAME16k ) + { + for (i=0; i 0.95f ) + { + *gain = 0.95f; + } + + if( clip_gain == 2 && *gain > 0.65f ) + { + *gain = 0.65f; + } + } + + /* find energy of new target xn2[] */ + updt_tar( xn, xn2, y1, *gain, L_subfr ); + ener = dotp( xn2, xn2, L_subfr ); + + return ener; +} + +/*-------------------------------------------------------------------* + * corr_xy1() + * + * Find the correlations between the target xn[] and the filtered adaptive + * codebook excitation y1[]. ( and -2 ) + *-------------------------------------------------------------------*/ + +float corr_xy1( /* o : pitch gain (0..GAIN_PIT_MAX) */ + const float xn[], /* i : target signal */ + const float y1[], /* i : filtered adaptive codebook excitation */ + float g_corr[], /* o : correlations and -2 */ + const short L_subfr, /* i : vector length */ + const short norm_flag /* i : flag for constraining pitch contribution */ +) +{ + float temp1, temp2, gain,gain_p_snr; + + /*-----------------------------------------------------------------* + * Find the ACELP correlations and the pitch gain + * (for current subframe) + *-----------------------------------------------------------------*/ + + /* Compute scalar product */ + temp1 = dotp(xn, y1, L_subfr); + + /* Compute scalar product */ + temp2 = dotp(y1, y1, L_subfr) + 0.01f; + + g_corr[0] = temp2; + g_corr[1] = -2.0f*temp1 + 0.01f; + + /* find pitch gain and bound it by [0,GAIN_PIT_MAX] */ + if( norm_flag ) + { + gain = (temp1 + 0.01f)/temp2; + } + else + { + gain = temp1/temp2; + } + + if( gain < 0.0f ) + { + gain = 0.0f; + } + if( gain > GAIN_PIT_MAX ) + { + gain = GAIN_PIT_MAX; + } + + /*Limit the energy of pitch contribution*/ + if( norm_flag ) + { + /* Compute scalar product */ + temp1 = dotp(xn, xn, L_subfr); + gain_p_snr = ACELP_GAINS_CONST*sqrt(temp1/temp2); + + if( gain>gain_p_snr ) + { + gain = gain_p_snr; + } + } + + return gain; +} diff --git a/lib_enc/lsf_enc.c b/lib_enc/lsf_enc.c new file mode 100644 index 000000000..270982ff9 --- /dev/null +++ b/lib_enc/lsf_enc.c @@ -0,0 +1,1950 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_enc.h" +#include "rom_com.h" +#include "prot.h" +#include "basop_proto_func.h" + +/*-----------------------------------------------------------------* + * Local constants + *-----------------------------------------------------------------*/ + +#define MSVQ_MAXCNT 3000 /* was 300 */ +#define LOWEMPH_LSFI 1.0f /* bigger value means more weight for lower frequencies */ + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ + +static void lsfq_CNG( Encoder_State *st, const float *lsf, const float *wghts, float *qlsf, unsigned int *p_offset_scale1, unsigned int * p_offset_scale2, + short * p_no_scales ); + +static void lsf_mid_enc( Encoder_State *st, const float int_fs, const float qisp0[], const float qisp1[], float isp[], const short coder_type, + const short bwidth, const long core_brate, float Bin_Ener[], short ppp_mode, short nelp_mode ); + +static float vq_lvq_lsf_enc( short pred_flag, short mode, float u[], short * levels, short stages, float w[], short Idx[], const float * lsf, + const float * pred, unsigned int p_offset_scale1[][MAX_NO_SCALES+1], unsigned int p_offset_scale2[][MAX_NO_SCALES+1], + short p_no_scales[][2], float *resq, float * lsfq ); + +static float qlsf_ARSN_tcvq_Enc_16k ( const float *x, float *y, short *indice, const float *w, const short nBits, short safety_net ); + +/*-------------------------------------------------------------------* + * lsf_enc() + * + * Quantization of LSF vector + *-------------------------------------------------------------------*/ + +void lsf_enc( + Encoder_State *st, /* i/o: state structure */ + const short L_frame, /* i : length of the frame */ + const short coder_type, /* i : coding type */ + float *lsf_new, /* o : quantized LSF vector */ + float *lsp_new, /* i/o: LSP vector to quantize/quantized */ + float *lsp_mid, /* i/o: mid-frame LSP vector */ + float *Aq, /* o : quantized A(z) for 4 subframes */ + float *stab_fac, /* o : LSF stability factor */ + const short Nb_ACELP_frames +) +{ + short nBits = 0; + float int_fs; + short force_sf = 0; + float fec_lsf[M], stab; + short i; + + /* initialize */ + if( L_frame == L_FRAME ) + { + int_fs = INT_FS_12k8; + } + else /* L_frame == L_FRAME16k */ + { + int_fs = INT_FS_16k; + } + + /* convert LSPs to LSFs */ + lsp2lsf( lsp_new, lsf_new, M, int_fs ); + + + /* check resonance for pitch clipping algorithm */ + gp_clip_test_lsf( st->core_brate, lsf_new, st->clip_var, 0 ); + + /*-------------------------------------------------------------------------------------* + * Find the number of bits for LSF quantization + *-------------------------------------------------------------------------------------*/ + + if ( st->core_brate == SID_2k40 ) + { + nBits = LSF_BITS_CNG; + } + else + { + if ( st->nelp_mode == 0 && st->ppp_mode == 0 ) + { + nBits = LSF_bits_tbl[LSF_BIT_ALLOC_IDX(st->core_brate, coder_type)]; + } + else if ( st->nelp_mode == 1 ) + { + if ( st->bwidth == NB ) + { + nBits = 32; /* Stole 1 bit for SID/NELP harmonization*/ + + } + else if ( st->bwidth == WB ) + { + nBits = 30; /* Stole 1 bit for SID/NELP harmonization */ + + } + } + else if ( st->ppp_mode == 1 ) + { + + /*The LSF bit scaling does not work here. */ + nBits = 26; /*Stole 1 bit for SID PPP harmonization*/ + + } + } + + if ( Nb_ACELP_frames < 3 ) + { + /* first three ACELP frames after an HQ frame shall be processed only with safety-net quantizer */ + force_sf = 1; + } + + if ( st->next_force_safety_net == 1 ) + { + /* in case of unstable filter, choose safety-net to help FEC */ + force_sf = 1; + st->next_force_safety_net = 0; + } + + /*-------------------------------------------------------------------------------------* + * LSF quantization + *-------------------------------------------------------------------------------------*/ + + + lsf_end_enc( st, lsf_new, lsf_new, st->mem_AR, st->mem_MA, nBits, coder_type, st->bwidth, st->Bin_E, int_fs, st->core_brate, + &st->streaklimit, &st->pstreaklen, force_sf, 0, 0, NULL, NULL, NULL, st->coder_type_raw ); + + /* convert quantized LSFs back to LSPs */ + lsf2lsp( lsf_new, lsp_new, M, int_fs ); + + if ( st->last_core == HQ_CORE && st->core == ACELP_CORE ) + { + /* don't use old LSF values if this is the first ACELP frame after HQ frames */ + mvr2r( lsf_new, st->lsf_old, M ); + } + + if ( st->core_brate == 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( st->last_L_frame != st->L_frame) + { + /* FEC - in case of core switching, use old LSFs that have been smoothed with adaptive mean */ + mvr2r( st->lsf_old, st->lsfoldbfi1, M ); + mvr2r( st->lsf_old, st->lsfoldbfi0, M ); + mvr2r( st->lsf_old, st->lsf_adaptive_mean, M ); + } + + FEC_lsf_estim_enc( st, st->L_frame, fec_lsf ); + + /* FEC - calculate LSF stability */ + stab = lsf_stab( lsf_new, fec_lsf, 0, st->L_frame); + + if (st->L_frame == L_FRAME16k && stab < STAB_FAC_LIMIT && coder_type == GENERIC ) + { + st->next_force_safety_net = 1; + } + else + { + if ( stab < STAB_FAC_LIMIT + && (st->clas == VOICED_CLAS + || (st->clas < VOICED_CLAS && coder_type == AUDIO) ) ) + { + st->next_force_safety_net = 1; + } + } + + /* FEC - update adaptive LSF mean vector */ + for (i=0; ilsf_adaptive_mean[i] = (st->lsfoldbfi1[i] + st->lsfoldbfi0[i] + lsf_new[i]) / 3; + } + + /* FEC - update LSF memories */ + mvr2r( st->lsfoldbfi0, st->lsfoldbfi1, M ); + mvr2r( lsf_new, st->lsfoldbfi0, M ); + + /*-------------------------------------------------------------------------------------* + * Mid-frame LSF encoding + * LSP interpolation and conversion of LSPs to A(z) + *-------------------------------------------------------------------------------------*/ + + if(st->rate_switching_reset) + { + /*extrapolation in case of unstable LSF convert*/ + mvr2r( lsp_new, st->lsp_old, M ); + mvr2r( lsf_new, st->lsf_old, M ); + } + + /* Mid-frame LSF encoding */ + lsf_mid_enc( st, int_fs, st->lsp_old, lsp_new, lsp_mid, coder_type, st->bwidth, + st->core_brate, st->Bin_E_old, st->ppp_mode, st->nelp_mode ); + + + if( st->last_core == HQ_CORE && st->core == ACELP_CORE ) + { + /* don't use old LSP/LSF values if this is the first ACELP frame after HQ frames */ + mvr2r( lsp_mid, st->lsp_old, M ); + lsp2lsf( lsp_mid, st->lsf_old, M, int_fs ); + } + + /* LSP interpolation and conversion of LSPs to A(z) */ + int_lsp4( L_frame, st->lsp_old, lsp_mid, lsp_new, Aq, M, 0 ); + + /*------------------------------------------------------------------* + * Check LSF stability (distance between old LSFs and current LSFs) + *------------------------------------------------------------------*/ + + *stab_fac = lsf_stab( lsf_new, st->lsf_old, 0, st->L_frame); + + return; +} + + +/*-------------------------------------------------------------------* + * lsfq_CNG() + * + * 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( + Encoder_State *st, /* i/o: encoder state structure */ + const float *lsf, + const float *wghts, + float *qlsf_out, + unsigned int *p_offset_scale1, + unsigned int *p_offset_scale2, + short *p_no_scales +) +{ + short i, j, idx_cv, idx_lvq[3]; + float min_dist, dist, dd[M], ddq[M]; + const float *p_cb; + short first_cb, last_cb; + int idx_lead_cng[2], idx_scale_cng[2]; + + float qlsf[M]; + idx_cv = 0; + + /* quantize first stage with 4 bits */ + if ( lsf[M-1] > WB_LIMIT_LSF ) /* 16kHz sampled LSF vector*/ + { + p_cb = &CNG_SN1[0]; + first_cb = 0; + last_cb = 6; + } + else /* 12.8kHz sampled LSF vector*/ + { + p_cb = &CNG_SN1[6*M]; + first_cb = 6; + last_cb = M; + } + + min_dist = 1.0e30f; + for ( i = first_cb; i < last_cb; i++ ) + { + dist = 0.0f; + for( j=0; j streaklimit * op_loop_thr ) + { + /* Safety-net */ + safety_net = 1; + } + else + { + /* Predictive */ + safety_net = 0; + } + + return safety_net; +} + + + +/*-------------------------------------------------------------------* + * lsf_end_enc() + * + * Quantization of LSF parameters + *-------------------------------------------------------------------*/ +void lsf_end_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const float *lsf, /* i : LSF in the frequency domain (0..6400) */ + float *qlsf, /* o : quantized LSF */ + float *mem_AR, /* i/o: quantizer memory for AR model */ + float *mem_MA, /* i/o: quantizer memory for MA model */ + const short nBits_in, /* i : number of bits to spend on ISF quantization */ + const short coder_type_org,/* i : coding type */ + const short bwidth, /* i : input signal bandwidth */ + float *Bin_Ener, /* i : FFT Bin energy 128 *2 sets */ + const float int_fs, /* i : sampling frequency */ + long core_brate, + float *streaklimit, /* i/o: Multiplier to prefer safety-net, more and more in long streaks of predictive frames*/ + short *pstreaklen, /* i/o: Count of consecutive predictive frames */ + short force_sf, /* i : Force safety-net usage (if possible), due to filter instability, MDCT-core switching etc. */ + short rf_flag, + short mode2_flag, + int * lpc_param, + short * no_indices, + short * bits_param_lpc, + short coder_type_raw +) +{ + short i; + short Idx0[MAX_VQ_STAGES+3]; /* Optimal codebook indices for safety-net quantizer */ + short Idx1[MAX_VQ_STAGES+3]; /* Optimal codebook indices for predictive quantizer */ + short indice[MAX_VQ_STAGES+3]; /* Temp. array of indice for vector de-quantizer */ + short mode_lvq = 0, mode_lvq_p = 0; + short bits0[MAX_VQ_STAGES], bits1[MAX_VQ_STAGES]; + const short *Bit_alloc1 = NULL; + float Err[2]; /* Quantization error for safety-net(0) and predictive(1) quantizers */ + float Tmp [M]; /* Temporary target vector (mean and prediction removed) */ + float pred0[M]; /* Prediction for the safety-net quantizer (usually mean) */ + float pred1[M]; /* Prediction for the predictive quantizer */ + float pred2[M]; /* Prediction for the predictive quantizer */ + float wghts[M]; /* Weighting used for quantizer (currently GSM based) */ + short stages0; /* Amount of stages used by safety-net quantizer */ + short stages1; /* Amount of stages used by predictive quantizer */ + short levels0[MAX_VQ_STAGES]; /* Sizes of different codebook stages for safety-net quantizer */ + short levels1[MAX_VQ_STAGES]; /* Sizes of different codebook stages for predictive quantizer */ + short predmode; /* 0: safety-net only, 1: predictive only, 2: best of the two */ + short safety_net, cumleft, num_bits; + short *Idx, stages, *bits; + float Tmp1[M], Tmp2[M]; /* Temporary target vectors for MA and AR quantizers respectively */ + float abs_threshold; /* Abslute Error value that is considered as "good enough" (in practice close to SD of 1.0dB)*/ + float lsfq[M*2], resq[M*2]; + + short coder_type; + short nBits; + short TCQIdx0[M+2]; /* Optimal codebook indices for VQ-TCQ quantizer */ + short *TCQIdx; + + + nBits = nBits_in; + + if((coder_type_org == GENERIC) && (int_fs == INT_FS_16k) && (rf_flag == 0) && (mode2_flag == 0)) + { + + if (coder_type_raw == VOICED) + { + coder_type = VOICED; /* Reflect Inactive mode */ + } + else + { + nBits--; /* This is for real Generic*/ + coder_type = coder_type_org; + } + } + else + { + coder_type = coder_type_org; + } + /*--------------------------------------------------------------------------------* + * Calculate the number of stages and levels for each stage based on allowed bit budget + * Set absolute threshold for codebook-type decision logic + *--------------------------------------------------------------------------------*/ + if ( bwidth == NB ) + { + abs_threshold = SFNETLOWLIMIT_NB; + } + else + { + abs_threshold = SFNETLOWLIMIT_WB; + } + Unified_weighting(&Bin_Ener[L_FFT/2], lsf, wghts, bwidth==NB, coder_type==UNVOICED, (int)(int_fs),M); + + /*--------------------------------------------------------------------------------* + * LSF quantization of SID frames + *--------------------------------------------------------------------------------*/ + + if ( core_brate == SID_2k40 ) + { + lsfq_CNG( st, lsf, wghts, qlsf, &st->offset_scale1[0][0], &st->offset_scale2[0][0], &st->no_scales[0][0] ); + v_sort( qlsf, 0, M-1 ); + reorder_lsf( qlsf, MODE1_LSF_GAP, M, int_fs ); + + return; + } + + predmode = find_pred_mode(coder_type, bwidth, int_fs, &mode_lvq, &mode_lvq_p,st->total_brate); + + /*----------------------------------------------------------------* + * Calculate number of stages and levels for each stage based on the allowed bit allocation + * (subtract one bit for LSF predictor selection) + *----------------------------------------------------------------*/ + + lsf_allocate( nBits-(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] = FLT_MAX; + Err[1] = FLT_MAX; + /* for mem_MA update */ + for (i=0; ioffset_scale1,st->offset_scale2, st->no_scales, resq, lsfq); + safety_net = 1; + *pstreaklen = 0; /* Streak is ended with safety-net */ + } + else if (predmode ==1) /* only MA prediction */ + { + v_sub(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,st->offset_scale2_p,st->no_scales_p,resq, lsfq ); + + safety_net = 0; + } + else /* Switched Safety-Net/AR prediction */ + { + /* Subtract mean and AR prediction */ + mvr2r(ModeMeans[mode_lvq], pred0, M); + /* subtract only mean */ + v_sub(lsf, pred0, Tmp, M); + for (i = 0; i < M; i++) + { + /* subtract mean and AR prediction */ + pred2[i] = pred0[i] + Predictors[mode_lvq_p][i]*(mem_AR[i]-pred0[i]); + Tmp2[i] = lsf[i] - pred2[i]; + } + /* 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. */ + if ( ((*pstreaklen > (STREAKLEN+3))&&(coder_type==VOICED)) || ((*pstreaklen > (STREAKLEN)) &&(coder_type!=VOICED))) + { + /* update the adaptive scaling factor to become smaller with increasing number of concecutive predictive frames. */ + *streaklimit *= STREAKMULT; + } + + if ( *pstreaklen == 0 ) + { + /* reset the adaptive scaling factor */ + *streaklimit = 1.0f; + } + + + /* VOICED_WB@16kHz */ + if ( int_fs == INT_FS_16k && coder_type == VOICED ) + { + /* select safety_net or predictive in open loop*/ + safety_net = qlsf_Mode_Select( lsf, wghts, pred2, *streaklimit, OP_LOOP_THR_HVO ); + + if ( force_sf == 1 ) + { + safety_net = 1; + } + + if ( safety_net ) + { + /* Safety-net - BC-TCQ quantization : SN */ + Err[0] = qlsf_ARSN_tcvq_Enc_16k( Tmp, lsfq, TCQIdx0, wghts, nBits-1, safety_net ); + *pstreaklen = 0; + } + else + { + /* predictive - BC-TCQ quantization : AR */ + /* For consistency Err[1] contains predictive error */ + Err[1] = qlsf_ARSN_tcvq_Enc_16k( Tmp2, lsfq, TCQIdx0, wghts, nBits-1, safety_net ); + (*pstreaklen)++; + } + } + /* all other frames (not VOICED@16kHz) */ + else + { + /* safety-net */ + Err[0] = vq_lvq_lsf_enc(0, mode_lvq, Tmp, levels0, stages0, wghts, Idx0, lsf, pred0, + st->offset_scale1,st->offset_scale2,st->no_scales, resq, lsfq); + /* Predictive quantizer is calculated only if it can be selected, this saves computation */ + if (!force_sf || 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, st->offset_scale2_p, st->no_scales_p, &resq[M], &lsfq[M]); + } + /* Select whether to use safety-net or predictive LSF quantizer. The decision is based on following: + if the non-predictive (safety-net) quantization error (Err[0]) is low enough 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 || Err[0]*(*streaklimit) < PREFERSFNET * Err[1] || Err[0] < abs_threshold ) + { + safety_net = 1; + *pstreaklen = 0; /* Reset the consecutive predictive frame counter */ + } + else + { + safety_net = 0; + (*pstreaklen)++; /* Increase the consecutive predictive frame counter by one */ + } + } + } + + /*--------------------------------------------------------------------------* + * Write indices to array + *--------------------------------------------------------------------------*/ + + if (mode2_flag == 0) + { + /* write coder_type bit for VOICED@16kHz or GENERIC@16kHz */ + if((coder_type_org == GENERIC) + &&(int_fs == INT_FS_16k) + ) + { + /* VOICED =2 and GENERIC=3, so "coder_type-2" means VOICED =0 and GENERIC=1*/ + push_indice( st, IND_LSF_PREDICTOR_SELECT_BIT, coder_type-2, 1 ); + } + /* write predictor selection bit */ + if ( predmode == 2 ) + { + push_indice( st, IND_LSF_PREDICTOR_SELECT_BIT, safety_net, 1 ); + } + + if ( (coder_type == VOICED) && (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 0 ) + { + indice[i] = Idx[i]; + + if ( cumleft > LEN_INDICE ) + { + num_bits = LEN_INDICE; + } + else + { + num_bits = cumleft; + } + + cumleft -= num_bits; + + push_indice( st, IND_LSF, indice[i], num_bits ); + + i++; + } + } + } + else + { + if ( (coder_type == VOICED) && (int_fs == INT_FS_16k) ) + { + /* BC-TCVQ (only for VOICED@16kHz) */ + /* Number of quantization indices */ + *no_indices = 10; + for(i=0; i<*no_indices; i++) + { + lpc_param[i] = (int)TCQIdx0[i]; + bits_param_lpc[i] = BC_TCVQ_BIT_ALLOC_40B[i]; + } + } + else + { + /* Number of quantization indices */ + + /* there are 31 bits */ + if (safety_net==1) + { + Idx = Idx0; + *no_indices = stages0+1; + for(i=0; i0; i--) + { + lpc_param[i] = lpc_param[i-1]; + bits_param_lpc[i] = bits_param_lpc[i-1]; + } + lpc_param[0] = safety_net; /* put the safety net info on the last param */ + bits_param_lpc[0] = 1; + *no_indices = *no_indices+1; + } + } + } + + + /*--------------------------------------------------------------------------* + * De-quantize encoded LSF vector + *--------------------------------------------------------------------------*/ + + if ( safety_net ) + { + /* Safety-net */ + if ( coder_type == VOICED && int_fs == INT_FS_16k ) + { + /* BC-TCQ */ + mvr2r( lsfq, mem_MA, M ); + v_add( lsfq, pred0, qlsf, M ); + } + else + { + vq_dec_lvq( 1, qlsf, &indice[0], stages0, M, mode_lvq, levels0[stages0-1], + &st->offset_scale1[0][0], &st->offset_scale2[0][0], &st->offset_scale1_p[0][0], &st->offset_scale2_p[0][0], + &st->no_scales[0][0], &st->no_scales_p[0][0] ); + + v_add(qlsf, pred0, qlsf, M ); + v_sub(qlsf, pred1,mem_MA, M); + } + } + else + { + if ( (coder_type == VOICED) && (int_fs == INT_FS_16k) ) + { + /* BC-TCVQ */ + mvr2r( lsfq, mem_MA, M ); + v_add( lsfq, pred2, qlsf, M ); + } + else + { + /* LVQ */ + vq_dec_lvq( 0, qlsf, &indice[0], stages1, M, mode_lvq_p, levels1[stages1-1], + &st->offset_scale1[0][0], &st->offset_scale2[0][0], &st->offset_scale1_p[0][0], + &st->offset_scale2_p[0][0], &st->no_scales[0][0], &st->no_scales_p[0][0] ); + if (predmode==1) + { + mvr2r(qlsf, mem_MA, M); + v_add( qlsf, pred1, qlsf, M ); + } + else + { + v_add( qlsf, pred2, qlsf, M ); + v_sub(qlsf, pred1, mem_MA, M); + } + } + } + + /*--------------------------------------------------------------------------* + * Sort the quantized vector + * Verify stability + * Update AR-predictor memory + *--------------------------------------------------------------------------*/ + + /* Sort the quantized vector to ascending order */ + v_sort( qlsf, 0, M-1 ); + + /* Verify stability by adding minimum separation */ + reorder_lsf( qlsf, MODE1_LSF_GAP, M, int_fs ); + + /* Update predictor memories */ + mvr2r( qlsf, mem_AR, M ); + + + return; +} + + + +/*-------------------------------------------------------------------* + * first_VQstages() + * + * + *-------------------------------------------------------------------*/ + +static void first_VQstages( + const float * const *cb, + float u[], /* i : vector to be encoded (prediction and mean removed) */ + short *levels, /* i : number of levels in each stage */ + short stagesVQ, /* i : number of stages */ + float w[], /* i : weights */ + short N, /* i : vector dimension */ + short max_inner, /* i : maximum number of swaps in inner loop */ + short indices_VQstage[] +) +{ + float ftmp, resid_buf[2*LSFMBEST*M], *resid[2], dist_buf[2*LSFMBEST], *dist[2]; + float en, tmp, Tmp[M], *pTmp; + short *pTmp_short, idx_buf[2*LSFMBEST*MAX_VQ_STAGES], parents[LSFMBEST], counter=0, j, + m, s,c, c2, p_max, *indices[2]; + short maxC = LSFMBEST; + + /*float dd[16];*/ + const float *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; + indices[1] = idx_buf + maxC*stagesVQ; + resid[0] = resid_buf; + resid[1] = resid_buf + maxC*N; + dist[0] = dist_buf; + dist[1] = dist_buf + maxC; + + set_s( idx_buf, 0, (const short)(2*stagesVQ*maxC) ); + set_s( parents, 0, maxC ) ; + + /* Set up inital distance vector */ + for( tmp = 0, j=0; j0) + { + /* first VQ stages */ + first_VQstages( cb, u, levels, stagesVQ, w, M, MSVQ_MAXCNT, indices_firstVQ ); + } + + + for ( i=0; i>2][fins][stage4]; + index = NTRANS2[branch+2][*prev_state]; + + /* Prediction */ + pred[0] = itc[stage1][0][0] * Q[stage1][*prev_state][0] + itc[stage1][0][1] * Q[stage1][*prev_state][1]; + pred[1] = itc[stage1][1][0] * Q[stage1][*prev_state][0] + itc[stage1][1][1] * Q[stage1][*prev_state][1]; + target[0] = x[stage][0] - pred[0]; + target[1] = x[stage][1] - pred[1]; + + minDist = (target[0] - CB[stage4][index][0]) * (target[0] - CB[stage4][index][0]) * W[stage][0]; + minDist += (target[1] - CB[stage4][index][1]) * (target[1] - CB[stage4][index][1]) * W[stage][1]; + bestCode = index; + + for(index = index + 8; index < 32; index += 8) + { + dist = (target[0] - CB[stage4][index][0]) * (target[0] - CB[stage4][index][0]) * W[stage][0]; + dist += (target[1] - CB[stage4][index][1]) * (target[1] - CB[stage4][index][1]) * W[stage][1]; + + if(dist < minDist) + { + minDist = dist; + bestCode = index; + } + } + + /* Update */ + *prev_state = NTRANS2[branch][*prev_state]; + c[fins][stage4] = bestCode; + Q[stage][*prev_state][0] = CB[stage4][bestCode][0] + pred[0]; + Q[stage][*prev_state][1] = CB[stage4][bestCode][1] + pred[1]; + + return minDist; + +} + +/*--------------------------------------------------------------------------- + * optimalPath() + * + * + *--------------------------------------------------------------------------*/ + +static short optimalPath( + float cDist[][16], + float blockDist[], + short blockCodeword[][4], + short bestCodeword[], + short codeWord[][16], + short bestState[], + short preState[][16] +) +{ + short stage, state; + float opDist[NUM_STATE]; + float minDist; + short fBlock; + short prev_state; + + for(state = 0; state < NUM_STATE; state++) + { + opDist[state] = cDist[3][state] + blockDist[state]; + } + + minDist = opDist[0]; + fBlock = 0; + + for(state = 1; state < NUM_STATE; state++) + { + if(opDist[state] < minDist) + { + minDist = opDist[state]; + fBlock = state; + } + } + + prev_state = bestState[4] = fBlock; + + for(stage = N_STAGE_VQ - 5; stage >= 0; stage --) + { + bestCodeword[stage] = codeWord[stage][prev_state]; + bestState[stage] = preState[stage][prev_state]; + prev_state = bestState[stage]; + } + + for(stage = 0; stage < 4; stage ++) + { + bestCodeword[stage + 4] = blockCodeword[fBlock][stage]; + } + + return fBlock; +} + +/*--------------------------------------------------------------------------- + * quantEnc() + * + * + *--------------------------------------------------------------------------*/ + +static void quantEnc( + float *y, + short c[], + const float CB_SUB1[][128][2], + const float CB_SUB2[][64][2], + const float CB_SUB3[][32][2], + const float itc[][2][2] +) +{ + short i,j; + short stage; + float pred[N_DIM], Y[8][2]; + + /* stage #1 */ + Y[0][0] = CB_SUB1[0][c[0]][0]; + Y[0][1] = CB_SUB1[0][c[0]][1]; + + /* stage #2 */ + pred[0] = itc[0][0][0] * Y[0][0] + itc[0][0][1]*Y[0][1]; + pred[1] = itc[0][1][0] * Y[0][0] + itc[0][1][1]*Y[0][1]; + Y[1][0] = CB_SUB1[1][c[1]][0] + pred[0]; + Y[1][1] = CB_SUB1[1][c[1]][1] + pred[1]; + + /* stage #3 - #4 */ + for(stage = 2; stage < N_STAGE_VQ-4; stage ++) + { + pred[0] = itc[stage-1][0][0] * Y[stage-1][0] + itc[stage-1][0][1]*Y[stage-1][1]; + pred[1] = itc[stage-1][1][0] * Y[stage-1][0] + itc[stage-1][1][1]*Y[stage-1][1]; + + Y[stage][0] = CB_SUB2[stage-2][c[stage]][0] + pred[0]; + Y[stage][1] = CB_SUB2[stage-2][c[stage]][1] + pred[1]; + } + + /* stage #5 - #8 */ + for(stage = N_STAGE_VQ-4; stage < N_STAGE_VQ; stage ++) + { + pred[0] = itc[stage-1][0][0] * Y[stage-1][0] + itc[stage-1][0][1]*Y[stage-1][1]; + pred[1] = itc[stage-1][1][0] * Y[stage-1][0] + itc[stage-1][1][1]*Y[stage-1][1]; + + Y[stage][0] = CB_SUB3[stage-4][c[stage]][0] + pred[0]; + Y[stage][1] = CB_SUB3[stage-4][c[stage]][1] + pred[1]; + } + + /* Transform Vector to Scalar */ + for(i = 0; i < N_STAGE_VQ; i++) + { + for(j = 0; j < N_DIM; j++) + { + y[i*N_DIM+j] = Y[i][j]; + } + } + + return; +} + +/*--------------------------------------------------------------------------- + * buildCode() + * + * + *--------------------------------------------------------------------------*/ + +static void buildCode( + short *ind, + short fins, + short c[], + short s[] +) +{ + short stage; + short BrIndex[4]; + + set_s(BrIndex, 0, (N_STAGE_VQ - 4)); + + + for(stage = N_STAGE_VQ - 4; stage >= 1; stage--) + { + if(s[stage] > 7) + { + BrIndex[stage-1] = 1; + } + } + ind[0] = fins; + + /* stage #1 - #2 */ + for(stage = 0; stage < 2; stage++) + { + ind[stage+1] = BrIndex[stage] << 4; + ind[stage+1] += c[stage] >> 3; + } + + /* stage #3 - #4 */ + for(stage = 2; stage < N_STAGE_VQ - 4; stage++) + { + ind[stage+1] = BrIndex[stage] << 3; + ind[stage+1] += c[stage] >> 3; + } + + /* Stage #5 - #8 */ + for(stage = N_STAGE_VQ-4; stage < N_STAGE_VQ; stage++) + { + ind[stage+1] = c[stage] >> 3; + } + + return; +} + +/*--------------------------------------------------------------------------- + * BcTcvq() + * + * + *--------------------------------------------------------------------------*/ + +static void BcTcvq( + short snFlag, + const float *x, + float *y, + const float *weight, + short *ind +) +{ + float X[N_STAGE_VQ][N_DIM], W[N_STAGE_VQ][N_DIM]; + + /* Count Variable */ + short i,j; + + /* TCVQ Structure */ + short stage, state, prev_state; + short preState[N_STAGE_VQ][NUM_STATE]; + short codeWord[N_STAGE_VQ][NUM_STATE]; + float acumDist[N_STAGE_VQ-4][NUM_STATE]; + short inis, fins, ptr_fins; + short fBlock; + short fState[NUM_STATE]; + short fCodeword[4][4]; + short iniBlock[NUM_STATE]; + short blockCodeword[NUM_STATE][4]; + + /* Prediction variable */ + float quant[N_STAGE_VQ][NUM_STATE][N_DIM]; + + /* Distortion variable */ + float minDist; + float fDist; + float blockDist[NUM_STATE]; + + /* Decoding variable */ + short bestCodeword[N_STAGE_VQ]; + short bestState[N_STAGE_VQ]; + + /* Code Share variable */ + const float (*TCVQ_CB_SUB1)[128][2], (*TCVQ_CB_SUB2)[64][2], (*TCVQ_CB_SUB3)[32][2]; + const float (*IntraCoeff)[2][2]; + + /* Memoryless Module */ + if(snFlag) + { + TCVQ_CB_SUB1 = SN_TCVQ_CB_SUB1; + TCVQ_CB_SUB2 = SN_TCVQ_CB_SUB2; + TCVQ_CB_SUB3 = SN_TCVQ_CB_SUB3; + IntraCoeff = SN_IntraCoeff; + } + else /* Memory Module */ + { + TCVQ_CB_SUB1 = AR_TCVQ_CB_SUB1; + TCVQ_CB_SUB2 = AR_TCVQ_CB_SUB2; + TCVQ_CB_SUB3 = AR_TCVQ_CB_SUB3; + IntraCoeff = AR_IntraCoeff; + } + + /* Transform Scalar to Vector */ + for(i = 0; i < N_STAGE_VQ; i++) + { + for(j = 0; j < N_DIM; j++) + { + X[i][j] = x[(N_DIM*i) + j]; + W[i][j] = weight[(N_DIM*i) + j]; + } + } + + /* Initialzie */ + for(i=0; i= 0; stage--) + { + prev_state = preState[stage][prev_state]; + } + iniBlock[state] = prev_state; + } + + /* stage #5 - #8 */ + for(state = 0; state < NUM_STATE; state++) + { + inis = iniBlock[state]; + ptr_fins = inis >> 2; + + minDist = FLT_MAX; + + for(i = 0; i < 4; i++) + { + fins = ptr_fins*4 + i; + + prev_state = state; + fDist = BcTcvq_FixSearch(X, TCVQ_CB_SUB3, fCodeword, quant, FixBranch_tbl, N_STAGE_VQ-4, inis, i, &prev_state, W, IntraCoeff); + + for(stage = N_STAGE_VQ-3; stage < N_STAGE_VQ; stage++) + { + fDist += BcTcvq_FixSearch(X, TCVQ_CB_SUB3, fCodeword, quant, FixBranch_tbl, stage, inis, i, &prev_state, W, IntraCoeff); + } + + if(fDist < minDist) + { + minDist = fDist; + blockDist[state] = minDist; + fState[state] = fins; + + for(j = 0; j < 4; j++) + { + blockCodeword[state][j] = fCodeword[i][j]; + } + } + } + } + + /* Select optimal path */ + fBlock = optimalPath(acumDist, blockDist, blockCodeword, bestCodeword, codeWord, bestState, preState); + + /* Select Quantized Value */ + quantEnc(y, bestCodeword, TCVQ_CB_SUB1, TCVQ_CB_SUB2, TCVQ_CB_SUB3, IntraCoeff); + + /* Buid Code for Decoder */ + buildCode(ind, fState[fBlock], bestCodeword, bestState); + + return; +} + + +/*--------------------------------------------------------------------------- + * SVQ_2d() + * + * + *--------------------------------------------------------------------------*/ + +static short SVQ_2d( + float *x, + float *y, + const float *W, + const float CB[][8], + short Size +) +{ + short i, j; + short index = 0; + float distortion; + float temp; + + temp = FLT_MAX; + + for(i = 0; i < Size; i++) + { + distortion = 0.0; + for(j = 0; j < 8; j++) + { + distortion += (x[j] - CB[i][j])*(x[j] - CB[i][j])*W[j]; + } + + if(distortion < temp) + { + temp = distortion; + index = i; + } + } + + for(i = 0; i < M/2; i++) + { + y[i] = CB[index][i]; + } + + return index; +} + + +/*--------------------------------------------------------------------------- + * qlsf_ARSN_tcvq_Enc_16k() + * + * Predictive BC-TCQ encoder for LSF quantization + *--------------------------------------------------------------------------*/ + +static float qlsf_ARSN_tcvq_Enc_16k ( + const float *x, /* i : Vector to be encoded */ + float *y, /* o : Quantized LSF vector */ + short *indice, /* o : Indices */ + const float *w, /* i : LSF Weights */ + const short nBits, /* i : number of bits */ + short safety_net /* i : safety_net flag */ +) +{ + short i; + float temp_f; + float yy[M]; + float error_svq[M], error_svq_q[M]; + float x_q[M]; + if(safety_net == 1) + { + indice[0] = 1; + BcTcvq(1, x, x_q, w, &indice[1]); + + if(nBits>30) + { + /* SVQ */ + for(i = 0; i < M; i++) + { + error_svq[i] = (x[i] - x_q[i]) * scale_inv_ARSN[i]; + } + + /* 5bits 1st Split VQ for Residual*/ + indice[10] = SVQ_2d(error_svq, error_svq_q, w, AR_SVQ_CB1, 32); + /* 4bits 2nd Split VQ for Residual*/ + indice[11] = SVQ_2d(&error_svq[8], &error_svq_q[8], &w[8], AR_SVQ_CB2, 16 ); + + for(i = 0; i < M; i++) + { + x_q[i] = x_q[i] + (error_svq_q[i] * scale_ARSN[i]); + } + } + } + else + { + indice[0] = 0; + BcTcvq(0, x, x_q, w, &indice[1]); + + if(nBits>30) + { + /* SVQ */ + for(i = 0; i < M; i++) + { + error_svq[i] = x[i] - x_q[i]; + } + + /* 5bits 1st Split VQ for Residual*/ + indice[10] = SVQ_2d(error_svq, error_svq_q, w, AR_SVQ_CB1, 32 ); + /* 4bits 2nd Split VQ for Residual*/ + indice[11] = SVQ_2d(&error_svq[8], &error_svq_q[8], &w[8], AR_SVQ_CB2, 16 ); + + for(i = 0; i < M; i++) + { + x_q[i] = x_q[i] + error_svq_q[i]; + } + } + } + + v_sub( x_q, x, yy, M ); + v_mult( yy, yy, yy, M ); + temp_f = dotp( yy, w, M ); + + /* Recover the quantized LSF */ + mvr2r(x_q, y, M); + + return temp_f; +} + +/*-------------------------------------------------------------------* + * lsf_mid_enc() + * + * Mid-frame LSF quantization + --------------------------------------------------------------------*/ + +static void lsf_mid_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const float int_fs, /* i : internal (ACELP) sampling frequency */ + const float qlsp0[], /* i : quantized LSPs from frame beginning */ + const float qlsp1[], /* i : quantized LSPs from frame end */ + float lsp[], /* i/o: mid-frame LSP */ + const short coder_type, /* i : coding type */ + const short bwidth, /* i : input signal bandwidth */ + const long core_brate, /* i : core bitrate */ + float Bin_Ener[], /* i : per bin log energy spectrum */ + short ppp_mode, + short nelp_mode +) +{ + float ftemp, lsf[M], qlsf[M], qlsf1[M], qlsf0[M], wghts[M], err, err_min; + short j, k, idx, nb_bits = 0, size = 0; + const float *ratio = 0; + + /* convert LSPs to LSFs */ + lsp2lsf( lsp, lsf, M, int_fs ); + lsp2lsf( qlsp0, qlsf0, M, int_fs ); + lsp2lsf( qlsp1, qlsf1, M, int_fs ); + + Unified_weighting( Bin_Ener, lsf, wghts, bwidth==NB, coder_type==UNVOICED, (int)(int_fs), M ); + + /* codebook selection, number of bits, size of the codebook */ + if ( ppp_mode == 0 && nelp_mode == 0 ) + { + nb_bits = mid_LSF_bits_tbl[LSF_BIT_ALLOC_IDX(core_brate, coder_type)]; + + /* codebook selection */ + if ( coder_type == VOICED ) + { + switch ( nb_bits ) + { + case 5: + { + ratio = tbl_mid_voi_wb_5b; + break; + } + case 4: + { + ratio = tbl_mid_voi_wb_4b; + break; + } + } + } + else if ( coder_type == UNVOICED ) + { + ratio = tbl_mid_unv_wb_5b; + } + else + { + /* GENERIC, TRANSITION, AUDIO and INACTIVE */ + switch ( nb_bits ) + { + case 5: + { + ratio = tbl_mid_gen_wb_5b; + break; + } + case 2: + { + ratio = tbl_mid_gen_wb_2b; + break; + } + } + } + + size = (short) pow2[nb_bits]; + } + else if ( ppp_mode == 1 ) + { + ratio = tbl_mid_voi_wb_1b; + nb_bits = 1; + size = 2; + } + else if ( nelp_mode == 1 ) + { + ratio = tbl_mid_unv_wb_4b; + nb_bits = 4; + size = 16; + } + + /* loop over codevectors */ + err_min = 1e30f; + idx = 0; + for ( k = 0; k < size; k++ ) + { + err = 0; + + for (j=0; j 0 && j < M && qlsf[j] < qlsf[j-1] + LSF_GAP_MID ) + { + qlsf[j] = qlsf[j-1] + LSF_GAP_MID; + } + + ftemp = lsf[j] - qlsf[j]; + err += wghts[j] * ftemp * ftemp; + } + + if ( err < err_min ) + { + err_min = err; + idx = k; + } + } + + /* 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]; + + if ( j > 0 && j < M && qlsf[j] < qlsf[j-1] + LSF_GAP_MID ) + { + qlsf[j] = qlsf[j-1] + LSF_GAP_MID; + } + } + + reorder_lsf( qlsf, LSF_GAP_MID, M, int_fs ); + + /* convert LSFs back to LSPs */ + lsf2lsp( qlsf, lsp, M, int_fs ); + + push_indice( st, 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 000000000..b76facfaf --- /dev/null +++ b/lib_enc/lsf_msvq_ma_enc.c @@ -0,0 +1,521 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include "rom_enc.h" +#include "basop_proto_func.h" + +#define WMC_TOOL_SKIP + +#define kMaxC 8 + +/*--------------------------------------------------------------------------* + * msvq_enc() + * + * MSVQ encoder + *--------------------------------------------------------------------------*/ + +void msvq_enc +( + const float *const *cb, /* i : Codebook (indexed cb[*stages][levels][p]) */ + const int dims[], /* i : Dimension of each codebook stage (NULL: full dim.) */ + const int offs[], /* i : Starting dimension of each codebook stage (NULL: 0) */ + float u[], /* i : Vector to be encoded (prediction and mean removed) */ + const int *levels, /* i : Number of levels in each stage */ + int maxC, /* i : Tree search size (number of candidates kept from */ + /* one stage to the next == M-best) */ + int stages, /* i : Number of stages */ + float w[], /* i : Weights */ + int N, /* i : Vector dimension */ + int maxN, /* i : Codebook dimension */ + int Idx[] /* o : Indices */ +) +{ + float *resid[2], *dist[2]; + float en, tmp, *pTmp,*p1; + const float *cb_stage, *cbp, *p2; + int *indices[2], j, m, s,c, c2, p_max, i; + float resid_buf[2*LSFMBEST_MAX*M_MAX], dist_buf[2*LSFMBEST_MAX], Tmp[M_MAX]; + int idx_buf[2*LSFMBEST_MAX*MAX_VQ_STAGES_USED], parents[LSFMBEST_MAX]; + int n, maxn, start; + + /*----------------------------------------------------------------* + * 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; + set_i( idx_buf, 0, 2*stages*maxC ); + + resid[0] = resid_buf; + pTmp = resid_buf + maxC*N; + resid[1] = pTmp; + + dist[0] = dist_buf; + dist[1] = dist_buf + maxC; + set_i( parents, 0, maxC); + + /* Set up initial distance vector */ + for(tmp=0.0, j=0; j dist[1][p_max]) + { + p_max = c2; + } + } + } /* if (tmp <= dist[1][p_max]) */ + } /* for (j=0; j dist[1][p_max]) + { + p_max = c2; + } + } + } /* if (tmp <= dist[1][p_max]) */ + } /* for(c=0; c 0 && j < N && pred[j] < pred[j-1] + LSF_GAP_MID ) + { + pred[j] = pred[j-1] + LSF_GAP_MID; + } + + tmp = lsf[j] - pred[j]; + err += wghts[j] * tmp * tmp; + } + + if ( err < err_min ) + { + err_min = err; + *idx = k; + } + } + + return; +} + + +/*--------------------------------------------------------------------------* + * Q_lsf_tcxlpc() + * + * + *--------------------------------------------------------------------------*/ + +int Q_lsf_tcxlpc( /* o : number of indices */ + /* const */ float lsf[], /* (I) original lsf */ + float lsf_q[], /* (O) quantized lsf */ + Word16 lsp_q_ind[], /* (O) quantized lsp (w/o MA prediction) */ + int indices[], /* (O) VQ indices */ + int narrowband, /* (I) narrowband flag */ + int cdk, /* (I) codebook selector */ + float mem_MA[], /* (I) MA memory */ + int coder_type, /* (I) acelp extended mode */ + float *Bin_Ener /* (I) Spectrum energy */ +) +{ + float weights[M]; + float pred[M16k]; + int i; + int NumIndices; + const float *means; + Word16 lsf_q_ind[M16k]; + float lsf_rem[M]; + float lsf_rem_q[M]; + Word16 lsf_rem_q_ind[M]; + + Unified_weighting( &Bin_Ener[L_FFT/2], lsf, weights, narrowband, coder_type==UNVOICED, 12800, M ); + + NumIndices = 0; + + /* Put disabled flag */ + indices[NumIndices++] = 0; + + /* Inter-frame prediction */ + means = lsf_means[narrowband]; + for (i=0; i +#include "wmc_auto.h" +#include "prot.h" + + +/*-------------------------------------------------------------------* + * ltd_stable() + * + * + *-------------------------------------------------------------------*/ + +void ltd_stable( + float frames_power[], /* i/o: energy of several frames */ + float ltd_stable_rate[], /* o : time-domain stable rate */ + float frame_energy, /* i : current frame energy */ + int frameloop /* i : number of frames */ +) +{ + int i; + float tmp; + float mid_frame_amp[28]; + float seg_amp; + float dif,apow; + + frames_power[0] = (float)(sqrt(frame_energy)+0.001); + + if(frameloop<3) + { + for(i=1; i0; i--) + { + frames_power[i] = frames_power[i-1]; + } + + return; +} diff --git a/lib_enc/mdct_classifier.c b/lib_enc/mdct_classifier.c new file mode 100644 index 000000000..3e2bd2772 --- /dev/null +++ b/lib_enc/mdct_classifier.c @@ -0,0 +1,245 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "prot.h" + +/*--------------------------------------------------------------------------* + * mdct_classifier() + * + * MDCT signal classifier for HQ_CORE/TCX_20_CORE + *--------------------------------------------------------------------------*/ + +#define SMOOTH_FILT_COEFF 0.8f +#define THRESH_UP 1.6f +#define THRESH_DOWN 1.1f +#define HQ_LOCAL 3 +#define TCX_LOCAL 1 + +short mdct_classifier( /* o : HQ_CORE/TCX_20_CORE decision */ + const float *Y, /* i : FFT spectrum from fft_rel */ + Encoder_State *st, /* i/o: Encoder state variable */ + short vadflag, + float *cldfbBuf_Ener /* i : CLDFB energies */ +) +{ + short c; + float X[129]; + short k; + float y[2]; + float nf; + float pe; + short np; + float max_cand; + short max_i; + float p_energy; + float n_energy; + short d_acc; + short pos_last; + float clas_sec; + short clas_final; + short i; + float gain1, gain2, gain3, gain11, gain4; + float peak_l, peak_h, avrg_l, avrg_h, peak_H1, avrg_H1, peak_H2, avrg_H2; + short condition1, condition2; + short condition3, condition4; + + for (k = 0; k < 127; k++) + { + X[1 + k] = Y[1 + k] * Y[1 + k] + Y[255 - k] * Y[255 - k]; + } + + for (k = 0; k < 2; k++) + { + y[k] = Y[k << 7] * Y[k << 7]; + } + + for (k = 0; k < 2; k++) + { + X[k << 7] = y[k]; + } + + nf = X[0]; + pe = X[0]; + np = 0; + max_cand = -1.0F; + max_i = 0; + p_energy = 0.0F; + n_energy = 0.0F; + d_acc = 0; + pos_last = -1; + + for (k = 0; k < 128; k++) + { + if (X[k + 1] > nf) + { + nf = 0.9578F * nf + 0.0422F * X[k + 1]; + } + else + { + nf = 0.6472F * nf + 0.3528F * X[k + 1]; + } + + if (X[k + 1] > pe) + { + pe = 0.42237F * pe + 0.57763F * X[k + 1]; + } + else + { + pe = 0.80285F * pe + 0.19715F * X[k + 1]; + } + + if (X[k + 1] > pe * 0.64F) + { + if (X[k + 1] > max_cand) + { + max_cand = X[k + 1]; + max_i = (short)(2 + k); + } + } + else + { + if (max_i > 0) + { + if (np > 0) + { + d_acc = (short)((short)(d_acc + max_i) - pos_last); + } + np++; + pos_last = max_i; + } + + max_cand = -1.0F; + max_i = 0; + } + + p_energy += pe * pe; + n_energy += nf * nf; + } + + if (np > 1) + { + nf = (float)d_acc / ((float)np - 1.0F); + } + else + { + nf = 0.0F; + } + gain1 = 0.0f; + gain2 = 0.0f; + gain3 = 0.0f; + for(i=0; i<8; i++) + { + gain1 += cldfbBuf_Ener[i]/8; + gain2 += cldfbBuf_Ener[8+i]/8; + gain3 += cldfbBuf_Ener[16+i]/8; + } + + gain11 = 8*(gain1 - cldfbBuf_Ener[0]/8)/7; + gain4 = 0.0f; + for(i=0; i<12; i++) + { + gain4 += cldfbBuf_Ener[12+i]/12; + } + + + peak_H1 = cldfbBuf_Ener[25]; + avrg_H1 = cldfbBuf_Ener[25]; + for(i=1; i<5; i++) + { + if(cldfbBuf_Ener[25+i] > peak_H1) + { + peak_H1 = cldfbBuf_Ener[25+i]; + } + avrg_H1 += cldfbBuf_Ener[25+i]; + } + + peak_H2 = cldfbBuf_Ener[20]; + avrg_H2 = cldfbBuf_Ener[20]; + for(i=1; i<5; i++) + { + if(cldfbBuf_Ener[20+i] > peak_H2) + { + peak_H2 = cldfbBuf_Ener[20+i]; + } + avrg_H2 += cldfbBuf_Ener[20+i]; + } + + + peak_l = 0.0f; + avrg_l = EPSILON; + peak_h = 0.0f; + avrg_h = EPSILON; + for(i=0; i<32; i++) + { + avrg_l += X[20+i]; + avrg_h += X[96+i]; + if(X[20+i] > peak_l) + { + peak_l = X[20+i]; + } + if(X[96+i] > peak_h) + { + peak_h = X[96+i]; + } + } + + condition1 = nf > 12.0F; + condition2 = p_energy - n_energy * 147.87276f > 0; + condition3 = gain3 > 1.2f*gain2 || + (gain3 >= 0.8f*gain2 && 5*peak_H1 > 2.0f*avrg_H1) || + (2.6f*peak_l*avrg_h < peak_h *avrg_l || peak_l*avrg_h > 2.6f*peak_h *avrg_l); + condition4 = (gain4 > 0.8f*gain11 && 2.56f*peak_l*avrg_h > peak_h *avrg_l && peak_l*avrg_h < 5.12f*peak_h *avrg_l) || + (gain4 > 0.3f*gain11 && 32*peak_h < 1.5f*avrg_h && 5*peak_H2 < 1.5f*avrg_H2) || + (2.56f*peak_l*avrg_h < peak_h *avrg_l && 32*peak_h > 1.5f*avrg_h) || (peak_l*avrg_h > 2.56f*peak_h *avrg_l && 32*peak_h < 1.5f*avrg_h); + + if ( ( st->total_brate == HQ_32k && ((!condition1 && condition2) || (condition1 && !condition2)|| condition3) ) + || (st->total_brate == HQ_24k40 && condition4)) + { + c = HQ_LOCAL; + } + else + { + c = TCX_LOCAL; + } + + /* Smooth decision from instantaneous decision*/ + clas_sec = (SMOOTH_FILT_COEFF * st->clas_sec_old) + ((1-SMOOTH_FILT_COEFF) * c); + + /* Do thresholding with hysteresis */ + if((st->clas_final_old == HQ_CORE || st->clas_final_old == TCX_20_CORE) + && ((st->last_gain1 > 0.5f*gain1 && st->last_gain1 < 2.0f*gain1) && (st->last_gain2 > 0.5f*gain2 && st->last_gain2 < 2.0f*gain2))) + { + clas_final = st->clas_final_old; + } + else if (clas_sec > st->clas_sec_old && clas_sec > THRESH_UP) /* Going up? */ + { + clas_final = HQ_CORE; + } + else if (clas_sec < THRESH_DOWN)/* Going down */ + { + clas_final = TCX_20_CORE; + } + else + { + clas_final = st->clas_final_old; + } + + /* Prevent the usage of HQ_CORE on noisy-speech or inactive */ + if ( st->mdct_sw_enable==MODE2 && (st->flag_noisy_speech_snr == 1 || vadflag == 0 ) && clas_final == HQ_CORE ) + { + clas_final = TCX_20_CORE; + } + + + /* Memory update */ + st->clas_sec_old = clas_sec; + st->clas_final_old = clas_final; + st->last_gain1 = gain1; + st->last_gain2 = gain2; + + return clas_final; +} diff --git a/lib_enc/mdct_selector.c b/lib_enc/mdct_selector.c new file mode 100644 index 000000000..f2511b879 --- /dev/null +++ b/lib_enc/mdct_selector.c @@ -0,0 +1,260 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_enc.h" +#include "rom_com.h" +#include "prot.h" +#include + +/*-----------------------------------------------------------------* + * Local constants + *-----------------------------------------------------------------*/ + +#define MDCT_SW_SIG_LINE_THR 2.85f /* Significant spectral line threshold above Etot (dB) */ +#define MDCT_SW_SIG_PEAK_THR 36.0f /* Significant peak threshold below Etot (dB) */ +#define MDCT_SW_HI_SPARSE_THR 0.25f /* Max. ratio of significant spectral lines for the spectrum to be considered sparse */ +#define MDCT_SW_HI_ENER_LO_THR 7.5f /* Hi band low energy threshold (dB) */ +#define MDCT_SW_1_VOICING_THR 0.9f /* Voicing threshold */ +#define MDCT_SW_1_HI_ENER_LO_THR 12.5f /* Hi band low energy threshold (dB) */ +#define MDCT_SW_1_SIG_HI_LEVEL_THR 28.0f /* High signal level threshold above noise floor (dB) */ +#define MDCT_SW_1_SIG_LO_LEVEL_THR 22.5f /* Low signal level threshold above noise floor (dB) */ +#define MDCT_SW_1_COR_THR 80.0f /* Threshold on cor_map_sum to indicate strongly tonal signal */ +#define MDCT_SW_1_SPARSENESS_THR 0.65f /* Threshold on spectrum sparseness */ + +#define MDCT_SW_2_VOICING_THR 0.6f /* Voicing threshold */ +#define MDCT_SW_2_HI_ENER_LO_THR 9.5f /* Hi band low energy threshold (dB) */ +#define MDCT_SW_2_SIG_HI_LEVEL_THR 19.0f /* High signal level threshold above noise floor (dB) */ +#define MDCT_SW_2_SIG_LO_LEVEL_THR 23.5f /* Low signal level threshold above noise floor (dB) */ +#define MDCT_SW_2_COR_THR 62.5f /* Threshold on cor_map_sum to indicate strongly tonal signal */ +#define MDCT_SW_2_SPARSENESS_THR 0.4f /* Threshold on spectrum sparseness */ + +#define MDCT_SW_HYST_FAC 0.8f /* Hysteresis tolerance factor */ + +#define LOG_10 2.30258509299f + +/*--------------------------------------------------------------------------* + * get_sparseness() + * + * + *--------------------------------------------------------------------------*/ + +static float get_sparseness( + const float Bin_E[], + short n, + float thr +) +{ + short num_max, i; + + thr *= log(10); /* Convert to 10*log() domain from 10*log10() domain */ + + thr = max(thr, 3.0f); /* Set an absolute minimum for close to silent signals */ + + num_max = 0; + for (i=1; i max(max(Bin_E[i-1], Bin_E[i+1]), thr)) + { + ++num_max; + } + } + + return 1.0f - num_max / (float)((n-2)/2); +} + +/*--------------------------------------------------------------------------* + * MDCT_selector() + * + * + *--------------------------------------------------------------------------*/ + +void MDCT_selector( + Encoder_State *st, /* i/o: Encoder State */ + float sp_floor, /* i : Noise floor estimate */ + float Etot, /* i : Total energy */ + float cor_map_sum, /* i : harmonicity factor */ + const float voicing[], /* i : voicing factors */ + const float enerBuffer[], /* i : CLDFB buffers */ + short vadflag +) +{ + if( st->mdct_sw_enable == MODE1 || st->mdct_sw_enable == MODE2 ) + { + float hi_ener, frame_voicing, sparseness; + int peak_count; + short prefer_tcx, prefer_hq_core, switching_point, hi_sparse, sparse; + int lob_cldfb, hib_cldfb, lob_fft, hib_fft; + int i; + float sig_lo_level_thr, sig_hi_level_thr, cor_thr, voicing_thr, sparseness_thr, hi_ener_lo_thr; + int last_core; + + if (st->bwidth == NB) + { + lob_cldfb = 3200/400; + hib_cldfb = 4000/400; + lob_fft = (L_FFT/2)/2; /* 3.2 KHz */ + hib_fft = (40*(L_FFT/2))/64; /* 4.0 KHz */ + } + else if (st->bwidth == WB) + { + lob_cldfb = 4800/400; + hib_cldfb = 8000/400; + lob_fft = 3*L_FFT/2/4; /* 4.8 KHz */ + hib_fft = L_FFT/2; /* 6.4 KHz (should be 8 KHz) */ + } + else + { + lob_cldfb = 6400/400; + hib_cldfb = 16000/400; + if (st->bwidth == FB) + { + hib_cldfb = 24000/400; + } + lob_fft = L_FFT/2; /* 6.4 KHz */ + hib_fft = L_FFT/2; /* 6.4 KHz (should be 8 KHz) */ + } + + /* st->last_core is reset to TCX_20_CORE in init_acelp() => fix it here */ + last_core = st->last_core; + if( st->last_codec_mode == MODE1 && last_core == TCX_20_CORE ) + { + last_core = HQ_CORE; + } + + /* Voicing */ + frame_voicing = (voicing[0]+voicing[1])*0.5f; + + /* Spectral sparseness */ + sparseness = get_sparseness(st->Bin_E, lob_fft, Etot - MDCT_SW_SIG_PEAK_THR); + + /* Hi band energy */ + hi_ener = (float)log10(mean(&enerBuffer[lob_cldfb], hib_cldfb-lob_cldfb)+0.0001f); + + /* Hi band sparseness */ + if (st->bwidth >= 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 */ + } + + peak_count = 0; + for (i=lob_fft; iBin_E[i] >= Etot + MDCT_SW_SIG_LINE_THR*LOG_10) + { + ++peak_count; + } + } + hi_sparse = peak_count <= anint((hib_fft - lob_fft) * MDCT_SW_HI_SPARSE_THR); + sparse = peak_count <= anint((hib_fft - lob_fft) * MDCT_SW_HI_SPARSE_THR/MDCT_SW_HYST_FAC); + + /* Hysteresis */ + if (st->prev_hi_sparse > 0 && sparse > 0 && min(min(voicing[0], voicing[1]), voicing[2]) >= MDCT_SW_1_VOICING_THR) + { + hi_sparse = 1; + } + + /* Allowed switching point? */ + switching_point = (last_core != HQ_CORE && last_core != TCX_20_CORE) || /* previous core was non-MDCT */ + (st->prev_hi_ener <= MDCT_SW_HI_ENER_LO_THR || hi_ener <= MDCT_SW_HI_ENER_LO_THR) || /* hi band is close to silent */ + (last_core == HQ_CORE && (st->mdct_sw_enable == MODE1 || (hi_sparse > 0 && st->prev_hi_sparse >= 0 && st->prev_hi_sparse <= 1))) || /* HQ_CORE and hi band became sparse */ + (last_core == TCX_20_CORE && (hi_sparse == 0 && st->prev_hi_sparse > 0)); /* TCX and hi band became dense */ + + if (st->mdct_sw_enable == MODE1) + { + sig_lo_level_thr = MDCT_SW_1_SIG_LO_LEVEL_THR; + sig_hi_level_thr = MDCT_SW_1_SIG_HI_LEVEL_THR; + cor_thr = MDCT_SW_1_COR_THR; + voicing_thr = MDCT_SW_1_VOICING_THR; + sparseness_thr = MDCT_SW_1_SPARSENESS_THR; + hi_ener_lo_thr = MDCT_SW_1_HI_ENER_LO_THR; + } + else + { + /* st->mdct_sw_enable == MODE2 */ + sig_lo_level_thr = MDCT_SW_2_SIG_LO_LEVEL_THR; + sig_hi_level_thr = MDCT_SW_2_SIG_HI_LEVEL_THR; + cor_thr = MDCT_SW_2_COR_THR; + voicing_thr = MDCT_SW_2_VOICING_THR; + sparseness_thr = MDCT_SW_2_SPARSENESS_THR; + hi_ener_lo_thr = MDCT_SW_2_HI_ENER_LO_THR; + } + + prefer_tcx = (Etot - sp_floor >= sig_hi_level_thr) && /* noise floor is low */ + (cor_map_sum >= cor_thr || frame_voicing >= voicing_thr || sparseness >= sparseness_thr) && /* strong tonal components */ + (hi_ener <= hi_ener_lo_thr || hi_sparse > 0); /* high freqs have low energy or are sparse */ + + prefer_hq_core = (Etot - sp_floor < sig_lo_level_thr) || /* noise floor is very high */ + (cor_map_sum < cor_thr*MDCT_SW_HYST_FAC && frame_voicing < voicing_thr*MDCT_SW_HYST_FAC && sparseness < sparseness_thr*MDCT_SW_HYST_FAC) || /* too weak tonal components */ + (st->mdct_sw_enable == MODE1 && !prefer_tcx && st->transientDetection.transientDetector.bIsAttackPresent == 1); + + /* Prefer HQ_CORE on transients */ + if ( st->mdct_sw_enable == MODE2 && st->transientDetection.transientDetector.bIsAttackPresent == 1 ) + { + prefer_tcx = 0; + prefer_hq_core = 1; + } + + if (switching_point && (prefer_tcx || prefer_hq_core)) + { + if (prefer_tcx) + { + st->core = TCX_20_CORE; + } + else /* prefer_hq_core */ + { + st->core = HQ_CORE; + } + } + else if (last_core == HQ_CORE || last_core == TCX_20_CORE) + { + st->core = last_core; + } + + /* Prevent the usage of HQ_CORE on noisy-speech or inactive */ + if ( st->mdct_sw_enable==MODE2 && st->core == HQ_CORE && (st->flag_noisy_speech_snr == 1 || vadflag == 0 ) ) + { + st->core = TCX_20_CORE; + } + + + /* Update memories */ + if (hi_sparse <= 0) + { + st->prev_hi_sparse = hi_sparse; + } + else + { + st->prev_hi_sparse += hi_sparse; + if (st->prev_hi_sparse >= 2) + { + st->prev_hi_sparse = 2; + } + } + st->prev_hi_ener = hi_ener; + } + + return; +} + +/*--------------------------------------------------------------------------* + * MDCT_selector_reset() + * + * + *--------------------------------------------------------------------------*/ + +void MDCT_selector_reset( + Encoder_State *st /* i/o: Encoder State */ +) +{ + st->prev_hi_ener = 0; + st->prev_hi_sparse = -1; + + return; +} diff --git a/lib_enc/mslvq_enc.c b/lib_enc/mslvq_enc.c new file mode 100644 index 000000000..ec86ed611 --- /dev/null +++ b/lib_enc/mslvq_enc.c @@ -0,0 +1,744 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "prot.h" +#include "rom_com.h" +#include "cnst.h" + +/*-----------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------*/ + +static float quantize_data( float *data, const float *w_in, float *qin, float *cv_out, int *idx_lead, int *idx_scale, const float *sigma, + const float * inv_sigma, + const float *scales, short no_scales, const int *no_lead ); +static float q_data( float *pTmp1, const float *w1, float *quant, float *cv_out, int *idx_lead, int *idx_scale, + const float * p_inv_sigma, + const float *p_sigma, const float *p_scales, short *p_no_scales, const int *p_no_lead ); +static void prepare_data( float *xsort, int *sign, + float *data, float *w, const float *w_in, + const float * sigma, + const float * inv_sigma, + int *p_sig ); +static float calculate_min_dist( float cv_pot[LATTICE_DIM], int no_scales, const float *scale, const float *w, int *p_best_scale, + int *p_best_idx, const int *no_leaders, int sig, int * indx); +static int find_pos( float *c, int len, float arg, int *p ); +static void take_out_val( float *v, float *v_out, float val, int len ); +static int index_leaders( float *cv, int idx_lead, int dim ); +static int c2idx( int n, int *p, int k ); +static int encode_sign_pc1( int parity, float *cv); +static int encode_comb( float *cv, int idx_lead ); +static void sort_desc_ind( float *s, int len, int *ind ); + + +/*-----------------------------------------------------------------* + * mslvq() + * + * Encodes the LSF residual + *-----------------------------------------------------------------*/ +float mslvq ( + float *pTmp, /* i : M-dimensional input vector */ + float *quant, /* o : quantized vector */ + float *cv_out, /* o : corresponding 8-dim lattice codevectors (without the scaling) */ + int *idx_lead, /* o : leader index for each 8-dim subvector */ + int *idx_scale, /* o : scale index for each subvector */ + float *w, /* i : weights for LSF quantization */ + short mode, /* i : number indicating the coding type (V/UV/G...)*/ + short mode_glb, /* i : LVQ coding mode */ + int pred_flag, /* i : prediction flag (0: safety net, 1,2 - predictive )*/ + short no_scales[][2] +) +{ + float dist; + const float * p_scales, *p_sigma, *p_inv_sigma; + const int *p_no_lead; + short * p_no_scales; + + dist = 0.0f; + p_no_scales = no_scales[mode_glb]; + if ( pred_flag == 0 ) + { + p_sigma = sigma_MSLVQ[mode]; + /* inverse sigma is precomputed to save complexity */ + p_inv_sigma = inv_sigma_MSLVQ[mode]; + p_scales = scales[mode_glb]; + p_no_lead = no_lead[mode_glb]; + + } + else + { + p_sigma = sigma_p[mode]; + /* inverse sigma is precomputed to save complexity */ + p_inv_sigma = inv_sigma_p[mode]; + p_scales = scales_p[mode_glb]; + p_no_lead = no_lead_p[mode_glb]; + } + /* first subvector */ + dist += quantize_data( 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 */ + dist += quantize_data( 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 ); + + return dist; +} +/*-----------------------------------------------------------------* + * q_data() + * + * (used for LSF quantization in CNG) + *-----------------------------------------------------------------*/ + +static float q_data ( + float *pTmp1, + const float *w1, + float *quant, + float *cv_out, + int *idx_lead, + int *idx_scale, + const float *p_sigma, + const float *p_inv_sigma, + const float *p_scales, + short *p_no_scales, + const int *p_no_lead +) +{ + float dist = 0.0f; + /* first subvector */ + dist += quantize_data( 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 */ + dist += quantize_data( 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 ); + + return dist; +} + +/*-----------------------------------------------------------------* + * mslvq_cng() + * + * Encodes the LSF residual in SID frames + *-----------------------------------------------------------------*/ + +float mslvq_cng ( + short idx_cv, /* i : index of cv from previous stage */ + float *pTmp, /* i : 16 dimensional input vector */ + float *quant, /* o : quantized vector */ + float *cv_out, /* o : corresponding 8-dim lattice codevectors (without the scaling) */ + int *idx_lead, /* o : leader index for each 8-dim subvector */ + int *idx_scale, /* o : scale index for each subvector */ + const float *w, /* i : weights for LSF quantization */ + short * no_scales +) +{ + float dist; + const float *p_scales, *p_sigma, *p_inv_sigma; + const int *p_no_lead; + short *p_no_scales; + short mode_glb, mode, i; + float pTmp1[M], w1[M]; + + dist = 0.0f; + mode = (short)LVQ_COD_MODES + idx_cv; + + /* for CNG there is only one bitrate but several quantizer structures, depending on the previous VQ stage */ + mode_glb = START_CNG + idx_cv; + + p_sigma = sigma_MSLVQ[mode]; + p_inv_sigma = inv_sigma_MSLVQ[mode]; + p_scales = scales[mode_glb]; + p_no_lead = no_lead[mode_glb]; + p_no_scales = &no_scales[mode_glb*2]; + /* check if LSF component permutation is needed or not */ + if ( cng_sort[idx_cv] ) + { + /* change order in subvecs */ + for( i=0; i0) + { + prepare_data( cv_pot, sign, data, w, w_in, sigma, inv_sigma, &sig ); + /* sorting of the input vector based on its absolute values; indx: permutation corresponding to the sorting */ + sort_desc_ind(cv_pot, LATTICE_DIM, indx); + smallest = indx[LATTICE_DIM-1]; + min_dist = calculate_min_dist(cv_pot, no_scales, scale, w, &best_scale, &best_idx, no_leaders, sig, indx); + if (best_scale > -1) + { + for(j=0; j -1 ) + { + index1 = encode_comb(quant, idx_lead[0]) + table_no_cv[idx_lead[0]] + p_offset_scale1[mode*len_offset +idx_scale[0]]; + } + + /* for second subvector */ + index2 = 0; + if ( idx_scale[1] > -1 ) + { + index2 = encode_comb(&quant[LATTICE_DIM], idx_lead[1]) + table_no_cv[idx_lead[1]] + p_offset_scale2[mode*len_offset+idx_scale[1]]; + } + + multiply32_32_64(index1, (unsigned int)(p_offset_scale2[mode*len_offset+p_no_scales[mode*2+1]]), idx); + + tmp = idx[0] + index2; + if ( tmp < idx[0] || tmp < index2 ) + { + idx[1] +=1; + } + + idx[0] = tmp; + + /* convert to 3 short */ + index[0] = ((idx[0])&(0xffff>>1)); + index[1] = ((idx[0])>>15)&(0xffff>>1); + index[2] = ((idx[0])>>30) + (((idx[1])<<2)&(0xffff>>1)); + + return; +} + + + +/*-----------------------------------------------------------------* + * encode_comb() + * + * creates an index for the lattice codevector + *-----------------------------------------------------------------*/ + +static int encode_comb( /* o : index of the absolute valued codevector */ + float *cv, /* i : codevector to be indexed */ + int idx_lead /* i : leader class index, to know the values */ +) +{ + int idx_sign, idx_ld_class; + + idx_sign = encode_sign_pc1( pl_par[idx_lead], cv ); + idx_ld_class = index_leaders( cv, idx_lead, LATTICE_DIM ); + + return idx_sign * pi0[idx_lead] + idx_ld_class; +} + + +/*-----------------------------------------------------------------* + * index_leaders() + * + * gives the index in a class of leaders without considering the sign yet + *-----------------------------------------------------------------*/ + +static int index_leaders( /* o : index */ + float *cv, /* i : codevector to be indexed */ + int idx_lead, /* i : leader class index */ + int dim /* i : vector dimension */ +) +{ + int index, i, no_vals_loc, nr, p[LATTICE_DIM], dim_loc; + float cv_copy[LATTICE_DIM], val_crt; + + no_vals_loc = no_vals[idx_lead]; + + if ( no_vals_loc == 1 ) + { + return 0; + } + + for( i=0; i 0 ) + { + cnt ++; + } + } + + return idx_sign; +} + +/*-----------------------------------------------------------------* + * take_out_val() + * + * removes the value val from the vector v + *-----------------------------------------------------------------*/ + +static void take_out_val( + float *v, /* i : input vector */ + float *v_out, /* o : output vector without the value val*/ + float val, /* i : value to be removed */ + int len /* i : input vector length */ +) +{ + int i, cnt; + + cnt = 0; + + for( i=0; i 0) + { + *sp_floor = 0; + for (i=0; i flor) + { + S[i] = Bin_E[i] - flor; + } + else + { + S[i] = 0; + } + + /* update the floor */ + flor += step; + } + } + else + { + *sp_floor = Bin_E[0]; + } + *sp_floor *= 1.0f/log(10); + + /* calculate the maximum dynamic per band */ + mean_dyn = mean( &S[L-40], 40 ); + mean_dyn = 0.6f * *st_mean_avr_dyn + 0.4f * mean_dyn; + + if ( mean_dyn < 9.6f && *cor_strong_limit != 0 ) + { + *cor_strong_limit = 0; + *st_last_sw_dyn = mean_dyn; + } + else if ((mean_dyn - *st_last_sw_dyn) > 4.5f) + { + *cor_strong_limit = 1; + } + + if( total_brate < ACELP_9k60 || total_brate > ACELP_16k40 ) + { + *cor_strong_limit = 1; + } + + *st_mean_avr_dyn = mean_dyn; + + /*------------------------------------------------------------------* + * calculation of the correlation map + *------------------------------------------------------------------*/ + + if (N_mins > 0) + { + corx2 = 0; + corxy = 0; + stemp = ind_mins[0]; + ftemp = old_S[stemp]; + cory2 = ftemp * ftemp; + k = 1; + for (i = stemp+1; i <= ind_mins[N_mins]; i++) + { + if (i == ind_mins[k]) + { + /* include the last peak point (new minimum) to the corr. sum */ + ftemp = old_S[i]; + cory2 += ftemp * ftemp; + + /* calculation of the norm. peak correlation */ + if ((corx2 == 0) || (cory2 == 0)) + { + cor = 0; + } + else + { + cor = corxy * corxy / (corx2 * cory2); + } + + /* save the norm. peak correlation in the correlation map */ + for (j=ind_mins[k-1]; j 0.95f) + { + cor_strong = 1; + } + } + + + /* summation of the LT correlation map */ + cor_map_LT_sum = sum_f(cor_map_LT, L); + + if ( bwidth == NB ) + { + cor_map_LT_sum *= 1.53f; + *cor_map_sum *= 1.53f; + } + + + /* final decision about multi-harmonicity */ + if ( (cor_map_LT_sum > *multi_harm_limit) || (cor_strong == 1) ) + { + harm = 1; + } + else + { + harm = 0; + } + + /*------------------------------------------------------------------* + * updating of the decision threshold + *------------------------------------------------------------------*/ + + if (cor_map_LT_sum > THR_CORR) + { + *multi_harm_limit -= THR_CORR_STEP; + } + else + { + *multi_harm_limit += THR_CORR_STEP; + } + + if (*multi_harm_limit > THR_CORR_MAX) + { + *multi_harm_limit = THR_CORR_MAX; + } + + if (*multi_harm_limit < THR_CORR_MIN) + { + *multi_harm_limit = THR_CORR_MIN; + } + + if (N_mins <= 0) + { + set_f(old_S, 0, L); + } + + return harm; +} diff --git a/lib_enc/nelp_enc.c b/lib_enc/nelp_enc.c new file mode 100644 index 000000000..12ba73c19 --- /dev/null +++ b/lib_enc/nelp_enc.c @@ -0,0 +1,409 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*-------------------------------------------------------------------* + * quantize_uvg() + * + * Quantize unvoiced gains + *--------------------------------------------------------------------*/ + +static void quantize_uvg( + float *G, /* i : unvoiced gain */ + int *iG1, /* i : gain 1 index */ + int *iG2, /* i : gain 2 index */ + float *quantG, /* o : quantized gain */ + short bwidth +) +{ + float G1[2], G2[10]; + int i, j, k; + float mse, mmse; + const float (*UVG1CB)[2] = NULL; + const float (*UVG2CB1)[5] = NULL; + const float (*UVG2CB2)[5] = NULL; + + if ( bwidth == NB ) + { + UVG1CB = UVG1CB_NB; + UVG2CB1 = UVG2CB1_NB; + UVG2CB2 = UVG2CB2_NB; + } + else if ( bwidth == WB || bwidth == SWB ) + { + UVG1CB = UVG1CB_WB; + UVG2CB1 = UVG2CB1_WB; + UVG2CB2 = UVG2CB2_WB; + } + + for (i=0; i<2; i++) + { + G1[i] = 0; + for (j=0; j<5; j++) + { + G1[i] += SQR(G[i*5+j]); + } + G1[i] = (float) log10(sqrt(G1[i]/5)); + } + + mmse = (float) 1e30; + *iG1 = 0; + + for (i=0; i< UVG1_CBSIZE; i++) + { + mse = SQR(G1[0]-(UVG1CB[i][0]))+SQR(G1[1]-(UVG1CB[i][1])); + if (mse < mmse) + { + *iG1 = i; + mmse = mse; + } + } + + G1[0] = (float) pow(10.0,(UVG1CB[*iG1][0])); + G1[1] = (float) pow(10.0,(UVG1CB[*iG1][1])); + + for (i=0; i<2; i++) + { + for (j=0; j<5; j++) + { + G2[i*5+j] = G[i*5+j]/G1[i]; + } + } + + for (i=0; i<2; i++) + { + mmse = (float) 1e30; + iG2[i] = 0; + for (j=0; jrf_mode; + + if ((st->last_nelp_mode == 1) && (st->bwidth != st->last_bwidth)) + { + st->last_nelp_mode = 0; + } + + if ( st->bwidth == NB ) + { + if (st->last_nelp_mode != 1) + { + set_f(st->bp1_filt_mem_nb, 0, 7*2); + } + } + else if ( st->bwidth == WB || st->bwidth == SWB ) + { + if (st->last_nelp_mode != 1) + { + set_f(st->bp1_filt_mem_wb, 0, 4*2); + } + } + + if (st->last_nelp_mode != 1) + { + if ( st->bwidth == WB || st->bwidth == SWB ) + { + set_f(st->shape1_filt_mem, 0, 20); + set_f(st->shape2_filt_mem, 0, 20); + set_f(st->shape3_filt_mem, 0, 20); + set_f(st->txlpf1_filt1_mem, 0, 20); + set_f(st->txlpf1_filt2_mem, 0, 20); + set_f(st->txhpf1_filt1_mem, 0, 20); + set_f(st->txhpf1_filt2_mem, 0, 20); + } + } + + /* Start Unvoiced/NELP Processing */ + if ( st->bwidth == WB || st->bwidth == SWB ) + { + for (i=0, E1=0.001f; itxlpf1_filt1_mem); + + for (i=0, EL1=0.001f; itxhpf1_filt1_mem); + + for (i=0, EH1=0.001f; ilast_nelp_mode != 1) /* if prev frame was not NELP then init mem*/ + { + st->nelp_gain_mem = Gains[0]; + } + + tmp = (float) (20.0 * (log10 (Gains[0]) - log10 (st->nelp_gain_mem) ) ); + var_dB = tmp * tmp; + for (i = 1; i < 10; i++) + { + tmp = (float) (20.0 * (log10 (Gains[i]) - log10 (Gains[i - 1]))); + var_dB += tmp * tmp; + } + + if (st->last_nelp_mode!=1) + { + var_dB *= 0.111f; + } + else + { + var_dB *= 0.1f; + } + + fdbck = (float) (0.82f / (1.0f + exp (0.25f * (var_dB - 20.0f)))); + + for (i = 0; i < 10; i++) + { + Gains[i] = (float)((1.0f - fdbck) * Gains[i] + fdbck * st->nelp_gain_mem); + st->nelp_gain_mem = Gains[i]; + } + + quantize_uvg(Gains, &iG1, iG2, Gains, (short) st->bwidth ); + + if( rf_flag ) + { + st->rf_indx_nelp_iG1[0] = (short) iG1; + st->rf_indx_nelp_iG2[0][0] = (short) iG2[0]; + st->rf_indx_nelp_iG2[0][1] = (short) iG2[1]; + } + else + { + push_indice( st, IND_IG1, iG1, 5 ); + push_indice( st, IND_IG2A, iG2[0], 6 ); + push_indice( st, IND_IG2B, iG2[1], 6 ); + } + + if ( st->bwidth == WB || st->bwidth == SWB ) + { + gain_fac = 1.16f; + } + else + { + gain_fac = 1.37f; + } + + generate_nelp_excitation( &(st->nelp_enc_seed), Gains, ptr, gain_fac ); + + if ( st->bwidth == WB || st->bwidth == SWB ) + { + polezero_filter(ptr,ptr_tmp,L_FRAME,bp1_num_coef_wb,bp1_den_coef_wb,4,st->bp1_filt_mem_wb); + mvr2r(ptr_tmp,ptr,L_FRAME); + } + else if ( st->bwidth == NB ) + { + polezero_filter(ptr,ptr_tmp,L_FRAME,bp1_num_coef_nb_fx_order7,bp1_den_coef_nb_fx_order7,7,st->bp1_filt_mem_nb); + mvr2r(ptr_tmp,ptr,L_FRAME); + } + + for (i=0, E3=0.001f; ibwidth == WB || st->bwidth == SWB ) + { + polezero_filter(ptr,ptr_tmp,L_FRAME,shape1_num_coef,shape1_den_coef,10, st->shape1_filt_mem); + mvr2r(ptr_tmp,ptr,L_FRAME); + + for (i=0, E2=0.001f; itxlpf1_filt2_mem); + mvr2r(ptr_tmp,filtRes,L_FRAME); + + for (i=0, EL2=0.001f; itxhpf1_filt2_mem); + mvr2r(ptr_tmp,filtRes,L_FRAME); + + for (i=0, EH2=0.001f; ishape3_filt_mem); + + /* filter the residual to desired shape */ + polezero_filter(ptr,ptr_tmp,L_FRAME,shape2_num_coef,shape2_den_coef,10,st->shape2_filt_mem); + + mvr2r(ptr_tmp,ptr,L_FRAME); + + break; + case 2: + /* Update other filter memory */ + polezero_filter(ptr,filtRes,L_FRAME,shape2_num_coef,shape2_den_coef,10,st->shape2_filt_mem); + + /* filter the residual to desired shape */ + polezero_filter(ptr,ptr_tmp,L_FRAME,shape3_num_coef,shape3_den_coef,10,st->shape3_filt_mem); + + mvr2r(ptr_tmp,ptr,L_FRAME); + + break; + default: + /* Update other filter memory */ + polezero_filter(ptr,filtRes,L_FRAME,shape2_num_coef,shape2_den_coef,10,st->shape2_filt_mem); + polezero_filter(ptr,filtRes,L_FRAME,shape3_num_coef,shape3_den_coef,10,st->shape3_filt_mem); + + break; + } + + for (i=0, E2=0.001f; irf_indx_nelp_fid[0] = (short)fid; + } + else + { + push_indice( st, IND_NELP_FID, fid, 2 ); + } + } + + if(rf_flag==0) + { + for (i = 0; i < L_FRAME; i++) + { + exc[i] = ptr[i]; + } + } + return; +} diff --git a/lib_enc/nois_est.c b/lib_enc/nois_est.c new file mode 100644 index 000000000..c038140c9 --- /dev/null +++ b/lib_enc/nois_est.c @@ -0,0 +1,884 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "cnst.h" +#include "prot.h" + +/*-----------------------------------------------------------------* + * Local constants + *-----------------------------------------------------------------*/ + +#define ALPHA 0.1f + +#define COR_MIN8 0.65f +#define COR_MAX8 0.7f +#define TH_PC8 14 +#define TH_EPS8 10.4f +#define TH_STA8 5.0e5f +#define K_8 0.0091f +#define C_8 0.3185f +#define ALPHA_MAX8 0.999f +#define THR_NCHAR8 1.0f + +#define COR_MIN16 0.52f +#define COR_MAX16 0.85f +#define TH_PC16 4 +#define TH_EPS16 1.6f +/* 10.0e5f causes problems with music - as the noise estimate starts to track the music */ +#define TH_STA16 3.5e5f +#define K_16 0.0245f +#define C_16 -0.235f +#define ALPHA_MAX16 0.99f +#define THR_NCHAR16 1.0f + +#define TH_PC 12 +#define TH_PRED 0.8f +#define THR_SPDIV 5 + +#define HC_CNT 20 /* limit for harm corr count */ +#define HC_CNT_SLOW 80 /* limit for harm corr count slow */ +#define BCKR_SLOW_UPDATE_SCALE 0.1f /* step size for slow bckr update */ + +#define HE_LT_THR1 10.0f +#define HE_LT_THR2 30.0f +#define HE_LT_CNT 30 + +/*-----------------------------------------------------------------* + * noise_est_init() + * + * Initialization of Noise estimator + *-----------------------------------------------------------------*/ + +void noise_est_init( + float *totalNoise, /* o : noise estimate over all critical bands */ + short *first_noise_updt, /* o : noise update initialization flag */ + float bckr[], /* o : per band background noise energy estimate */ + float enrO[], /* o : per band old input energy */ + float ave_enr[], /* o : per band long-term average energies */ + short *pitO, /* o : open-loop pitch values from preceed. frame */ + short *aEn, /* o : noise adaptation hangover counter */ + short *st_harm_cor_cnt, /* i/o: 1st harm correlation timer */ + short *bg_cnt, /* i/o: pause burst length counter */ + float *lt_tn_track, + float *lt_tn_dist, + float *lt_Ellp_dist, + float *lt_haco_ev, + short *low_tn_track_cnt + ,float *Etot_st_est, + float *Etot_sq_st_est +) +{ + short i; + + for( i=0; i *Etot_h ) + { + *Etot_h = Etot; + } + *Etot_l += 0.08f; + + /* Could even be higher but it also delays first entry to DTX */ + if ( harm_cor_cnt > 50 ) + { + if ( ini_frame < min(150,MAX_FRAME_COUNTER-1) && + (*Etot_h - *Etot_lp) < 3.0f ) + { + *Etot_l += min(2,(*Etot_last-*Etot_l)*0.1f); + } + + /* Avoids large steps in short active segments */ + if ( *Etot_last - *Etot_l > HE_LT_THR2 && harm_cor_cnt > 250 ) + { + *Etot_l += (*Etot_last-*Etot_l)*0.02f; + } + else if ( (*Etot_last - *Etot_l) > HE_LT_THR1 ) + { + *Etot_l += 0.08f; + } + } + if ( Etot < *Etot_l ) + { + *Etot_l = Etot; + } + + if ( ini_frame < 100 && *Etot_l < *Etot_l_lp ) + { + *Etot_l_lp = 0.1f * *Etot_l + (1.0f - 0.1f) **Etot_l_lp; + } + else if ( ( harm_cor_cnt > HE_LT_CNT && (*Etot_last - *Etot_l) > HE_LT_THR2 ) || ( harm_cor_cnt > HE_LT_CNT && (ini_frame < 150 ) ) || + ( (*Etot_l_lp - *Etot_l) > HE_LT_THR2 ) ) + { + *Etot_l_lp = 0.03f * *Etot_l + (1.0f - 0.03f) **Etot_l_lp; + } + else + { + *Etot_l_lp = 0.02f * *Etot_l + (1.0f - 0.02f) **Etot_l_lp; + } + *sign_dyn_lp = 0.1f * (*Etot_h - *Etot_l) + (1.0f - 0.1f) **sign_dyn_lp; + } + + return; +} + +/*-----------------------------------------------------------------* + * noise_est_down() + * + * Down-ward noise udatation routine + * Total Noise computation, relative frame Energy computation + * Noise energy update - here, the energy is updated only if it is + * decreasing to improve noise suppression. Otherwise, the noise + * update is done on noise-only frames and this decision is made in + * nois_est() later in this file. + *-----------------------------------------------------------------*/ + +void noise_est_down( + const float fr_bands[], /* i : per band input energy (contains 2 vectors) */ + float bckr[], /* i/o: per band background noise energy estimate */ + float tmpN[], /* o : temporary noise update */ + float enr[], /* o : averaged energy over both subframes */ + const short min_band, /* i : minimum critical band */ + const short max_band, /* i : maximum critical band */ + float *totalNoise, /* o : noise estimate over all critical bands */ + const float Etot, /* i : Energy of current frame */ + float *Etot_last, /* i/o: Energy of last frame */ + float *Etot_v_h2 /* i/o: Energy variaions of noise frames */ +) +{ + const float *pt1, *pt2; + short i; + float Etot_v; + + /*-----------------------------------------------------------------* + * Estimate total noise energy + *-----------------------------------------------------------------*/ + + *totalNoise = 0.0f; + for( i = min_band; i <= max_band; i++ ) + { + *totalNoise += bckr[i]; + } + *totalNoise = 10.0f * (float)log10( *totalNoise ); + + /*-----------------------------------------------------------------* + * Average energy per frame for each frequency band + *-----------------------------------------------------------------*/ + + pt1 = fr_bands; + pt2 = fr_bands + NB_BANDS; + + for( i=0 ; i < NB_BANDS; i++ ) + { + enr[i] = 0.5f * ( *pt1++ + *pt2++ ); + } + + /*-----------------------------------------------------------------* + * Background noise energy update + *-----------------------------------------------------------------*/ + + for( i=0; i< NB_BANDS; i++ ) + { + tmpN[i] = (1-ALPHA) * bckr[i] + ALPHA * enr[i]; + if( tmpN[i] < bckr[i] ) + { + bckr[i] = tmpN[i]; /* Defend to increase noise estimate: keep as it is or decrease */ + } + } + + /*------------------------------------------------------------------* + * Energy variation update + *------------------------------------------------------------------*/ + + Etot_v = (float) fabs(*Etot_last - Etot); + *Etot_v_h2 = (1.0f-0.02f) **Etot_v_h2 + 0.02f * min(3.0f,Etot_v); + if (*Etot_v_h2 < 0.1f) + { + *Etot_v_h2 = 0.1f; + } + + return; +} + +/*-----------------------------------------------------------------* + * noise_est() + * + * Noise energy estimation (noise energy is updated in case of noise-only frame) + *-----------------------------------------------------------------*/ + +void noise_est( + Encoder_State *st, /* i/o: encoder state structure */ + const float tmpN[], /* i : temporary noise update */ + const short *pitch, /* i : open-loop pitch values for each half-frame */ + const float *voicing, /* i : normalized correlation for all half-frames */ + const float *epsP, /* i : LP prediction error energies */ + const float Etot, /* i : total channel E */ + const float relE, /* i : relative frame energy */ + const float corr_shift, /* i : normalized correlation correction */ + const float enr[], /* i : averaged energy over both subframes */ + float fr_bands[], /* i : spectrum per critical bands of the current frame */ + float *cor_map_sum, /* o : sum of correlation map from mult-harm analysis */ + float *sp_div, /* o : soectral diversity feature */ + float *non_staX, /* o : non-stationarity for sp/mus classifier */ + short *loc_harm, /* o : multi-harmonicity flag for UV classifier */ + const float *lf_E, /* i : per bin energy for low frequencies */ + short *st_harm_cor_cnt, /* i/o : 1st harm correlation timer */ + const float Etot_l_lp, /* i : Smoothed low energy */ + float *sp_floor /* o : noise floor estimate */ +) +{ + short i, tmp_pc, pc, spec_div, noise_char; + float alpha, th_eps, th_sta, non_sta, cor_min, cor_max; + float non_sta2, alpha2, sum_num, sum_den, *pt1, *pt2, ftemp, ftemp2, nchar_thr; + float updt_step,log_enr; + + short aE_bgd,sd1_bgd,bg_bgd2; + short tn_ini; + + float epsP_0_2,epsP_0_2_ad,epsP_0_2_ad_lp_max; + float epsP_2_16,epsP_2_16_dlp,epsP_2_16_dlp_max; + short PAU,BG_1,NEW_POS_BG; + + float haco_ev_max; + float Etot_l_lp_thr; + float comb_ahc_epsP,comb_hcm_epsP; + + short enr_bgd,cns_bgd,lp_bgd,ns_mask; + short lt_haco_mask, bg_haco_mask; + short SD_1,bg_bgd3,PD_1,PD_2,PD_3,PD_4,PD_5; + + float tmp_enr,tmp_ave,tmp_ave2; + float non_staB; + + float lim_Etot; + + /*-----------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + + st->ener_RAT = 10.0f * (float)log10( mean(lf_E, 8) ); + st->ener_RAT /= (Etot + 0.01f); + + if( st->ener_RAT < 0.0f ) + { + st->ener_RAT = 0.0f; + } + + if( st->ener_RAT > 1.0 ) + { + st->ener_RAT = 1.0f; + } + + /*-----------------------------------------------------------------* + * 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( st->input_bwidth != NB ) + { + /* WB input */ + th_eps = TH_EPS16; + th_sta = TH_STA16; + cor_min = COR_MIN16; + cor_max = COR_MAX16; + } + else + { + /* NB input */ + th_eps = TH_EPS8; + th_sta = TH_STA8; + cor_min = COR_MIN8; + cor_max = COR_MAX8; + } + + /*-----------------------------------------------------------------* + * Estimation of pitch stationarity + *-----------------------------------------------------------------*/ + + pc = (short)( abs(pitch[0] - st->pitO) + abs(pitch[1] - pitch[0]) ); + + if ( ( (voicing[0] + voicing[1] + voicing[2]) / 3.0f + corr_shift ) < cor_min ) + { + /* low correlation -> probably inactive signal */ + tmp_pc = TH_PC; + } + else + { + tmp_pc = pc; + } + + st->pitO = pitch[1]; + + /*-----------------------------------------------------------------* + * Multi-harmonic analysis + *-----------------------------------------------------------------*/ + + *loc_harm = multi_harm( st->Bin_E, st->old_S, st->cor_map, &st->multi_harm_limit, st->total_brate, + st->bwidth, &st->cor_strong_limit, &st->mean_avr_dyn, &st->last_sw_dyn, cor_map_sum, sp_floor ); + + /*-----------------------------------------------------------------* + * Detection of frames with non-stationary spectral content + *-----------------------------------------------------------------*/ + + /* weighted sum of spectral changes per critical bands */ + sum_num = 0; + sum_den = 0; + + pt1 = fr_bands + 10; + pt2 = st->fr_bands2 + 10; + for (i = 10; i <= st->max_band; i++) + { + if (*pt1 > *pt2) + { + sum_num += *pt1 **pt1 / *pt2; + sum_den += *pt1; + } + else + { + sum_num += *pt2 **pt2 / *pt1; + sum_den += *pt2; + } + + pt1++; + pt2++; + } + + /* calculation of spectral diversity */ + if (sum_num > THR_SPDIV * sum_den) + { + spec_div = 1; + } + else + { + spec_div = 0; + } + + *sp_div = sum_num / (sum_den + 1e-5f); + + /*-----------------------------------------------------------------* + * Detection of frames with high energy content in high frequencies + *-----------------------------------------------------------------*/ + + /* calculation of energy in first 10 critical bands */ + ftemp = sum_f( &fr_bands[st->min_band], 10 - st->min_band ); + + /* calculation of energy in the rest of bands */ + ftemp2 = sum_f( &fr_bands[10], st->max_band - 10 + 1 ); + + if ( ftemp < 1e2 || ftemp2 < 1e2 ) + { + ftemp2 = 0; + } + else + { + ftemp2 /= ftemp; + } + + if ( ftemp2 > 10 ) + { + ftemp2 = 10; + } + + /* update LT value of the final parameter */ + st->noise_char = M_ALPHA * st->noise_char + (1-M_ALPHA) * ftemp2; + + if( st->input_bwidth == NB ) + { + nchar_thr = THR_NCHAR8; + } + else + { + nchar_thr = THR_NCHAR16; + } + + if( st->noise_char > nchar_thr ) + { + noise_char = 1; + } + else + { + noise_char = 0; + } + + /* save the 2 last spectra per crit. bands for the future */ + mvr2r( st->fr_bands1, st->fr_bands2, NB_BANDS ); + mvr2r( fr_bands+NB_BANDS, st->fr_bands1, 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; + } + + alpha = 0.064f * ftemp + 0.75f; + + if( alpha > 0.999f ) + { + alpha = 0.999f; + } + + /* during significant attacks, replace LT energy by the */ + /* current energy - this will cause non_sta2 failures to occur in */ + /* different frames than non_sta failures */ + alpha2 = alpha; + if ( spec_div > 0) + { + alpha2 = 0.0f; + } + + /* calculate non-stationarity */ + non_sta = 1.0f; + non_sta2 = 1.0f; + *non_staX = 0.0f; + non_staB =0.0f; + for( i = st->min_band; i <= st->max_band; i++ ) + { + /* + 1.0f added to reduce sencitivity to non stationarity in low energies */ + tmp_enr = enr[i] + 1.0f; + if( non_sta <= th_sta ) /* Just to limit the saturation */ + { + tmp_ave = st->ave_enr[i] + 1.0f; + if( tmp_enr > tmp_ave ) + { + non_sta = non_sta * (tmp_enr / tmp_ave ); /* non_stationarity measure */ + } + else + { + non_sta = non_sta * (tmp_ave / tmp_enr ); /* non_stationarity measure */ + } + } + st->ave_enr[i] = alpha * st->ave_enr[i] + (1-alpha) * enr[i]; /* update long-term average */ + + /* 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 ); + } + } + + st->ave_enr2[i] = alpha2 * st->ave_enr2[i] + (1-alpha2) * enr[i]; + + /* calculate non-stationarity feature for speech/music classifier */ + if( i >= START_BAND_SPMUS && i < NB_BANDS_SPMUS+START_BAND_SPMUS ) + { + log_enr = (float)log(enr[i]); + if( log_enr > st->past_log_enr[i-START_BAND_SPMUS] ) + { + *non_staX += log_enr - st->past_log_enr[i-START_BAND_SPMUS]; + } + else + { + *non_staX += st->past_log_enr[i-START_BAND_SPMUS] - log_enr; + } + + st->past_log_enr[i-START_BAND_SPMUS] = log_enr; + } + /* calculate non-stationarity feature relative background */ + if (st->ini_frame < 100) + { + /* During init don't include updates */ + if ( i >= 2 && i <= 16 ) + { + non_staB += (float)fabs(log(enr[i] + 1.0f) - + log(E_MIN + 1.0f)); + } + } + else + { + /* After init compare with background estimate */ + if ( i >= 2 && i <= 16 ) + { + non_staB += (float)fabs(log(enr[i] + 1.0f) - + log(st->bckr[i] + 1.0f)); + } + } + if (non_staB >= 128) + { + non_staB = 32767.0/256.0f; + } + } + if ( Etot < -5.0f ) + { + non_sta = 1.0f; + non_sta2 = 1.0f; + } + + lim_Etot = max(20.0f,Etot); + + if ( st->ini_frame < 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->Etot_sq_st_est = 0.25f * lim_Etot * lim_Etot + (1.0f-0.25f) * st->Etot_sq_st_est; + } + else + { + st->Etot_st_est = 0.25f * lim_Etot + (1.0f-0.25f) * st->Etot_st_est; + st->Etot_sq_st_est = 0.25f * lim_Etot * lim_Etot + (1.0f-0.25f) * st->Etot_sq_st_est; + } + /*-----------------------------------------------------------------* + * Count frames since last correlation or harmonic event + *-----------------------------------------------------------------*/ + if ( Etot > 0 && + (*loc_harm > 0 || 0.5f * (voicing[0] + voicing[1]) > 0.85f) ) + + { + st->harm_cor_cnt = 0; + } + else + { + st->harm_cor_cnt += 1; + } + + if ( st->harm_cor_cnt > 1 && ( ( Etot < 15.0f ) || + ( st->ini_frame>10 && + ( Etot-st->Etot_lp ) > 7.0f ) + ) + ) + { + st->harm_cor_cnt = 1; + } + if ( st->harm_cor_cnt > 1 && + Etot > 30.0f && + (st->Etot_sq_st_est - st->Etot_st_est*st->Etot_st_est) > 8.0f) + { + st->harm_cor_cnt = max(1,(short) round_f( (float) st->harm_cor_cnt / 4.0f )) ; + } + + /*-----------------------------------------------------------------* + * Energy-based pause-length counter + *-----------------------------------------------------------------*/ + + if ( st->bg_cnt >= 0 && (Etot - st->Etot_l_lp) > 5 ) + { + /* probably speech burst */ + st->bg_cnt = -1; + } + else + { + if ( st->bg_cnt == -1 && (Etot - st->Etot_l_lp) < 5 ) + { + /* probably start of speech pause */ + st->bg_cnt = 0; + } + } + + if (st->bg_cnt >= 0) + { + st->bg_cnt += 1; + } + + /*-----------------------------------------------------------------* + * Linear predition efficiency 0 to 2 order + *-----------------------------------------------------------------*/ + + epsP_0_2 = max(0 , min(8, epsP[0] / epsP[2])); + st->epsP_0_2_lp = 0.15f * epsP_0_2 + (1.0f-0.15f) * st->epsP_0_2_lp; + epsP_0_2_ad = (float) fabs(epsP_0_2 - st->epsP_0_2_lp ); + 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; + } + epsP_0_2_ad_lp_max = max(epsP_0_2_ad,st->epsP_0_2_ad_lp); + + /*-----------------------------------------------------------------* + * Linear predition efficiency 2 to 16 order + *-----------------------------------------------------------------*/ + + epsP_2_16 = max(0 , min(8, epsP[2] / epsP[16])); + 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; + + epsP_2_16_dlp = st->epsP_2_16_lp-st->epsP_2_16_lp2; + + 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; + } + + epsP_2_16_dlp_max = max(epsP_2_16_dlp,st->epsP_2_16_dlp_lp2); + + /*-----------------------------------------------------------------* + * long term extensions of frame features + *-----------------------------------------------------------------*/ + + st->lt_tn_track = 0.03f* (Etot - st->totalNoise < 10) + 0.97f*st->lt_tn_track; + st->lt_tn_dist = 0.03f* (Etot - st->totalNoise) + 0.97f*st->lt_tn_dist; + st->lt_Ellp_dist = 0.03f* (Etot - st->Etot_l_lp) + 0.97f*st->lt_Ellp_dist; + + if (st->harm_cor_cnt == 0) + { + st->lt_haco_ev = 0.03f + 0.97f*st->lt_haco_ev; + } + else + { + st->lt_haco_ev = 0.99f*st->lt_haco_ev; + } + + if (st->lt_tn_track<0.05f) + { + st->low_tn_track_cnt++; + } + else + { + st->low_tn_track_cnt=0; + } + + + /* 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; + } + + /*-----------------------------------------------------------------* + * Increment/decrement counter for enabling background noise update + *-----------------------------------------------------------------*/ + 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)) + ) + + { + /* active signal present - increment counter */ + st->aEn = st->aEn + 2; + } + else + { + /* background noise present - decrement counter */ + st->aEn = st->aEn - 1; + } + + if( st->aEn > 6 ) + { + st->aEn = 6; + } + else if ( st->aEn < 0 ) + { + st->aEn = 0; + } + + /*--------------------------------------------------------------* + * Background noise update + * (if this is not noise-only frame, bckr has been already updated downwards in nois_est_down()) + *--------------------------------------------------------------*/ + /* Additional detectors */ + + comb_ahc_epsP = max(max(st->act_pred,st->lt_haco_ev),epsP_2_16_dlp); + comb_hcm_epsP = max(max(st->lt_haco_ev,epsP_2_16_dlp_max),epsP_0_2_ad_lp_max); + + haco_ev_max = max(*st_harm_cor_cnt==0,st->lt_haco_ev); + Etot_l_lp_thr = st->Etot_l_lp + (1.5f + 1.5f * (st->Etot_lp<50.0f))*st->Etot_v_h2; + + + enr_bgd = Etot < Etot_l_lp_thr; + cns_bgd = (epsP_0_2 > 7.95f) && (non_sta< 1e3f); + lp_bgd = epsP_2_16_dlp_max < 0.10f; + ns_mask = non_sta < 1e5f; + lt_haco_mask = st->lt_haco_ev < 0.5f; + bg_haco_mask = haco_ev_max < 0.4f; + + SD_1 = ( (epsP_0_2_ad > 0.5f) && (epsP_0_2 > 7.95f) ); + + bg_bgd3 = enr_bgd || ( ( cns_bgd || lp_bgd ) && ns_mask && lt_haco_mask && SD_1==0 ); + + PD_1 = (epsP_2_16_dlp_max < 0.10f ) ; + PD_2 = (epsP_0_2_ad_lp_max < 0.10f ) ; + PD_3 = (comb_ahc_epsP < 0.85f ); + PD_4 = comb_ahc_epsP < 0.15f; + PD_5 = comb_hcm_epsP < 0.30f; + + BG_1 = ( (SD_1==0) || (Etot < Etot_l_lp_thr) ) && bg_haco_mask && (st->act_pred < 0.85f) && (st->Etot_lp < 50.0f); + + PAU = (st->aEn==0) || ( (Etot < 55.0f) && (SD_1==0) && ( ( PD_3 && (PD_1 || PD_2 ) ) || ( PD_4 || PD_5 ) ) ); + + NEW_POS_BG = (PAU | BG_1) & bg_bgd3; + + /* Original silence detector works in most cases */ + aE_bgd = st->aEn == 0; + + /* 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; + + /* init conditions steadily dropping act_pred and/or lt_haco_ev */ + tn_ini = st->ini_frame < 150 && st->harm_cor_cnt > 5 && + (Etot-st->Etot_lp) < 7 && + ( (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 + || ( Etot < 42.0f + && st->harm_cor_cnt > 10 + && st->lt_haco_ev <0.35f + && st->act_pred <0.8f ) + ); + /* Energy close to the background estimate serves as a mask for other background detectors */ + bg_bgd2 = Etot < Etot_l_lp_thr || tn_ini ; + + updt_step=0.0f; + if (( bg_bgd2 && ( aE_bgd || sd1_bgd || st->lt_tn_track >0.90f || NEW_POS_BG ) ) || + tn_ini ) + { + if( ( ( st->act_pred < 0.85f ) && + aE_bgd && + ( 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 && st->lt_aEn_zero > 0.5f ) || + ( tn_ini && ( aE_bgd || non_staB < 10.0 || st->harm_cor_cnt > 80 ) ) + ) + { + updt_step=1.0f; + st->first_noise_updt = 1; + for( i=0; i< NB_BANDS; i++ ) + { + st->bckr[i] = tmpN[i]; + } + } + 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 + ) + { + updt_step=0.1f; + if ( !aE_bgd && + st->harm_cor_cnt < 50 && + ( st->act_pred > 0.6f || + ( !tn_ini && Etot_l_lp - st->totalNoise < 10.0f && non_staB > 8.0f ) ) ) + { + updt_step=0.01f; + } + if (updt_step > 0.0f ) + { + st->first_noise_updt = 1; + for( i=0; i< NB_BANDS; i++ ) + { + st->bckr[i] = st->bckr[i] + updt_step * (tmpN[i]-st->bckr[i]); + } + } + } + else if (aE_bgd || st->harm_cor_cnt > 100 ) + { + ( st->first_noise_updt) += 1; + } + } + else + { + /* If in music lower bckr to drop further */ + if ( st->low_tn_track_cnt > 300 && st->lt_haco_ev >0.9f && st->totalNoise > 0.0f) + { + updt_step=-0.02f; + for( i=0; i< NB_BANDS; i++ ) + { + if (st->bckr[i] > 2*E_MIN) + { + st->bckr[i] = 0.98f*st->bckr[i]; + } + } + } + } + st->lt_aEn_zero = 0.2f * (st->aEn==0) + (1-0.2f)*st->lt_aEn_zero; + return ; +} diff --git a/lib_enc/noise_adjust.c b/lib_enc/noise_adjust.c new file mode 100644 index 000000000..6ef863aa3 --- /dev/null +++ b/lib_enc/noise_adjust.c @@ -0,0 +1,82 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*--------------------------------------------------------------------------* + * noise_adjust() + * + * Calculate attenuation + *--------------------------------------------------------------------------*/ + +short noise_adjust( /* o : index of noise attenuation */ + const float *coeffs_norm, /* i : normalized coefficients */ + const short *bitalloc, /* i : bit allocation */ + const short *sfm_start, + const short *sfm_end, + const short core_sfm /* i : index of the end band for core */ +) +{ + short nf_idx, sfm, bin, num_coeffs; + int E, diff, tmp; + + E = 0; + num_coeffs = 0; + + 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 = E - 1; + } + else + { + tmp = (int)(floor(log10(fabs(coeffs_norm[bin] * L_FRAME))/0.301030f)+1); + if (tmp < 0) + { + tmp = 0; + } + E = E + tmp; + } + + num_coeffs = num_coeffs + 1; + } + } + } + + if (num_coeffs != 0) + { + E = E/num_coeffs; + } + else + { + E = 0; + } + + diff = 7 - E; + + if ( diff >= 0 ) + { + nf_idx = (short)diff; + if ( diff > 3 ) + { + nf_idx = 3; + } + } + else + { + nf_idx = 0; + } + + return nf_idx; +} diff --git a/lib_enc/normalizecoefs.c b/lib_enc/normalizecoefs.c new file mode 100644 index 000000000..c8c08ba6d --- /dev/null +++ b/lib_enc/normalizecoefs.c @@ -0,0 +1,38 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------------- + * normalizecoefs() + * + * Normalize MDCT coefficients with quantized norms + *--------------------------------------------------------------------------*/ + +void normalizecoefs( + float *coefs, /* i/o: MDCT coefficients */ + const short *ynrm, /* i : quantization indices for norms */ + const short num_bands, /* i : Number of bands */ + const short *band_start, /* i : Start of bands */ + const short *band_end /* i : End of bands */ +) +{ + short i, band; + float normq; + + for (band = 0; band < num_bands; band++) + { + normq = dicn_inv[ynrm[band]]; + + for (i = band_start[band]; i < band_end[band]; i++) + { + coefs[i] *= normq; + } + } + + return; +} diff --git a/lib_enc/peak_vq_enc.c b/lib_enc/peak_vq_enc.c new file mode 100644 index 000000000..9b379becc --- /dev/null +++ b/lib_enc/peak_vq_enc.c @@ -0,0 +1,593 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + +/*-------------------------------------------------------------------------- + * Local functions + *--------------------------------------------------------------------------*/ + +void quant_peaks( Encoder_State *st, const float *vect_in, float *vect_out, const float *peak_gain, short *vq_idx ,const short overlap, + const short brate, const short Npeaks ); + +static short hvq_code_pos( Encoder_State *st, const short *inp, const short length, const short num_peaks ); +static short sparse_code_pos( const short *inp, const short length, short *result ); + +/*-------------------------------------------------------------------------- + * peak_vq_enc() + * + * Vector Quantization of MDCT peaks + *--------------------------------------------------------------------------*/ + +short peak_vq_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const float *coefs, /* i : Input coefficient vector */ + float *coefs_out, /* o : Quantized output vector */ + const short brate, /* i : Core bitrate */ + const short num_bits, /* i : Number of bits for HVQ */ + const short vq_peaks, /* i : Number of identified peaks */ + const short *ynrm, /* i : Envelope coefficients */ + short *R, /* i/o: Bit allocation/updated bit allocation */ + short *vq_peak_idx, /* i : Peak index vector */ + float *nf_gains /* i : Estimated noise floor gains */ +) +{ + short pos_bits; + float normq; + float pgain_q[HVQ_MAX_PEAKS_32k]; + float peak_gains[HVQ_MAX_PEAKS_32k]; + float coefs_pvq[HVQ_PVQ_BUF_LEN]; + float pvq_vector[HVQ_PVQ_BUF_LEN]; + float *pPvqVectorBandStart; + float fg_pred[NB_SFM_MAX]; + short i, j, k, m, r, pvq_bands, num_overlap_bins; + short hcode_l, FlagN, low_peak_bin, vq_cb_idx, max_peaks, bin_th; + short bits = 0; + short q_nf_gain_idx[HVQ_NF_GROUPS]; + short nf_seed = RANDOM_INITSEED; + short pgain_cb_idx[HVQ_MAX_PEAKS], pgain_difidx[HVQ_MAX_PEAKS]; + short pvq_norm[MAX_PVQ_BANDS]; + short pvq_bits, bit_budget; + short pos_vec[HVQ_THRES_BIN_32k]; + short npulses[MAX_PVQ_BANDS]; + short pvq_inp_vector[HVQ_PVQ_BUF_LEN]; + short k_sort[MAX_PVQ_BANDS]; + short Rk[MAX_PVQ_BANDS]; + short Rk_f[MAX_PVQ_BANDS]; /*Q3*/ + float gopt[NB_SFM]; + short sel_bnds[HVQ_NUM_SFM_24k]; + short n_sel_bnds; + int manE_peak, manPkEnrg; + short expE_peak, expPkEnrg; + short hvq_band_end[MAX_PVQ_BANDS]; + short hvq_band_start[MAX_PVQ_BANDS]; + short hvq_band_width[MAX_PVQ_BANDS]; + short n; + short s; + set_f( coefs_pvq, 0.0f, HVQ_PVQ_BUF_LEN ); + set_f( pvq_vector, 0.0f, HVQ_PVQ_BUF_LEN ); + set_s( npulses, 0, MAX_PVQ_BANDS ); + + /* Set bitrate dependent variables */ + if (brate == HQ_24k40) + { + max_peaks = HVQ_MAX_PEAKS_24k; + bin_th = HVQ_THRES_BIN_24k; + } + else + { + max_peaks = HVQ_MAX_PEAKS_32k; + bin_th = HVQ_THRES_BIN_32k; + } + + for (i = 0; i < bin_th; i++) + { + pos_vec[i] = 0; + } + + /* Quantize noise floor gains */ + for (i = 0; i < HVQ_NF_GROUPS; i++) + { + logqnorm(&nf_gains[i], &q_nf_gain_idx[i], 32, 1, &thren_HQ[0]); + nf_gains[i] = 0.5f*dicn[q_nf_gain_idx[i]]; + push_indice( st, IND_HVQ_NF_GAIN , q_nf_gain_idx[i], 5); + bits += 5; + } + + /* Signal number of peaks */ + i = max_peaks - vq_peaks; + push_indice( st, IND_NUM_PEAKS, i, 5); + bits += 5; + + /* Identify position of first peak and arrange peak gains by position */ + low_peak_bin = bin_th; + for (i = 0; i < vq_peaks; i++) + { + if (vq_peak_idx[i] < low_peak_bin) + { + low_peak_bin = vq_peak_idx[i]; + } + pos_vec[vq_peak_idx[i]] = (short) sign((float) coefs[vq_peak_idx[i]]); + } + + for (i = 0, j = 0; i < bin_th; i++) + { + if(pos_vec[i] != 0) + { + peak_gains[j] = (float) fabs(coefs[i]); + vq_peak_idx[j] = i; + j++; + } + } + + /* Scale down peak gains */ + for (i = 0; i < vq_peaks; i++) + { + peak_gains[i] *= 0.25f; + } + + /* Quantize peak gains */ + logqnorm(&peak_gains[0],&pgain_cb_idx[0],32,1,&thren_pg[0]); + for (i = 1; i < vq_peaks; i++) + { + logqnorm(&peak_gains[i],&pgain_cb_idx[i],45,1,&thren_pg[0]); + } + + /* Code quantized peak gain indices */ + diffcod(vq_peaks, pgain_cb_idx, &pgain_difidx[1]); + for(i = 0; i < vq_peaks; i++) + { + pgain_q[i] = dicn_pg[pgain_cb_idx[i]]; + } + pgain_difidx[0] = pgain_cb_idx[0]; + + /* Scale up peak gains and accumulate peak energy */ + manE_peak = 0; + expE_peak = 32; + for (i = 0; i < vq_peaks; i++) + { + pgain_q[i] *= 4.0f; + manPkEnrg = manPkEnrg_tbl[pgain_cb_idx[i]]; + expPkEnrg = expPkEnrg_tbl[pgain_cb_idx[i]]; + floating_point_add(&manE_peak, &expE_peak, manPkEnrg, expPkEnrg); + } + + /* Huffman coding */ + hcode_l = 0; + for (i = 1; i < vq_peaks; i++) + { + hcode_l += pgain_huffsizn[pgain_difidx[i]]; + } + + FlagN = HUFCODE; + + if (hcode_l >= GAINI_BITS * (vq_peaks - 1)) + { + hcode_l = GAINI_BITS * (vq_peaks - 1); + FlagN = NOHUFCODE; + } + + push_indice( st, IND_FLAGN, FlagN, 1); + push_indice( st, IND_PG_IDX, pgain_difidx[0], GAIN0_BITS); + + if (FlagN) + { + for (i = 1; i < vq_peaks; i++) + { + j = pgain_difidx[i]; + m = pgain_huffnorm[j]; + r = pgain_huffsizn[j]; + + push_indice( st, IND_PG_IDX, m, r ); + } + } + else + { + for (i = 1; i < vq_peaks; i++) + { + push_indice( st, IND_PG_IDX, pgain_difidx[i], GAINI_BITS ); + } + } + + /* Number of bits used for peak gain quantization */ + bits += FLAGN_BITS + GAIN0_BITS + hcode_l; + + /* Add sign for peak shape normalization */ + for (i = 0; i < vq_peaks; i++) + { + peak_gains[i] = pos_vec[vq_peak_idx[i]] * pgain_q[i]; + } + + /* Quantize peak shapes */ + for (i = 0; i < vq_peaks-1; i++) + { + num_overlap_bins = 5-(vq_peak_idx[i+1]-vq_peak_idx[i]); + quant_peaks( st, &coefs[vq_peak_idx[i]-2], &coefs_out[vq_peak_idx[i]-2], &peak_gains[i], &vq_cb_idx, num_overlap_bins, brate, vq_peaks ); + push_indice( st, IND_HVQ_PEAKS, vq_cb_idx, 8 ); + bits += 9; + } + + quant_peaks( st, &coefs[vq_peak_idx[i]-2], &coefs_out[vq_peak_idx[i]-2], &peak_gains[i], &vq_cb_idx, 0, brate, vq_peaks ); + push_indice( st, IND_HVQ_PEAKS, vq_cb_idx, 8 ); + bits += 9; + + pos_bits = hvq_code_pos( st, pos_vec, bin_th, vq_peaks ); + + bits += pos_bits; + bit_budget = num_bits - bits; + + /* Calculate number of PVQ bands to code and assign bits */ + pvq_bands = hvq_pvq_bitalloc(bit_budget, brate, st->bwidth, ynrm, manE_peak, expE_peak, Rk, R, sel_bnds, &n_sel_bnds ); + + /* Get band limits for concatenated PVQ target */ + hvq_concat_bands( pvq_bands, sel_bnds, n_sel_bnds, hvq_band_start, hvq_band_width, hvq_band_end ); + + /* Quantize PVQ bands */ + i = 0; + n = 0; + s = 0; + for (k = 0; k < pvq_bands; k++) + { + if( k >= pvq_bands - n_sel_bnds) + { + i = band_start_harm[sel_bnds[s]]; + s++; + } + k_sort[k] = (int) k; + j = 0; + pPvqVectorBandStart = &pvq_vector[n]; + while ( j < hvq_band_width[k] ) + { + if (coefs_out[i] == 0) + { + pvq_vector[n] = coefs[i]; + j++; + n++; + } + i++; + } + logqnorm( pPvqVectorBandStart, &pvq_norm[k], 40, hvq_band_width[k], &thren_HQ[0] ); + } + + normalizecoefs( pvq_vector, pvq_norm, pvq_bands, hvq_band_start, hvq_band_end ); + + bit_budget -= HVQ_PVQ_GAIN_BITS*pvq_bands; + for (k = 0; k < pvq_bands; k++) + { + Rk_f[k] = Rk[k] * 8; + } + + pvq_bits = bit_budget; + set_s( npulses, 0, MAX_PVQ_BANDS ); + + pvq_encode_frame( st, pvq_vector, coefs_pvq, gopt, npulses, pvq_inp_vector, hvq_band_start, + hvq_band_end, hvq_band_width, pvq_bands, Rk_f, pvq_bits, HQ_CORE ); + + for(i=0; i= pvq_bands - n_sel_bnds) + { + i = band_start_harm[sel_bnds[s++]]; + } + while (j < hvq_band_width[k]) + { + normq = dicn[pvq_norm[k]]; + if (coefs_out[i] == 0) + { + coefs_out[i] = coefs_pvq[n]*fg_pred[k]; + coefs_out[i] = coefs_out[i]*normq; + j++; + n++; + } + i++; + } + + } + + bits += pvq_bits; + + /* Noise fill unquantized coeffs with one gain per group */ + for (i = 0; i < HVQ_NF_GROUPS; i++) + { + for (j = i*(bin_th/HVQ_NF_GROUPS); j < (i+1)*(bin_th/HVQ_NF_GROUPS); j++) + { + if (coefs_out[j] == 0) + { + coefs_out[j] = ((float)own_random(&nf_seed)/MAX16B)*nf_gains[i]; + } + } + } + + return bits; +} + +/*-------------------------------------------------------------------------- + * quant_peaks() + * + * Applies VQ on input vector + *--------------------------------------------------------------------------*/ + +void quant_peaks( + Encoder_State *st, /* i/o: encoder state structure */ + const float *vect_in, /* i : Target vector */ + float *vect_out, /* i/o: Quantized vector */ + const float *peak_gain, /* i : Peak gain vector */ + short *vq_idx, /* o : Codebook index */ + const short overlap, /* i : Overlap indicator */ + const short brate, /* i : Core bitrate */ + const short Npeaks /* i : Number of peaks */ +) +{ + float x[4]; + float xq[4]; + short weights[4]; + short i, cb_class, search_overlap; + + set_s(weights,1,4); + + x[0] = vect_in[0] / (*peak_gain); + x[1] = vect_in[1] / (*peak_gain); + x[2] = vect_in[3] / (*peak_gain); + x[3] = vect_in[4] / (*peak_gain); + + if(vect_out[0] != 0 ) + { + if( fabs(peak_gain[-1]) > fabs(*peak_gain)) + { + weights[0] = 0; + + if (vect_out[1] != 0) + { + weights[1] = 0; + } + } + } + if(overlap > 0) + { + if( fabs(peak_gain[1]) > fabs(*peak_gain) ) + { + for(i = 3; i> 3-overlap; i--) + { + weights[i] = 0; + } + } + } + + + /* Classify */ + cb_class = (short) w_vquant(x, 0, weights, 0, hvq_class_c, HVQ_VQ_DIM-1, HVQ_NUM_CLASS, 0); + search_overlap = (brate == HQ_24k40) ? hvq_cb_search_overlap24k[HVQ_MAX_PEAKS_24k-Npeaks] : hvq_cb_search_overlap32k[HVQ_MAX_PEAKS_32k-Npeaks]; + + /* Quantize */ + if( cb_class == 0 ) + { + *vq_idx = (short) w_vquant(x, 0, weights, xq, hvq_peak_cb, 4, HVQ_CB_SIZE/2+search_overlap, 0); + push_indice( st, IND_HVQ_PEAKS, 0, 1 ); + } + else if( cb_class == 1 ) + { + *vq_idx = (short) w_vquant(x, 0, weights, xq, &hvq_peak_cb[HVQ_CB_SIZE*2-search_overlap*4], 4, HVQ_CB_SIZE/2+search_overlap, 0); + *vq_idx += HVQ_CB_SIZE/2-search_overlap; + push_indice( st, IND_HVQ_PEAKS, 0, 1 ); + } + else if( cb_class == 2 ) + { + *vq_idx = (short) w_vquant(x, 0, weights, xq, &hvq_peak_cb[HVQ_CB_SIZE*2-search_overlap*4], 4, HVQ_CB_SIZE/2+search_overlap, 1); + *vq_idx += HVQ_CB_SIZE/2-search_overlap; + push_indice( st, IND_HVQ_PEAKS, 1, 1 ); + } + else + { + *vq_idx = (short) w_vquant(x, 0, weights, xq, hvq_peak_cb, 4, HVQ_CB_SIZE/2+search_overlap, 1); + push_indice( st, IND_HVQ_PEAKS, 1, 1 ); + } + + vect_out[0] = weights[0] * (xq[0] * (*peak_gain)) + (weights[0]^1)*vect_out[0]; + vect_out[1] = weights[1] * (xq[1] * (*peak_gain)) + (weights[1]^1)*vect_out[1]; + vect_out[2] = *peak_gain; + vect_out[3] = weights[2] * (xq[2] * (*peak_gain)) + (weights[2]^1)*vect_out[3]; + vect_out[4] = weights[3] * (xq[3] * (*peak_gain)) + (weights[3]^1)*vect_out[4]; + + return; +} + +/*-------------------------------------------------------------------------- + * code_pos() + * + * Code pulse positions + *--------------------------------------------------------------------------*/ + +static short sparse_code_pos( + const short *inp, + const short length, + short *result +) +{ + short layer2[HVQ_CP_L2_MAX]; + short layer_length; + short i,j; + short val, idx; + short bits = 0; + short mask; + + set_s(layer2, 0, HVQ_CP_L2_MAX); + + layer_length = (short)((float)length/HVQ_CP_L1_LEN + 0.5); + + for (j = 0; j < layer_length; j++) + { + for (i = j*HVQ_CP_L1_LEN; i < min((j+1)*HVQ_CP_L1_LEN, length); i++) + { + if (inp[i]) + { + layer2[j] = 1; + break; + } + } + } + + for (i = 0; i < layer_length; i++) + { + result[i] = layer2[i]; + } + bits += layer_length; + + for (j = 0; j < layer_length; j++) + { + if (layer2[j]) + { + val = 0; + for (i = j*HVQ_CP_L1_LEN; i < min((j+1)*HVQ_CP_L1_LEN, length); i++) + { + val <<= 1; + val |= inp[i]; + } + + for (idx = 0; idx < HVQ_CP_MAP_LEN; idx++) + { + if (hvq_cp_layer1_map5[idx] == val) + { + break; + } + } + + mask = 1<<(HVQ_CP_MAP_IDX_LEN - 1); + for (i = 0; i < HVQ_CP_MAP_IDX_LEN; i++) + { + result[bits++] = (idx&mask) >> (HVQ_CP_MAP_IDX_LEN - 1 - i); + mask >>= 1; + } + } + } + + return bits; +} + +/*-------------------------------------------------------------------------- + * hvq_code_pos() + * + * Code pulse positions + *--------------------------------------------------------------------------*/ + +static short hvq_code_pos( + Encoder_State *st, /* i/o: encoder state structure */ + const short *inp, + const short length, + const short num_peaks +) +{ + short sparse_result[4*HVQ_THRES_BIN_32k/HVQ_CP_L1_LEN]; + short delta[HVQ_MAX_PEAKS_32k]; + short peak_idx[HVQ_MAX_PEAKS_32k]; + short inp_abs[HVQ_THRES_BIN_32k]; + short inp_sign[HVQ_MAX_PEAKS_32k]; + + short i, j; + short bits; + short delta_max; + short delta_bits, sparse_bits; + + bits = 0; + + /* Extract sorted peak index vector and sign vector */ + for (i = 0, j = 0; i < length; i++) + { + inp_abs[i] = (short)abs(inp[i]); + if (inp[i]) + { + peak_idx[j] = i; + inp_sign[j++] = inp[i]; + } + } + + /* Calculate delta */ + delta[0] = peak_idx[0] + HVQ_CP_HUFF_OFFSET; + delta_max = delta[0]; + for (i = 1; i < num_peaks; i++) + { + delta[i] = peak_idx[i] - peak_idx[i-1] - HVQ_CP_HUFF_OFFSET; + if (delta_max < delta[i]) + { + delta_max = delta[i]; + } + } + + /* Calculate bits needed for huffman coding of deltas */ + delta_bits = -1; + if (delta_max <= HVQ_CP_HUFF_MAX) + { + delta_bits = 0; + for (i = 0; i < num_peaks; i++) + { + delta_bits += hvq_cp_huff_len[delta[i]]; + } + } + + /* Calculate bits neeed for sparse coding */ + sparse_bits = sparse_code_pos(inp_abs, length, sparse_result); + + /* Decide which coding mode to use */ + if (delta_bits > sparse_bits || delta_bits < 0) + { + push_indice(st, IND_POS_IDX, HVQ_CP_SPARSE, 1); + + for (i = 0; i < sparse_bits; i++) + { + push_indice(st, IND_POS_IDX, sparse_result[i], 1); + } + bits += sparse_bits + 1; + } + else + { + push_indice(st, IND_POS_IDX, HVQ_CP_DELTA, 1); + + for (i = 0; i < num_peaks; i++) + { + j = delta[i]; + push_indice(st, IND_POS_IDX, hvq_cp_huff_val[j], hvq_cp_huff_len[j]); + } + bits += delta_bits + 1; + } + + /* Send sign */ + for (i = 0; i < num_peaks; i++) + { + push_indice(st, IND_POS_IDX, (inp_sign[i] < 0 ? 0 : 1), 1); + } + bits += num_peaks; + + return bits; +} diff --git a/lib_enc/pit_enc.c b/lib_enc/pit_enc.c new file mode 100644 index 000000000..8dd493ff3 --- /dev/null +++ b/lib_enc/pit_enc.c @@ -0,0 +1,1320 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "cnst.h" +#include "prot.h" +#include "rom_enc.h" +#include "rom_com.h" + + +/*------------------------------------------------------------------* + * pit_encode() + * + * Close-loop pitch lag search and pitch lag quantization + * Adaptive excitation construction + *------------------------------------------------------------------*/ + +float pit_encode( /* o : Fractional pitch for each subframe */ + Encoder_State *st, /* i/o: encoder state structure */ + const long core_brate, /* i : core bitrate */ + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short L_frame, /* i : length of the frame */ + const short coder_type, /* i : coding type */ + short *limit_flag, /* i/o: restrained(0) or extended(1) Q limits */ + const short i_subfr, /* i : subframe index */ + float *exc, /* i/o: pointer to excitation signal frame */ + const short L_subfr, /* i : subframe length */ + const short *T_op, /* i : open loop pitch estimates in current frame */ + short *T0_min, /* i/o: lower limit for close-loop search */ + short *T0_max, /* i/o: higher limit for close-loop search */ + short *T0, /* i/o: close loop integer pitch */ + short *T0_frac, /* i/o: close loop fractional part of the pitch */ + const float *h1, /* i : weighted filter input response */ + const float *xn /* i : target vector */ +) +{ + float pitch; + short pit_flag, delta, mult_Top, nBits; + + /*----------------------------------------------------------------* + * Initializations + *----------------------------------------------------------------*/ + + /* Set pit_flag to 0 for every subframe with absolute pitch search */ + pit_flag = i_subfr; + if( i_subfr == 2*L_SUBFR ) + { + pit_flag = 0; + } + + /*-----------------------------------------------------------------* + * Limit range of pitch search + * Fractional pitch search + * Pitch quantization + *-----------------------------------------------------------------*/ + + mult_Top = 1; + + if( !Opt_AMR_WB ) + { + /*----------------------------------------------------------------* + * Set limit_flag to 0 for restrained limits, and 1 for extended limits + *----------------------------------------------------------------*/ + + if( i_subfr == 0 ) + { + *limit_flag = 1; + if( coder_type == VOICED ) + { + *limit_flag = 2; /* double-extended limits */ + } + + if( coder_type == GENERIC && core_brate == ACELP_7k20 ) + { + *limit_flag = 0; + } + } + else if( i_subfr == 2*L_SUBFR && coder_type == GENERIC && core_brate <= ACELP_13k20 ) + { + if( *T0 > (PIT_FR1_EXTEND_8b + PIT_MIN)>>1 ) + { + *limit_flag = 0; + } + } + + /* check the minimum pitch value */ + if( *limit_flag == 0 ) + { + if( ( i_subfr == 0 && T_op[0] < PIT_MIN ) || + ( i_subfr == 2*L_SUBFR && T_op[1] < PIT_MIN ) ) + { + mult_Top = 2; + } + } + + /*-------------------------------------------------------* + * Retrieve the number of Q bits + *-------------------------------------------------------*/ + + nBits = 0; + if( coder_type != AUDIO ) + { + /* find the number of bits */ + if( L_frame == L_FRAME ) + { + nBits = ACB_bits_tbl[BIT_ALLOC_IDX(core_brate, coder_type, i_subfr, 0)]; + } + else /* L_frame == L_FRAME16k */ + { + nBits = ACB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ(core_brate, coder_type, i_subfr, 0)]; + } + } + + if( coder_type == AUDIO ) + { + /*-------------------------------------------------------* + * Pitch encoding in AUDIO mode + * (both ACELP@12k8 and ACELP@16k cores) + *-------------------------------------------------------*/ + + delta = 4; + + if( L_subfr == L_frame/2 && i_subfr != 0 ) + { + pit_flag = L_SUBFR; + } + + if( pit_flag == 0 ) + { + nBits = 10; + } + else + { + nBits = 6; + } + + /* pitch lag search limitation */ + if( i_subfr == 0 ) + { + limit_T0( L_FRAME, delta, pit_flag, *limit_flag, mult_Top*T_op[0], 0, T0_min, T0_max ); + } + else if( i_subfr == 2*L_SUBFR && pit_flag == 0 ) + { + limit_T0( 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( &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( st, 0, nBits, delta, pit_flag, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + else if( coder_type == VOICED ) + { + /*-------------------------------------------------------* + * Pitch encoding in VOICED mode (ACELP@12k8 core only) + *-------------------------------------------------------*/ + + delta = 4; + + if( i_subfr == 2*L_SUBFR ) + { + pit_flag = i_subfr; + } + + /* pitch lag search limitation */ + if( i_subfr == 0 ) + { + limit_T0( 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 */ + if( nBits == 9 || nBits == 5 ) + { + *T0 = pitch_fr4( &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 ); + } + else if( nBits == 10 ) + { + *T0 = pitch_fr4( &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( st, 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; + + /* pitch lag search limitation */ + if( i_subfr == 0 ) + { + limit_T0( L_frame, delta, pit_flag, *limit_flag, mult_Top*T_op[0], 0, T0_min, T0_max ); + } + else if( i_subfr == 2*L_SUBFR ) + { + limit_T0( 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( L_frame == L_FRAME ) + { + if( nBits == 8 || nBits == 5 ) + { + if( *limit_flag == 0 ) + { + *T0 = pitch_fr4( &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( &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( nBits == 9 || nBits == 6 ) + { + if( *limit_flag == 0 ) + { + *T0 = pitch_fr4( &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( &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( nBits == 10 ) + { + *T0 = pitch_fr4( &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( st, 0, nBits, delta, pit_flag, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + else /* L_frame == L_FRAME16k */ + { + if( nBits == 9 || nBits == 6 ) + { + *T0 = pitch_fr4( &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( &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( st, nBits, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + } + } + + /*-------------------------------------------------------* + * Pitch encoding in AMR-WB IO mode + *-------------------------------------------------------*/ + + else + { + delta = 8; + *limit_flag = 0; + + if( core_brate == ACELP_6k60 ) + { + nBits = 5; + + /* pitch lag search limitation */ + if( i_subfr == 0 ) + { + limit_T0( L_FRAME, delta, pit_flag, *limit_flag, mult_Top*T_op[0], 0, T0_min, T0_max ); + nBits = 8; + } + + if( i_subfr == 2*L_SUBFR ) + { + /* rewrite pit_flag - it must not be zero */ + pit_flag = i_subfr; + } + + /* search and encode the closed loop pitch period */ + *T0 = pitch_fr4( &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( core_brate == ACELP_8k85 ) + { + nBits = 5; + + /* pitch lag search limitation */ + if( i_subfr == 0 ) + { + limit_T0( L_FRAME, delta, pit_flag, *limit_flag, mult_Top*T_op[0], 0, T0_min, T0_max ); + nBits = 8; + } + else if( i_subfr == 2*L_SUBFR ) + { + limit_T0( L_FRAME, delta, pit_flag, *limit_flag, mult_Top*T_op[1], 0, T0_min, T0_max ); + nBits = 8; + } + + /* search and encode the closed loop pitch period */ + *T0 = pitch_fr4( &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; + + /* pitch lag search limitation */ + if( i_subfr == 0 ) + { + limit_T0( L_FRAME, delta, pit_flag, *limit_flag, mult_Top*T_op[0], 0, T0_min, T0_max ); + nBits = 9; + } + else if( i_subfr == 2*L_SUBFR ) + { + limit_T0( L_FRAME, delta, pit_flag, *limit_flag, mult_Top*T_op[1], 0, T0_min, T0_max ); + nBits = 9; + } + else + { + limit_T0( 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( &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( st, 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 */ + + return pitch; +} + +/*-------------------------------------------------------------------* + * pitch_fr4() + * + * Find the closed loop pitch period with 1/4 subsample resolution. + *-------------------------------------------------------------------*/ + +short pitch_fr4( /* o : chosen integer pitch lag */ + const float exc[], /* i : excitation buffer */ + const float xn[], /* i : target signal */ + const float h[], /* i : weighted synthesis filter impulse response */ + const short t0_min, /* i : minimum value in the searched range. */ + const short t0_max, /* i : maximum value in the searched range. */ + short *pit_frac, /* o : chosen fraction (0, 1, 2 or 3) */ + const short i_subfr, /* i : flag to first subframe */ + const short limit_flag, /* i : flag for limits (0=restrained, 1=extended) */ + const short t0_fr2, /* i : minimum value for resolution 1/2 */ + const short t0_fr1, /* i : minimum value for resolution 1 */ + const short L_frame, /* i : length of the frame */ + const short L_subfr /* i : size of subframe */ +) +{ + short i, fraction, step; + short t0, t1, t_min, t_max, pit_min; + float cor_max, max, temp; + float *corr, corr_v[15+2*L_INTERPOL1+1]; + + /* initialization */ + if( limit_flag == 0 ) + { + if( L_frame == L_FRAME ) + { + pit_min = PIT_MIN; + } + else /* L_frame == L_FRAME16k */ + { + pit_min = PIT16k_MIN; + } + } + else + { + if( L_frame == L_FRAME ) + { + pit_min = PIT_MIN_EXTEND; + if( limit_flag == 2 ) + { + pit_min = PIT_MIN_DOUBLEEXTEND; + } + } + else /* L_frame == L_FRAME16k */ + { + pit_min = PIT16k_MIN_EXTEND; + } + } + + + /*-----------------------------------------------------------------* + * - Find interval to compute normalized correlation + * - allocate memory to normalized correlation vector + * - Compute normalized correlation between target and filtered + * excitation + *-----------------------------------------------------------------*/ + + t_min = t0_min - L_INTERPOL1; + t_max = t0_max + L_INTERPOL1; + corr = &corr_v[-t_min]; /* corr[t_min..t_max] */ + + norm_corr( exc, xn, h, t_min, t_max, corr, L_subfr ); + + /*-----------------------------------------------------------------* + * Find integer pitch + *-----------------------------------------------------------------*/ + + max = corr[t0_min]; + t0 = t0_min; + + for( i=t0_min+1; i<=t0_max; i++ ) + { + if( corr[i] >= max) + { + max = corr[i]; + t0 = i; + } + } + + if( t0_fr1 == pit_min ) + { + /* don't search fraction (for 7b/4b quant) */ + if((i_subfr == 0) && (t0 >= t0_fr2)) + { + i = (t0>>1)*2; /* 2 samples resolution */ + if( (i+2) > PIT_MAX ) + { + i -= 2; + } + if( corr[i] > corr[i+2] ) + { + t0 = i; + } + else + { + t0 = i+2; + } + } + + *pit_frac = 0; + + return(t0); + } + if( (i_subfr == 0) && (t0 >= t0_fr1) ) + { + *pit_frac = 0; + + 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; + step = 1; /* 1/4 subsample resolution */ + fraction = 1; + if( ((i_subfr == 0) && (t0 >= t0_fr2)) || (t0_fr2 == pit_min) ) + { + step = 2; /* 1/2 subsample resolution */ + fraction = 2; + } + + if( t0 == t0_min ) /* Limit case */ + { + fraction = 0; + cor_max = interpolation( &corr[t0], E_ROM_inter4_1, fraction, PIT_UP_SAMP, 4 ); + } + else /* Process negative fractions */ + { + t0--; + cor_max = interpolation( &corr[t0], E_ROM_inter4_1, fraction, PIT_UP_SAMP, 4 ); + for( i=(fraction+step); i<=3; i=i+step ) + { + temp = interpolation( &corr[t0], E_ROM_inter4_1, i, PIT_UP_SAMP, 4 ); + if (temp > cor_max) + { + cor_max = temp; + fraction = i; + } + } + } + + for( i=0; i<=3; i=i+step ) /* Process positive fractions */ + { + temp = interpolation( &corr[t1], E_ROM_inter4_1, i, PIT_UP_SAMP, 4 ); + if( temp > cor_max ) + { + cor_max = temp; + fraction = i; + t0 = t1; + } + } + + *pit_frac = fraction; + + 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( + const float exc[], /* i : excitation buffer */ + const float xn[], /* i : target signal */ + const float h[], /* i : weighted synthesis filter impulse response */ + const short t_min, /* i : minimum value of searched range */ + const short t_max, /* i : maximum value of searched range */ + float corr_norm[], /* o : normalized correlation */ + const short L_subfr /* i : subframe size */ +) +{ + short t, j, k; + float excf[L_FRAME]; /* filtered past excitation */ /* length up to L_FRAME in GSC */ + float alp, ps, norm; + + k = - t_min; + + /*-----------------------------------------------------------------* + * compute the filtered excitation for the first delay t_min + *-----------------------------------------------------------------*/ + + conv( &exc[k], h, excf, L_subfr ); + + /*-----------------------------------------------------------------* + * loop for every possible period + *-----------------------------------------------------------------*/ + + for (t = t_min; t <= t_max; t++) + { + /* Compute correlation between xn[] and excf[] */ + + ps = 0.0f; + for (j = 0; j < L_subfr; ++j) + { + ps += xn[j]*excf[j]; + } + + /* Compute 1/sqrt(energie of excf[]) */ + + alp = 0.01f; + for (j = 0; j < L_subfr; ++j) + { + alp += excf[j]*excf[j]; + } + norm = inv_sqrt(alp); + + /* Normalize correlation = correlation * (1/sqrt(energie)) */ + corr_norm[t] = ps*norm; + + /* update the filtered excitation excf[] for the next iteration */ + if (t != t_max) + { + k--; + for (j = L_subfr-1; j > 0; j--) + { + excf[j] = excf[j-1] + exc[k]*h[j]; + } + excf[0] = exc[k]; + } + } + return; +} + +/*-------------------------------------------------------------------* + * 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 9 bits + *-------------------------------------------------------------------*/ + +short abs_pit_enc( /* o : pitch index */ + const short fr_steps, /* i : fractional resolution step */ + const short limit_flag, /* i : restrained(0) or extended(1) limits */ + const short T0, /* i : integer pitch lag */ + const short T0_frac /* i : pitch fraction */ +) +{ + short pitch_index; + + if( limit_flag == 0 ) + { + if( 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( T0 < PIT_FR1_8b ) + { + pitch_index = T0*2 + (T0_frac>>1) - (PIT_MIN*2); + } + else + { + pitch_index = T0 - PIT_FR1_8b + ((PIT_FR1_8b-PIT_MIN)*2); + } + + } + else if( 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( T0 < PIT_FR2_9b ) + { + pitch_index = T0*4 + T0_frac - (PIT_MIN*4); + } + else if( T0 < PIT_FR1_9b ) + { + pitch_index = T0*2 + (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); + } + + } + else /* fr_step == 0 */ + { + /* not used in the codec */ + pitch_index = 0; + } + } + else if( limit_flag == 1 ) /* extended Q range */ + { + if( 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 resolution 1 (frac = 0) + *-----------------------------------------------------------------*/ + + if( T0 < PIT_FR1_EXTEND_8b ) + { + pitch_index = T0*2 + (T0_frac>>1) - (PIT_MIN_EXTEND*2); + } + else + { + pitch_index = T0 - PIT_FR1_EXTEND_8b + ((PIT_FR1_EXTEND_8b-PIT_MIN_EXTEND)*2); + } + + } + else if( 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 resolution 1 (frac = 0) + *-------------------------------------------------------------------*/ + + if( T0 < PIT_FR2_EXTEND_9b ) + { + pitch_index = T0*4 + 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); + } + 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); + } + + } + else /* fr_step == 0 */ + { + /* not used in the codec */ + pitch_index = 0; + } + } + else /* double-extended Q range */ + { + if( 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 resolution 1 (frac = 0) + *-----------------------------------------------------------------*/ + + if( T0 < PIT_FR1_DOUBLEEXTEND_8b ) + { + pitch_index = T0*2 + (T0_frac>>1) - (PIT_MIN_DOUBLEEXTEND*2); + } + else + { + pitch_index = T0 - PIT_FR1_DOUBLEEXTEND_8b + ((PIT_FR1_DOUBLEEXTEND_8b-PIT_MIN_DOUBLEEXTEND)*2); + } + } + else if( 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 resolution 1 (frac = 0) + *-------------------------------------------------------------------*/ + + if( T0 < PIT_FR2_DOUBLEEXTEND_9b ) + { + pitch_index = T0*4 + T0_frac - (PIT_MIN_DOUBLEEXTEND*4); + } + else if( 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); + } + 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); + } + } + else /* fr_step == 0 */ + { + /* not used in the codec */ + pitch_index = 0; + } + } + + 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: resolution 1 (frac = 0), or + * fr_step = 2: resolution 1/2 (frac = 0 or 2), or + * fr_step = 4: resolution 1/4 (frac = 0, 1, 2, or 3) + *-------------------------------------------------------------------*/ + +short delta_pit_enc( /* o : pitch index */ + const short fr_steps, /* i : fractional resolution step */ + const short T0, /* i : integer pitch lag */ + const short T0_frac, /* i : pitch fraction */ + const short T0_min /* i : delta search min */ +) +{ + short pitch_index; + + if( fr_steps == 0 ) + { + pitch_index = T0 - T0_min; + } + else if( fr_steps == 2 ) + { + pitch_index = (T0 - T0_min) * 2 + (T0_frac>>1); + } + else /* fr_steps == 4 */ + { + pitch_index = (T0 - T0_min) * 4 + T0_frac; + } + + return pitch_index; +} + +/*-------------------------------------------------------------------* + * pit_Q_enc() + * + * Encode subframe pitch lag + *-------------------------------------------------------------------*/ + +void pit_Q_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const short nBits, /* i : # of Q bits */ + const short delta, /* i : Half the CL searched interval */ + const short pit_flag, /* i : absolute(0) or delta(1) pitch Q */ + const short limit_flag, /* i : restrained(0) or extended(1) Q limits */ + const short T0, /* i : integer pitch lag */ + const short T0_frac, /* i : pitch fraction */ + short *T0_min, /* i/o: delta search min */ + short *T0_max /* o : delta search max */ +) +{ + short pitch_index; + + if( nBits == 10 ) /* absolute encoding with 10 bits */ + { + if( limit_flag == 0 ) + { + pitch_index = T0*4 + T0_frac - (PIT_MIN*4); + } + else if( limit_flag == 1 ) + { + pitch_index = T0*4 + T0_frac - (PIT_MIN_EXTEND*4); + } + else /* limit_flag == 2 */ + { + pitch_index = T0*4 + T0_frac - (PIT_MIN_DOUBLEEXTEND*4); + } + } + else if( nBits == 9 ) /* absolute encoding with 9 bits */ + { + pitch_index = abs_pit_enc( 4, limit_flag, T0, T0_frac ); + + /* find T0_min and T0_max for delta search */ + if( Opt_AMR_WB ) + { + limit_T0( L_FRAME, delta, pit_flag, 0, T0, 0, T0_min, T0_max ); /* T0_frac==0 to keep IO with AMR-WB */ + } + } + else if( nBits == 8 ) /* absolute encoding with 8 bits */ + { + pitch_index = abs_pit_enc( 2, limit_flag, T0, T0_frac ); + + /* find T0_min and T0_max for delta search */ + if( Opt_AMR_WB ) + { + limit_T0( L_FRAME, delta, pit_flag, 0, T0, 0, T0_min, T0_max ); /* T0_frac==0 to keep IO with AMR-WB */ + } + } + else if( nBits == 6 ) /* relative encoding with 6 bits */ + { + pitch_index = delta_pit_enc( 4, T0, T0_frac, *T0_min ); + } + else if( nBits == 5 ) /* relative encoding with 5 bits */ + { + if( delta == 8 ) + { + pitch_index = delta_pit_enc( 2, T0, T0_frac, *T0_min ); + } + else /* delta == 4 */ + { + pitch_index = delta_pit_enc( 4, T0, T0_frac, *T0_min ); + } + } + else /* nBits == 4 ) */ /* relative encoding with 4 bits */ + { + if( delta == 8 ) + { + pitch_index = delta_pit_enc( 0, T0, T0_frac, *T0_min ); + } + else /* delta == 4 */ + { + pitch_index = delta_pit_enc( 2, T0, T0_frac, *T0_min ); + } + } + + if( !Opt_AMR_WB ) + { + /* find T0_min and T0_max for delta search */ + limit_T0( L_FRAME, delta, L_SUBFR, limit_flag, T0, T0_frac, T0_min, T0_max ); + } + + push_indice( st, IND_PITCH, pitch_index, nBits ); + + return; +} + +/*-------------------------------------------------------------------* + * pit16k_Q_enc() + * + * Encode subframe pitch lag @16kHz core + *-------------------------------------------------------------------*/ + +void pit16k_Q_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const short nBits, /* i : # of Q bits */ + const short limit_flag, /* i : restrained(0) or extended(1) Q limits */ + const short T0, /* i : integer pitch lag */ + const short T0_frac, /* i : pitch fraction */ + short *T0_min, /* i/o: delta search min */ + short *T0_max /* o : delta search max */ +) +{ + short pitch_index; + + if( nBits == 10 ) /* absolute encoding with 10 bits */ + { + { + if( T0 < PIT16k_FR2_EXTEND_10b ) + { + pitch_index = T0*4 + 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); + } + } + + push_indice( st, IND_PITCH, pitch_index, nBits ); + } + else if( 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 resolution 1 (frac = 0) + *-------------------------------------------------------------------*/ + + if( T0 < PIT16k_FR2_EXTEND_9b ) + { + pitch_index = T0*4 + T0_frac - (PIT16k_MIN_EXTEND*4); + } + else if( 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); + } + 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); + } + } + + push_indice( st, IND_PITCH, pitch_index, 9 ); + } + else /* nBits == 6 */ /* relative encoding with 6 bits */ + { + pitch_index = (T0 - *T0_min) * 4 + T0_frac; + + push_indice( st, IND_PITCH, pitch_index, nBits ); + } + + limit_T0( L_FRAME16k, 8, L_SUBFR, limit_flag, T0, T0_frac, T0_min, T0_max ); + + return; +} + + +/*------------------------------------------------------------------* + * limit_T0_voiced2: + * + * + *------------------------------------------------------------------*/ + +static void limit_T0_voiced2( + int res, + const short *T_op, + int *T0_min, + int *T0_min_frac, + int *T0_max, + int *T0_max_frac, + short pit_min, + short pit_max, + int i_subfr +) +{ + int t, temp1, temp2; + + /* Lower-bound */ + if (i_subfr == 0) + { + temp1 = (T_op[0]*res) - 32; + } + else + { + temp1 = (T_op[1]*res) - 32; + } + + if (T_op[0]t) + { + temp1 = t; + } + + temp2 = temp1 / res; + *T0_max = temp2; + *T0_max_frac = temp1 - temp2*res; + + if ( *T0_max > pit_max) + { + *T0_max = pit_max; + *T0_max_frac = res - 1; + temp1 = (*T0_max*res) - 64 + res; + temp2 = temp1 / res; + *T0_min = temp2; + *T0_min_frac = temp1 - temp2*res; + } + + return; +} + + +/*------------------------------------------------------------------* + * Mode2_pit_encode: + * + * Close-loop pitch lag search and pitch lag quantization + * Adaptive excitation construction + *------------------------------------------------------------------*/ + +void Mode2_pit_encode( + short coder_type, /* i : coding model */ + short i_subfr, /* i : subframe index */ + int **pt_indice, /* i/o: quantization indices pointer */ + float *exc, /* i/o: pointer to excitation signal frame */ + const short *T_op, /* i : open loop pitch estimates in current frame */ + int *T0_min, /* i/o: lower limit for close-loop search */ + int *T0_min_frac, /* i/o: lower limit for close-loop search */ + int *T0_max, /* i/o: higher limit for close-loop search */ + int *T0_max_frac, /* i/o: higher limit for close-loop search */ + int *T0, /* i/o: close loop integer pitch */ + int *T0_frac, /* i/o: close loop fractional part of the pitch */ + int *T0_res, /* i/o: close loop pitch resolution */ + float *h1, /* i : weighted filter impulse response */ + float *xn, /* i : target vector */ + int pit_min, + int pit_fr1, + int pit_fr1b, + int pit_fr2, + int pit_max, + int pit_res_max) +{ + int pit_flag; + + /* Pitch flag */ + pit_flag = i_subfr; + + if (i_subfr == (2*L_SUBFR)) + { + pit_flag = 0; + } + + /*-----------------------------------------------------------------* + * - Limit range of pitch search + * - Fractional pitch search + * - Pitch quantization + *-----------------------------------------------------------------*/ + + if(coder_type == 0) /*Unvoiced Coding do nothing*/ + { + *T0 = L_SUBFR; + *T0_frac = 0; + *T0_res = 1; + } + else if(coder_type == 1) /* 8/4/4/4 (EVS) */ + { + if (i_subfr == 0) + { + limit_T0_voiced( 4, 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, 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, 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, (pit_res_max>>1), *T0_min, *T0_min_frac, pt_indice ); + } + + } + else if(coder_type == 2) /* 8/5/8/5 (EVS) */ + { + + if (i_subfr == 0) + { + limit_T0_voiced( 5, 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, 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, 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, pit_res_max>>1, T0_frac, T0_res, pit_res_max, + pit_flag, pit_min, pit_min, pit_fr1b, L_SUBFR); + + 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, (pit_res_max>>1), *T0_min, *T0_min_frac, pt_indice ); + } + } + else if(coder_type == 3) /* 9/6/6/6 (HRs- VC) */ + { + int pit_res_max2 = pit_res_max; + + if ( pit_min==PIT_MIN_16k ) + { + + pit_res_max2 = 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); + + 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) */ + { + int pit_res_max2 = pit_res_max; + + if ( pit_min==PIT_MIN_16k ) + { + + pit_res_max2 = pit_res_max >> 1; + } + + + if ( (i_subfr == 0) || (i_subfr == 2*L_SUBFR) ) + { + + 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(coder_type == 8) /* 8/5/5/5 (RF all pred mode) */ + { + if (i_subfr == 0) + { + limit_T0_voiced( 5, 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, 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, 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, (pit_res_max>>1), *T0_min, *T0_min_frac, pt_indice ); + } + } + else if(coder_type == 9) /* 8/0/8/0 (RF mode Gen pred) */ + { + if (i_subfr == 0) + { + limit_T0_voiced( 4, 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, 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, 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, (pit_res_max>>1), *T0_min, *T0_min_frac, pt_indice ); + } + } + else + { + assert(0); + } + + return; +} + + +/*-------------------------------------------------------------------* + * Mode2_abs_pit_enc: + * + * Encode pitch lag absolutely + *-------------------------------------------------------------------*/ + +void Mode2_abs_pit_enc( + short T0, /* i : integer pitch lag */ + int T0_frac, /* i : pitch fraction */ + int **pt_indice, /* i/o: pointer to Vector of Q indexes */ + short pit_min, + short pit_fr1, + short pit_fr2, + short pit_res_max +) +{ + short pit_res_max_half; + + pit_res_max_half= pit_res_max>>1; + + if (T0 < pit_fr2) + { + **pt_indice = T0*pit_res_max + T0_frac - (pit_min*pit_res_max); + } + else if (T0 < pit_fr1) + { + **pt_indice = T0*pit_res_max_half + T0_frac - (pit_fr2*pit_res_max_half) + ((pit_fr2-pit_min)*pit_res_max); + + } + else + { + **pt_indice = T0 - pit_fr1 + ((pit_fr2-pit_min)*pit_res_max) + ((pit_fr1-pit_fr2)*pit_res_max_half); + } + + (*pt_indice)++; + + return; +} + + +/*-------------------------------------------------------------------* + * Mode2_delta_pit_enc: + * + * Encode pitch lag differentially + *-------------------------------------------------------------------*/ + +void Mode2_delta_pit_enc( + short T0, /* i : integer pitch lag */ + int T0_frac, /* i : pitch fraction */ + int T0_res, /* i : pitch resolution */ + short T0_min, /* i/o: delta search min */ + short T0_min_frac, /* i/o: delta search min */ + int **pt_indice /* i/o: pointer to Vector of Q indexes */ +) +{ + + **pt_indice = (T0 - T0_min) * T0_res + T0_frac - T0_min_frac; + + (*pt_indice)++; + + return; +} diff --git a/lib_enc/pitch_ol.c b/lib_enc/pitch_ol.c new file mode 100644 index 000000000..7b9261581 --- /dev/null +++ b/lib_enc/pitch_ol.c @@ -0,0 +1,960 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "prot.h" +#include "cnst.h" +#include "rom_com.h" +#include "rom_enc.h" + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ + +#define PIT_MIN2 20 /* pit_min for pitch tracking */ +#define PIT_MIN_1 44 /* pitch tracking */ +#define PIT_MIN2_1 24 +#define THR_relE -11.0f +#define THRES0 1.17f /* Threshold to favor smaller pitch lags */ +#define DELTA0 2.0f /* initial range of multiples search */ +#define STEP 1.0f /* increment in range of multiples search */ +#define THRES1 0.4f /* Threshold to favor pitch lags coherence for neighbours */ +#define DELTA_COH 14 /* Maximum pitch lags difference for neighbours to be considered as coherent */ +#define THRES3 0.7f /* Threshold to favor pitch lags coherence with previous frames */ +#define CORR_TH0 0.4f /* Noise threshold for reinforcement with past frame pitch */ +#define CORR_TH1 0.5f /* Noise threshold for reinforcement with neighbourhood pitch correlations */ +#define LEN_X ((PIT_MAX/OPL_DECIM)-(PIT_MIN2/OPL_DECIM)+1) /* Correlation buffer length */ +#define COH_FAC 1.4f /* Factor for measuring the pitch coherence */ +#define NSECT 4 +#define NHFR 3 +#define L_FIR_PO 5 +#define L_MEM (L_FIR_PO-2) + +/*-----------------------------------------------------------------* + * Local function prototypes + *-----------------------------------------------------------------*/ + +static void pitch_neighbour( const short sect0, const short pitch_tmp[], short pitch[NHFR][2*NSECT], + const float corr_tmp[], float corr[3][2*NSECT], const float thres1[2*NHFR], const short ind_tmp[2*NHFR] ); + +static void find_mult( float *fac, const short pitch0, const short pitch1, const short pit_max0, + float *corr, short *old_pitch, float *old_corr, float delta, const float step); + +static short pitch_coherence( const short pitch0, const short pitch1, const float fac_max, const short diff_max ); + +static void lp_decim2( const float x[], float y[], const short l, float *mem ); + + +/*-----------------------------------------------------------------* + * pitch_ol_init + * + * Open loop pitch variable initialization + *-----------------------------------------------------------------*/ + +void pitch_ol_init( + float *old_thres, /* o : threshold for reinforcement of past pitch influence */ + short *old_pitch, /* o : pitch of the 1st half-frame of previous frame */ + short *delta_pit, /* o : pitch evolution extrapolation */ + float *old_corr /* o : correlation */ +) +{ + *old_thres = 0.0f; + *old_pitch = 0; + *delta_pit = 0; + *old_corr = 0.0f; + + return; +} + +/*-----------------------------------------------------------------* + * pitch_ol() + * + * Compute the open loop pitch lag. + * + * The pitch lag search is divided in three sections of two sets. + * Each section cannot have a pitch multiple. + * We find a maximum for each section. + * We compare the maxima of each section. + * + * 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 than or equal to the longest pitch delay + *------------------------------------------------------------------*/ + +void pitch_ol( + short pitch[3], /* o : open loop pitch lag for each half-frame */ + float voicing[3], /* o : maximum normalized correlation for each half-frame */ + short *old_pitch, /* i/o: OL pitch of the 2nd half-frame of the last frame */ + float *old_corr, /* i/o: correlation */ + float corr_shift, /* i : normalized correlation correction */ + float *old_thres, /* i/o: maximum correlation weighting with respect to past frame pitch */ + short *delta_pit, /* i/o: old pitch extrapolation correction (added to old pitch) */ + float *st_old_wsp2, /* i/o: weighted speech memory */ + const float *wsp, /* i : weighted speech for current frame and look-ahead */ + float mem_decim2[3], /* i/o: wsp decimation filter memory */ + const float relE, /* i : relative frame energy */ + const short L_look, /* i : look-ahead */ + const short last_class, /* i : frame classification of last frame */ + const short bwidth, /* i : bandwidth */ + const short Opt_SC_VBR /* i : SC-VBR flag */ +) +{ + float old_wsp2[(L_WSP-L_INTERPOL)/OPL_DECIM], *wsp2; + float tmp_mem[3], scale1[2*DELTA_COH-1]; + float scaled_buf[2*LEN_X + 3*(DELTA_COH-1)]; + float cor_temp, cor_buf[2*LEN_X], *pt1, *pt2, *pt3, *pt4, *pt5 = 0, *pt6 = 0, *pt_cor0, *pt_cor1, *pt_cor2, *pt_cor3, *pt_cor4; + float thres1[2*NHFR]; + short diff, cnt, ind, ind1, offset, offset1, offset_la = 0, offset_la1 = 0, coh_flag, coh_flag1; + + short i, j, k, m, pit_min, pit_min1, sect0, subsect0, old_tmp, old_tmp1, len_x, len_x1, len_temp, len_temp1; + short pitchX[NHFR][2*NSECT], pitch_tmp[2*NHFR], ind_tmp[2*NHFR], tmp_buf[NHFR+1]; + float enr, enr1 = 0.0f, enr_norm[NSECT], enr_norm1[NSECT], fac; + float scaledX[NHFR][2*NSECT], corX[NHFR][2*NSECT], cor_tmp[2*NHFR], cor_mean; + + const short *nb_sect, *nb_subsect, *len, *len1, *sublen, *sublen1, *pit_max, *sec_length, *sec_length1; + short ind_corX, ind1_corX; + float pit_min_coding; + + /*--------------------------------------------------------------* + * Initialization + *--------------------------------------------------------------*/ + + nb_sect = nb_sect_12k8; + nb_subsect = nb_subsect_12k8; + + len = len_12k8; + len1 = len1_12k8; + sublen = sublen_12k8; + sublen1 = sublen1_12k8; + pit_max = pit_max_12k8; + sec_length = sec_length_12k8; + sec_length1 = sec_length1_12k8; + + if( last_class < VOICED_TRANSITION && bwidth != NB ) + { + /* reset last pitch reinforcement in case of unvoiced or transitions: it avoids some pitch doublings */ + *old_thres = 0.0f; + } + + pit_min_coding = PIT_MIN_EXTEND; + if( ( bwidth != NB && *old_pitch > PIT_MIN ) || + ( bwidth == NB && (*old_pitch > PIT_MIN2_1 || *old_thres < 0.1) ) ) + { + pit_min = PIT_MIN/OPL_DECIM; + pit_min1= PIT_MIN_1/OPL_DECIM; + subsect0 = 2; + sect0 = 1; + } + else + { + pit_min = PIT_MIN2/OPL_DECIM; + pit_min1= PIT_MIN2_1/OPL_DECIM; + subsect0 = 0 ; + sect0 = 0; + } + + len_x = PIT_MAX/OPL_DECIM - pit_min + 1; + len_x1= PIT_MAX/OPL_DECIM - pit_min1 + 1; + + /*--------------------------------------------------------------* + * 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 + *--------------------------------------------------------------*/ + + mvr2r( st_old_wsp2, old_wsp2, (L_WSP_MEM-L_INTERPOL)/OPL_DECIM ); + wsp2 = old_wsp2 + ((L_WSP_MEM-L_INTERPOL)/OPL_DECIM); + lp_decim2( wsp, wsp2, L_FRAME, mem_decim2 ); + + mvr2r( mem_decim2, tmp_mem, 3 ); + lp_decim2( &wsp[L_FRAME], &wsp2[L_FRAME/OPL_DECIM], L_look, tmp_mem ); + + mvr2r( &old_wsp2[L_FRAME/OPL_DECIM], 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 *= 0.5f; + set_f( scaled_buf, 0, DELTA_COH-1 ); + set_f( scaled_buf + (DELTA_COH-1) + len_x, 0, DELTA_COH-1 ); + set_f( scaled_buf + 2*(DELTA_COH-1) + len_x + len_x1, 0, DELTA_COH-1 ); + + pt1 = scale1 + DELTA_COH-1; + pt2 = pt1; + for( i=0 ; i< DELTA_COH ; i++ ) + { + *pt1 = -(*old_thres)/DELTA_COH * i + *old_thres + 1.0f; + *pt2-- = *pt1++; + } + + /*-----------------------------------------------------------------* + * Estimate the new pitch by extrapolating the old pitch value + * for 2 half-frames + *-----------------------------------------------------------------*/ + + old_tmp = *old_pitch + *delta_pit; + + if( old_tmp > PIT_MAX/OPL_DECIM ) + { + old_tmp = PIT_MAX/OPL_DECIM; + } + + if( old_tmp < pit_min ) + { + old_tmp = pit_min; + } + + old_tmp1 = old_tmp + *delta_pit; + if( old_tmp1 > PIT_MAX/OPL_DECIM ) + { + old_tmp1 = PIT_MAX/OPL_DECIM; + } + + if( old_tmp1 < pit_min ) + { + 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 0; k-- ) + { + enr += *pt3 **pt3; + pt3++; + } + enr_norm[j] = enr; + + /* Reduce complexity (length of 'enr1' section is equal or larger than 'enr') */ + pt5 = pt3; + enr1 = enr; + + /* 2nd set */ + k = (short)(pt1 - pt5); + for( k = k+len1[j]; k > 0; k-- ) + { + enr1 += *pt5 **pt5 ; + pt5++ ; + } + enr_norm1[j] = enr1 ; + } + + /*-----------------------------------------------------------------* + * Find correlation for the non-overlapping pitch lag values + *-----------------------------------------------------------------*/ + k = (short)(pt2 - pt1); + for( k = k + pit_max[subsect0]; k >= 0; k-- ) + { + *pt_cor1++ = dotp( pt1, pt2--, sublen[0] ) ; + } + + /*-----------------------------------------------------------------* + * For each subsection, find the correlation + *-----------------------------------------------------------------*/ + for( j = subsect0; j < nb_subsect[i]; j++ ) + { + len_temp = sublen[j]; + len_temp1= sublen1[j]; + + k = (short)(pt2-pt1); + if (len_temp < len_temp1) + { + for ( k = k + pit_max[j+1]; k >= 0; k-- ) + { + cor_temp = pt1[0] * pt2[0]; + for ( m = 1; m < len_temp; m++ ) + { + cor_temp += pt1[m] * pt2[m]; + } + *pt_cor1++ = cor_temp; + for ( ; m < len_temp1; m++ ) + { + cor_temp += pt1[m] * pt2[m]; + } + *pt_cor3++ = cor_temp; + pt2--; + } + } + else + { + for ( k = k + pit_max[j+1]; k >= 0; k-- ) + { + cor_temp = pt1[0] * pt2[0]; + for ( m = 1; m < len_temp1; m++ ) + { + cor_temp += pt1[m] * pt2[m]; + } + *pt_cor3++ = cor_temp; + for ( ; m < len_temp; m++ ) + { + cor_temp += pt1[m] * pt2[m]; + } + *pt_cor1++ = cor_temp; + pt2--; + } + } + } + } + + /*-----------------------------------------------------------------* + * Third half-frame (look-ahead) + *-----------------------------------------------------------------*/ + + else + { + /*-----------------------------------------------------------------* + * For each section in both sets, find fixed vector energy + *-----------------------------------------------------------------*/ + + pt6 = pt1 + L_look/OPL_DECIM - 1; + pt3 = pt6; + pt5 = pt6; + + for( j = sect0; j < nb_sect[i]; j++ ) /* loop for each section */ + { + /* 1st set */ + k = (short)(pt3 - pt6); + for( k = k + len[j]; k > 0; k-- ) + { + enr += *pt3 **pt3; + pt3--; + } + + enr_norm[j] = enr; + + pt5 = pt3; + enr1 = enr; + + /* 2nd set */ + k = (short)(pt5 - pt6); + for( k = k + len1[j]; k > 0; k-- ) + { + enr1 += *pt5 **pt5 ; + pt5-- ; + } + + enr_norm1[j] = enr1 ; + } + + /* Set pointers */ + if( sect0 == 0 ) + { + pt2 = pt6 - pit_min; + k = 2; + } + else + { + pt2 = pt6 - pit_max[1] - 1; + k = pit_max[2] - pit_max[1]; + } + + /*-----------------------------------------------------------------* + * Find correlation for the non-overlapping pitch lag values + *-----------------------------------------------------------------*/ + + for( ; k > 0; k-- ) + { + *pt_cor1 = 0; + for( m=0; m 0; k-- ) + { + cor_temp = pt6[0] * pt2[0]; + for ( m = 1; m < len_temp; m++ ) + { + cor_temp += pt6[-m] * pt2[-m]; + } + *pt_cor1++ = cor_temp; + for ( ; m < len_temp1; m++ ) + { + cor_temp += pt6[-m] * pt2[-m]; + } + *pt_cor3++ = cor_temp; + pt2--; + } + } + else + { + for ( ; k > 0; k-- ) + { + cor_temp = pt6[0] * pt2[0]; + for ( m = 1; m < len_temp1; m++ ) + { + cor_temp += pt6[-m] * pt2[-m]; + } + *pt_cor3++ = cor_temp; + for ( ; m < len_temp; m++ ) + { + cor_temp += pt6[-m] * pt2[-m]; + } + *pt_cor1++ = cor_temp; + pt2--; + } + } + } + } + + /* Save unscaled correlation vector */ + mvr2r( pt_cor0, cor_buf, len_x ); + mvr2r( 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++ ) + { + *pt_cor1++ *= (*pt2); + *pt_cor3++ *= (*pt2++); + } + + /* update for next half-frame */ + 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; + offset = 0; + pt_cor3 = pt_cor0 + (DELTA_COH-1) + len_x; + offset1 = 0; + for( j=sect0; j < nb_sect[i] ; j++ ) /* loop for each section */ + { + /* 1st set */ + if( i==2 ) + { + offset_la = L_look/OPL_DECIM - 1 - (len[j]-1); + } + else + { + offset_la = 0; + } + + /* 2nd set */ + if( i==2 ) + { + offset_la1 = L_look/OPL_DECIM - 1 - (len1[j]-1); + } + else + { + offset_la1 = 0; + } + + /* 1st set of candidates */ + ind = maximum( pt_cor1, sec_length[j], 0 ) + offset; + pitchX[i][j] = ind + pit_min; + pt2 = pt1 - pitchX[i][j] + offset_la; /* selected moving vector */ + enr1 = dotp( pt2, pt2, len[j] ) + 0.01f; + enr1 = inv_sqrt( enr_norm[j] * enr1 ); /* 1/sqrt(energy) */ + corX[i][j] = cor_buf[ind] * enr1; /* find best normalized correlation per section */ + scaledX[i][j] = pt_cor0[ind] * enr1; /* find best scaled normalized correlation per section */ + + pt_cor1 += sec_length[j]; + offset = offset + sec_length[j]; + + /* 2nd set of candidates */ + ind1 = maximum( pt_cor3, sec_length1[j], 0 ) + offset1; + pitchX[i][j+NSECT] = ind1 + pit_min1; + pt4 = pt1 - pitchX[i][j+NSECT] + offset_la1; /* selected moving vector */ + enr1 = dotp( pt4, pt4, len1[j] ) + 0.01f; + enr1 = inv_sqrt( enr_norm1[j] * enr1 ); /* 1/sqrt(energy) */ + corX[i][j+NSECT] = cor_buf[ind1+len_x] * enr1; /* find best normalized correlation per section */ + scaledX[i][j+NSECT] = pt_cor0[ind1+(DELTA_COH-1)+len_x] * enr1; /* find best scaled normalized correlation per section */ + + pt_cor3 += sec_length1[j]; + offset1 = offset1 + sec_length1[j]; + } + } + /*-----------------------------------------------------------------* + * 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; + find_mult( &fac, pitchX[i][2], pitchX[i][3], pit_max[7], &scaledX[i][2], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in longest-delay section */ + find_mult( &fac, pitchX[i][1], pitchX[i][2], pit_max[5], &scaledX[i][1], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 3rd section */ + + if((sect0==0) && ((pitchX[i][0]*2) >= pit_min_coding)) + { + find_mult( &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; + find_mult( &fac, pitchX[i][NSECT+2], pitchX[i][NSECT+3], pit_max[7], &scaledX[i][NSECT+2], old_pitch, old_corr, DELTA0, STEP ) ; /* Multiples in longest-delay section */ + find_mult( &fac, pitchX[i][NSECT+1], pitchX[i][NSECT+2], pit_max[6], &scaledX[i][NSECT+1], old_pitch, old_corr, DELTA0, STEP ) ; /* Multiples in 3rd section */ + + if( (sect0 == 0) && (pitchX[i][NSECT+0]*2 >= pit_min_coding) ) + { + find_mult( &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; /* the look-ahead */ + find_mult( &fac, pitchX[i][2], pitchX[i][3], pit_max[7], &scaledX[i][2], old_pitch, old_corr, 2.0f, 2.0f ); /* Multiples in longest-delay section */ + find_mult( &fac, pitchX[i][1], pitchX[i][2], pit_max[5], &scaledX[i][1], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 3rd section */ + + if( (sect0 == 0) && (pitchX[i][0]*2 >= pit_min_coding) ) + { + find_mult( &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; /* the look-ahead */ + find_mult( &fac, pitchX[i][NSECT+2], pitchX[i][NSECT+3], pit_max[7], &scaledX[i][NSECT+2], old_pitch, old_corr, 2.0f, 2.0f ) ; /* Multiples in longest-delay section */ + find_mult( &fac, pitchX[i][NSECT+1], pitchX[i][NSECT+2], pit_max[6], &scaledX[i][NSECT+1], old_pitch, old_corr, DELTA0, STEP ) ; /* Multiples in 3rd section */ + + if( (sect0 == 0) && (pitchX[i][NSECT+0]*2 >= pit_min_coding)) + { + find_mult( &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 */ + } + + /*-----------------------------------------------------------------* + * Do 1st estimate for pitch values + * Adjust the normalized correlation using estimated noise level + * Compute the maximum scaling for the neighbour correlation + * reinforcement + *-----------------------------------------------------------------*/ + + for( i=0; i 1.0f ) + { + cor_tmp[i] = 1.0f; + } + thres1[i] = THRES1 * cor_tmp[i]; /* Higher is the neighbour's correlation, higher is the weighting */ + + /* 2nd set of pitch candidates */ + ind1 = maximum( scaledX[i]+sect0+NSECT, (short)(NSECT-sect0), 0 ); + ind1 += (sect0 + NSECT); + ind_tmp[i+NHFR] = ind1; + pitch_tmp[i+NHFR] = pitchX[i][ind1]; + cor_tmp[i+NHFR] = corX[i][ind1]; + cor_tmp[i+NHFR] += corr_shift; + + if( cor_tmp[i+NHFR] > 1.0f ) + { + cor_tmp[i+NHFR] = 1.0f; + } + thres1[i+NHFR] = THRES1 * cor_tmp[i+NHFR]; /* Higher is the neighbour's correlation, higher is the weighting */ + } + /*-----------------------------------------------------------------* + * 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( sect0, pitch_tmp, pitchX, cor_tmp, scaledX, thres1, ind_tmp ); + for( i=0; i scaledX[i][ind] ) + { + ind = ind1; + } + + if( Opt_SC_VBR && corX[i][ind1_corX] > corX[i][ind_corX] ) + { + ind_corX = ind1_corX; + } + + if( Opt_SC_VBR && (pitchX[i][ind]*0.4 < pitchX[i][ind_corX]) && (pitchX[i][ind]*0.6 > pitchX[i][ind_corX]) && (corX[i][ind_corX]>=0.9) ) /* && (pitchX[i][ind]>50)) */ + { + pitch[i] = pitchX[i][ind_corX]; + voicing[i] = corX[i][ind_corX]; + } + else + { + pitch[i] = pitchX[i][ind]; + voicing[i] = corX[i][ind]; + } + } + + /*-----------------------------------------------------------------* + * Increase the threshold for correlation reinforcement with + * the past if correlation is high and pitch is stable + *-----------------------------------------------------------------*/ + + cor_mean = 0.5f * (voicing[0] + voicing[1]) + corr_shift; + if( cor_mean > 1.0f ) + { + cor_mean = 1.0f; + } + + /* pitch unstable in present frame or from previous frame or normalized correlation too low */ + coh_flag = pitch_coherence( (short)pitch[0], (short)pitch[1], COH_FAC, DELTA_COH ); + coh_flag1 = pitch_coherence( (short)pitch[0], (short)*old_pitch, COH_FAC, DELTA_COH ); + if( ( coh_flag == 0 ) || ( coh_flag1 == 0 ) || ( cor_mean < CORR_TH0 ) || (relE < THR_relE) ) + { + *old_thres = 0.0f; /* Reset the threshold */ + } + else + { + *old_thres += (0.16f * cor_mean); /* The threshold increase is directly dependent on normalized correlation */ + } + + if( *old_thres > THRES3 ) + { + *old_thres = THRES3; + } + + if( voicing[1] > voicing[0] ) + { + *old_corr = voicing[1]; + } + else + { + *old_corr = cor_mean; + } + + /*-----------------------------------------------------------------* + * 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; + for( i=0; i (float)*old_pitch * 0.4f ) + { + /* reinforce the normalized correlation */ + *corr *= *fac; + } + *fac *= THRES0; + } + pit_min = pit_min + pitch0; /* next multiple */ + delta += step; /* add the incertitude to the allowed range */ + } + return; +} + +/*---------------------------------------------------------------------------* + * pitch_neighbour + * + * Verifies if the maximum correlation pitch lag is coherent with neighbour + * values + *---------------------------------------------------------------------------*/ +static void pitch_neighbour( + const short sect0, /* i : indicates whether section 0 (below PIT_MIN) is used */ + const short pitch_tmp[], /* i : estimated pitch values for each half-frame & look-ahead */ + short pitch[NHFR][2*NSECT], /* i : tested pitch values for each half-frame & look-ahead */ + const float corr_tmp[], /* i : raw normalized correlation (before different scalings) */ + float corr[NHFR][2*NSECT], /* i/o: normalized correlation for each half-frame & look-ahead */ + const float thres1[2*NHFR], /* i : maximum scaling for the immediate neighbours */ + const short ind_tmp[2*NHFR] /* i : maximum section indices */ +) +{ + short delta, i, j, k, K, coh_flag; + + for( k=sect0 ; k= CORR_TH1 ) /* reinforcement can happen only if the correlation is high enough */ + { + delta = (short)abs( pitch[i][k] - pitch_tmp[j] ); /* Find difference of pitch values */ + coh_flag = pitch_coherence( (short)pitch[i][k], (short)pitch_tmp[j], COH_FAC, DELTA_COH ); + if( coh_flag != 0 ) + { + /* Favour section-wise stability */ + if ( ind_tmp[j] == k ) + { + corr[i][k] *= ( -thres1[j]/DELTA_COH * delta + thres1[j]+1.0f ); /* Favour closer values */ + } + else + { + corr[i][k] *= ( -thres1[j]/DELTA_COH * 0.625f * delta + thres1[j] * 0.625f +1.0f ) ; + } + } + } + } + } + } + } + /*---------------------* + * 2nd set of sections + *---------------------*/ + for( k=sect0 ; k= CORR_TH1 ) /* reinforcement can happen only if the correlation is high enough */ + { + delta = (short)abs( pitch[i][NSECT+k] - pitch_tmp[j+NHFR] ); /* Find difference of pitch values */ + coh_flag = pitch_coherence( (short)pitch[i][NSECT+k], (short)pitch_tmp[j+NHFR], COH_FAC, DELTA_COH ); + if( coh_flag != 0 ) + { + /* Favour section-wise stability */ + if ( ind_tmp[j+NHFR] == (NSECT + k) ) + { + corr[i][NSECT+k] *= ( -thres1[j+NHFR]/DELTA_COH * delta + thres1[j+NHFR]+1.0f ); /* Favour closer values */ + } + else + { + corr[i][NSECT+k] *= ( -thres1[j+NHFR]/DELTA_COH * 0.625f * delta + thres1[j+NHFR] * 0.625f +1.0f ) ; + } + } + } + } + } + } + } + return; +} + +/*-----------------------------------------------------------------* + * pitch_coherence + * + * Verify if pitch evolution is smooth + *-----------------------------------------------------------------*/ + +static short pitch_coherence( + const short pitch0, /* i : first pitch to compare */ + const short pitch1, /* i : 2nd pitch to compare */ + const float fac_max, /* i : max ratio of both values */ + const short diff_max /* i : max difference of both values */ +) +{ + short smaller, larger; + if( pitch1 < pitch0 ) /* Finds smaller and larger of 2 short values */ + { + smaller = pitch1; + larger = pitch0; + } + else + { + smaller = pitch0; + larger = pitch1; + } + if( ((float)larger < fac_max * (float)smaller) && ( (larger-smaller) < diff_max) ) + { + return 1; + } + else + { + return 0; + } +} + + +/*-----------------------------------------------------------------* + * lp_decim2: + * + * Decimate a vector by 2 with 2nd order fir filter. + *-----------------------------------------------------------------*/ +static void lp_decim2( + const float x[], /* i : signal to process */ + float y[], /* o : processed signals */ + const short l, /* i : size of filtering */ + float *mem /* i/o: memory (size=3) */ +) +{ + const float *p_h; + float temp, *p_x, x_buf[L_FRAME_PLUS+L_MEM]; + short i, j, k; + + /* copy initial filter states into buffer */ + p_x = x_buf; + for (i=0; i +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "rom_enc.h" +#include "prot.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 PIT_MAX ) + { + t0_max = PIT_MAX; + } + t_max = t0_max + L_INTERPOL1; + + pt_wsp = wsp + pos; + pt_cor = cor; + for ( t=t_min; t<=t_max; t++ ) + { + *pt_cor++ = dotp( pt_wsp, pt_wsp-t, L_SUBFR ); + } + + pt_cor = cor + L_INTERPOL1; + cor_max = *pt_cor++; + t1 = t0_min; + for ( t=t0_min+1; t<=t0_max; t++ ) + { + if ( *pt_cor > cor_max ) + { + cor_max = *pt_cor; + t1 = t; + } + pt_cor++; + } + + /*------------------------------------------------------------------* + * 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 + L_INTERPOL1 - t0_min; + t0 = t1; + + step = 1; /* 1/4 subsample resolution */ + fraction = 1; + + if (t0 == t0_min) /* Limit case */ + { + fraction = 0; + cor_max = interpolation( &pt_cor[t0], E_ROM_inter4_1, fraction, PIT_UP_SAMP, 4 ); + } + else /* Process negative fractions */ + { + t0--; + cor_max = interpolation( &pt_cor[t0], E_ROM_inter4_1, fraction, PIT_UP_SAMP, 4 ); + for ( i=(fraction+step); i<=3; i=i+step ) + { + temp = interpolation( &pt_cor[t0], E_ROM_inter4_1, i, PIT_UP_SAMP, 4 ); + if (temp > cor_max) + { + cor_max = temp; + fraction = i; + } + } + } + + for ( i=0; i<=3; i=i+step ) /* Process positive fractions */ + { + temp = interpolation( &pt_cor[t1], E_ROM_inter4_1, i, PIT_UP_SAMP, 4 ); + if (temp > cor_max) + { + cor_max = temp; + fraction = i; + t0 = t1; + } + } + + *pitch_fr = t0 + (float)fraction / 4.0f; + pred_lt4( pt_wsp, wsp_fr, t0, fraction, L_SUBFR, E_ROM_inter4_1, 4, PIT_UP_SAMP); + + enr_wsp = dotp( pt_wsp, pt_wsp, L_SUBFR ) + 0.01f; + enr_old = dotp( wsp_fr, wsp_fr, L_SUBFR ) + 0.01f; + *voicing_fr = cor_max * inv_sqrt(enr_wsp * enr_old); + + return; +} + + +/*-------------------------------------------------------------------* + * StableHighPitchDetect() + * + * Very short stable pitch detection + *-------------------------------------------------------------------*/ + +void StableHighPitchDetect( + short *flag_spitch, /* o : flag to indicate very short stable pitch */ + short pitch[], /* i/o: OL pitch buffer */ + const float voicing[], /* i : OL pitch gains */ + const float Bin_E[], /* i : per bin log energy spectrum */ + const float wsp[], /* i : weighted speech */ + const short localVAD, + float *voicing_sm, /* i/o: smoothed open-loop pitch gains */ + float *voicing0_sm, /* i/o: smoothed high pitch gains */ + float *LF_EnergyRatio_sm, /* i/o: smoothed [0, 300Hz] relative peak energy*/ + short *predecision_flag, /* i/o: predecision flag */ + float *diff_sm, /* i/o: smoothed pitch frequency difference */ + float *energy_sm /* i/o: smoothed energy around pitch frequency */ +) +{ + short i, pitch_freq_point, pit_min_up; + short T, Tp, pit_min; + + float voicing_m; + float energy0, energy1, ratio, cor_max, diff, sum_energy; + const float *pt_wsp; + + voicing_m = mean( voicing, 3 ); + *voicing_sm = 0.75f * (*voicing_sm) + 0.25f * voicing_m; + + + /* initial short pitch possibility pre-decision */ + pitch_freq_point = (short)(L_FFT/pitch[1] + 0.5f ); + diff = 0.0f; + sum_energy = 0.0f; + + for( i=1; i<2*pitch_freq_point; i++ ) + { + diff += (Bin_E[pitch_freq_point] - Bin_E[i]); + sum_energy += Bin_E[i]; + } + sum_energy /= (2*pitch_freq_point-1); + + *diff_sm = 0.2f * diff + 0.8f * *diff_sm; + *energy_sm = 0.2f * sum_energy + 0.8f * *energy_sm; + diff /= sum_energy; + + if( *diff_sm < -10 && *energy_sm < 38.5 && diff < -0.8 ) + { + *predecision_flag = 1; + } + + if( *diff_sm > 10 && *energy_sm > 83 && diff > 0.5 ) + { + *predecision_flag = 0; + } + + /* short pitch possiblity pre-decision */ + maximum(Bin_E, 7, &energy0); + maximum(Bin_E+8, 7, &energy1); + ratio = max(energy1-energy0,0); + ratio *= max(voicing_m,0); + + *LF_EnergyRatio_sm = (15*(*LF_EnergyRatio_sm) + ratio)/16; + + if( *LF_EnergyRatio_sm > 35 || ratio > 50 ) + { + *predecision_flag = 1; + } + + if( *LF_EnergyRatio_sm < 16 ) + { + *predecision_flag = 0; + } + + /* short pitch candidate detection */ + Tp = pitch[1]; + cor_max = 0; + + pt_wsp = wsp + 3*L_SUBFR; + pit_min = PIT_MIN_DOUBLEEXTEND; + pit_min_up = PIT_MIN; + + for( T=pit_min; T<=pit_min_up; T++ ) + { + energy1 = dotp( pt_wsp, pt_wsp-T, L_SUBFR ); + + if( energy1 > cor_max || T == pit_min ) + { + cor_max = energy1; + Tp = T; + } + } + + energy0 = dotp( pt_wsp, pt_wsp, L_SUBFR ) + 0.01f; + energy1 = dotp( pt_wsp-Tp, pt_wsp-Tp, L_SUBFR ) + 0.01f; + cor_max *= inv_sqrt( energy0*energy1 ); + *voicing0_sm = 0.75f*(*voicing0_sm) + 0.25f*cor_max; + + /* final short pitch correction */ + *flag_spitch = 0; + if( localVAD && *predecision_flag && *voicing0_sm > 0.65f && *voicing0_sm > 0.7f * (*voicing_sm) ) + { + *flag_spitch = 1; + + pitch[0] = Tp; + pitch[1] = Tp; + pitch[2] = Tp; + } + + return; +} + +/*-------------------------------------------------------------------* + * pitchDoubling_det() + * Multiple pitch doubling detector + * + *-------------------------------------------------------------------*/ + +void pitchDoubling_det( + float *wspeech, + short *pitch_ol, + float *pitch_fr, + float *voicing_fr +) +{ + float new_op_fr[2]; + float new_voicing[2]; + short new_Top[2]; + int m, T; + + /*save initial values*/ + new_Top[0]=pitch_ol[0]; + new_Top[1]=pitch_ol[1]; + for(m=2; m<5; m++) + { + T = pitch_ol[0]/m; + if(T>=PIT_MIN_12k8) + { + pitch_ol2( PIT_MIN_SHORTER, T, &new_op_fr[0], &new_voicing[0], 0, wspeech, 2 ); + pitch_ol2( PIT_MIN_SHORTER, T, &new_op_fr[1], &new_voicing[1], L_SUBFR, wspeech, 2 ); + + if((new_voicing[0]+new_voicing[1])>(voicing_fr[0]+voicing_fr[1])) + { + new_Top[0]=T; + pitch_fr[0]=new_op_fr[0]; + pitch_fr[1]=new_op_fr[1]; + voicing_fr[0]=new_voicing[0]; + voicing_fr[1]=new_voicing[1]; + } + } + + T = pitch_ol[1]/m; + if(T>=PIT_MIN_12k8) + { + pitch_ol2( PIT_MIN_SHORTER, T, &new_op_fr[0], &new_voicing[0], 2*L_SUBFR, wspeech, 2 ); + pitch_ol2( PIT_MIN_SHORTER, T, &new_op_fr[1], &new_voicing[1], 3*L_SUBFR, wspeech, 2 ); + + if((new_voicing[0]+new_voicing[1])>(voicing_fr[2]+voicing_fr[3])) + { + new_Top[1]=T; + pitch_fr[2]=new_op_fr[0]; + pitch_fr[3]=new_op_fr[1]; + voicing_fr[2]=new_voicing[0]; + voicing_fr[3]=new_voicing[1]; + } + } + } + pitch_ol[0]=new_Top[0]; + pitch_ol[1]=new_Top[1]; + + return; +} diff --git a/lib_enc/plc_enc_ext.c b/lib_enc/plc_enc_ext.c new file mode 100644 index 000000000..4328d98e0 --- /dev/null +++ b/lib_enc/plc_enc_ext.c @@ -0,0 +1,110 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "prot.h" +#include "typedef.h" +#include "stat_enc.h" +#include "cnst.h" +#include "rom_com.h" + + +#define NBITS_GACELP 5 + +/*-------------------------------------------------------------------* +* open_PLC_ENC_EVS() +* +* +*-------------------------------------------------------------------*/ + +void open_PLC_ENC_EVS( + HANDLE_PLC_ENC_EVS hPlcExt, + int sampleRate +) +{ + short itr; + + + hPlcExt->enableGplc = 0; + hPlcExt->calcOnlylsf = 1; + hPlcExt->nBits = NBITS_GACELP; + hPlcExt->stab_fac = 0; + set_f(hPlcExt->lsfoldbfi0, 0.0f, M); + set_f(hPlcExt->lsfoldbfi1, 0.0f, M); + set_f(hPlcExt->lsf_adaptive_mean, 0.0f, M); + set_f(hPlcExt->old_exc, 0.0f, 8); + set_f(hPlcExt->mem_MA, 0.0f, M); + set_f(hPlcExt->lsfold, 0.0f, M); + set_f(hPlcExt->lspold, 0.0f, M); + if( sampleRate == 12800 ) + { + hPlcExt->T0_4th = L_SUBFR; + hPlcExt->T0 = L_SUBFR; + for( itr=0; itrlsf_con[itr] = lsf_init[itr]; + hPlcExt->last_lsf_ref[itr] = lsf_init[itr]; + hPlcExt->last_lsf_con[itr] = lsf_init[itr]; + } + } + else + { + hPlcExt->T0_4th = L_SUBFR; + hPlcExt->T0 = L_SUBFR; + for( itr=0; itrlsf_con[itr] = lsf_init[itr] * 1.25f; + hPlcExt->last_lsf_ref[itr] = lsf_init[itr] * 1.25f; + hPlcExt->last_lsf_con[itr] = lsf_init[itr] * 1.25f; + } + } + + + return; +} + + +/*-------------------------------------------------------------------* +* gPLC_encInfo() +* +* Function to extract and write guided information +*-------------------------------------------------------------------*/ + +void gPLC_encInfo( + HANDLE_PLC_ENC_EVS self, + const int brate, + const int bwidth, + const short last_clas, + const int coder_type +) +{ + if (self) + { + self->calcOnlylsf = 1; + if(bwidth >= WB && brate == ACELP_24k40 ) + { + self->enableGplc = 1; + + if( ( last_clas == VOICED_CLAS || last_clas == ONSET ) + && (coder_type == VOICED || coder_type == GENERIC) ) + { + self->nBits = NBITS_GACELP; + self->calcOnlylsf = 0; + } + else + { + self->nBits = 1; + } + } + else + { + self->enableGplc = 0; + self->nBits = 0; + } + + } + + return; +} diff --git a/lib_enc/ppp_enc.c b/lib_enc/ppp_enc.c new file mode 100644 index 000000000..e67121d21 --- /dev/null +++ b/lib_enc/ppp_enc.c @@ -0,0 +1,203 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + + +/*-------------------------------------------------------------------* + * ppp_quarter_encoder() + * + * PPP quarter encoder + *--------------------------------------------------------------------*/ + +short ppp_quarter_encoder( + Encoder_State *st, /* i/o: encoder state structure */ + DTFS_STRUCTURE *CURRCW_Q, /* o : Quantized (amp/phase) DTFS */ + DTFS_STRUCTURE *TARGETCW, /* o : DTFS with quant phase but unquant Amp */ + int prevCW_lag, /* i : previous lag */ + DTFS_STRUCTURE vCURRCW_NQ, /* i : Unquantized DTFS */ + const float *curr_lpc, /* i : LPCS */ + float *lastLgainE, /* i/o: last low band gain */ + float *lastHgainE, /* i/o: last high band gain */ + float *lasterbE, /* i/o: last ERB vector */ + DTFS_STRUCTURE PREV_CW_E /* i : past DTFS */ +) +{ + DTFS_STRUCTURE *PREVDTFS; + + float tmp, temp_pl, temp_l; + int l; + short returnFlag = 1; + int POWER_IDX; /* Codebook index for the power quantization for PPP */ + int AMP_IDX[2]; /* Codebook index for the Amplitude quantization for PPP */ + float Erot = 0.0, z = 0.0; + + PREVDTFS = DTFS_new(); + + DTFS_copy( CURRCW_Q, vCURRCW_NQ ); + DTFS_copy( PREVDTFS, PREV_CW_E ); + + l = CURRCW_Q->lag; + temp_l = (float) CURRCW_Q->lag; + temp_pl = (float) prevCW_lag; + + DTFS_adjustLag( PREVDTFS, 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)))); + + DTFS_phaseShift( PREVDTFS, (float)(PI2*Erot/CURRCW_Q->lag)) ; + DTFS_car2pol(PREVDTFS); + + /* Amplitude Quantization */ + DTFS_car2pol(CURRCW_Q); /* at this point currCW_q=curr_nq */ + + returnFlag = DTFS_quant_cw(CURRCW_Q,prevCW_lag, curr_lpc, &POWER_IDX, AMP_IDX, lastLgainE, lastHgainE, lasterbE); + + push_indice( st, IND_AMP0, AMP_IDX[0], 6 ); + push_indice( st, IND_AMP1, AMP_IDX[1], 6 ); + push_indice( st, IND_POWER, POWER_IDX, 6 ); + + DTFS_copy(TARGETCW,*CURRCW_Q); + + /* Copying phase spectrum over */ + mvr2r(PREVDTFS->b, CURRCW_Q->b, (short)(CURRCW_Q->lag>>1)+1 ); + + DTFS_pol2car(CURRCW_Q); + DTFS_pol2car(TARGETCW); + tmp = DTFS_alignment_fine_new(*TARGETCW,*CURRCW_Q, 0.0) ; + + if (((tmp+3)>7) || ((tmp+3)<0)) + { + tmp = 0; + returnFlag = 0; + } + + DTFS_phaseShift( CURRCW_Q,(float)(PI2*tmp/CURRCW_Q->lag) ); + + push_indice( st, IND_GLOBAL_ALIGNMENT, (short) (tmp+3), 3 ); + + free( PREVDTFS ); + + return returnFlag; +} + +/*-------------------------------------------------------------------* + * set_ppp_mode() + * + * Determine if the current frame should be coded by PPP or not + * Impose PPP - CELP - CELP pattern + *-------------------------------------------------------------------*/ + +void set_ppp_mode( + Encoder_State *st, /* i/o: encoder state structure */ + short *coder_type, /* i/o: coder type */ + const short noisy_speech_HO, /* i : SC-VBR noisy speech HO flag */ + const short clean_speech_HO, /* i : SC-VBR clean speech HO flag */ + const short NB_speech_HO, /* i : SC-VBR NB speech HO flag */ + const short localVAD, + const short localVAD_he, /* i : HE-SAD flag without hangover */ + short *vad_flag + ,short T_op[] /* i : open loop pitch lag */ + ,short sp_aud_decision1 /* i : Speech Audio Decision */ +) +{ + if( *vad_flag == 1 && + ( noisy_speech_HO == 1 || clean_speech_HO == 1 || NB_speech_HO == 1 ) && + ( localVAD == 0 || localVAD_he == 0 ) ) + + { + *coder_type = UNVOICED; + } + + if( *coder_type == INACTIVE && *vad_flag == 0 && st->last_nelp_mode == 1 ) /* avoid HO frame go to GSC */ + { + *coder_type = UNVOICED; + } + + /* 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 ( st->ini_frame < 5 ) + { + *coder_type = UNVOICED; + *vad_flag = 1; + } + + /* Pattern PPP-CELP-CELP (pppcountE holds number of consecutive PPP frames) */ + if ( *coder_type != VOICED || st->last_coder_type == TRANSITION ) + { + /* ensure no transient to PPP transition */ + st->pppcountE = 0; + } + else + { + /* current mode is voiced */ + st->pppcountE++; + + if ( ( st->pppcountE == 1 && st->last_last_ppp_mode != 1 && !st->rate_control ) || + ( st->pppcountE == 1 && st->mode_QQF ) ) + { + st->ppp_mode = 1; + st->core_brate = PPP_NELP_2k80; + } + else if ( st->pppcountE == 2 ) + { + if ( st->last_ppp_mode == 1 && !st->mode_QQF ) + { + /* QFF mode */ + st->ppp_mode = 0; + } + else + { + /* QQF Mode */ + st->ppp_mode = 1; + st->core_brate = PPP_NELP_2k80; + } + } + else + { + st->ppp_mode = 0; + st->pppcountE = 0; + } + } + + if ( st->ppp_mode == 0 && st->set_ppp_generic == 1 ) + { + st->set_ppp_generic = 0; + *coder_type = GENERIC; + } + + if( st->last_core == HQ_CORE ) + { + st->ppp_mode = 0; + st->set_ppp_generic = 0; + *coder_type = TRANSITION; + } + + if(st->last_ppp_mode && !st->ppp_mode && sp_aud_decision1 && st->bwidth == NB && st->Opt_SC_VBR) /*if it were about to go from ppp->HQ*/ + { + st->avoid_HQ_VBR_NB = 1; + *coder_type = GENERIC; + } + + if(st->last_nelp_mode && sp_aud_decision1 && st->bwidth == NB && st->Opt_SC_VBR) /*if it were about to go from nelp->HQ*/ + { + st->avoid_HQ_VBR_NB = 1; + *coder_type = GENERIC; + } + + if ((( st->old_pitch_buf[(2*NB_SUBFR)-1] > PPP_LAG_THRLD) || (T_op[1]>PPP_LAG_THRLD) || !st->last_Opt_SC_VBR ) && (st->ppp_mode==1)) + { + st->ppp_mode = 0; + st->core_brate = ACELP_7k20; + } + + return; +} diff --git a/lib_enc/pre_proc.c b/lib_enc/pre_proc.c new file mode 100644 index 000000000..67ed09da3 --- /dev/null +++ b/lib_enc/pre_proc.c @@ -0,0 +1,913 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_enc.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * pre_proc() + * + * Pre-processing (spectral analysis, LP analysis, VAD, OL pitch calculation, coder mode selection, ...) + *--------------------------------------------------------------------*/ + +void pre_proc( + Encoder_State *st, /* i/o: encoder state structure */ + const short input_frame, /* i : frame length */ + const float signal_in[], /* i : new samples */ + float old_inp_12k8[], /* i/o: buffer of old input signal */ + float old_inp_16k[], /* i/o: buffer of old input signal @ 16kHz */ + float **inp, /* o : ptr. to inp. signal in the current frame */ + short *sp_aud_decision1, /* o : 1st stage speech/music classification */ + short *sp_aud_decision2, /* o : 2nd stage speech/music classification */ + float fr_bands[2*NB_BANDS], /* o : energy in frequency bands */ + short *vad_flag, + short *localVAD, + float *Etot, /* o : total energy */ + float *ener, /* o : residual energy from Levinson-Durbin */ + short pitch[3], /* o : open-loop pitch values for quantiz. */ + float voicing[3], /* o : OL maximum normalized correlation */ + float A[NB_SUBFR16k*(M+1)], /* o : A(z) unquantized for the 4 subframes */ + float Aw[NB_SUBFR16k*(M+1)], /* o : weighted A(z) unquantized for subframes */ + float epsP[M+1], /* o : LP prediction errors */ + float lsp_new[M], /* o : LSPs at the end of the frame */ + float lsp_mid[M], /* o : LSPs in the middle of the frame */ + short *coder_type, /* o : coder type */ + short *sharpFlag, /* o : formant sharpening flag */ + short *vad_hover_flag, + short *attack_flag, /* o : flag signalling attack encoded by AC mode (GSC) */ + float *new_inp_resamp16k, /* o : new input signal @16kHz, non pre-emphasised, used by the WB TBE/BWE */ + short *Voicing_flag, /* o : voicing flag for HQ FEC */ + float realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o : real buffer */ + float imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o : imag buffer */ + short *hq_core_type /* o : HQ core type */ +) +{ + short delay; + float *inp_12k8, *new_inp_12k8, *inp_16k, *new_inp_16k; /* pointers to current frame and new data */ + float old_wsp[L_WSP], *wsp; /* weighted input signal buffer */ + float pitch_fr[NB_SUBFR]; /* fractional pitch values */ + float voicing_fr[NB_SUBFR]; /* fractional pitch gains */ + float lf_E[2*VOIC_BINS]; /* per bin spectrum energy in lf */ + float tmpN[NB_BANDS]; /* Temporary noise update */ + float tmpE[NB_BANDS]; /* Temporary averaged energy of 2 sf. */ + float ee[2]; /* Spectral tilt */ + float corr_shift; /* correlation shift */ + float relE; /* frame relative energy */ + short loc_harm; /* harmonicity flag */ + float cor_map_sum, sp_div, PS[128]; /* speech/music clasif. parameters */ + short L_look; /* length of look-ahead */ + float snr_sum_he; /* HE SAD parameters */ + short localVAD_HE_SAD; /* HE SAD parameters */ + short vad_flag_dtx; /* HE-SAD flag with additional DTX HO */ + short vad_flag_cldfb; + float old_cor; + short uc_clas; + float hp_E[2]; /* Energy in HF */ + short noisy_speech_HO, clean_speech_HO, NB_speech_HO; /* SC-VBR HO flags */ + float non_staX; /* unbound non-stationarity for sp/mus clas. */ + short sr_core_tmp; + short L_frame_tmp; + short flag_spitch; + float lsf_new[M], stab_fac; + float band_energies[2*NB_BANDS]; /* energy in critical bands without minimum noise floor E_MIN */ + float enerBuffer[CLDFB_NO_CHANNELS_MAX]; + float currFlatness; + short high_lpn_flag; + short cldfb_addition = 0; + short alw_pitch_lag_12k8[2]; + float alw_voicing[2]; + float fft_buff[2*L_FFT]; + float sp_floor; + short sp_aud_decision0; + short last_core_orig; + short old_pitch1; + + /*------------------------------------------------------------------* + * Initialization + *------------------------------------------------------------------*/ + + localVAD_HE_SAD = 0; + NB_speech_HO = 0; + clean_speech_HO = 0; + noisy_speech_HO = 0; + snr_sum_he = 0; + currFlatness = 0; + + *vad_hover_flag = 0; + uc_clas = VOICED_CLAS; + *sp_aud_decision1 = 0; + *sp_aud_decision2 = 0; + *coder_type = GENERIC; + st->noise_lev = NOISE_LEVEL_SP0; + *attack_flag = 0; + + st->bump_up = 0; + st->ppp_mode = 0; + st->nelp_mode = 0; + st->avoid_HQ_VBR_NB = 0; + + L_look = L_LOOK_12k8; /* 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 */ + mvr2r( st->old_inp_12k8, old_inp_12k8, L_INP_MEM ); + + mvr2r( st->old_wsp, 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; /* save old_cor for speech/music classifier */ + + st->rf_mode = st->Opt_RF_ON; + + last_core_orig = st->last_core; + + /*--------------------------------------------------------------* + * Cldfb analysis + *---------------------------------------------------------------*/ + + st->prevEnergyHF = st->currEnergyHF; + + analysisCldfbEncoder( st, signal_in, input_frame, realBuffer, imagBuffer, enerBuffer ); + + /*----------------------------------------------------------------* + * Change the sampling frequency to 12.8 kHz + *----------------------------------------------------------------*/ + + modify_Fs( signal_in, input_frame, st->input_Fs, new_inp_12k8, 12800, st->mem_decim,(st->max_bwidth == NB) ); + + /* save input resampled at 12.8kHz, non-preemhasised */ + mvr2r( new_inp_12k8, st->buf_speech_enc+L_FRAME32k, L_FRAME ); + + /*------------------------------------------------------------------* + * Perform fixed preemphasis (12.8 kHz signal) through 1 - g*z^-1 + *-----------------------------------------------------------------*/ + + preemph( new_inp_12k8, PREEMPH_FAC, L_FRAME, &st->mem_preemph ); + + /*-------------------------------------------------------------------------* + * Spectral analysis + *--------------------------------------------------------------------------*/ + + analy_sp( inp_12k8, st->Bin_E, st->Bin_E_old, fr_bands, lf_E, Etot, st->min_band, st->max_band, band_energies, PS, fft_buff ); + + /*----------------------------------------------------------------* + * SAD (1-signal, 0-noise) + *----------------------------------------------------------------*/ + + noise_est_pre( *Etot, st->ini_frame, &st->Etot_l, &st->Etot_h, &st->Etot_l_lp, &st->Etot_last, + &st->Etot_v_h2, &st->sign_dyn_lp, st->harm_cor_cnt, &st->Etot_lp ); + + *vad_flag = wb_vad( st, fr_bands, localVAD, &noisy_speech_HO, &clean_speech_HO, &NB_speech_HO, &snr_sum_he, &localVAD_HE_SAD, &(st->flag_noisy_speech_snr) ); + + vad_flag_cldfb = vad_proc( realBuffer, imagBuffer, enerBuffer, st->cldfbAnaEnc->no_channels, &st->vad_st, &cldfb_addition,*vad_flag ); + + if (st->Pos_relE_cnt < 20) /* Ensure the level is high enough and cldfb decision is reliable */ + { + /* Combine decisions from SADS */ + if (*vad_flag == 1 && vad_flag_cldfb == 0) + { + *localVAD = 0; + } + + *vad_flag = vad_flag_cldfb; + } + + + + vad_flag_dtx = dtx_hangover_addition( st, *localVAD, *vad_flag, st->lp_speech-st->lp_noise, cldfb_addition, vad_hover_flag ); + + /*----------------------------------------------------------------* + * NB/WB/SWB/FB bandwidth detector + *----------------------------------------------------------------*/ + + bw_detect( st, signal_in, *localVAD, enerBuffer ); + + /*----------------------------------------------------------------* + * 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( fr_bands, st->bckr, tmpN, tmpE, st->min_band, st->max_band, &st->totalNoise, *Etot, &st->Etot_last, &st->Etot_v_h2 ); + + relE = *Etot - st->lp_speech; + + if (relE > 1.5f) + { + st->Pos_relE_cnt = 0; + } + else if (relE < 0.0f && *vad_flag == 1) + { + st->Pos_relE_cnt++; + } + corr_shift = correlation_shift( st->totalNoise ); + + /*----------------------------------------------------------------* + * FD-CNG Noise Estimator + *----------------------------------------------------------------*/ + + resetFdCngEnc ( st ); + + perform_noise_estimation_enc( band_energies, enerBuffer, st->hFdCngEnc ); + + /*-----------------------------------------------------------------* + * Select SID or FRAME_NO_DATA frame if DTX enabled + *-----------------------------------------------------------------*/ + + dtx( st, vad_flag_dtx, inp_12k8 ); + + /*----------------------------------------------------------------* + * Adjust FD-CNG Noise Estimator + *----------------------------------------------------------------*/ + + if( (st->last_total_brate != st->total_brate) || (st->last_bwidth != st->bwidth) ) + { + configureFdCngEnc( st->hFdCngEnc, st->bwidth, st->rf_mode&& st->total_brate==13200? 9600: st->total_brate ); + } + if ( st->hFdCngEnc != NULL && st->Opt_DTX_ON ) + { + AdjustFirstSID( st->hFdCngEnc->hFdCngCom->npart, st->hFdCngEnc->msPeriodog, st->hFdCngEnc->energy_ho, + st->hFdCngEnc->msNoiseEst, st->hFdCngEnc->msNoiseEst_old, &(st->hFdCngEnc->hFdCngCom->active_frame_counter), st ); + } + + /*----------------------------------------------------------------* + * Reconfigure Mode 2 + *----------------------------------------------------------------*/ + + if ( st->codec_mode == MODE2 ) + { + SetModeIndex( st, st->total_brate, st->bwidth ); + } + + calcLoEnvCheckCorrHiLo( st->cldfbAnaEnc->no_col, freqTable, st->tecEnc.loBuffer, st->tecEnc.loTempEnv, + st->tecEnc.loTempEnv_ns, st->tecEnc.hiTempEnv, &(st->tecEnc.corrFlag) ); + + /*---------------------------------------------------------------* + * Time Domain Transient Detector + *---------------------------------------------------------------*/ + + 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; + alw_pitch_lag_12k8[1] = st->old_pitch_la; + alw_voicing[0] = st->old_voicing_la; + alw_voicing[1] = st->old_voicing_la; + + analy_lp( inp_12k8, L_FRAME, L_look, ener, A, epsP, lsp_new, lsp_mid, st->lsp_old1, alw_pitch_lag_12k8, alw_voicing, 12800 ); + + lsp2lsf( lsp_new, lsf_new, M, 12800 ); + stab_fac = lsf_stab( lsf_new, st->lsf_old1, 0, L_FRAME ); + mvr2r( lsf_new, st->lsf_old1, M ); + + /*----------------------------------------------------------------* + * Compute weighted input (for OL pitch analysis) + * OL pitch analysis + * stable high pitch detection + * 1/4 pitch precision improvement + *----------------------------------------------------------------*/ + + find_wsp( L_FRAME, L_SUBFR, NB_SUBFR, A, Aw, inp_12k8, TILT_FAC, wsp, &st->mem_wsp, GAMMA1, L_look ); + + if( *vad_flag == 0 ) + { + /* reset the OL pitch tracker memories during inactive frames */ + pitch_ol_init( &st->old_thres, &st->old_pitch, &st->delta_pit, &st->old_corr ); + } + + pitch_ol( pitch, voicing, &st->old_pitch, &st->old_corr, corr_shift, &st->old_thres, &st->delta_pit, + st->old_wsp2, wsp, st->mem_decim2, relE, L_look, st->clas, st->input_bwidth, st->Opt_SC_VBR ); + + /* Updates for adaptive lag window memory */ + st->old_pitch_la = pitch[2]; + st->old_voicing_la = voicing[2]; + + /* Detection of very short stable pitch period (MODE1 bit-rates) */ + StableHighPitchDetect( &flag_spitch, pitch, voicing, st->Bin_E, wsp, *localVAD, &st->voicing_sm, &st->voicing0_sm, + &st->LF_EnergyRatio_sm, &st->predecision_flag, &st->diff_sm, &st->energy_sm ); + + /* 1/4 pitch precision improvement */ + if( st->total_brate <= ACELP_24k40 ) + { + pitch_ol2( PIT_MIN_EXTEND, pitch[0], &pitch_fr[0], &voicing_fr[0], 0, wsp, 7 ); + pitch_ol2( PIT_MIN_EXTEND, pitch[0], &pitch_fr[1], &voicing_fr[1], L_SUBFR, wsp, 7 ); + pitch_ol2( PIT_MIN_EXTEND, pitch[1], &pitch_fr[2], &voicing_fr[2], 2*L_SUBFR, wsp, 7 ); + pitch_ol2( PIT_MIN_EXTEND, pitch[1], &pitch_fr[3], &voicing_fr[3], 3*L_SUBFR, wsp, 7 ); + } + else + { + pitch_fr[0] = pitch[0]; + pitch_fr[1] = pitch[0]; + pitch_fr[2] = pitch[1]; + pitch_fr[3] = pitch[1]; + + voicing_fr[0] = voicing[0]; + voicing_fr[1] = voicing[0]; + voicing_fr[2] = voicing[1]; + voicing_fr[3] = voicing[1]; + } + + old_pitch1 = st->pitO; + + /*------------------------------------------------------------------* + * Update estimated noise energy and voicing cut-off frequency + *-----------------------------------------------------------------*/ + + noise_est( st, tmpN, pitch, voicing, epsP, *Etot, relE, corr_shift, tmpE, fr_bands, &cor_map_sum, + &sp_div, &non_staX, &loc_harm, lf_E, &st->harm_cor_cnt, st->Etot_l_lp, &sp_floor ); + + /*------------------------------------------------------------------* + * Update parameters used in the VAD and DTX + *-----------------------------------------------------------------*/ + + vad_param_updt( st, pitch, voicing, old_pitch1, corr_shift, A ); + + /*-----------------------------------------------------------------* + * Find spectral tilt + * UC and VC frame selection + *-----------------------------------------------------------------*/ + + find_tilt( fr_bands, st->bckr, ee, pitch, voicing, lf_E, corr_shift, st->input_bwidth, + st->max_band, hp_E, st->codec_mode, &(st->bckr_tilt_lt), st->Opt_SC_VBR); + + *coder_type = find_uv( st, pitch_fr, voicing_fr, voicing, inp_12k8, *localVAD, ee, + corr_shift, relE, *Etot, hp_E, &flag_spitch, st->voicing_sm, last_core_orig ); + + /*-----------------------------------------------------------------* + * channel aware mode configuration * + *-----------------------------------------------------------------*/ + + if( !st->Opt_RF_ON ) + { + st->rf_mode = 0; + st->rf_target_bits_write = 0; + } + else if( st->rf_mode && st->core_brate != FRAME_NO_DATA && st->core_brate != 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 = signal_clas( st, coder_type, voicing, inp_12k8, *localVAD, pitch, ee, relE, L_look, &uc_clas ); + + st->Local_VAD = *localVAD; + + /*----------------------------------------------------------------* + * Speech/music classification + * AC frame selection + *----------------------------------------------------------------*/ + + speech_music_classif( st, &sp_aud_decision0, sp_aud_decision1, sp_aud_decision2, new_inp_12k8, inp_12k8, *vad_flag, + *localVAD, localVAD_HE_SAD, pitch, voicing, lsp_new, cor_map_sum, epsP, PS, + *Etot, old_cor, coder_type, attack_flag, non_staX, relE, &high_lpn_flag, flag_spitch ); + + long_enr( st, *Etot, localVAD_HE_SAD, high_lpn_flag ); + + /*----------------------------------------------------------------* + * Final VAD correction ( when HE-SAD is used instead of the normal VAD, + * rewrite the VAD flag by VAD flag with DTX hangover for further processing) + *----------------------------------------------------------------*/ + + if( st->Opt_DTX_ON ) + { + *vad_flag = vad_flag_dtx; + } + + /*----------------------------------------------------------------* + * Selection of internal ACELP Fs (12.8 kHz or 16 kHz) + *----------------------------------------------------------------*/ + + if( st->codec_mode == MODE1 ) + { + if( st->core_brate == FRAME_NO_DATA ) + { + /* prevent "L_frame" changes in CNG segments */ + st->L_frame = st->last_L_frame; + } + else if( st->core_brate == SID_2k40 && st->bwidth >= WB && st->first_CNG && st->act_cnt2 < MIN_ACT_CNG_UPD ) + { + /* prevent "L_frame" changes in SID frame after short segment of active frames */ + st->L_frame = st->last_CNG_L_frame; + } + else if( ( st->core_brate == SID_2k40 && st->total_brate >= ACELP_9k60 && ((st->bwidth == WB && !( st->total_brate == ACELP_13k20 && st->cng_type == FD_CNG )) || (st->cng_type == LP_CNG && st->bwidth > WB && st->total_brate >= ACELP_16k40)) ) || + ( st->total_brate > ACELP_24k40 && st->total_brate < HQ_96k ) || ( st->total_brate == ACELP_24k40 && st->bwidth >= WB ) ) + { + st->L_frame = L_FRAME16k; + } + else + { + st->L_frame = L_FRAME; + } + + if( st->ini_frame == 0 ) + { + /* avoid switching of internal ACELP Fs in the very first frame */ + st->last_L_frame = st->L_frame; + } + + if( st->L_frame == L_FRAME ) + { + st->gamma = GAMMA1; + st->preemph_fac = PREEMPH_FAC; + } + else + { + st->gamma = GAMMA16k; + st->preemph_fac = PREEMPH_FAC_16k; + } + + st->sr_core = 50*st->L_frame; + st->encoderLookahead_enc = NS2SA(st->sr_core, ACELP_LOOK_NS); + st->encoderPastSamples_enc = (st->L_frame*9)>>4; + } + + /*-----------------------------------------------------------------* + * coder_type rewriting in case of switching + * IC frames selection + * enforce TC frames in case of switching + *-----------------------------------------------------------------*/ + + if( st->codec_mode == MODE1 ) + { + /* enforce TRANSITION frames */ + if( st->last_L_frame != st->L_frame && st->core_brate != FRAME_NO_DATA && st->core_brate != SID_2k40 && (st->coder_type_raw != VOICED) ) + { + /* enforce TC frame in case of ACELP@12k8 <-> ACELP@16k core switching */ + *coder_type = TRANSITION; + } + else if( st->last_core == HQ_CORE || st->last_core == TCX_10_CORE || st->last_core == TCX_20_CORE ) + { + /* enforce TC frame in case of HQ -> ACELP core switching */ + *coder_type = TRANSITION; + } + else if( st->last_core_brate <= SID_2k40 && st->cng_type == FD_CNG ) + { + /* enforce TC frame in case of FD_CNG -> ACELP switching (past excitation not available) */ + *coder_type = TRANSITION; + } + + /* select INACTIVE frames */ + else if( st->total_brate <= ACELP_24k40 && *vad_flag == 0 ) + { + /* inactive frames will be coded by GSC technology */ + /* except for the VBR mode. VBR mode uses NELP for that */ + if( !( st->Opt_SC_VBR && vad_flag_dtx) ) + { + *coder_type = INACTIVE; + st->noise_lev = NOISE_LEVEL_SP3; + } + } + else if( st->total_brate > ACELP_24k40 && + ( (*vad_flag == 0 && st->bwidth >= SWB && st->max_bwidth >= SWB) || (*localVAD == 0 && (st->bwidth <= WB || st->max_bwidth <= WB)) ) + ) + { + /* inactive frames will be coded by AVQ technology */ + *coder_type = INACTIVE; + } + } + else /* st->codec_mode == MODE2 */ + { + if( !(*vad_flag) ) + { + *coder_type = INACTIVE; + } + else if( *coder_type > GENERIC ) + { + *coder_type = GENERIC; + } + } + + /*---------------------------------------------------------------* + * SC-VBR - decision about PPP/NELP mode + *---------------------------------------------------------------*/ + + if( st->Opt_SC_VBR ) + { + set_ppp_mode( st, coder_type, noisy_speech_HO, clean_speech_HO, NB_speech_HO, + *localVAD, localVAD_HE_SAD, vad_flag, pitch, *sp_aud_decision1 ); + } + + if ( !st->Opt_AMR_WB && !st->rf_mode ) + { + if ( st->total_brate == ACELP_13k20 || st->total_brate == ACELP_32k ) + { + st->mdct_sw_enable = MODE1; + } + else if ( ACELP_16k40 <= st->total_brate && st->total_brate <= ACELP_24k40 ) + { + st->mdct_sw_enable = MODE2; + } + } + + if( st->codec_mode == MODE1 ) + { + /*---------------------------------------------------------------------* + * Decision matrix (selection of technologies) + *---------------------------------------------------------------------*/ + + decision_matrix_enc( st, *sp_aud_decision1, *sp_aud_decision2, *coder_type, *vad_flag, hq_core_type ); + + /* HQ_CORE/TCX_20_CORE decision */ + if( st->core == HQ_CORE ) /* Decision matrix decided for MDCT coding */ + { + if( (st->bwidth == SWB || st->bwidth == FB) && st->total_brate == ACELP_32k ) + { + /* Select MDCT Core */ + st->core = mdct_classifier( fft_buff, st, *vad_flag, enerBuffer ); + } + if( st->total_brate == ACELP_13k20 && st->bwidth != FB ) + { + MDCT_selector( st, sp_floor, *Etot, cor_map_sum, voicing, enerBuffer, *vad_flag ); + } + } + else + { + MDCT_selector_reset( st ); + } + + /* Switch to MODE2 if TCX_20_CORE */ + if( st->core == TCX_20_CORE ) + { + st->codec_mode = MODE2; + + if ( st->last_codec_mode == MODE1 ) + { + int last_total_brate = st->last_total_brate; + st->last_total_brate = -1; + SetModeIndex( st, st->total_brate, st->bwidth ); + st->last_total_brate = last_total_brate; + } + else + { + SetModeIndex( st, st->total_brate, st->bwidth ); + + st->sr_core = getCoreSamplerateMode2( st->total_brate, st->bwidth, st->rf_mode ); + st->L_frame = st->sr_core / 50; + st->encoderLookahead_enc = NS2SA(st->sr_core, ACELP_LOOK_NS); + st->encoderPastSamples_enc = (st->L_frame*9)>>4; + + if ( st->sr_core == 12800 ) + { + st->preemph_fac = PREEMPH_FAC; + st->gamma = GAMMA1; + } + else + { + st->preemph_fac = PREEMPH_FAC_16k; + st->gamma = GAMMA16k; + } + + st->igf = getIgfPresent( st->total_brate, st->bwidth, st->rf_mode ); + } + + *coder_type = st->coder_type_raw; + + if( *vad_flag == 0 ) + { + *coder_type = INACTIVE; + } + else if( *coder_type > GENERIC ) + { + *coder_type = GENERIC; + } + + st->mdct_sw = MODE1; + } + } + + /*-----------------------------------------------------------------* + * Update of ACELP harmonicity counter (used in ACELP transform codebook @32kbps) + *-----------------------------------------------------------------*/ + + if( st->total_brate == ACELP_32k && loc_harm == 1 && cor_map_sum > 50 && + st->clas == VOICED_CLAS && *coder_type == GENERIC ) + { + st->last_harm_flag_acelp++; + + if( st->last_harm_flag_acelp > 10 ) + { + st->last_harm_flag_acelp = 10; + } + } + else + { + st->last_harm_flag_acelp = 0; + } + + /*-----------------------------------------------------------------* + * Update audio frames counter (used for UV decision) + *-----------------------------------------------------------------*/ + + if( *coder_type == AUDIO ) + { + st->audio_frame_cnt += AUDIO_COUNTER_STEP; + } + else if (*coder_type != INACTIVE) + { + st->audio_frame_cnt--; + } + + if( st->audio_frame_cnt > AUDIO_COUNTER_MAX ) + { + st->audio_frame_cnt = AUDIO_COUNTER_MAX; + } + + if( st->audio_frame_cnt < 0 ) + { + st->audio_frame_cnt = 0; + } + + /*-----------------------------------------------------------------* + * Set formant sharpening flag + *-----------------------------------------------------------------*/ + + *sharpFlag = 0; + if( *coder_type == TRANSITION ) + { + if( ( st->total_brate > ACELP_48k && st->bwidth < SWB ) || /* Deactivate for core bitrates higher than 48.0 kb/s */ + ( st->total_brate >= ACELP_13k20 && st->total_brate <= ACELP_16k40 ) || /* Deactivate for bitrates <13.2, 16.4> kb/s (this is basically due to lack of signaling configurations */ + ( st->total_brate > ACELP_16k40 && st->lp_noise > FORMANT_SHARPENING_NOISE_THRESHOLD ) ) /* Deactivate for bitrates >= 24.4 kb/s if the long-term noise level exceeds 34 dB */ + { + *sharpFlag = 0; + } + else + { + *sharpFlag = 1; + } + } + + if( *coder_type == GENERIC || *coder_type == VOICED ) + { + if( *vad_hover_flag || + ( st->total_brate > ACELP_48k && st->bwidth < SWB ) || /* Deactivate for core bitrates higher than 48.0 kb/s */ + ( st->total_brate >= ACELP_13k20 && st->lp_noise > FORMANT_SHARPENING_NOISE_THRESHOLD + && st->total_brate > CNA_MAX_BRATE) ) /* Deactivate for bitrates >= 13.2 kb/s if the long-term noise level exceeds 34 dB */ + { + *sharpFlag = 0; + } + else + { + *sharpFlag = 1; + } + } + + /* channel-aware mode - due to lack of signalling bit, sharpFlag is 1 always in RF mode */ + if( st->rf_mode && ( *coder_type == VOICED || *coder_type == GENERIC ) ) + { + *sharpFlag = 1; + } + + /*-----------------------------------------------------------------* + * Set voicing flag for HQ FEC + *-----------------------------------------------------------------*/ + + if ( *sp_aud_decision1 == 0 && ( *coder_type == VOICED || *coder_type == GENERIC ) ) + { + *Voicing_flag = 1; + } + else + { + *Voicing_flag = 0; + } + + /*---------------------------------------------------------------* + * Preprocessing at other sampling frequency rate (16/25.6/32kHz) + *----------------------------------------------------------------*/ + + sr_core_tmp = (st->codec_mode == MODE1)? 16000 : max(16000,st->sr_core); /* indicates the ACELP sampling rate */ + L_frame_tmp = (st->codec_mode == MODE1)? L_FRAME16k : max(L_FRAME16k,st->L_frame); + + L_look = NS2SA(sr_core_tmp, ACELP_LOOK_NS); /* lookahead at other sampling rate (16kHz, 25.6kHz, 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 */ + mvr2r( st->old_inp_16k, old_inp_16k, L_INP_MEM ); + + /*---------------------------------------------------------------* + * Change the sampling frequency to 16/25.6/32 kHz + *----------------------------------------------------------------*/ + + if( st->input_Fs == sr_core_tmp ) + { + /* no resampling needed, only delay adjustment to account for the FIR resampling delay */ + delay = NS2SA(st->input_Fs, DELAY_FIR_RESAMPL_NS); + mvr2r( st->mem_decim16k + delay, new_inp_16k, delay ); + mvr2r( signal_in, new_inp_16k + delay, input_frame - delay ); + mvr2r( signal_in + input_frame - 2*delay, st->mem_decim16k, 2*delay ); + } + else if( st->input_Fs == 32000 || st->input_Fs == 48000 ) + { + modify_Fs( signal_in, input_frame, st->input_Fs, new_inp_16k, sr_core_tmp, st->mem_decim16k, 0 ); + } + else /* keep memories up-to-date in case of bit-rate switching */ + { + /* no resampling needed, only delay adjustment to account for the FIR resampling delay */ + delay = NS2SA(st->input_Fs, DELAY_FIR_RESAMPL_NS); + mvr2r( st->mem_decim16k + delay, new_inp_16k, delay ); + mvr2r( signal_in, new_inp_16k + delay, input_frame - delay ); + mvr2r( signal_in + input_frame - 2*delay, st->mem_decim16k, 2*delay ); + } + + if( sr_core_tmp == 16000 ) + { + /* save input resampled at 16kHz, non-preemhasised */ + mvr2r( new_inp_16k, new_inp_resamp16k, L_FRAME16k ); + } + else if( sr_core_tmp > 16000 ) + { + /* reset the buffer, the signal is needed for WB BWEs */ + set_f( new_inp_resamp16k, 0.0f, L_FRAME16k ); + } + + /*------------------------------------------------------------------* + * Perform fixed preemphasis (16kHz signal) through 1 - g*z^-1 + *-----------------------------------------------------------------*/ + + if( (st->tcxonly == 0 || st->codec_mode == MODE1) && st->input_Fs > 8000 ) + { + st->mem_preemph_enc = new_inp_16k[L_frame_tmp-1]; + } + + if( st->input_Fs > 8000 && sr_core_tmp == 16000 ) + { + preemph( new_inp_16k, PREEMPH_FAC_16k, L_FRAME16k, &(st->mem_preemph16k) ); + } + else if( st->input_Fs > 8000 ) /* keep memory up-to-date in case of bit-rate switching */ + { + st->mem_preemph16k = new_inp_16k[L_frame_tmp-1]; + } + + /*-----------------------------------------------------------------* + * Redo LP analysis at 16kHz if ACELP@16k core was selected + * update buffers + *-----------------------------------------------------------------*/ + + if( ( ((st->tcxonly == 0) || !(st->core_brate != FRAME_NO_DATA && st->core_brate != SID_2k40)) && st->L_frame == L_FRAME16k && st->codec_mode == MODE2 ) || + ( st->L_frame == L_FRAME16k && st->codec_mode == MODE1 ) ) + { + /* update signal buffers */ + mvr2r( new_inp_resamp16k, st->buf_speech_enc+L_FRAME16k, L_FRAME16k ); + mvr2r( new_inp_16k, st->buf_speech_enc_pe+L_FRAME16k, L_FRAME16k ); + + /*--------------------------------------------------------------* + * LPC analysis + *---------------------------------------------------------------*/ + + if( st->last_L_frame == L_FRAME && st->codec_mode == MODE1 ) + { + /* this is just an approximation, but it is sufficient */ + mvr2r( st->lsp_old1, st->lspold_enc, M ); + } + + analy_lp( inp_16k, L_FRAME16k, L_look, ener, A, epsP, lsp_new, lsp_mid, st->lspold_enc, pitch, voicing, 16000 ); + + /*--------------------------------------------------------------* + * Compute Weighted Input + *---------------------------------------------------------------*/ + + if( st->codec_mode == MODE2 ) + { + find_wsp( L_FRAME16k, L_SUBFR, st->nb_subfr, A, Aw, st->speech_enc_pe, PREEMPH_FAC_16k, st->wspeech_enc, &st->mem_wsp_enc, st->gamma, L_LOOK_16k ); + } + else + { + weight_a_subfr( NB_SUBFR16k, A, Aw, GAMMA16k, M ); + } + + } + else + { + /* update signal buffers */ + mvr2r( new_inp_12k8, st->buf_speech_enc_pe+st->L_frame, L_FRAME ); + mvr2r( st->buf_speech_enc+L_FRAME32k, st->buf_speech_enc+st->L_frame, L_FRAME ); + + if( st->tcxonly == 0 ) + { + mvr2r( wsp, st->wspeech_enc, L_FRAME + L_LOOK_12k8 ); + } + } + + /*-----------------------------------------------------------------* + * ACELP/TCX20 Switching Decision + *-----------------------------------------------------------------*/ + + if( st->codec_mode == MODE2 ) + { + if( st->core_brate != FRAME_NO_DATA && st->core_brate != 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 ); + } + + if( st->mdct_sw_enable == MODE2 && !st->rf_mode ) + { + if (st->core == TCX_20_CORE) /* Switching only possible from TCX_20 frames, not from TCX_10 frames */ + { + /* Select MDCT Core */ + if( (st->bwidth == SWB || st->bwidth == FB) && st->total_brate == ACELP_24k40 ) + { + st->core = mdct_classifier( fft_buff, st, *vad_flag, enerBuffer ); + } + + if( st->total_brate == ACELP_16k40 && st->bwidth != FB ) + { + MDCT_selector( st, sp_floor, *Etot, cor_map_sum, voicing, enerBuffer, *vad_flag ); + } + } + else + { + MDCT_selector_reset( st ); + } + + /* Do the switching that was decided in the MDCT selector */ + if( st->core == HQ_CORE ) + { + st->codec_mode = MODE1; + st->mdct_sw = MODE2; + } + else if( st->last_codec_mode == MODE1 && st->last_core == HQ_CORE ) + { + int L_frame_old = st->last_L_frame; + st->last_L_frame = st->L_frame; + SetModeIndex( st, st->total_brate, st->bwidth ); + st->last_L_frame = L_frame_old; + } + } + + /*--------------------------------------------------------------* + * TCX mode decision + *---------------------------------------------------------------*/ + + SetTCXModeInfo( st, &st->transientDetection, &st->tcx_cfg.tcx_curr_overlap_mode ); + } + + /*-----------------------------------------------------------------* + * Updates + *-----------------------------------------------------------------*/ + + /* update old weighted speech buffer - for OL pitch analysis */ + mvr2r( &old_wsp[L_FRAME], st->old_wsp, L_WSP_MEM ); + + /* update old input signal buffer */ + mvr2r( &old_inp_12k8[L_FRAME], st->old_inp_12k8, L_INP_MEM ); + + /* update old input signal @16kHz buffer */ + if( st->input_Fs > 8000 && sr_core_tmp == 16000 ) + { + mvr2r( &old_inp_16k[L_frame_tmp], st->old_inp_16k, L_INP_MEM ); + } + else if( st->input_Fs > 8000 ) + { + lerp( st->old_inp_12k8+L_INP_MEM-L_INP_MEM*4/5, st->old_inp_16k, L_INP_MEM, L_INP_MEM*4/5 ); + } + + if( (sr_core_tmp == 16000) && st->tcxonly && st->codec_mode == MODE2 ) + { + /* copy input resampled at 16kHz, non-preemhasised */ + mvr2r( new_inp_resamp16k, new_inp_16k, L_FRAME16k ); + } + + /* update of old per-band energy spectrum */ + mvr2r( fr_bands + NB_BANDS, st->enrO, NB_BANDS ); + + /* set the pointer of the current frame for the ACELP core */ + if ( st->L_frame == L_FRAME ) + { + *inp = inp_12k8; + } + else + { + *inp = inp_16k; + } + + + return; +} diff --git a/lib_enc/pvq_core_enc.c b/lib_enc/pvq_core_enc.c new file mode 100644 index 000000000..3a4aae560 --- /dev/null +++ b/lib_enc/pvq_core_enc.c @@ -0,0 +1,511 @@ + +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "wmc_auto.h" +#include +#include +#include "options.h" +#include "rom_com.h" +#include "prot.h" +#include "prot.h" +#include "stl.h" + +/*-------------------------------------------------------------------* +* Local functions +*--------------------------------------------------------------------*/ + +static short calc_pvq_splits( Encoder_State *st, const short band_bits, const short sfmsize, const float *y, short *bits ); +static void obtainEnergyParameter( float Enear, float Eopp, short *param); + +static void densityIndexSymbolEncode( Encoder_State *st, short density , short r_dim, short l_dim , short index_phi); + +/*-------------------------------------------------------------------* +* pvq_encode_band() +* +* Encode band with PVQ +*--------------------------------------------------------------------*/ + +static void pvq_encode_band( + Encoder_State *st, + const float *coefs_norm, + short *pulse_vector, + short *npulses, + float *coefs_quant, + const short sfmsize, + const short band_bits, + short *bits_left, + const short strict_bits +) +{ + short K_val; + short j, Np; + float enr, E_part[MAX_SPLITS+1]; + short part_start[MAX_SPLITS+1], dim_part[MAX_SPLITS+1], bits_part[MAX_SPLITS+1]; + short pool_tot, pool_part, dim_parts; + float g_part[MAX_SPLITS]; + short g_part_s[MAX_SPLITS]; + short sg_part[MAX_SPLITS+1]; + short idx_sort[MAX_SPLITS+1]; + short js, band_bits_tot, split_bit; + + Np = calc_pvq_splits(st, band_bits, sfmsize, coefs_norm, &split_bit); + band_bits_tot = band_bits - split_bit; + + enr = 0.0f; + for(j = 0; j 1) + { + encode_energies( st, coefs_norm, Np, dim_part, E_part, bits_part, g_part_s, band_bits_tot, bits_left, enr, sfmsize, strict_bits ); + } + else + { + bits_part[0] = band_bits_tot; + } + + pool_tot = 0; + pool_part = 0; + + for (j = 0; j < Np; j++) + { + g_part[j] = -((float)g_part_s[j])/32768; + g_part_s[j] = -g_part_s[j]; + } + + srt_vec_ind(g_part_s,sg_part,idx_sort,Np); + for(j = 0; j < Np; j++) + { + js = idx_sort[Np-1-j]; + + + pool_part = shrtCDivSignedApprox(pool_tot, Np-j); + bits_part[js] = max(0, min(bits_part[js]+pool_part, 256)); + + conservativeL1Norm(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 >= 1 ) + { + pvq_encode(st, coefs_norm + part_start[js], pulse_vector + part_start[js], + coefs_quant + part_start[js], K_val, dim_part[js], g_part[js]); + } + else + { + set_f(coefs_quant + part_start[js],0.0f,dim_part[js]); + set_s(pulse_vector + part_start[js],0,dim_part[js]); + } + } + + return; +} + +/*-------------------------------------------------------------------* +* pvq_encode_frame() +* +* +*--------------------------------------------------------------------*/ + +void pvq_encode_frame( + Encoder_State *st, + const float *coefs_norm, /* i : normalized coefficients to encode */ + float *coefs_quant, /* o : quantized coefficients */ + float *gopt, /* o : optimal shape gains */ + short *npulses, /* o : number of pulses per band */ + short *pulse_vector, /* o : non-normalized pulse shapes */ + const short *sfm_start, /* i : indices of first coefficients in the bands */ + const short *sfm_end, /* i : indices of last coefficients in the bands */ + const short *sfmsize, /* i : band sizes */ + const short nb_sfm, /* i : total number of bands */ + const short *R, /* i : bitallocation per band (Q3)*/ + const short pvq_bits, /* i : number of bits avaiable */ + const short core /* i : core */ +) +{ + short i, j; + short band_bits, bits_left; + short bit_pool = 0; + short coded_bands, bands_to_code; + short curr_bits; + short R_sort[NB_SFM]; /*Q3*/ + short is, i_sort[NB_SFM]; + short strict_bits; + + rc_enc_init(st, pvq_bits); + curr_bits = (pvq_bits - RC_BITS_RESERVED)<<3; + + bands_to_code = 0; + for (i = 0; i < nb_sfm; i++) + { + if (R[i] > 0) + { + bands_to_code++; + } + } + + if (core == ACELP_CORE) + { + strict_bits = 1; + srt_vec_ind (R, R_sort, i_sort, nb_sfm); + } + else + { + strict_bits = 0; + for(i=0; i 0) + { + bandBitsAdjustment(st->rc_num_bits, st->rc_range, curr_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( st, &coefs_norm[sfm_start[is]], &pulse_vector[sfm_start[is]], + &npulses[is], &coefs_quant[sfm_start[is]], sfmsize[is], band_bits, + &bits_left, strict_bits); + gopt[is] = dotp(coefs_quant+sfm_start[is], coefs_norm+sfm_start[is], sfmsize[is]) / + (dotp(coefs_quant+sfm_start[is], coefs_quant+sfm_start[is], sfmsize[is]) + 1e-15f); + if (gopt[is] == 0.0f) + { + gopt[is] = 1e-10f; + } + /* Updates */ + coded_bands++; + } + else + { + for (j = sfm_start[is]; j < sfm_end[is]; j++) + { + coefs_quant[j] = 0.0f; + pulse_vector[j] = 0; + } + } + } + + rc_enc_finish(st); + + return; +} + +/*---------------------------------------------------------------------* + * pvq_core_enc() + * + * Main Generic Audio Encoder Routine + *---------------------------------------------------------------------*/ + +short pvq_core_enc ( + Encoder_State *st, + float coefs_norm[], + float coefs_quant[], + short bits_tot, /* total number of bits */ + short nb_sfm, + const short *sfm_start, + const short *sfm_end, + const short *sfmsize, + short *R, + short *Rs, + short *npulses, + short *maxpulse, + const short core +) +{ + short i; + short R_upd; /*Q3*/ + short ord[NB_SFM_MAX]; + float fg_pred[NB_SFM_MAX]; + short pvq_bits; + short pulse_vector[L_FRAME48k]; + float gopt[NB_SFM]; + short gain_bits_array[NB_SFM]; + short gain_bits_tot; + + R_upd = bits_tot * 8; + gain_bits_tot = assign_gain_bits( core, nb_sfm, sfmsize, R, gain_bits_array, &R_upd ); + pvq_bits = R_upd >> 3; + pvq_encode_frame( st, coefs_norm, coefs_quant, gopt, npulses, pulse_vector, + sfm_start, sfm_end, sfmsize, nb_sfm, R, pvq_bits, core ); + bits_tot = pvq_bits + gain_bits_tot; + + + + if( Rs != NULL ) + { + for(i=0; i 0); /* Update Rs in case no pulses were assigned */ + } + } + + for(i=0; i 0); /* Update in case no pulses were assigned */ + } + + get_max_pulses( sfm_start, sfm_end, ord, npulses, nb_sfm, pulse_vector, maxpulse ); + + fine_gain_pred( sfm_start, sfm_end, sfmsize, ord, npulses, maxpulse, R, nb_sfm, + coefs_quant, pulse_vector, fg_pred, core); + + fine_gain_quant(st, ord, nb_sfm, gain_bits_array, fg_pred, gopt); + + apply_gain(ord, sfm_start, sfm_end, nb_sfm, fg_pred, coefs_quant); + + return bits_tot; +} + + +/*-------------------------------------------------------------------* +* encode_energies() +* +* +*--------------------------------------------------------------------*/ + +void encode_energies( + Encoder_State *st, + const float *coefs, + short Np, + short *dim_part, + float *E_part, + short *bits_part, + short *g_part, + short qband, + + short *bits_left, + float enr, + short dim, + const short strict_bits +) +{ + short i, j, l_Np, r_Np; + short l_bits, r_bits, l_dim, r_dim; + float l_enr, r_enr; + short il, ir; + short oppRQ3, qzero; + short density; + short phi; + short index_phi=-1; + + l_Np = Np>>1; + r_Np = Np-l_Np; + + l_enr = 0.0f; + l_bits = 0; + l_dim = 0; + for(i=0; irc_num_bits, st->rc_range, &qzero); + densityAngle2RmsProjEnc(density, phi , &index_phi, &ir, &il, &oppRQ3); + densityIndexSymbolEncode(st, density, r_dim, l_dim, index_phi); + + for(i = 0; i> 15; + } + + for(i = l_Np; i> 15; + } + NearOppSplitAdjustment( qband, qzero, st->rc_num_bits, st->rc_range, *bits_left, + strict_bits, Np, dim_part[0], dim_part[Np-1], + l_dim, r_dim, oppRQ3, + &l_bits, &r_bits, bits_left); + if(l_Np > 1) + { + encode_energies( st, 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; + bits_part[0] = l_bits; + } + if(r_Np > 1) + { + encode_energies( st, &coefs[l_dim], 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; + bits_part[1] = r_bits; + } + return; +} + +static void densityIndexSymbolEncode(Encoder_State *st, + short density , + short opp_sz, + short near_sz , + short index_phi) +{ + short angle, c ; + int sym_freq = 1, cum_freq, tot; + short densityPlOne , densitySubC; + short densitySubIndex,nearFlag; + + if ((0xFFFE&density) != 0 ) /* even */ + { + 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); + + densityPlOne = 1 + density; + densitySubC = density - c; + + tot = 2 + density*densityPlOne; /* c==0, c==density*/ + sym_freq = 1 + 2*index_phi ; /* c==density */ + cum_freq = index_phi*index_phi; /* c==density*/ + + if (c == 0) + { + sym_freq = 2*densityPlOne - sym_freq; + cum_freq = 2*index_phi*(densityPlOne) - cum_freq; + } + else if( densitySubC != 0 ) /* c n.eq. density */ + { + densitySubIndex = density - index_phi; + nearFlag = (index_phi <= c); + + tot = densityPlOne + density*c*(densitySubC); + sym_freq = nearFlag ? ( 1 + 2*index_phi*densitySubC ) : ( 1 + 2*densitySubIndex*c ); + cum_freq = nearFlag ? ( index_phi*((index_phi-1)*densitySubC + 1)) : + ( tot - densityPlOne - densitySubIndex*(densitySubIndex+1)*c + index_phi); + } + /* else keep values for c==density*/ + rc_encode(st, cum_freq, sym_freq, tot); + } + + return; +} + + +/*--------------------------------------------------------------------------* + * calc_pvq_splits() + * + * Calculate the number of segments needed + *--------------------------------------------------------------------------*/ + +static short calc_pvq_splits( /* o : Number of segments */ + Encoder_State *st, /* i/o: Encoder state */ + const short band_bits, /* i : Band bit rate */ + const short sfmsize, /* i : Band width */ + const float *y, /* i : Target vector */ + short *bits /* o : Consumed bits */ +) +{ + short Np; + short Npart; + short i,j,k; + float E[MAX_SPLITS]; + float Emean; + float tmp; + float max_dev; + Np = (short)(intLimCDivPos( (int)band_bits, 67)>>2); + if (band_bits - 268*Np != 0 || Np == 0 ) /* L_msu */ + { + Np++; /* ceil */ + } + *bits = 0; + + if ( Np < MAX_SPLITS && (band_bits - (8*sfmsize * THR_ADD_SPLIT ) > 0)) + { + Npart = (short) intLimCDivPos( (int)sfmsize, Np); + *bits = 8; + Emean = 0; + k = 0; + for ( i = 0; i < Np; i++) + { + E[i] = EPSILON; + for (j = 0; j < Npart; j++, k++) + { + E[i] += y[k]*y[k]; + } + E[i] = 30 - norm_l(max((int)E[i], 1)); /* a 0 input integer Ei yields a zeroed log2(Ei) out */ + Emean += E[i]; + } + Emean /= Np; + + max_dev = -1; + for ( i = 0; i < Np; i++) + { + tmp = (float)fabs(E[i] - Emean); + if ( tmp > max_dev ) + { + max_dev = tmp; + } + } + + if ( max_dev > (32 - band_bits/(8*Np)) ) + { + rc_enc_bits(st, 1, 1); + Np += 1; + } + else + { + rc_enc_bits(st, 0, 1); + } + } + + Np = max(Np, (short)(ceil((float)sfmsize/PVQ_MAX_BAND_SIZE))); + Np = min(MAX_SPLITS, Np); + Np = min((short)floor((float)sfmsize/MIN_BAND_SIZE), Np); + return Np; +} + + +#define EPSILON_obtainEnergyParameter 0.00373f /**/ +#define C_obtainEnergyParameter ((float)(1 << 15) / EVS_PI + EPSILON_obtainEnergyParameter) + +void obtainEnergyParameter( + float Enear, + float Eopp, + short *param +) +{ + if (!Eopp) + { + *param=0; + return; + } + if (!Enear) + { + *param = 1 << 14; + return; + } + *param = (short) (C_obtainEnergyParameter * atan2( (float)sqrt(Eopp) , (float) sqrt(Enear)) + 0.5f); + return; +} +#undef C_obtainEnergyParameter +#undef EPSILON_obtainEnergyParameter diff --git a/lib_enc/pvq_encode.c b/lib_enc/pvq_encode.c new file mode 100644 index 000000000..6691728a7 --- /dev/null +++ b/lib_enc/pvq_encode.c @@ -0,0 +1,162 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "prot.h" +#include "rom_com.h" +#include "prot.h" +#include "math.h" + +static void pyramidSearch(const float *s, short L, short Ptot, float A, short *ztak, float *stak ) ; + +void pvq_encode( + Encoder_State *st, + const float *x, /* i: vector to quantize */ + short *y, /* o: quantized vector (non-scaled int)*/ + float *xq, /* o: quantized vector (scaled float) */ + const short pulses, /* i: number of allocated pulses */ + const short dim, /* i: Length of vector */ + const float gain /* i: Gain */ +) +{ + PvqEntry entry; + + pyramidSearch(x, dim, pulses, gain, y, xq ); + + entry = mpvq_encode_vec(y, dim, pulses); + if(dim != 1) + { + rc_enc_bits(st, (unsigned int)entry.lead_sign_ind, 1); + rc_enc_uniform(st, entry.index, entry.size); + } + else + { + rc_enc_bits(st, (unsigned int)entry.lead_sign_ind, 1); + } + return; + +} + +static float L1norm( + const float *s, + float *abso_s, + short *sign_s, + short L +) +{ + int i; + float ftmp, r = 0.0f; + + for( i=0; i < L; i++ ) + { + ftmp = s[i]; + sign_s[i] = (short)sign(ftmp); + abso_s[i] = fabs(ftmp); + r += abso_s[i]; + } + return r; +} + + +void pyramidSearch(const float *s, + short L, + short Ptot, + float A, + short *ztak, + float *stak + ) +{ + short i, high_pulse_dens; + short z[PVQ_MAX_BAND_SIZE]; + float sL1; + float energy,xcorr; + short P; + float energy1,energy2; + float xcorr1sq, xcorr2sq ; + float zscale, sscale; + float abso_s[PVQ_MAX_BAND_SIZE]; + short sign_s[PVQ_MAX_BAND_SIZE]; + short n = 0; + + high_pulse_dens = Ptot > (short )(0.501892089843750f * L); + sL1 = L1norm(s, abso_s,sign_s, L ); + if (high_pulse_dens && sL1 > 0 && A>0) + { + P = Ptot - PYR_OFFSET; + zscale = P/sL1; + for(i=0; i < L; i++) + { + z[i] = floor(zscale * abso_s[i]) ; + } + } + else + { + for( i=0; i < L; i++) + { + z[i] = 0; + } + } + + energy = 0.0f; + if (sL1 > 0 && A > 0) + { + xcorr = 0.0f; + P = 0; + for( i = 0; i < L; i++) + { + xcorr += abso_s[i] * z[i]; + energy += z[i] * z[i]; + P += z[i]; + } + energy = 0.5f*energy; + while( P < Ptot) + { + energy += 0.5f; + n = 0; + xcorr1sq = xcorr + abso_s[0]; + xcorr1sq *= xcorr1sq; + energy1 = energy + z[0]; + for( i = 1; i < L; i++) + { + xcorr2sq = xcorr + abso_s[i] ; + xcorr2sq *= xcorr2sq; + energy2 = energy + z[i] ; + + if ((xcorr1sq*energy2) < (xcorr2sq*energy1)) + { + n = i; + xcorr1sq = xcorr2sq; + energy1 = energy2; + } + } + z[n]++; + xcorr += abso_s[n]; + energy = energy1; + P++; + } + } + else + { + if (L > 1) + { + z[0] = (short)(Ptot*0.5f); + z[L-1] = - (Ptot - z[0]); + energy = 0.5f*(z[0] * z[0] + z[L-1] * z[L-1]); + } + else + { + z[0] = Ptot; + energy = 0.5f*(z[0] * z[0]); + } + } + + sscale = (float) A/(float)sqrt(2.0f * energy); + for(i = 0; i < L; i++) + { + ztak[i] = z[i] * sign_s[i]; + stak[i] = sscale * ztak[i] ; + } + return; +} diff --git a/lib_enc/q_gain2p.c b/lib_enc/q_gain2p.c new file mode 100644 index 000000000..7a41fb72f --- /dev/null +++ b/lib_enc/q_gain2p.c @@ -0,0 +1,368 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "prot.h" +#include "cnst.h" +#include "rom_com.h" + + +/*-------------------------------------------------------------------------* + * Local functions * + *-------------------------------------------------------------------------*/ + +static int gain_enc_uv( const float *code, int lcode, float *gain_pit, float *gain_code, + ACELP_CbkCorr *coeff, float *past_gcode, float *gain_inov ); + +static int gain_enc_gacelp_uv( const float *code, const float *code2, int lcode, const float mean_ener, float *gain_pit, float *gain_code, + float *gain_code2, ACELP_CbkCorr *coeff, float *past_gcode, float *gain_inov, short noisy_speech_flag ); + + +/*-------------------------------------------------------------------------* + * procedure q_gain2_plus * + * ~~~~~~~~~~~~~~~~~~~~~~ * + * Quantization of pitch and codebook gains. * + * The following routines is Q_gains updated for AMR_WB_PLUS. * + * MA prediction is removed and MEAN_ENER is now quantized with 2 bits and * + * transmitted once every ACELP frame to the gains decoder. * + * The pitch gain and the code gain are vector quantized and the * + * mean-squared weighted error criterion is used in the quantizer search. * + *-------------------------------------------------------------------------*/ + +void encode_acelp_gains( + float *code, + int gains_mode, + float mean_ener_code, + short clip_gain, + ACELP_CbkCorr *g_corr, + float *gain_pit, + float *gain_code, + int **pt_indice, + float *past_gcode, + float *gain_inov, + int L_subfr, + float *code2, + float *gain_code2, + short noisy_speech_flag +) +{ + int index = 0; + + if (((gains_mode>0) && (gains_mode <4))) + { + /* Memory-less gain coding */ + index = Mode2_gain_enc_mless( code, L_subfr, gain_pit, gain_code, g_corr, mean_ener_code, + clip_gain, past_gcode, gain_inov,gains_mode-1 ); + } + else if (gains_mode == 6) + { + /* UV gains quantizer (6bits/subfr) */ + index = gain_enc_uv(code, L_subfr, gain_pit, gain_code, g_corr, past_gcode, gain_inov ); + } + else if (gains_mode == 7) + { + /* GACELP_UV gains quantizer (7=5-2bits/subfr) */ + index = gain_enc_gacelp_uv(code, code2, L_subfr, mean_ener_code, gain_pit, gain_code,gain_code2, g_corr, past_gcode, gain_inov, noisy_speech_flag ); + } + else + { + fprintf(stderr, "invalid gains coding for acelp!\n"); + assert(0); + } + + **pt_indice = index; + (*pt_indice)++; + + return; +} + +/*---------------------------------------------------------------------* + * procedure Mode2_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 + *---------------------------------------------------------------------*/ + +int Mode2_gain_enc_mless( + const float *code, /* i : algebraic excitation */ + int lcode, /* (i) : Subframe size */ + float *gain_pit, /* o : quantized pitch gain */ + float *gain_code, /* o : quantized codebook gain */ + ACELP_CbkCorr *pcoeff, /* i/o : correlations , -2,, -2 and 2*/ + float mean_ener, /* (i) : mean_ener defined in open-loop (3 bits) */ + const short clip_gain, /* i : gain pitch clipping flag (1 = clipping) */ + float *past_gcode, /* (i/o): past gain of code */ + float *gain_inov, /* (o) : unscaled innovation gain */ + const short coder_type /* (i) : coder type */ +) +{ + short index, i, size,size_clip; + const Word16 *p, *t_qua_gain; + float dist, dist_min, g_pitch, g_code, gcode0, ener_code; + ACELP_CbkCorr coeff; + + /*-----------------------------------------------------------------* + * - calculate the unscaled innovation energy + * - calculate the predicted gain code + *-----------------------------------------------------------------*/ + + if(coder_type == 0) + { + *gain_inov = 1.0f/ (float)sqrt( ( dotp( code, code, lcode ) + 0.01f ) / lcode ); + ener_code = 10 * (float)log10( ( dotp( code, code, lcode ) + 0.01f ) / lcode ); + gcode0 = (float) pow(10, 0.05 * (mean_ener - ener_code)); + } + else + { + ener_code = 0.01F; + for(i=0; i, -2,, -2 and 2 */ + float *past_gcode, /* (i/o): past gain of code */ + float *gain_inov /* (o) : unscaled innovation gain */ +) +{ + short index; + float g_code,g_code_corr,g_code_nrg; + + /*-----------------------------------------------------------------* + * - calculate the unscaled innovation energy + *-----------------------------------------------------------------*/ + + *gain_inov = 1.0f/ (float)sqrt( ( dotp( code, code, lcode ) + 0.01f ) / lcode ); + + g_code_corr = coeff->xy2/(coeff->y2y2*(*gain_inov)); /*Correlation based*/ + + (void) g_code_nrg; + g_code=g_code_corr; + + /*90dB max of gain for 2^15 amplitude code, */ + if( g_code>0.000001f ) + { + index=(int)(((20.f*log10(g_code)+30.f)/1.9f)+0.5f); + + if( index>63 ) + { + index=63; + } + else if(index<0) + { + index=0; + } + } + else + { + index=0; + } + + *gain_code= (float) pow(10.f,(((index*1.9f)-30.f)/20.f)); + *past_gcode=*gain_code; /*unscaled gain*/ + *gain_code *= *gain_inov; /*scaled gain*/ + *gain_pit=0.f; + + return index; +} + +/*---------------------------------------------------------------------* +* procedure gain_enc_gacelp_uv +* 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 +*---------------------------------------------------------------------*/ + +static int gain_enc_gacelp_uv( + const float *code, /* i : algebraic excitation */ + const float *code2, /* i : gaussian excitation */ + int lcode, /* (i) : Subframe size */ + const float mean_ener, /* i : quantized mean energy of the frame */ + float *gain_pit, /* o : quantized pitch gain */ + float *gain_code, /* o : quantized codebook gain */ + float *gain_code2, /* o : quantized codebook gain */ + ACELP_CbkCorr *coeff, /* i/o : correlations , -2,, -2 and 2 */ + float *past_gcode, /* (i/o): past gain of code */ + float *gain_inov /* (o) : unscaled innovation gain */ + ,short noisy_speech_flag /* (i) : noisy speech flag */ +) +{ + short index; + float gcode,gcode2,pred_nrg_frame; + float norm_code2; + short i; + float c, c_index2,c_first; + short index2; + + /*-----------------------------------------------------------------* + * - calculate the unscaled innovation energy + *-----------------------------------------------------------------*/ + + *gain_inov = 1.0f/ (float)sqrt( ( dotp( code, code, lcode ) + 0.01f ) / lcode ); + pred_nrg_frame = (float)pow(10.0,mean_ener/20.0); + gcode=pred_nrg_frame*(*gain_inov); + norm_code2 = 1.0f/ (float)sqrt( ( dotp( code2, code2, lcode ) + 0.01f ) / lcode ); + gcode2=pred_nrg_frame*(norm_code2); + + /*-----------------------------------------------------------------* + * search for the best quantizer + *-----------------------------------------------------------------*/ + + *gain_code = coeff->xy2/(coeff->y2y2*gcode); + + if(*gain_code>0.000001f) + { + index=(int)(((20.f*log10(*gain_code)+20.f)/1.25f)+0.5f); + + if(index>31) + { + index=31; + } + else if(index<0) + { + index=0; + } + } + else + { + index=0; + } + + *gain_code= (float) pow(10.f,(((index*1.25f)-20.f)/20.f)); + *gain_code *= gcode; + + if( noisy_speech_flag ) + { + c_first=0.8f*coeff->xx-(*gain_code)*(*gain_code)*coeff->y2y2; + } + else + { + c_first=coeff->xx-(*gain_code)*(*gain_code)*coeff->y2y2; + } + index2=0; + *gain_code2 = (float) (index2*0.25f+0.25f)*(*gain_code*(gcode2/gcode)); + + c_index2=c_first-(*gain_code2)*(*gain_code2)*coeff->y1y1-2*(*gain_code)*(*gain_code2)*coeff->y1y2; + + for(i=1; i<4; i++) + { + *gain_code2 = (float) (i*0.25f+0.25f)*(*gain_code*(gcode2/gcode)); + + c=c_first-(*gain_code2)*(*gain_code2)*coeff->y1y1-2*(*gain_code)*(*gain_code2)*coeff->y1y2; + + if(fabs(c) +#include "wmc_auto.h" +#include +#include "prot.h" + + +/*-------------------------------------------------------------------* +* qlpc_avq() +* +* +*--------------------------------------------------------------------*/ + +void qlpc_avq( + const float *lsf, /* (i) Input LSF vectors */ + const float *lsfmid, + float *lsf_q, /* (o) Quantized LFS vectors */ + float *lsfmid_q, + int *index, /* (o) Quantization indices */ + int *nb_indices, /* (o) Number of quantization indices */ + int *nbbits, /* (o) Number of quantization bits */ + int core, + float sr_core +) +{ + int i; + float lsfmid_q0[M]; + int *tmp_index, indxt[256], nbits, nbt, nit; + float dummy[M]; + + /* Init */ + tmp_index = &index[0]; + *nb_indices = 0; + + /* Quantize end_frame LPC */ + for (i=0; i= 16) + { + push_next_indice(st, 0xffffU, 16); + nb_bits += 16; + ind -= 16; + } + if (ind > 0) + { + push_next_indice(st, (1U< 4) + { + push_next_indice(st, prm[i], 4); + nbits -= 4; + i++; + } + push_next_indice(st, prm[i], nbits); + i++; + } + + return(i); +} + + +/*-------------------------------------------------------------------* +* encode_lpc_avq() +* +* +*--------------------------------------------------------------------*/ + +int encode_lpc_avq( + Encoder_State *st, + int numlpc, + int *param_lpc, + int mode +) +{ + int k,j; + int q_type, nb_ind; + int i,qn1,qn2,nb,avqBits,st1=0; + int nb_bits; + + j = 0; + nb_bits = 0; + + for (k=0; k3)) + { + i = 3; + } + push_next_indice(st, i, 2); + + i = qn2-2; + + if ((i<0) || (i>3)) + { + i = 3; + } + push_next_indice(st, i, 2); + + /* Unary code for abs and rel LPC0/LPC2 */ + /* Q5 = 0, Q6=10, Q0=110, Q7=1110, ... */ + nb = qn1; + + if (nb > 6) + { + nb -= 3; + } + else if (nb > 4) + { + nb -= 4; + } + else if (nb == 0) + { + nb = 3; + } + else + { + nb = 0; + } + + if (nb > 0) + { + unary_code(nb, st); + } + nb_bits += nb; + + nb = qn2; + + if (nb > 6) + { + nb -= 3; + } + else if (nb > 4) + { + nb -= 4; + } + else if (nb == 0) + { + nb = 3; + } + else + { + nb = 0; + } + + if (nb > 0) + { + unary_code(nb, st); + } + nb_bits += nb; + + avqBits = 4*qn1; + unpack4bits(avqBits, ¶m_lpc[j], st); + j += qn1; + nb_bits += avqBits; + + avqBits = 4*qn2; + unpack4bits(avqBits, ¶m_lpc[j], st); + j += qn2; + nb_bits += avqBits; + } + else + { + 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 000000000..c93d8f2c8 --- /dev/null +++ b/lib_enc/qlpc_stoch.c @@ -0,0 +1,314 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include "rom_enc.h" +#include "basop_proto_func.h" + +/*-------------------------------------------------------------------* +* lpc_quantization() +* +* +*--------------------------------------------------------------------*/ + +void lpc_quantization( + Encoder_State * st, + int core, + int lpcQuantization, + float lsf_old[], + const float lsp[], + const float lspmid[], + float lsp_q[], + float lsf_q[], + float lspmid_q[], + float mem_MA[], + float mem_AR[], + int narrowBand, + short coder_type, + int acelp_midLpc, + int param_lpc[], + int nbits_lpc[], + short *seed_acelp, + int sr_core, + float *Bin_Ener, + float *Bin_Ener_old, + short * bits_param_lpc, + short * no_param_lpc +) +{ + int nb_indices=0; + float lsfmid_q[M]; + short lsfmid_idx; + int i; + float lsf[M], lsfmid[M]; + short force_sf; + + float fec_lsf[M], stab; + + + /****** High-rate LPC quantizer *******/ + if( lpcQuantization == 0 ) + { + lsp2lsf( lsp, lsf, M, sr_core ); + + if( core == TCX_10_CORE ) + { + lsp2lsf( lspmid, lsfmid, M, sr_core ); + } + + qlpc_avq( lsf, lsfmid, lsf_q, lsfmid_q, param_lpc, &nb_indices, nbits_lpc, core, sr_core ); + + lsf2lsp( lsf_q, lsp_q, M, sr_core ); + + if( core == TCX_10_CORE ) + { + lsf2lsp( lsfmid_q, lspmid_q, M, sr_core ); + } + + assert(nb_indices<=NPRM_LPC_NEW); + } + + /****** Low-rate LPC quantizer *******/ + + else if( lpcQuantization == 1 ) + { + + lsp2lsf( lsp, lsf, M, sr_core ); + + force_sf = 0; + /*Force safety net when possible in case of transitions*/ + if( st->tc_cnt >= 1 || st->last_core_brate <= SID_2k40 || st->next_force_safety_net ) + { + force_sf = 1; + st->next_force_safety_net = 0; + } + + if( st->next_force_safety_net == 1 && st->Opt_RF_ON ) + { + force_sf = 1; + st->next_force_safety_net = 0; + } + + if( sr_core == INT_FS_16k && coder_type == UNVOICED ) + { + lsf_end_enc( st, lsf, lsf_q, mem_AR, mem_MA, ENDLSF_NBITS, GENERIC, st->bwidth, Bin_Ener, sr_core, st->core_brate, + &st->streaklimit, &st->pstreaklen, force_sf, 0, 1, param_lpc, no_param_lpc, bits_param_lpc, GENERIC ); + + nb_indices = (int)(*no_param_lpc); + } + else + { + lsf_end_enc( st, lsf, lsf_q, mem_AR, mem_MA, ENDLSF_NBITS, coder_type, st->bwidth, Bin_Ener, sr_core, st->core_brate, + &st->streaklimit, &st->pstreaklen, force_sf, 0, 1, param_lpc, no_param_lpc, bits_param_lpc, coder_type ); + + nb_indices = (int)(*no_param_lpc); + } + + FEC_lsf_estim_enc( st, st->L_frame, fec_lsf ); + + /* FEC - calculate LSF stability */ + stab = lsf_stab( lsf_q, fec_lsf, 0, st->L_frame); + + if (stab < ( STAB_FAC_LIMIT + 0.2 ) && ( coder_type == VOICED || coder_type == GENERIC) && st->Opt_RF_ON ) + { + st->next_force_safety_net = 1; + } + + lsf2lsp( lsf_q, lsp_q, M, sr_core ); + + *nbits_lpc = ENDLSF_NBITS; + } + else + { + assert(0); + } + + *seed_acelp = 0; + for( i=nb_indices-1; i>=0; i-- ) + { + /* rightshift before *seed_acelp+param_lpc[i] to avoid overflows*/ + *seed_acelp=(short)((((*seed_acelp)>>1)+param_lpc[i]) * 31821L + 13849L); + } + + /* Mid-frame LPC quantization */ + if( lpcQuantization && acelp_midLpc ) + { + if( st->rate_switching_reset == 0 ) + { + lsp2lsf( lspmid, lsfmid, M, sr_core ); + midlsf_enc( lsf_old, lsf_q, lsfmid, &lsfmid_idx, M, Bin_Ener_old, narrowBand, sr_core, coder_type ); + param_lpc[nb_indices++] = (int)lsfmid_idx; + + midlsf_dec( lsf_old, lsf_q, lsfmid_idx, lsfmid_q, M, coder_type, NULL, 0, 1 ); + + reorder_lsf( lsfmid_q, LSF_GAP_MID, M, sr_core ); + lsf2lsp( lsfmid_q, lspmid_q, M, sr_core ); + } + else + { + param_lpc[nb_indices++] = 0; + } + } + + return; +} + + + +/*-------------------------------------------------------------------* + * Unified_weighting() + * + * LSF weighting + *-------------------------------------------------------------------*/ + +void Unified_weighting( + float Bin_Ener_128[], /* i : FFT Bin energy 128 bins in two sets */ + const float lsf[], /* i : LSF vector */ + float w[], /* o : LP weighting filter (numerator) */ + const short narrowBand, /* i : flag for Narrowband */ + const short unvoiced, /* i : flag for Unvoiced frame */ + const short sr_core, /* i : sampling rate of core-coder */ + const int order /* i : LP order */ +) +{ + short i; + float nf; + const Word16 (*ptr_lsf_fit_model)[M]; + int norm_lsf[M]; + float tmp, min; + float w_fft[M]; + float Bin_Ener_160[160]; + float *Bin_Ener; + const float *Freq_w_Table; + short last_bin; + /*float compen;*/ + + + /*Config. weighting*/ + if( narrowBand ) + { + ptr_lsf_fit_model = lsf_unified_fit_model_nb; + nf = 6400.f; + + last_bin = 127; + Bin_Ener = Bin_Ener_128; + } + else if( sr_core == 12800 ) + { + ptr_lsf_fit_model = lsf_unified_fit_model_wb; + nf = 6400.f; + + last_bin = 127; + Bin_Ener = Bin_Ener_128; + } + else + { + ptr_lsf_fit_model = lsf_unified_fit_model_wbhb; + nf = 8000.f; + + /* Fill the missing part (128~159) of the bin energy */ + last_bin = 159; + + mvr2r( Bin_Ener_128, Bin_Ener_160, L_FFT/2 ); + + /* Find average bin energy (32 Energy) */ + tmp = 0.f; + for( i=95; i<127; i++ ) + { + tmp += Bin_Ener_160[i]; + } + + tmp = tmp/32.f; + for( i=127; i<160; i++ ) + { + Bin_Ener_160[i] = tmp; + } + + Bin_Ener = Bin_Ener_160; + } + + /* 1) FFT weights*/ + if( unvoiced ) + { + Freq_w_Table = Freq_Weight_UV; + } + else + { + Freq_w_Table = Freq_Weight_Com; + } + + /* Use Envelope */ + min = 1000.0f; + for( i=0; i +#include "wmc_auto.h" +#include +#include +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static void rc_enc_shift(Encoder_State *st); +static void rc_enc_write(Encoder_State *st, short byte, short bits); + + +/*-------------------------------------------------------------------* + * rc_enc_init() + * + * Initalize range coder + *-------------------------------------------------------------------*/ + +void rc_enc_init( + Encoder_State *st, /* i/o: Encoder state */ + short tot_bits /* i : Total bit budget */ +) +{ + st->rc_low = 0; + st->rc_range = 0xffffffff; + st->rc_cache = -1; + st->rc_carry = 0; + st->rc_carry_count = 0; + st->rc_num_bits = 0; + st->rc_tot_bits = tot_bits; + st->rc_offset = 0; + + return; +} + +/*-------------------------------------------------------------------* + * rc_encode() + * + * Encode symbol with range coder + *-------------------------------------------------------------------*/ + +void rc_encode( + Encoder_State *st, /* i/o: Encoder state */ + unsigned int cum_freq, /* i : Cumulative frequency up to symbol */ + unsigned int sym_freq, /* i : Symbol probability */ + unsigned int tot /* i : Total cumulative frequency */ +) +{ + unsigned int r, tmp; + unsigned int inv_tot; + short exp; + + inv_tot = UL_inverse(tot, &exp); + tmp = UMult_32_32(st->rc_range, inv_tot); + r = tmp >> (exp - 32); + tmp = r*cum_freq; + + st->rc_low = st->rc_low + tmp; + if (st->rc_low < tmp) + { + st->rc_carry = 1; + } + + st->rc_range = r*sym_freq; + + while (st->rc_range < 1<<24) + { + st->rc_range = st->rc_range << 8; + st->rc_num_bits += 8; + rc_enc_shift(st); + } + + return; +} + +/*-------------------------------------------------------------------* + * rc_enc_finish() + * + * Finalize range coder + *-------------------------------------------------------------------*/ + +void rc_enc_finish( + Encoder_State *st /* i/o: Encoder state */ +) +{ + unsigned int val, mask, high; + short bits, over1, over2; + + bits = norm_ul(st->rc_range) + 1; /* aligned to BASOP */ + + mask = 0xffffffff >> bits; + + val = st->rc_low + mask; + high = st->rc_low + st->rc_range; + + over1 = val < st->rc_low; + over2 = high < st->rc_low; + + val = val & ~mask; + + if ( !(over1 ^ over2) ) + { + if ((val + mask) >= high) + { + bits++; + mask >>= 1; + val = (st->rc_low + mask) & ~mask; + } + + if (val < st->rc_low) + { + st->rc_carry = 1; + } + } + + st->rc_low = val; + + if (bits > st->rc_tot_bits - st->rc_num_bits) + { + bits = st->rc_tot_bits - st->rc_num_bits; + + } + + st->rc_num_bits += bits; + while (bits > 0) + { + rc_enc_shift(st); + bits -= 8; + } + + bits += 8; + + if ( st->rc_carry_count > 0 ) + { + rc_enc_write(st, st->rc_cache + st->rc_carry, 8); + + while (st->rc_carry_count > 1) + { + rc_enc_write(st, (st->rc_carry + 0xff), 8); + st->rc_carry_count--; + } + rc_enc_write(st, (st->rc_carry + 0xff) & ((1<rc_cache + st->rc_carry)>>(8-bits), bits); + } + + bits = st->rc_num_bits; + while (bits < st->rc_tot_bits-16) + { + rc_enc_write(st, 0, 16); + bits += 16; + } + + bits = st->rc_tot_bits - bits; + if (bits > 0) + { + rc_enc_write(st, 0, bits); + } + + return; +} + +/*-------------------------------------------------------------------* + * rc_enc_shift() + * + * Shift a byte out to bitstream + *-------------------------------------------------------------------*/ + +static void rc_enc_shift( + Encoder_State *st /* i/o: Encoder state */ +) +{ + if ( st->rc_low < (0xffUL << 24) || st->rc_carry ) + { + if (st->rc_cache >= 0) + { + rc_enc_write(st, st->rc_cache + st->rc_carry, 8); + } + + while (st->rc_carry_count > 0) + { + rc_enc_write(st, (st->rc_carry + 0xff) & 255, 8); + st->rc_carry_count--; + } + + st->rc_cache = st->rc_low >> 24; + st->rc_carry = 0; + } + else + { + st->rc_carry_count++; + } + + st->rc_low = st->rc_low << 8; + + return; +} + +/*-------------------------------------------------------------------* + * rc_enc_bits() + * + * + *-------------------------------------------------------------------*/ + +void rc_enc_bits( + Encoder_State *st, /* i/o: Encoder state */ + unsigned int value, /* i : Value to encode */ + short bits /* i : Number of bits used */ +) +{ + if ( rc_get_bits2(st->rc_num_bits, st->rc_range) + bits <= st->rc_tot_bits) + { + st->rc_num_bits += bits; + if ( bits > 16 ) + { + push_indice(st, IND_RC_END - st->rc_offset, value >> 16, bits - 16); + st->rc_offset++; + + push_indice(st, IND_RC_END - st->rc_offset, value & ((1 << 16) - 1), 16); + st->rc_offset++; + } + else + { + push_indice(st, IND_RC_END - st->rc_offset++, value, bits); + } + } + else + { + } + + return; +} + +/*-------------------------------------------------------------------* + * rc_enc_uniform() + * + * Encode with uniform distribution + *-------------------------------------------------------------------*/ + +void rc_enc_uniform( + Encoder_State *st, /* i/o: Encoder state */ + unsigned int value, /* i : Value to encode */ + unsigned int tot /* i : Maximum value */ +) +{ + short n; + + n = 32 - norm_ul(tot-1); /* aligned to BASOP */ + + if (n <= 8) + { + rc_encode(st, value, 1, tot); + } + else + { + n -= 8; + rc_encode(st, value >> n, 1, (tot >> n) + 1); + rc_enc_bits(st, value & ((1<=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( x, n, k, c, &ka ); + + /* safeguard in case that the AVQ subquantizer is not found - might happen for extremely strong onsets at the end of the frame */ + if( ka >= NB_LEADER ) + { + *n = 0; + set_i( x, 0, 8 ); + } + + /* compute the index I (only if c is in Q2, Q3 or Q4) */ + if( *n > 0 ) + { + re8_compute_base_index( c, ka, I ); + } + + return; +} diff --git a/lib_enc/reordernorm.c b/lib_enc/reordernorm.c new file mode 100644 index 000000000..d6dc32c61 --- /dev/null +++ b/lib_enc/reordernorm.c @@ -0,0 +1,58 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "prot.h" +#include "cnst.h" +#include "rom_com.h" + +/*--------------------------------------------------------------------------*/ +/* Function reordernorm */ +/* ~~~~~~~~~~~~~~~~~~~~~ */ +/* */ +/* Reorder quantization indices and norms */ +/*--------------------------------------------------------------------------*/ +/* short *ynrm (i) quantization indices for norms */ +/* short *normqlg2 (i) quantized norms */ +/* short *idxbuf (o) reordered quantization indices */ +/* short *normbuf (o) reordered quantized norms */ +/* short *nb_sfm (i) number of bands */ +/*--------------------------------------------------------------------------*/ + +void reordernorm( + const short *ynrm, + const short *normqlg2, + short *idxbuf, + short *normbuf, + const short nb_sfm +) +{ + short i; + const short *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]]; + normbuf[i] = normqlg2[order[i]]; + } + + return; +} diff --git a/lib_enc/rom_enc.c b/lib_enc/rom_enc.c new file mode 100644 index 000000000..518eb127a --- /dev/null +++ b/lib_enc/rom_enc.c @@ -0,0 +1,703 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" + +const short hangover_hd_tbl[3] = {1, 1, 3}; +const short hangover_sf_tbl[6] = {1, 3, 4, 1, 1, 2}; +const short bwd_start_bin[BWD_N_BINS_MAX] = {1, 3, 6, 11}; +const short bwd_end_bin[BWD_N_BINS_MAX] = {1, 4, 9, 12}; + +const short BAND_NUM_TAB[5] = {10,10,20,40,60}; /* {OFFSET, NB, WB, SWB, FB} */ + +const float M_inr[16] = +{ + 1.00000000f, 0.98078525f, 0.92387950f, 0.83146960f, 0.70710677f, 0.55557019f, 0.38268343f, 0.19509035f, + 0.00000008f, -0.19509020f, -0.38268328f, -0.55557019f, -0.70710677f, -0.83146966f, -0.92387962f, -0.98078531f +}; + +const float M_ini[16] = +{ + 0.00000000f, 0.19509032f, 0.38268346f, 0.55557024f, 0.70710677f, 0.83146966f, 0.92387950f, 0.98078525f, + 1.00000000f, 0.98078531f, 0.92387956f, 0.83146966f, 0.70710677f, 0.55557019f, 0.38268328f, 0.19509009f +}; + +const float M_r[8] = +{ + 1.00000000f, 0.92387950f, 0.70710677f, 0.38268343f, -0.00000004f, -0.38268352f, -0.70710677f, -0.92387950f +}; + +const float M_i[8] = +{ + 0.00000000f, 0.38268346f, 0.70710677f, 0.92387950f, 1.00000000f, 0.92387950f, 0.70710677f, 0.38268349f +}; + +const float M_Wr[16]= +{ + 9.9518473e-001f, 9.5694034e-001f, 8.8192126e-001f, 7.7301045e-001f, 6.3439328e-001f, 4.7139674e-001f, 2.9028468e-001f, 9.8017140e-002f, + -9.8017140e-002f, -2.9028468e-001f, -4.7139674e-001f, -6.3439328e-001f, -7.7301045e-001f, -8.8192126e-001f, -9.5694034e-001f, -9.9518473e-001f +}; + +const float M_Wi[16] = +{ + 9.8017140e-002f, 2.9028468e-001f, 4.7139674e-001f, 6.3439328e-001f, 7.7301045e-001f, 8.8192126e-001f, 9.5694034e-001f, 9.9518473e-001f, + 9.9518473e-001f, 9.5694034e-001f, 8.8192126e-001f, 7.7301045e-001f, 6.3439328e-001f, 4.7139674e-001f, 2.9028468e-001f, 9.8017140e-002f +}; + +const short SP_CENTER_BAND_NUM_TAB[5] = {10, 10, 20, 24, 24}; + +/* 107374184.f = 32768.f * 32768.f * 0.1 */ +const float DELTA1[5] = {107374184.f, 0.0f, 107374184.f, 107374184.f, 0.0f}; +const float DELTA2[5] = {107374184.f, 1.f, 107374184.f, 107374184.f, 107374184.f}; + +const int NREGION_INDEX_NB[9] = {0,1,2,3,4,5,6,7, 9}; +const int NREGION_INDEX_WB[13] = {0,1,2,3,4,5,6,8,10,12,16}; +const int NREGION_INDEX_SWB[16] = {0,1,2,3,4,5,6,8,10,12,16,24,36}; +const int NREGION_INDEX_FB[16] = {0,1,2,3,4,5,6,8,10,12,16,24,36}; +const int ENERGY_BAND_NUM[4] = {8,10,12,MAX_SUBBAND_NUM}; +const int *const REGION_INDEX[4] = {NREGION_INDEX_NB, NREGION_INDEX_WB,NREGION_INDEX_SWB,NREGION_INDEX_FB}; +const float MAX_LF_SNR_TAB[4] = {0.8f, 0.8f, 1.6f, 0.8f}; + +const float COMVAD_INIT_SNR_DELTA[5] = {1.0f, 0.6f, 0.86f, 1.16f, 1.0f}; +const float LS_MIN_SELENCE_SNR[3] = {7.5f, 7.5f, 6.8f}; +const float LT_MIN_SILENCE_SNR[3] = {4.5f, 4.5f, 4.5f}; + +/* half of the square root hanning window for spectral analysis */ +const float sqrt_han_window[L_FFT/2+1]= +{ + 0.000000f, 0.012272f, 0.024541f, 0.036807f, 0.049068f, 0.061321f, 0.073565f, 0.085797f, + 0.098017f, 0.110222f, 0.122411f, 0.134581f, 0.146730f, 0.158858f, 0.170962f, 0.183040f, + 0.195090f, 0.207111f, 0.219101f, 0.231058f, 0.242980f, 0.254866f, 0.266713f, 0.278520f, + 0.290285f, 0.302006f, 0.313682f, 0.325310f, 0.336890f, 0.348419f, 0.359895f, 0.371317f, + 0.382683f, 0.393992f, 0.405241f, 0.416430f, 0.427555f, 0.438616f, 0.449611f, 0.460539f, + 0.471397f, 0.482184f, 0.492898f, 0.503538f, 0.514103f, 0.524590f, 0.534998f, 0.545325f, + 0.555570f, 0.565732f, 0.575808f, 0.585798f, 0.595699f, 0.605511f, 0.615232f, 0.624860f, + 0.634393f, 0.643832f, 0.653173f, 0.662416f, 0.671559f, 0.680601f, 0.689541f, 0.698376f, + 0.707107f, 0.715731f, 0.724247f, 0.732654f, 0.740951f, 0.749136f, 0.757209f, 0.765167f, + 0.773010f, 0.780737f, 0.788346f, 0.795837f, 0.803208f, 0.810457f, 0.817585f, 0.824589f, + 0.831470f, 0.838225f, 0.844854f, 0.851355f, 0.857729f, 0.863973f, 0.870087f, 0.876070f, + 0.881921f, 0.887640f, 0.893224f, 0.898674f, 0.903989f, 0.909168f, 0.914210f, 0.919114f, + 0.923880f, 0.928506f, 0.932993f, 0.937339f, 0.941544f, 0.945607f, 0.949528f, 0.953306f, + 0.956940f, 0.960431f, 0.963776f, 0.966976f, 0.970031f, 0.972940f, 0.975702f, 0.978317f, + 0.980785f, 0.983105f, 0.985278f, 0.987301f, 0.989177f, 0.990903f, 0.992480f, 0.993907f, + 0.995185f, 0.996313f, 0.997290f, 0.998118f, 0.998795f, 0.999322f, 0.999699f, 0.999925f, + 1.000000f +}; + +/*----------------------------------------------------------------------------------* + * Starting points for pulse position search in Algebraic innovation codebook + *----------------------------------------------------------------------------------*/ + +const short 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, + 1, 2, 3, 0 /* end point for 28 pulses &ipos[39], 4th iter */ +}; + +/*----------------------------------------------------------------------------------* + * 1/4 resolution interpolation filter (-3 dB at 0.791*fs/2) + * for fractional pitch search + *----------------------------------------------------------------------------------*/ + +/* 1/4 resolution interpolation filter (-3 dB at 0.791*fs/2) */ +const float E_ROM_inter4_1[PIT_UP_SAMP * L_INTERPOL1 + 1] = +{ + 0.900000F, + 0.818959F, 0.604850F, 0.331379F, 0.083958F, + -0.075795F, -0.130717F, -0.105685F, -0.046774F, + 0.004467F, 0.027789F, 0.025642F, 0.012571F, + 0.001927F, -0.001571F, -0.000753F, 0.000000f +}; + +/* 1/6 resolution interpolation filter (-3 dB at 0.9*fs/2) */ +const float E_ROM_inter6_1[PIT_UP_SAMP6 * L_INTERPOL1 + 1] = +{ + 0.900848F, + 0.864136F, 0.760071F, 0.605408F, 0.424072F, + 0.242462F, 0.0840759F, -0.0343933F, -0.105560F, + -0.131348F, -0.121124F, -0.0884705F, -0.0476379F, + -0.0102539F, 0.0162964F, 0.0296021F, 0.0312195F, + 0.0251160F, 0.0157471F, 0.00671387F, 0.000000F, + -0.00399780F, -0.00592041F, -0.00656128F, 0.000000F +}; + +/*----------------------------------------------------------------------------------* + * Open-loop pitch tables + *----------------------------------------------------------------------------------*/ +const short nb_sect_12k8[3] = { 4, 4, 4 }; +const short nb_subsect_12k8[3] = { 7, 7, 7 }; +const short pit_max_12k8[8] = { 11, 16, 21, 31, 40, 61, 77, 115}; + +const short len_12k8[4] = { 40, 40, 62, 115 }; +const short len1_12k8[4] = { 40, 50, 80, 115 }; +const short sublen_12k8[7] = { 40, 40, 40, 62, 62, 115, 115 }; +const short sublen1_12k8[7] = { 40, 40, 50, 50, 80, 80, 115 } ; +const short sec_length_12k8[4] = { 7, 15, 30, 54 }; +const short sec_length1_12k8[4] = { 10, 19, 37, 38 }; +const float h_fir[5] = {0.13f, 0.23f, 0.28f, 0.23f, 0.13f}; + +const float W_HIST[DTX_HIST_SIZE] = +{ + 0.2f, 0.16f, 0.128f, 0.1024f, 0.08192f, 0.065536f, 0.0524288f, 0.01048576f +}; + +const float preemphCompensation[NB_BANDS] = { 9.7461f, 9.5182f, 9.0262f, 8.3493f, 7.5764f, 6.7838f, 5.8377f, 4.8502f, 4.0346f, 3.2788f, 2.6283f, 2.0920f, 1.6304f, 1.2850f, 1.0108f, 0.7916f, 0.6268f, 0.5011f, 0.4119f, 0.3637f }; + +/*----------------------------------------------------------------------------------* + * LSF quantizer + *----------------------------------------------------------------------------------*/ + +const int lsf_numlevels[TCXLPC_NUMSTAGES] = { 32, 16, 16 }; +const int lsf_ind_numlevels[TCXLPC_IND_NUMSTAGES] = { 4 }; + +const short 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 short 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 short 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} +}; + +/* LPC weights used in SWB TBE */ +const float lpc_weights[LPC_SHB_ORDER+1] = +{ + 1.0f, 0.975000000f, 0.950625000f, 0.926859375f, 0.903687891f, + 0.881095693f, 0.859068301f, 0.837591593f, 0.816651804f, + 0.796235509f, 0.776329621f +}; + +/* LSF weighting */ +const float Freq_Weight_Com[160] = +{ + 0.50000000f, 0.62940955f, 0.75000000f, 0.85355341f, 0.93301272f, 0.98296291f, 1.00000000f, 1.00000000f, + 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, + 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f, 0.97272730f, 0.94690263f, 0.92241377f, + 0.89915967f, 0.87704921f, 0.85600001f, 0.83593750f, 0.81679392f, 0.79850745f, 0.78102189f, 0.76428574f, + 0.74825174f, 0.73287672f, 0.71812081f, 0.70394737f, 0.69032258f, 0.67721522f, 0.66459626f, 0.65243900f, + 0.64071858f, 0.62941176f, 0.61849713f, 0.60795456f, 0.59776539f, 0.58791208f, 0.57837838f, 0.56914896f, + 0.56020945f, 0.55154639f, 0.54314721f, 0.53500003f, 0.52709359f, 0.51941746f, 0.51196170f, 0.50471699f, + 0.49767441f, 0.49082568f, 0.48416290f, 0.47767857f, 0.47136563f, 0.46521738f, 0.45922747f, 0.45338982f, + 0.44769874f, 0.44214877f, 0.43673471f, 0.43145162f, 0.42629483f, 0.42125985f, 0.41634241f, 0.41153845f, + 0.40684411f, 0.40225562f, 0.39776951f, 0.39338234f, 0.38909090f, 0.38489208f, 0.38078293f, 0.37676057f, + 0.37282231f, 0.36896551f, 0.36518770f, 0.36148649f, 0.35785952f, 0.35430464f, 0.35081968f, 0.34740260f, + 0.34405145f, 0.34076434f, 0.33753943f, 0.33437499f, 0.33126935f, 0.32822084f, 0.32522798f, 0.32228917f, + 0.31940299f, 0.31656805f, 0.31378299f, 0.31104651f, 0.30835736f, 0.30571428f, 0.30311614f, 0.30056179f, + 0.29805014f, 0.29558012f, 0.29315069f, 0.29076087f, 0.28840971f, 0.28609625f, 0.28381962f, 0.28157896f, + 0.27937338f, 0.27720207f, 0.27506426f, 0.27295917f, 0.27088606f, 0.26884422f, 0.26683292f, 0.26485148f, + 0.26289925f, 0.26097560f, 0.25907990f, 0.25721154f, 0.25536993f, 0.25355449f, 0.25176471f, 0.25000000f, + 0.24825986f, 0.24654378f, 0.24485126f, 0.24318182f, 0.24153499f, 0.23991032f, 0.23830736f, 0.23672566f, + 0.23516484f, 0.23362446f, 0.23210412f, 0.23060344f, 0.22912206f, 0.22765957f, 0.22621565f, 0.22478992f, + 0.22338204f, 0.22199170f, 0.22061856f, 0.21926230f, 0.21792261f, 0.21659920f, 0.21529175f, 0.21400000f, + 0.21272366f, 0.21146245f, 0.21021610f, 0.20898438f, 0.20776699f, 0.20656371f, 0.20537429f, 0.20419848f +}; + +const float Freq_Weight_UV[160] = +{ + 0.50000000f, 0.62940955f, 0.75000000f, 0.85355341f, 0.93301272f, 0.98296291f, 1.00000000f, 0.99180329f, + 0.98373985f, 0.97580647f, 0.96799999f, 0.96031743f, 0.95275593f, 0.94531250f, 0.93798447f, 0.93076921f, + 0.92366409f, 0.91666669f, 0.90977442f, 0.90298510f, 0.89629632f, 0.88970590f, 0.88321167f, 0.87681162f, + 0.87050360f, 0.86428571f, 0.85815603f, 0.85211265f, 0.84615386f, 0.84027779f, 0.83448273f, 0.82876712f, + 0.82312924f, 0.81756759f, 0.81208056f, 0.80666667f, 0.80132449f, 0.79605263f, 0.79084969f, 0.78571427f, + 0.78064513f, 0.77564102f, 0.77070063f, 0.76582277f, 0.76100630f, 0.75625002f, 0.75155282f, 0.74691355f, + 0.74233127f, 0.73780489f, 0.73333335f, 0.72891569f, 0.72455090f, 0.72023809f, 0.71597636f, 0.71176469f, + 0.70760232f, 0.70348835f, 0.69942194f, 0.69540232f, 0.69142854f, 0.68750000f, 0.68361580f, 0.67977530f, + 0.67597765f, 0.67222220f, 0.66850829f, 0.66483516f, 0.66120219f, 0.65760869f, 0.65405405f, 0.65053761f, + 0.64705884f, 0.64361703f, 0.64021164f, 0.63684213f, 0.63350785f, 0.63020831f, 0.62694299f, 0.62371135f, + 0.62051284f, 0.61734694f, 0.61421317f, 0.61111110f, 0.60804021f, 0.60500002f, 0.60199004f, 0.59900987f, + 0.59605908f, 0.59313726f, 0.59024388f, 0.58737862f, 0.58454108f, 0.58173078f, 0.57894737f, 0.57619047f, + 0.57345974f, 0.57075471f, 0.56807512f, 0.56542057f, 0.56279069f, 0.56018519f, 0.55760366f, 0.55504584f, + 0.55251139f, 0.55000001f, 0.54751134f, 0.54504502f, 0.54260087f, 0.54017860f, 0.53777778f, 0.53539824f, + 0.53303963f, 0.53070176f, 0.52838427f, 0.52608699f, 0.52380955f, 0.52155173f, 0.51931328f, 0.51709402f, + 0.51489359f, 0.51271188f, 0.51054853f, 0.50840336f, 0.50627613f, 0.50416666f, 0.50207472f, 0.50000000f, + 0.49794239f, 0.49590164f, 0.49387756f, 0.49186993f, 0.48987854f, 0.48790324f, 0.48594376f, 0.48400000f, + 0.48207173f, 0.48015872f, 0.47826087f, 0.47637796f, 0.47450981f, 0.47265625f, 0.47081712f, 0.46899223f, + 0.46718147f, 0.46538460f, 0.46360153f, 0.46183205f, 0.46007603f, 0.45833334f, 0.45660377f, 0.45488721f, + 0.45318353f, 0.45149255f, 0.44981414f, 0.44814816f, 0.44649446f, 0.44485295f, 0.44322345f, 0.44160584f +}; + +/*----------------------------------------------------------------------------------* + * Speech/music classification + *----------------------------------------------------------------------------------*/ + +const float w_spmus[HANG_LEN][HANG_LEN] = +{ + {1.0f, 0, 0, 0, 0, 0, 0, 0}, + {0.6f, 0.4f, 0, 0, 0, 0, 0, 0}, + {0.47f, 0.33f, 0.2f, 0, 0, 0, 0, 0}, + {0.4f, 0.3f, 0.2f, 0.1f, 0, 0, 0, 0}, + {0.30f, 0.25f, 0.2f, 0.15f, 0.1f, 0, 0, 0}, + {0.233f, 0.207f, 0.18f, 0.153f, 0.127f, 0.1f, 0, 0}, + {0.235f, 0.205f, 0.174f, 0.143f, 0.112f, 0.081f, 0.05f, 0}, + {0.200f, 0.179f, 0.157f, 0.136f, 0.114f, 0.093f, 0.071f, 0.05f} +}; + +const float m_speech[N_MIXTURES*N_FEATURES] = +{ + 0.287950f, 0.915145f, 0.146341f, 0.215938f, 0.337233f, 0.416424f, 0.464061f, 0.463680f, 0.059083f, 0.853025f, 0.768184f, 0.314352f, + 0.306930f, 0.936427f, 0.255783f, 0.304095f, 0.328435f, 0.264893f, 0.353664f, 0.481807f, 0.050087f, 0.816373f, 0.828952f, 0.335445f, + 0.241923f, 0.953049f, 0.219456f, 0.259538f, 0.436515f, 0.498549f, 0.456902f, 0.490619f, 0.062629f, 0.832243f, 0.845146f, 0.331393f, + 0.424629f, 0.528660f, 0.325986f, 0.502250f, 0.543419f, 0.561620f, 0.591057f, 0.386511f, 0.067280f, 0.903251f, 0.891515f, 0.344377f, + 0.380487f, 0.727792f, 0.209973f, 0.314364f, 0.421881f, 0.398734f, 0.446999f, 0.402498f, 0.105313f, 0.867979f, 0.877883f, 0.317694f, + 0.344962f, 0.658148f, 0.240913f, 0.348251f, 0.433178f, 0.480324f, 0.498983f, 0.419444f, 0.187060f, 0.868077f, 0.855516f, 0.347290f +}; + +const float invV_speech[N_MIXTURES*N_FEATURES*N_FEATURES] = +{ + -39.495125f, -14.409725f, -38.632778f, -17.688078f, 8.772461f, -11.402443f, 0.439471f, -10.340120f, -48.738274f, 0.349716f, 16.818443f, 32.142887f, + -14.409725f, -195.908417f, -27.029999f, -27.433266f, -16.451397f, -6.243556f, 5.814015f, 12.751663f, -65.479347f, -46.738777f, -8.373536f, 18.300566f, + -38.632782f, -27.029999f, -753.940247f, 115.388985f, -47.167007f, 27.107189f, -36.896187f, 72.593445f, -298.310120f, -22.776127f, 177.255432f, 89.802238f, + -17.688076f, -27.433270f, 115.388954f, -222.724594f, 40.140877f, -45.163593f, 21.461746f, 7.970023f, -27.137230f, 76.520920f, 25.476706f, 38.804222f, + 8.772461f, -16.451405f, -47.167007f, 40.140877f, -94.404678f, 40.199402f, -17.781452f, 3.901072f, -14.428046f, 23.148809f, 13.478944f, 17.505091f, + -11.402439f, -6.243560f, 27.107193f, -45.163593f, 40.199394f, -93.411865f, 57.189003f, 3.581622f, 0.100851f, 5.812640f, 9.256781f, 10.823537f, + 0.439471f, 5.814015f, -36.896187f, 21.461748f, -17.781452f, 57.189003f, -89.808571f, -5.465971f, -46.055283f, -15.567553f, 14.521687f, 10.769546f, + -10.340121f, 12.751663f, 72.593445f, 7.970019f, 3.901072f, 3.581622f, -5.465971f, -100.358055f, 24.768887f, -20.986031f, -47.276218f, 13.192144f, + -48.738274f, -65.479347f, -298.310120f, -27.137238f, -14.428048f, 0.100851f, -46.055275f, 24.768887f, -1377.781250f, -56.637291f, 233.195129f, -114.883377f, + 0.349715f, -46.738777f, -22.776127f, 76.520912f, 23.148806f, 5.812638f, -15.567553f, -20.986031f, -56.637291f, -216.730820f, -0.914011f, 39.627998f, + 16.818443f, -8.373537f, 177.255432f, 25.476713f, 13.478942f, 9.256781f, 14.521687f, -47.276218f, 233.195129f, -0.914013f, -153.435181f, -48.048389f, + 32.142887f, 18.300564f, 89.802223f, 38.804218f, 17.505091f, 10.823533f, 10.769546f, 13.192144f, -114.883377f, 39.628006f, -48.048389f, -313.631622f, + -53.471222f, -47.464245f, -0.896915f, -25.132132f, 30.892912f, -27.316641f, 22.758862f, -18.016706f, -66.564011f, -3.584184f, -7.795120f, 35.122147f, + -47.464249f, -438.709412f, -11.227010f, -14.463504f, 12.490106f, -11.184597f, 2.622577f, -3.664124f, -84.887161f, -29.377838f, -53.413090f, 17.047739f, + -0.896916f, -11.227015f, -251.993881f, 153.947250f, 4.508913f, 26.900564f, -22.145449f, 7.110321f, -215.903503f, -47.320839f, 78.247871f, 16.021702f, + -25.132132f, -14.463490f, 153.947235f, -326.623169f, 62.711872f, 7.543400f, 23.738796f, 19.846117f, -97.089355f, 2.828130f, 75.120659f, 34.945835f, + 30.892912f, 12.490105f, 4.508915f, 62.711872f, -289.161591f, 178.348740f, -26.642651f, 11.309997f, -10.248929f, 16.504482f, 48.839104f, 20.334949f, + -27.316643f, -11.184605f, 26.900568f, 7.543384f, 178.348740f, -267.764130f, 15.141651f, 4.242836f, -7.640367f, 77.632545f, -2.166305f, 12.531335f, + 22.758862f, 2.622574f, -22.145449f, 23.738796f, -26.642651f, 15.141647f, -71.479584f, 2.006794f, -4.579958f, 30.676281f, 15.085149f, 8.568682f, + -18.016706f, -3.664128f, 7.110321f, 19.846119f, 11.309998f, 4.242836f, 2.006794f, -76.086823f, 56.165844f, -8.384334f, -103.682259f, 6.086752f, + -66.564011f, -84.887161f, -215.903488f, -97.089355f, -10.248927f, -7.640366f, -4.579959f, 56.165840f, -1920.100708f, -8.861668f, 500.888123f, -16.967447f, + -3.584186f, -29.377846f, -47.320839f, 2.828135f, 16.504475f, 77.632553f, 30.676281f, -8.384336f, -8.861669f, -181.010406f, -15.615012f, 8.247152f, + -7.795123f, -53.413109f, 78.247864f, 75.120659f, 48.839104f, -2.166309f, 15.085151f, -103.682251f, 500.888123f, -15.615015f, -433.988953f, -70.138153f, + 35.122147f, 17.047737f, 16.021706f, 34.945835f, 20.334948f, 12.531336f, 8.568681f, 6.086751f, -16.967451f, 8.247154f, -70.138176f, -217.081589f, + -94.138069f, -64.204018f, 0.309024f, -46.150829f, 42.051434f, -41.965660f, 10.197500f, -19.122877f, -42.942600f, -19.220772f, -21.222412f, 46.903416f, + -64.204025f, -818.921143f, 30.093992f, -42.236637f, 6.486305f, -4.382217f, 10.975861f, 0.330433f, -16.922922f, -58.340889f, -111.845398f, -1.666081f, + 0.309030f, 30.093992f, -342.960907f, 202.719925f, -66.503586f, 59.412266f, -81.710594f, 14.449543f, -155.271118f, 13.000940f, 119.772522f, 37.219341f, + -46.150829f, -42.236637f, 202.719910f, -315.177094f, 74.731415f, -97.374359f, 58.435394f, 19.693314f, -62.044556f, 6.968471f, 74.460442f, 22.385506f, + 42.051434f, 6.486304f, -66.503578f, 74.731415f, -93.988602f, 52.841560f, -21.181007f, 2.344793f, -35.600548f, -19.262661f, 37.872654f, 6.642675f, + -41.965660f, -4.382209f, 59.412254f, -97.374352f, 52.841560f, -278.285614f, 214.990295f, -0.626728f, -43.822613f, -21.303955f, 15.663709f, 3.870531f, + 10.197496f, 10.975868f, -81.710587f, 58.435387f, -21.181000f, 214.990295f, -234.196167f, 1.970801f, -16.810629f, -1.859668f, 16.002600f, 3.998644f, + -19.122877f, 0.330433f, 14.449545f, 19.693314f, 2.344791f, -0.626729f, 1.970801f, -57.165413f, 20.255400f, -9.028506f, -83.099960f, 8.659401f, + -42.942604f, -16.922922f, -155.271103f, -62.044556f, -35.600552f, -43.822613f, -16.810629f, 20.255400f, -986.222534f, 27.520060f, 397.979370f, -10.706357f, + -19.220772f, -58.340889f, 13.000940f, 6.968470f, -19.262661f, -21.303955f, -1.859668f, -9.028505f, 27.520063f, -181.756256f, -31.725298f, 5.532037f, + -21.222410f, -111.845398f, 119.772507f, 74.460449f, 37.872654f, 15.663704f, 16.002598f, -83.099960f, 397.979370f, -31.725298f, -499.032318f, -64.723236f, + 46.903416f, -1.666086f, 37.219345f, 22.385508f, 6.642675f, 3.870531f, 3.998645f, 8.659404f, -10.706349f, 5.532042f, -64.723228f, -245.227646f, + -20.650835f, 1.359996f, -2.309748f, 3.667799f, -4.431922f, -1.491803f, 2.244124f, -6.511281f, -7.420423f, -2.656161f, -5.103209f, 2.977657f, + 1.359996f, -45.519173f, -27.833733f, 11.524545f, -5.826983f, 8.198447f, -4.084381f, 13.450377f, 18.150373f, -9.569582f, -6.539153f, -3.438999f, + -2.309748f, -27.833733f, -75.630455f, 54.383217f, -10.366678f, 10.230091f, -6.134814f, 5.390231f, -18.911335f, 8.611535f, -4.468428f, 2.542004f, + 3.667800f, 11.524545f, 54.383224f, -148.724060f, 102.126076f, -8.536950f, 14.920280f, -2.707708f, 16.232759f, -12.092183f, -2.761442f, 5.324492f, + -4.431922f, -5.826983f, -10.366676f, 102.126083f, -239.405472f, 114.426819f, -4.901945f, 3.331610f, -2.787818f, -19.461893f, 9.501407f, 1.843912f, + -1.491803f, 8.198447f, 10.230090f, -8.536962f, 114.426842f, -252.874207f, 133.055328f, -2.890811f, -8.063058f, -19.651783f, -6.576759f, -6.167914f, + 2.244124f, -4.084381f, -6.134819f, 14.920280f, -4.901949f, 133.055328f, -188.368149f, 0.868558f, -5.905251f, -73.150818f, 15.489239f, 3.931309f, + -6.511280f, 13.450379f, 5.390231f, -2.707708f, 3.331610f, -2.890812f, 0.868557f, -291.328827f, 8.357405f, 5.690188f, -65.318748f, -3.008168f, + -7.420423f, 18.150373f, -18.911335f, 16.232759f, -2.787818f, -8.063062f, -5.905251f, 8.357409f, -817.866455f, -35.719170f, 465.940338f, -57.209427f, + -2.656161f, -9.569582f, 8.611535f, -12.092187f, -19.461897f, -19.651789f, -73.150826f, 5.690184f, -35.719170f, -273.267426f, 28.788002f, 35.708652f, + -5.103208f, -6.539154f, -4.468427f, -2.761442f, 9.501406f, -6.576763f, 15.489231f, -65.318748f, 465.940338f, 28.788004f, -993.901489f, -74.051056f, + 2.977657f, -3.439001f, 2.542004f, 5.324495f, 1.843912f, -6.167918f, 3.931307f, -3.008166f, -57.209423f, 35.708649f, -74.051048f, -188.919189f, + -29.690845f, -6.602296f, -5.942207f, -8.191399f, 12.539626f, -17.187153f, 8.095049f, -11.539900f, -3.959312f, -2.929833f, -13.009781f, 14.593680f, + -6.602297f, -27.784903f, -12.036678f, -8.735461f, 10.268900f, -8.173005f, -0.508073f, 2.189236f, -3.210277f, -19.652676f, 0.174784f, 12.064508f, + -5.942207f, -12.036678f, -176.179718f, 87.371017f, -19.441795f, 2.946336f, -40.577980f, 4.105769f, -30.427385f, -23.225182f, 84.964821f, 43.734604f, + -8.191399f, -8.735461f, 87.371017f, -143.001602f, 51.919571f, -27.973251f, 29.284573f, -2.447426f, -11.954906f, 27.745192f, 11.595254f, 0.393728f, + 12.539626f, 10.268898f, -19.441788f, 51.919567f, -178.068130f, 128.031281f, -3.544543f, 6.851246f, -10.772905f, -42.477104f, 34.736156f, 40.172005f, + -17.187153f, -8.173005f, 2.946335f, -27.973251f, 128.031281f, -165.563629f, 51.259937f, -4.838826f, 3.758103f, 40.516190f, -7.739178f, -19.154724f, + 8.095048f, -0.508073f, -40.577976f, 29.284571f, -3.544538f, 51.259933f, -108.403847f, -0.894440f, 3.337809f, 2.241667f, 3.315053f, 1.456518f, + -11.539901f, 2.189236f, 4.105764f, -2.447426f, 6.851246f, -4.838827f, -0.894440f, -214.332535f, -4.848935f, -3.779825f, -75.247871f, -1.171161f, + -3.959312f, -3.210277f, -30.427393f, -11.954905f, -10.772905f, 3.758103f, 3.337807f, -4.848933f, -266.199005f, 2.878902f, 180.030838f, -44.094963f, + -2.929832f, -19.652674f, -23.225182f, 27.745188f, -42.477104f, 40.516193f, 2.241667f, -3.779825f, 2.878902f, -156.775406f, -11.596662f, 4.385890f, + -13.009781f, 0.174784f, 84.964828f, 11.595254f, 34.736156f, -7.739182f, 3.315054f, -75.247871f, 180.030838f, -11.596662f, -489.502777f, -57.779266f, + 14.593680f, 12.064507f, 43.734604f, 0.393729f, 40.172005f, -19.154715f, 1.456519f, -1.171165f, -44.094959f, 4.385883f, -57.779274f, -250.653564f, + -23.921967f, -5.683947f, -2.099401f, 0.128250f, 5.166994f, -10.038282f, 6.450608f, -0.731379f, -2.247439f, -4.157187f, 6.583568f, 4.081524f, + -5.683947f, -30.142115f, -8.658390f, -12.576810f, -1.309613f, 1.993960f, -4.383123f, 6.826682f, -0.827366f, -21.146013f, 3.620328f, 11.092305f, + -2.099401f, -8.658390f, -121.018547f, 88.485786f, -27.739552f, 24.281445f, -27.560604f, 3.724861f, 6.288231f, -12.520897f, 2.671664f, 12.669825f, + 0.128251f, -12.576811f, 88.485771f, -144.032974f, 84.679276f, -37.420727f, 25.546324f, 1.023258f, -7.474452f, 16.698721f, 8.763003f, 1.241009f, + 5.166994f, -1.309613f, -27.739553f, 84.679291f, -144.411407f, 72.554382f, -14.219510f, 2.006990f, 17.638592f, 1.209377f, -4.082684f, 14.381269f, + -10.038282f, 1.993960f, 24.281441f, -37.420734f, 72.554382f, -164.510483f, 115.127594f, -0.853720f, -16.850563f, 0.659630f, 12.865159f, -12.793469f, + 6.450607f, -4.383123f, -27.560604f, 25.546320f, -14.219501f, 115.127594f, -144.301163f, -12.984586f, 2.706392f, -4.143620f, -4.696592f, 1.570192f, + -0.731379f, 6.826682f, 3.724859f, 1.023259f, 2.006988f, -0.853720f, -12.984586f, -75.763382f, -31.576742f, -4.753652f, 9.548754f, -6.625205f, + -2.247438f, -0.827366f, 6.288230f, -7.474454f, 17.638592f, -16.850563f, 2.706394f, -31.576742f, -68.203148f, 11.220890f, 20.883671f, -23.079214f, + -4.157187f, -21.146011f, -12.520897f, 16.698721f, 1.209376f, 0.659629f, -4.143620f, -4.753652f, 11.220889f, -148.282272f, -2.460779f, 12.595567f, + 6.583566f, 3.620328f, 2.671665f, 8.763003f, -4.082685f, 12.865157f, -4.696593f, 9.548755f, 20.883675f, -2.460779f, -59.110310f, -3.725027f, + 4.081524f, 11.092305f, 12.669825f, 1.241007f, 14.381269f, -12.793469f, 1.570194f, -6.625203f, -23.079216f, 12.595569f, -3.725027f, -62.429104f +}; + +const float lvm_speech[N_MIXTURES] = +{ + 31.996607f, 32.762783f, 32.964325f, 31.979258f, 30.885334f, 26.185850f +}; + +const float m_music[N_MIXTURES*N_FEATURES] = +{ + 0.451772f, 0.776554f, 0.271046f, 0.354725f, 0.395602f, 0.413925f, 0.451482f, 0.627645f, 0.031510f, 0.835348f, 0.725457f, 0.357440f, + 0.487510f, 0.629043f, 0.236111f, 0.388441f, 0.440188f, 0.465005f, 0.494082f, 0.465069f, 0.069486f, 0.918461f, 0.858141f, 0.351628f, + 0.538064f, 0.605061f, 0.283209f, 0.430647f, 0.474700f, 0.497116f, 0.519075f, 0.527071f, 0.034547f, 0.951717f, 0.846345f, 0.380536f, + 0.484100f, 0.744331f, 0.238170f, 0.341071f, 0.358081f, 0.365782f, 0.392370f, 0.702362f, 0.021764f, 0.879612f, 0.725783f, 0.420504f, + 0.305845f, 0.692470f, 0.378321f, 0.465361f, 0.486968f, 0.499951f, 0.520584f, 0.473288f, 0.125325f, 0.726521f, 0.692794f, 0.374433f, + 0.513981f, 0.696380f, 0.246046f, 0.343276f, 0.374858f, 0.396051f, 0.418772f, 0.646286f, 0.026468f, 0.930184f, 0.778228f, 0.369588f +}; + +const float invV_music[N_MIXTURES*N_FEATURES*N_FEATURES] = +{ + -7.693553f, -0.657163f, -1.988950f, -0.864460f, -0.230076f, -0.650926f, 0.731884f, -1.685300f, -19.945335f, -0.839110f, 2.405366f, 3.916922f, + -0.657164f, -30.621262f, -1.553432f, -2.976453f, -1.828387f, 1.246830f, -3.716787f, 8.629019f, 5.424546f, -1.983033f, -10.816823f, -7.156825f, + -1.988950f, -1.553432f, -64.019180f, 41.928944f, -11.140388f, 11.880524f, 0.733497f, 8.586295f, 23.512827f, -15.433292f, -2.485986f, -2.458197f, + -0.864460f, -2.976454f, 41.928940f, -86.408936f, 41.949852f, -12.773962f, 4.663799f, 14.073083f, 23.178215f, -5.600554f, 14.946990f, 14.853354f, + -0.230076f, -1.828387f, -11.140390f, 41.949852f, -88.611122f, 37.060493f, -1.752939f, 3.927101f, -34.439037f, 12.153290f, 13.335299f, 16.994671f, + -0.650926f, 1.246830f, 11.880524f, -12.773962f, 37.060493f, -84.266197f, 37.053310f, 3.348819f, -5.522115f, 5.531706f, 8.455176f, -0.010933f, + 0.731884f, -3.716787f, 0.733498f, 4.663802f, -1.752939f, 37.053310f, -76.037888f, -8.315558f, -72.524521f, 21.789789f, 3.751793f, 0.630349f, + -1.685300f, 8.629018f, 8.586294f, 14.073083f, 3.927101f, 3.348819f, -8.315558f, -57.921276f, -118.393280f, 1.583935f, -8.300871f, 4.850578f, + -19.945335f, 5.424546f, 23.512829f, 23.178215f, -34.439041f, -5.522115f, -72.524521f, -118.393280f, -5404.569336f, 171.743378f, 241.973938f, -289.196930f, + -0.839109f, -1.983034f, -15.433292f, -5.600554f, 12.153290f, 5.531708f, 21.789789f, 1.583935f, 171.743362f, -101.897446f, -1.140457f, 31.464947f, + 2.405366f, -10.816823f, -2.485986f, 14.946990f, 13.335299f, 8.455174f, 3.751793f, -8.300871f, 241.973923f, -1.140458f, -77.658661f, -44.502563f, + 3.916922f, -7.156825f, -2.458197f, 14.853354f, 16.994675f, -0.010933f, 0.630349f, 4.850579f, -289.196899f, 31.464947f, -44.502563f, -243.168915f, + -9.878029f, 0.598697f, -4.302856f, -0.393763f, 0.713794f, 0.876955f, 0.341871f, -1.948222f, -8.764623f, -0.165505f, -1.265450f, 1.204445f, + 0.598697f, -29.943895f, -12.133356f, -1.089194f, -1.817891f, 2.837961f, -2.426654f, 12.585359f, -8.634910f, -11.784335f, 4.719538f, 2.997951f, + -4.302856f, -12.133356f, -84.521080f, 48.461727f, -11.249048f, 15.025650f, -19.584152f, 20.383547f, -13.363368f, 27.676975f, 22.609833f, -0.788566f, + -0.393763f, -1.089193f, 48.461727f, -128.134705f, 79.103844f, 1.020304f, 3.012457f, 7.957530f, -11.608212f, -3.021832f, 42.826736f, 14.192619f, + 0.713794f, -1.817891f, -11.249048f, 79.103836f, -220.859680f, 112.957855f, 8.839993f, -6.276199f, -19.145348f, -19.927418f, 7.305478f, 5.922347f, + 0.876955f, 2.837961f, 15.025646f, 1.020303f, 112.957878f, -275.141998f, 147.030670f, -5.400043f, 0.264864f, -5.583443f, 1.633528f, 7.493776f, + 0.341871f, -2.426655f, -19.584156f, 3.012456f, 8.839993f, 147.030670f, -196.030136f, -21.359327f, -9.146851f, 10.225628f, -2.139116f, 3.010611f, + -1.948222f, 12.585359f, 20.383547f, 7.957529f, -6.276197f, -5.400044f, -21.359325f, -108.690598f, -28.919056f, -26.963711f, -53.457581f, -9.210483f, + -8.764623f, -8.634909f, -13.363366f, -11.608211f, -19.145348f, 0.264862f, -9.146851f, -28.919056f, -602.275146f, 73.117203f, 185.012711f, -77.751747f, + -0.165505f, -11.784335f, 27.676975f, -3.021834f, -19.927414f, -5.583444f, 10.225626f, -26.963711f, 73.117210f, -350.919952f, -12.616115f, 28.914690f, + -1.265450f, 4.719537f, 22.609833f, 42.826729f, 7.305476f, 1.633531f, -2.139116f, -53.457581f, 185.012711f, -12.616107f, -398.114899f, -16.563597f, + 1.204445f, 2.997951f, -0.788567f, 14.192617f, 5.922347f, 7.493775f, 3.010611f, -9.210481f, -77.751747f, 28.914690f, -16.563597f, -176.464386f, + -12.120523f, 5.409175f, -1.857854f, 0.089656f, 2.747151f, 0.330849f, -0.110976f, -1.052840f, -23.532089f, -2.869304f, -1.769891f, 0.390127f, + 5.409175f, -35.374779f, -7.060057f, -0.748528f, -2.384489f, 2.017226f, -2.828100f, 8.307317f, 16.044216f, -11.155272f, -11.784020f, -0.186719f, + -1.857854f, -7.060059f, -112.721130f, 43.297070f, 11.361997f, 13.618838f, -3.489388f, 22.195547f, -71.385941f, 116.419769f, 68.520813f, 4.576182f, + 0.089655f, -0.748527f, 43.297066f, -183.503693f, 79.711113f, 24.255428f, 12.465648f, 1.436299f, -42.306995f, -23.502007f, 43.622116f, 3.459679f, + 2.747151f, -2.384489f, 11.361995f, 79.711113f, -288.300781f, 101.748329f, 51.744507f, -3.170304f, -142.892792f, -76.845322f, 33.559555f, -2.748073f, + 0.330848f, 2.017227f, 13.618836f, 24.255434f, 101.748344f, -339.510773f, 165.319336f, -4.353420f, -124.114395f, -92.283844f, 41.981186f, 5.566007f, + -0.110976f, -2.828100f, -3.489391f, 12.465652f, 51.744499f, 165.319336f, -302.816223f, -18.169355f, -26.544678f, -18.664721f, -2.650121f, 0.010451f, + -1.052840f, 8.307317f, 22.195547f, 1.436298f, -3.170304f, -4.353420f, -18.169355f, -67.658730f, 39.626808f, -46.781792f, -132.578033f, -6.489147f, + -23.532089f, 16.044214f, -71.385941f, -42.306988f, -142.892792f, -124.114395f, -26.544678f, 39.626808f, -8048.467285f, -69.854523f, 1809.758301f, -171.409134f, + -2.869304f, -11.155272f, 116.419769f, -23.502005f, -76.845306f, -92.283836f, -18.664721f, -46.781792f, -69.854530f, -1329.704834f, -35.750607f, 26.050083f, + -1.769890f, -11.784019f, 68.520813f, 43.622116f, 33.559555f, 41.981186f, -2.650122f, -132.578033f, 1809.758423f, -35.750607f, -1306.246704f, -81.942009f, + 0.390127f, -0.186719f, 4.576182f, 3.459679f, -2.748072f, 5.566006f, 0.010449f, -6.489147f, -171.409149f, 26.050083f, -81.942001f, -218.411270f, + -8.602416f, 3.247867f, -1.244849f, -1.473311f, 1.389639f, 1.193549f, -0.749351f, -3.831526f, -63.977875f, -5.851153f, 9.731353f, 3.762766f, + 3.247867f, -31.158295f, -1.860033f, 4.017265f, -4.594161f, 1.111136f, -0.570251f, 10.457798f, 101.742371f, 5.974397f, -29.646946f, -5.117320f, + -1.244849f, -1.860033f, -180.090790f, 66.379784f, -17.006353f, 31.490606f, -6.954518f, 15.675142f, -2.924051f, -51.747025f, 22.995018f, 27.119001f, + -1.473310f, 4.017266f, 66.379791f, -156.629517f, 84.327309f, -8.737753f, 13.449555f, 8.031604f, 3.398430f, 2.564645f, 23.766497f, 1.825905f, + 1.389639f, -4.594161f, -17.006353f, 84.327293f, -194.113434f, 66.407173f, 7.188343f, 13.696414f, 10.890992f, 22.594927f, 12.302410f, 9.738532f, + 1.193549f, 1.111136f, 31.490606f, -8.737754f, 66.407173f, -162.236801f, 56.553402f, 17.216257f, 115.981384f, 38.547184f, 1.763872f, 7.097052f, + -0.749351f, -0.570251f, -6.954517f, 13.449550f, 7.188342f, 56.553402f, -120.315659f, 2.011221f, 46.796513f, 58.099625f, 10.238644f, -4.947532f, + -3.831526f, 10.457799f, 15.675138f, 8.031604f, 13.696414f, 17.216261f, 2.011219f, -88.214516f, -358.424683f, -29.549349f, -19.958910f, -2.982261f, + -63.977875f, 101.742371f, -2.924051f, 3.398430f, 10.890991f, 115.981384f, 46.796513f, -358.424683f, -16459.796875f, -177.281921f, 882.743164f, -92.799385f, + -5.851152f, 5.974398f, -51.747017f, 2.564646f, 22.594927f, 38.547184f, 58.099625f, -29.549349f, -177.281921f, -313.395386f, -11.227232f, 55.211266f, + 9.731353f, -29.646946f, 22.995022f, 23.766500f, 12.302408f, 1.763873f, 10.238644f, -19.958918f, 882.743225f, -11.227232f, -192.809204f, -15.728045f, + 3.762767f, -5.117321f, 27.118999f, 1.825905f, 9.738532f, 7.097054f, -4.947530f, -2.982259f, -92.799385f, 55.211269f, -15.728045f, -105.412018f, + -14.256830f, -2.369603f, -4.383267f, 2.198855f, 0.019220f, -0.679427f, -2.574428f, 5.400897f, 1.071412f, 0.106907f, 1.327079f, 2.677950f, + -2.369603f, -22.438606f, 1.295039f, -4.309244f, -6.401002f, 0.194309f, -2.196638f, 15.858343f, 6.752327f, -6.119870f, 1.303229f, -0.311533f, + -4.383267f, 1.295039f, -37.935478f, 39.653362f, -15.988548f, -0.134974f, 6.192506f, 2.302801f, -5.721854f, 1.463135f, -1.312438f, -3.824724f, + 2.198855f, -4.309245f, 39.653366f, -92.374901f, 67.554337f, -3.709706f, -16.418154f, -5.289310f, -10.926604f, -3.034606f, 2.011261f, -3.425366f, + 0.019220f, -6.401002f, -15.988548f, 67.554329f, -118.435379f, 53.987152f, 0.083914f, 3.628703f, 11.506127f, -9.430386f, 3.335730f, 0.535830f, + -0.679426f, 0.194309f, -0.134974f, -3.709705f, 53.987152f, -103.065208f, 60.766655f, 5.174506f, 3.534084f, 1.888132f, -2.451842f, 0.595043f, + -2.574428f, -2.196638f, 6.192506f, -16.418154f, 0.083914f, 60.766647f, -77.825020f, -7.066206f, -9.501147f, -2.838846f, 2.729818f, 0.055436f, + 5.400897f, 15.858343f, 2.302801f, -5.289312f, 3.628702f, 5.174504f, -7.066205f, -51.364357f, -39.811016f, -5.072917f, 2.924570f, 10.896112f, + 1.071412f, 6.752328f, -5.721853f, -10.926604f, 11.506124f, 3.534082f, -9.501149f, -39.811012f, -93.637161f, 18.029125f, 2.729363f, -18.075464f, + 0.106908f, -6.119870f, 1.463135f, -3.034606f, -9.430385f, 1.888131f, -2.838846f, -5.072917f, 18.029125f, -28.455194f, 2.956357f, 16.863293f, + 1.327079f, 1.303229f, -1.312438f, 2.011261f, 3.335730f, -2.451841f, 2.729818f, 2.924570f, 2.729363f, 2.956357f, -10.622586f, -6.668186f, + 2.677950f, -0.311532f, -3.824724f, -3.425365f, 0.535831f, 0.595042f, 0.055436f, 10.896112f, -18.075462f, 16.863293f, -6.668186f, -47.191391f, + -9.240052f, 2.899430f, -1.061725f, -1.878852f, 1.384787f, -0.341924f, 0.387138f, -3.050452f, -34.497913f, 0.665648f, 3.172123f, 5.710633f, + 2.899430f, -28.464540f, -2.599636f, 2.343385f, -2.987666f, 2.706673f, 0.826991f, 8.178236f, 58.632381f, -6.619084f, -22.678297f, -7.513733f, + -1.061725f, -2.599636f, -168.556702f, 81.834229f, 2.535699f, 32.237877f, 3.761089f, 12.106804f, 80.076279f, -79.117699f, 15.459833f, 34.635460f, + -1.878852f, 2.343384f, 81.834229f, -199.355972f, 64.456390f, 2.859692f, 17.605833f, 14.360981f, 8.356211f, 15.654006f, 43.245403f, 35.328991f, + 1.384787f, -2.987666f, 2.535698f, 64.456375f, -197.841049f, 46.107910f, 19.035957f, 10.296391f, -4.554988f, 45.390419f, 10.640046f, 17.738880f, + -0.341924f, 2.706673f, 32.237885f, 2.859688f, 46.107910f, -193.370590f, 74.545746f, 13.889868f, 120.411064f, 69.282364f, 1.826012f, 8.071488f, + 0.387138f, 0.826990f, 3.761087f, 17.605829f, 19.035957f, 74.545746f, -173.431549f, -5.219500f, 77.031425f, 112.113403f, -0.166995f, 3.456159f, + -3.050452f, 8.178238f, 12.106802f, 14.360980f, 10.296390f, 13.889872f, -5.219500f, -66.011856f, -245.560532f, -53.745152f, -21.376526f, 7.093097f, + -34.497917f, 58.632385f, 80.076279f, 8.356211f, -4.554988f, 120.411072f, 77.031425f, -245.560532f, -12485.017578f, -211.927429f, 791.254944f, -708.115784f, + 0.665648f, -6.619084f, -79.117699f, 15.654002f, 45.390419f, 69.282356f, 112.113403f, -53.745152f, -211.927429f, -775.154602f, -7.915978f, 73.130432f, + 3.172123f, -22.678297f, 15.459837f, 43.245403f, 10.640046f, 1.826011f, -0.166995f, -21.376526f, 791.254944f, -7.915982f, -312.138367f, -76.008308f, + 5.710633f, -7.513731f, 34.635460f, 35.328983f, 17.738880f, 8.071489f, 3.456159f, 7.093094f, -708.115784f, 73.130432f, -76.008293f, -469.943726f +}; + +const float lvm_music[N_MIXTURES] = +{ + 27.932661f, 30.347250f, 34.528702f, 31.239647f, 20.447638f, 33.589111f +}; + +const float m_noise[N_MIXTURES*N_FEATURES] = +{ + 0.452427f, 0.570086f, 0.242006f, 0.342721f, 0.403700f, 0.415107f, 0.444218f, 0.438761f, 0.034564f, 0.893050f, 0.819168f, 0.404974f, + 0.436768f, 0.457530f, 0.286204f, 0.393398f, 0.429530f, 0.444983f, 0.474495f, 0.377982f, 0.032033f, 0.980933f, 0.864315f, 0.377762f, + 0.554771f, 0.507113f, 0.244596f, 0.401393f, 0.425160f, 0.441338f, 0.467793f, 0.361573f, 0.031537f, 0.971703f, 0.866892f, 0.372985f, + 0.482864f, 0.545745f, 0.098616f, 0.246756f, 0.304649f, 0.303124f, 0.352083f, 0.363268f, 0.031057f, 0.901759f, 0.838419f, 0.339094f, + 0.421798f, 0.491610f, 0.266544f, 0.367277f, 0.407442f, 0.415130f, 0.458496f, 0.395402f, 0.035484f, 0.951506f, 0.861898f, 0.362091f, + 0.422524f, 0.475384f, 0.321804f, 0.436169f, 0.468526f, 0.481682f, 0.505572f, 0.389095f, 0.048487f, 0.967269f, 0.878799f, 0.409561f +}; + +const float invV_noise[N_MIXTURES*N_FEATURES*N_FEATURES] = +{ + -10.867715f, -0.756548f, -0.787901f, 4.638586f, -4.208551f, -1.593690f, 1.654504f, 0.517274f, -24.544769f, -2.342500f, 1.593914f, 1.892730f, + -0.756548f, -42.676064f, -5.171525f, -22.601748f, -3.989791f, -1.960918f, 9.223408f, 12.652583f, 16.718012f, 10.374084f, -17.742804f, -14.035854f, + -0.787901f, -5.171525f, -115.159836f, 77.010605f, -22.974529f, 22.149885f, -7.457938f, 51.154774f, 20.176580f, -1.104116f, 17.582054f, -18.231829f, + 4.638585f, -22.601746f, 77.010605f, -162.083023f, 69.046974f, -0.931657f, 9.922201f, 6.555853f, 49.297676f, 18.854517f, -9.951534f, 16.527628f, + -4.208551f, -3.989791f, -22.974525f, 69.046974f, -181.796692f, 112.212860f, -28.314665f, 9.765093f, 17.263042f, -17.941118f, -20.316977f, -12.281874f, + -1.593690f, -1.960918f, 22.149881f, -0.931659f, 112.212860f, -230.312469f, 120.808189f, -3.664834f, 21.109715f, 8.984108f, 15.273976f, -10.366921f, + 1.654504f, 9.223406f, -7.457942f, 9.922205f, -28.314672f, 120.808205f, -152.423096f, -1.527340f, -7.447964f, 5.038412f, 13.851591f, -12.278207f, + 0.517274f, 12.652583f, 51.154770f, 6.555853f, 9.765094f, -3.664836f, -1.527341f, -113.809120f, -127.203827f, -2.824038f, -50.058937f, -1.399267f, + -24.544767f, 16.718014f, 20.176580f, 49.297676f, 17.263042f, 21.109715f, -7.447963f, -127.203827f, -6696.807617f, -22.621326f, 415.747192f, -168.268478f, + -2.342500f, 10.374086f, -1.104114f, 18.854517f, -17.941120f, 8.984108f, 5.038413f, -2.824039f, -22.621326f, -153.911545f, 9.088697f, 20.155067f, + 1.593914f, -17.742804f, 17.582056f, -9.951534f, -20.316977f, 15.273976f, 13.851592f, -50.058945f, 415.747162f, 9.088697f, -180.485260f, -2.179248f, + 1.892730f, -14.035856f, -18.231823f, 16.527628f, -12.281875f, -10.366921f, -12.278206f, -1.399268f, -168.268478f, 20.155067f, -2.179248f, -92.283646f, + -23.031761f, -1.252800f, 2.168407f, 5.677273f, -1.038399f, -5.394459f, 4.921468f, -0.398360f, -7.562253f, 64.160614f, -4.832063f, 1.192536f, + -1.252800f, -99.841995f, 18.003206f, -17.730101f, -6.070672f, 16.703362f, -1.826001f, 24.508341f, 95.143112f, 31.486519f, -75.776428f, -4.459583f, + 2.168407f, 18.003206f, -298.278900f, 136.582794f, 23.557480f, 32.080963f, -44.544701f, 44.470726f, 121.132362f, 294.113434f, -22.118645f, 3.540136f, + 5.677273f, -17.730099f, 136.582779f, -552.121826f, 236.890076f, 45.754177f, 49.528828f, -18.333956f, -155.456558f, 137.723495f, 87.803368f, 9.539282f, + -1.038398f, -6.070671f, 23.557480f, 236.890076f, -779.760498f, 250.522018f, 101.655136f, 9.155396f, -82.543655f, -398.953156f, 95.902740f, 4.389515f, + -5.394459f, 16.703358f, 32.080971f, 45.754185f, 250.522049f, -825.768005f, 305.349487f, -6.825818f, 49.064461f, -530.656738f, -41.630035f, 0.097057f, + 4.921468f, -1.825999f, -44.544685f, 49.528828f, 101.655106f, 305.349457f, -714.934082f, 14.071314f, 81.227341f, -137.562592f, -2.118532f, -2.266444f, + -0.398360f, 24.508341f, 44.470741f, -18.333960f, 9.155393f, -6.825818f, 14.071318f, -306.676453f, 267.131439f, -29.354313f, -247.414047f, -3.381219f, + -7.562254f, 95.143112f, 121.132362f, -155.456558f, -82.543648f, 49.064457f, 81.227341f, 267.131439f, -18849.244141f, -929.838013f, 3582.389648f, -91.670364f, + 64.160622f, 31.486523f, 294.113434f, 137.723495f, -398.953186f, -530.656738f, -137.562607f, -29.354321f, -929.838013f, -15657.494141f, -160.551666f, -23.622292f, + -4.832063f, -75.776428f, -22.118641f, 87.803375f, 95.902733f, -41.630043f, -2.118535f, -247.414047f, 3582.389648f, -160.551666f, -2443.248535f, -102.662750f, + 1.192536f, -4.459581f, 3.540133f, 9.539283f, 4.389517f, 0.097059f, -2.266439f, -3.381226f, -91.670372f, -23.622292f, -102.662750f, -246.260574f, + -11.285410f, 5.316821f, 1.028375f, 1.780153f, -1.713055f, -6.356722f, 3.452291f, -0.472106f, 5.616539f, 22.361168f, -4.266212f, 2.444066f, + 5.316821f, -59.978729f, -45.510380f, 0.510493f, -4.121831f, 5.250934f, -14.358817f, 2.281706f, 4.310630f, 4.492869f, 17.377964f, 5.232576f, + 1.028376f, -45.510380f, -192.404053f, 60.491817f, 29.311884f, 10.877782f, -13.830601f, 4.475446f, 14.358991f, 170.638504f, 103.112320f, 3.708024f, + 1.780153f, 0.510493f, 60.491817f, -566.125488f, 303.482666f, -24.292496f, -8.399674f, -1.485864f, -37.162815f, -301.527344f, 10.013409f, 11.255829f, + -1.713055f, -4.121831f, 29.311880f, 303.482666f, -852.739014f, 287.208618f, 7.622868f, 2.283498f, -27.422876f, -496.049957f, -5.396815f, -1.631967f, + -6.356722f, 5.250934f, 10.877782f, -24.292484f, 287.208618f, -723.304810f, 301.939606f, -18.888754f, -49.648453f, -140.429428f, 26.881662f, 4.222802f, + 3.452292f, -14.358817f, -13.830603f, -8.399690f, 7.622864f, 301.939575f, -496.315796f, 24.400175f, 203.557098f, -224.619278f, -47.202961f, -9.425015f, + -0.472106f, 2.281706f, 4.475447f, -1.485866f, 2.283498f, -18.888754f, 24.400175f, -354.005493f, 136.772644f, -115.911537f, -131.393005f, 0.959444f, + 5.616539f, 4.310630f, 14.358991f, -37.162819f, -27.422880f, -49.648449f, 203.557098f, 136.772644f, -20332.845703f, -321.084869f, 3009.444580f, -97.580765f, + 22.361168f, 4.492869f, 170.638519f, -301.527344f, -496.049957f, -140.429428f, -224.619293f, -115.911537f, -321.084839f, -7067.310059f, -220.679733f, -46.764927f, + -4.266212f, 17.377964f, 103.112320f, 10.013409f, -5.396815f, 26.881662f, -47.202957f, -131.393005f, 3009.444336f, -220.679733f, -2442.017334f, -122.001373f, + 2.444066f, 5.232576f, 3.708023f, 11.255831f, -1.631966f, 4.222802f, -9.425015f, 0.959446f, -97.580765f, -46.764931f, -122.001373f, -270.966095f, + -14.192688f, 3.186916f, -7.950537f, 12.989626f, 5.455102f, 1.765226f, -5.165048f, 0.461338f, 7.198293f, -20.877787f, -2.402384f, 0.581967f, + 3.186916f, -44.923344f, -55.269123f, 8.982286f, -0.746719f, 13.665676f, 5.123918f, 2.567272f, -14.412151f, -21.068356f, 5.512080f, 3.727387f, + -7.950538f, -55.269123f, -874.676270f, 396.753632f, -241.704224f, 70.721024f, -240.685715f, 31.769787f, -186.425156f, -72.526421f, 58.346741f, 10.030197f, + 12.989626f, 8.982285f, 396.753632f, -538.253601f, 134.091171f, 33.957142f, -5.240913f, 40.302223f, 65.792999f, 256.190460f, 41.462269f, 59.464478f, + 5.455101f, -0.746719f, -241.704254f, 134.091171f, -942.252197f, 384.468231f, 36.093376f, 5.026894f, 111.673508f, 64.876976f, -19.179228f, 18.067732f, + 1.765226f, 13.665678f, 70.721085f, 33.957142f, 384.468231f, -885.075134f, 358.333008f, 13.728846f, 74.583847f, 277.755707f, 15.872023f, 32.199970f, + -5.165048f, 5.123920f, -240.685776f, -5.240921f, 36.093372f, 358.333008f, -694.631653f, 22.914997f, 82.867088f, 154.286697f, 2.264358f, 21.074474f, + 0.461338f, 2.567272f, 31.769791f, 40.302223f, 5.026892f, 13.728846f, 22.915001f, -341.417511f, -72.276520f, -87.553932f, -17.271832f, 7.437448f, + 7.198294f, -14.412151f, -186.425171f, 65.792999f, 111.673508f, 74.583847f, 82.867088f, -72.276520f, -16628.691406f, -258.116119f, 387.521759f, -260.230133f, + -20.877787f, -21.068354f, -72.526451f, 256.190460f, 64.876984f, 277.755707f, 154.286697f, -87.553932f, -258.116089f, -851.111816f, 3.469927f, 2.253677f, + -2.402384f, 5.512080f, 58.346741f, 41.462273f, -19.179226f, 15.872023f, 2.264359f, -17.271832f, 387.521759f, 3.469929f, -327.105011f, -45.187340f, + 0.581967f, 3.727389f, 10.030209f, 59.464478f, 18.067736f, 32.199970f, 21.074471f, 7.437444f, -260.230133f, 2.253681f, -45.187363f, -348.881165f, + -20.546539f, -1.232953f, -6.539483f, 7.977976f, -1.242327f, -4.323449f, 4.044850f, -8.261212f, -61.714569f, -16.814053f, 0.693824f, 2.217177f, + -1.232953f, -81.245918f, -33.514919f, -26.628014f, 2.160939f, -0.234839f, -0.764257f, 21.764839f, 133.689529f, 9.364232f, -27.287352f, -6.621866f, + -6.539483f, -33.514919f, -321.563904f, 105.228661f, 0.660729f, -32.550903f, -45.134315f, 42.045963f, -200.154724f, -42.022831f, 200.115005f, 19.959410f, + 7.977976f, -26.628016f, 105.228653f, -362.669098f, 100.723396f, 10.423860f, 45.250904f, -3.221930f, -63.687748f, -41.052856f, -5.156573f, 12.700191f, + -1.242327f, 2.160941f, 0.660730f, 100.723396f, -410.276917f, 189.899841f, 1.538413f, 21.637842f, -26.361103f, 35.868237f, 46.390850f, 13.527671f, + -4.323449f, -0.234840f, -32.550911f, 10.423860f, 189.899841f, -359.953278f, 149.268143f, 13.839684f, 104.534042f, 43.236813f, -23.356220f, -8.712662f, + 4.044850f, -0.764257f, -45.134308f, 45.250904f, 1.538413f, 149.268143f, -274.089874f, -8.017480f, 39.217266f, 23.817112f, 13.071558f, 8.212641f, + -8.261212f, 21.764839f, 42.045967f, -3.221937f, 21.637842f, 13.839684f, -8.017480f, -250.062653f, 77.902710f, -1.225836f, -98.802437f, 0.740895f, + -61.714565f, 133.689514f, -200.154709f, -63.687748f, -26.361105f, 104.534027f, 39.217266f, 77.902695f, -12793.175781f, 257.379974f, 1953.936523f, -236.987503f, + -16.814053f, 9.364232f, -42.022831f, -41.052856f, 35.868237f, 43.236813f, 23.817108f, -1.225832f, 257.379974f, -1194.391846f, -211.503952f, -22.654963f, + 0.693823f, -27.287352f, 200.115005f, -5.156573f, 46.390850f, -23.356216f, 13.071561f, -98.802437f, 1953.936523f, -211.503983f, -1273.349854f, -88.061317f, + 2.217178f, -6.621865f, 19.959414f, 12.700191f, 13.527678f, -8.712662f, 8.212641f, 0.740895f, -236.987518f, -22.654963f, -88.061317f, -364.010010f, + -23.764925f, -0.313664f, -1.392676f, 1.488295f, 1.913436f, -4.066601f, 6.848008f, -3.074351f, -7.675101f, 9.171298f, 3.117799f, 2.142688f, + -0.313664f, -88.759735f, -8.855761f, -26.637909f, 5.178853f, 10.666278f, 2.244489f, 21.984133f, 16.797499f, 4.685480f, 13.074540f, -2.708393f, + -1.392676f, -8.855759f, -175.915054f, 83.474174f, 41.251793f, 14.369057f, -12.605553f, 33.395245f, 65.670242f, 39.710125f, 36.098553f, -9.562349f, + 1.488295f, -26.637909f, 83.474182f, -383.095245f, 216.683212f, 12.198986f, 32.383698f, -14.022625f, 7.763216f, -100.727264f, -28.525242f, -5.235438f, + 1.913436f, 5.178854f, 41.251801f, 216.683212f, -586.877808f, 253.507355f, 29.591257f, 7.710151f, -31.813087f, -112.656593f, 20.279724f, -7.102311f, + -4.066601f, 10.666278f, 14.369057f, 12.198978f, 253.507355f, -597.128113f, 296.967621f, 6.174671f, -41.961372f, -36.203259f, -20.597570f, -14.877533f, + 6.848009f, 2.244488f, -12.605548f, 32.383701f, 29.591269f, 296.967590f, -456.794678f, 26.321606f, -34.872383f, 28.424320f, 34.979023f, -8.548788f, + -3.074351f, 21.984133f, 33.395245f, -14.022625f, 7.710150f, 6.174670f, 26.321606f, -265.545593f, 2.918175f, 0.831582f, -125.449432f, -11.139709f, + -7.675101f, 16.797503f, 65.670242f, 7.763219f, -31.813070f, -41.961380f, -34.872383f, 2.918175f, -1731.894409f, -210.794144f, 739.213074f, -97.542229f, + 9.171299f, 4.685479f, 39.710129f, -100.727264f, -112.656593f, -36.203262f, 28.424320f, 0.831581f, -210.794113f, -2326.243652f, -106.282173f, 1.036536f, + 3.117799f, 13.074540f, 36.098553f, -28.525242f, 20.279724f, -20.597570f, 34.979023f, -125.449432f, 739.213074f, -106.282112f, -1878.532593f, -113.480858f, + 2.142687f, -2.708396f, -9.562349f, -5.235439f, -7.102309f, -14.877532f, -8.548790f, -11.139709f, -97.542229f, 1.036536f, -113.480865f, -101.406532f +}; + +const float lvm_noise[N_MIXTURES] = +{ + 28.723963f, 41.180500f, 39.296734f, 38.508724f, 37.029205f, 35.496319f +}; + +const float SF[N_FEATURES*2] = +{ + 0.0048f, -0.0952f, + 1.0002f, 0, + 0.6226f, -0.0695f, + 0.5497f, -0.1265f, + 0.4963f, -0.2230f, + 0.5049f, -0.4103f, + 0.5069f, -0.5717f, + 0.0041f, 0, + 0.0022f, -0.0029f, + 0.0630f, 1.0015f, + 0.0684f, 0.9103f, + 0.1159f, -0.2931f +}; + +const float SF_8k[N_FEATURES*2] = +{ + 0.0041f, 0, + 0.8572f, 0.1020f, + 0.6739f, -0.1000f, + 0.6257f, -0.1678f, + 0.5495f, -0.2380f, + 0.5793f, -0.4646f, + 0.2502f, 0, + 0.0041f, 0, + 0.0020f, 0, + 0.0630f, 1.0015f, + 0.0598f, 0.8967f, + 0.0631f, 0 +}; + + +/* searching thresholds for quantization of peak gains */ +const float thren_pg[44] = +{ + 120193.5539509f, 101070.3286539f, + 84989.6770536f, 71467.5147680f, + 60096.7769755f, 50535.1643270f, + 42494.8385268f, 35733.7573840f, + 30048.3884877f, 25267.5821635f, + 19483.9693722f, 13777.2468675f, + 9741.9846861f, 6888.6234338f, + 4870.9923431f, 3444.3117169f, + 2435.4961715f, 1722.1558584f, + 1217.7480858f, 861.0779292f, + 608.8740429f, 430.5389646f, + 304.4370214f, 215.2694823f, + 152.2185107f, 107.6347412f, + 76.1092554f, 53.8173706f, + 38.0546277f, 26.9086853f, + 19.0273138f, 13.4543426f, + 9.5136569f, 6.7271713f, + 4.7568285f, 3.3635857f, + 2.3784142f, 1.6817928f, + 1.1892071f, 0.840896f, + 0.594604f, 0.420448f, + 0.297302f, 0.210224f +}; + +/* Huffmann coding - searching thresholds for quantization of peak gains */ +const short huffnorm_e[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 short huffnorm_n[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 short huffsizn_e[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 short huffsizn_n[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 short resize_huffnorm[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 short huffnorm[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 short pgain_huffnorm[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 short hessize[8]= +{ + 7, 5, 3, 2, 1, 4, 6, 7 +}; + +const short hescode[8]= +{ + 11, 3, 1, 1, 1, 0, 4, 10 +}; + +/*----------------------------------------------------------------------------------* + * BWD + *----------------------------------------------------------------------------------*/ + +const float hann_window_320[BWD_TOTAL_WIDTH/2] = +{ + 0.0f, 0.000096984948331f, 0.000387902169007f, 0.000872638803658f, + 0.001551006803657f, 0.002422743003060f, 0.003487509220708f, 0.004744892391413f, + 0.006194404726209f, 0.007835483901579f, 0.009667493277608f, 0.011689722144956f, + 0.013901386000576f, 0.016301626852047f, 0.018889513550430f, 0.021664042151495f, + 0.024624136305188f, 0.027768647673197f, 0.031096356374430f, 0.034605971458262f, + 0.038296131405342f, 0.042165404655783f, 0.046212290164521f, 0.050435217983627f, + 0.054832549871356f, 0.059402579927684f, 0.064143535256096f, 0.069053576651361f, + 0.074130799313035f, 0.079373233584409f, 0.084778845716614f, 0.090345538657597f, + 0.096071152865649f, 0.101953467147178f, 0.107990199518396f, 0.114179008090596f, + 0.120517491978659f, 0.127003192232455f, 0.133633592790768f, 0.140406121457376f, + 0.147318150898908f, 0.154366999664091f, 0.161549933223991f, 0.168864165032848f, + 0.176306857609086f, 0.183875123636085f, 0.191566027082286f, 0.199376584340196f, + 0.207303765383847f, 0.215344494944262f, 0.223495653702478f, 0.231754079499652f, + 0.240116568563785f, 0.248579876752599f, 0.257140720812064f, 0.265795779650105f, + 0.274541695624985f, 0.283375075847868f, 0.292292493499057f, 0.301290489157390f, + 0.310365572142292f, 0.319514221867944f, 0.328732889209064f, 0.338017997877748f, + 0.347365945810858f, 0.356773106567405f, 0.366235830735390f, 0.375750447347553f, + 0.385313265305494f, 0.394920574811589f, 0.404568648808175f, 0.414253744423419f, + 0.423972104423331f, 0.433719958669339f, 0.443493525580883f, 0.453289013602435f, + 0.463102622674396f, 0.472930545707291f, 0.482768970058690f, 0.492614079012283f, + 0.502462053258538f, 0.512309072376361f, 0.522151316315189f, 0.531984966876945f, + 0.541806209197260f, 0.551611233225420f, 0.561396235202429f, 0.571157419136643f, + 0.580890998276382f, 0.590593196578969f, 0.600260250175597f, 0.609888408831494f, + 0.619473937400779f, 0.629013117275481f, 0.638502247828131f, 0.647937647847382f, + 0.657315656966103f, 0.666632637081372f, 0.675884973765851f, 0.685069077669957f, + 0.694181385914321f, 0.703218363471965f, 0.712176504539683f, 0.721052333898081f, + 0.729842408259752f, 0.738543317605065f, 0.747151686505047f, 0.755664175430844f, + 0.764077482049264f, 0.772388342503876f, 0.780593532681191f, 0.788689869461429f, + 0.796674211953372f, 0.804543462712845f, 0.812294568944333f, 0.819924523685287f, + 0.827430366972643f, 0.834809186991105f, 0.842058121202763f, 0.849174357457574f, + 0.856155135084319f, 0.862997745961565f, 0.869699535568266f, 0.876257904013544f, + 0.882670307045301f, 0.888934257037231f, 0.895047323953867f, 0.901007136293294f, + 0.906811382007145f, 0.912457809397536f, 0.917944227990593f, 0.923268509386220f, + 0.928428588083795f, 0.933422462283452f, 0.938248194662667f, 0.942903913127819f, + 0.947387811540448f, 0.951698150417930f, 0.955833257608292f, 0.959791528938907f, + 0.963571428838810f, 0.967171490934417f, 0.970590318618383f, 0.973826585591401f, + 0.976879036376732f, 0.979746486807249f, 0.982427824484824f, 0.984922009211872f, + 0.987228073394887f, 0.989345122419805f, 0.991272334999066f, 0.993008963490220f, + 0.994554334185968f, 0.995907847575523f, 0.997068978577180f, 0.998037276742018f, + 0.998812366428647f, 0.999393946948934f, 0.999781792684653f, 0.999975753175008f +}; + +/*----------------------------------------------------------------------------------* + * Starting line for the noise measurement in TCX. + *----------------------------------------------------------------------------------*/ +const int startLineWB[11] = { 8, 23, 36, 45, 66, 128 /* 13.2kbps */, 200, 320, 320, 320 /* 48kbps */, 320 }; +const int startLineSWB[9] = { 8, 44, 96 /* 13.2kbps */, 160, 320, 320, 256 /* 48kbps */, 341, 640 }; diff --git a/lib_enc/rom_enc.h b/lib_enc/rom_enc.h new file mode 100644 index 000000000..e9a69ad32 --- /dev/null +++ b/lib_enc/rom_enc.h @@ -0,0 +1,148 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#ifndef ROM_ENC_H +#define ROM_ENC_H + +#include "wmc_auto.h" +#include +#include "options.h" +#include "stat_enc.h" +#include "cnst.h" + +/*----------------------------------------------------------------------------------* + * General tables + *----------------------------------------------------------------------------------*/ + +extern const float sqrt_han_window[]; /* Half of the square root hanning window */ +extern const short tipos[]; /* Starting points for pulse position search in Algebraic innovation codebook */ +extern const Float32 E_ROM_inter4_1[PIT_UP_SAMP * L_INTERPOL1 + 1]; +extern const Float32 E_ROM_inter6_1[PIT_UP_SAMP6 * L_INTERPOL1 + 1]; +extern const Float32 E_ROM_inter4_1[PIT_UP_SAMP * L_INTERPOL1 + 1]; +extern const Float32 E_ROM_inter6_1[PIT_UP_SAMP6 * L_INTERPOL1 + 1]; +extern const float W_HIST[DTX_HIST_SIZE]; /* CNG & DTX - table for calculation of average excitation energy */ + +extern const short bwd_start_bin[]; +extern const short bwd_end_bin[]; + +extern const float h_fir[]; /* 2nd order fir filter for wsp, decimation by 2 */ + +extern const float preemphCompensation[]; + +/*----------------------------------------------------------------------------------* + * VAD tables + *----------------------------------------------------------------------------------*/ +extern const short hangover_hd_tbl[3]; +extern const short hangover_sf_tbl[6]; +/*----------------------------------------------------------------------------------* + * Open-loop pitch search tables + *----------------------------------------------------------------------------------*/ + +extern const short nb_sect_12k8[]; +extern const short nb_subsect_12k8[]; +extern const short len_12k8[]; +extern const short len1_12k8[]; +extern const short sublen_12k8[]; +extern const short sublen1_12k8[]; +extern const short pit_max_12k8[]; +extern const short sec_length_12k8[]; +extern const short sec_length1_12k8[]; + +/*----------------------------------------------------------------------------------* + * LSF quantizer + *----------------------------------------------------------------------------------*/ + +extern const int lsf_numlevels[TCXLPC_NUMSTAGES]; +extern const int lsf_ind_numlevels[TCXLPC_IND_NUMSTAGES]; + +extern const short lsf_unified_fit_model_nb[4][16]; +extern const short lsf_unified_fit_model_wb[4][16]; +extern const short lsf_unified_fit_model_wbhb[4][16]; + +extern const float Freq_Weight_Com[160]; +extern const float Freq_Weight_UV[160]; + +/*----------------------------------------------------------------------------------* + * Speech/music classification + *----------------------------------------------------------------------------------*/ + +extern const float w_spmus[HANG_LEN][HANG_LEN]; + +extern const float m_speech[]; +extern const float invV_speech[]; +extern const float lvm_speech[]; + +extern const float m_music[]; +extern const float invV_music[]; +extern const float lvm_music[]; + +extern const float m_noise[]; +extern const float invV_noise[]; +extern const float lvm_noise[]; + +extern const float SF[]; +extern const float SF_8k[]; + +/*----------------------------------------------------------------------------------* + * SWB TBE + *----------------------------------------------------------------------------------*/ + +extern const float lpc_weights[]; + +/*----------------------------------------------------------------------------------* + * WB, SWB and FB bandwidth detector + *----------------------------------------------------------------------------------*/ + +extern const float hann_window_320[]; + +/*----------------------------------------------------------------------------------* + * Huffman coding + *----------------------------------------------------------------------------------*/ + +extern const short huffsizn_e[32]; +extern const short huffsizn_n[32]; + +extern const short huffnorm_e[32]; +extern const short huffnorm_n[32]; +extern const short hessize[8]; +extern const short hescode[8]; + +/*----------------------------------------------------------------------------------* + * VAD + *----------------------------------------------------------------------------------*/ + +extern const short BAND_NUM_TAB[5]; + +extern const float M_inr[16]; +extern const float M_ini[16]; +extern const float M_r[8]; +extern const float M_i[8]; +extern const float M_Wr[16]; +extern const float M_Wi[16]; + +extern const short SP_CENTER_BAND_NUM_TAB[5]; +extern const float DELTA1[5]; +extern const float DELTA2[5]; + +extern const int NREGION_INDEX_NB[9]; +extern const int NREGION_INDEX_WB[13]; +extern const int NREGION_INDEX_SWB[16]; +extern const int NREGION_INDEX_FB[16]; +extern const int ENERGY_BAND_NUM[4]; +extern const int *const REGION_INDEX[4]; +extern const float MAX_LF_SNR_TAB[4]; + +extern const float COMVAD_INIT_SNR_DELTA[5]; +extern const float LS_MIN_SELENCE_SNR[3]; +extern const float LT_MIN_SILENCE_SNR[3]; + +/*----------------------------------------------------------------------------------* + * Starting line for the noise measurement in TCX. + *----------------------------------------------------------------------------------*/ +extern const int startLineWB[11]; +extern const int startLineSWB[9]; + + +#endif + diff --git a/lib_enc/rst_enc.c b/lib_enc/rst_enc.c new file mode 100644 index 000000000..656f0f1e1 --- /dev/null +++ b/lib_enc/rst_enc.c @@ -0,0 +1,59 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + + +/*-------------------------------------------------------------------* + * CNG_reset_enc() + * + * Reset encoder static variables after a CNG frame + *-------------------------------------------------------------------*/ + +void CNG_reset_enc( + Encoder_State *st, /* i/o: encoder state structure */ + LPD_state *mem, /* i/o: encoder memories */ + float *pitch_buf, /* o : floating pitch for each subframe */ + float *voice_factors /* o : voicing factors */ + ,short VBR_cng_reset_flag +) +{ + init_gp_clip(st->clip_var); + mvr2r( UVWB_Ave, st->mem_AR, M ); + set_f(st->mem_MA, 0, M ); + mem->mem_w0 = 0.0f; + mem->tilt_code = 0.0f; + mem->gc_threshold = 0.0f; + if( VBR_cng_reset_flag ) + { + set_f( mem->mem_syn, 0, M ); + } + set_f( st->dispMem, 0, 8 ); + + /* last good received frame for FEC in ACELP */ + st->clas = UNVOICED_CLAS; + /* reset the pitch buffer in case of FRAME_NO_DATA or SID frames */ + if(st->L_frame == L_FRAME ) + { + set_f( pitch_buf, (float)L_SUBFR, NB_SUBFR ); + } + else /* st->L_frame == L_FRAME16k */ + { + set_f( pitch_buf, (float)L_SUBFR16k, NB_SUBFR16k ); + } + + set_f( voice_factors, 1.0, NB_SUBFR16k ); + + /* Reset active frame counter */ + st->act_cnt2 = 0; + + /* deactivate bass post-filter */ + st->bpf_off = 1; + + return; +} diff --git a/lib_enc/set_impulse.c b/lib_enc/set_impulse.c new file mode 100644 index 000000000..b0859aaa1 --- /dev/null +++ b/lib_enc/set_impulse.c @@ -0,0 +1,302 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "cnst.h" +#include "wmc_auto.h" +#include "rom_com.h" +#include "prot.h" + +/*-----------------------------------------------------------------* + * Local constant + *-----------------------------------------------------------------*/ +#define INPOL 4 /* +- range in samples for impulse position searching */ + +/*-----------------------------------------------------------------* + * Local function prototype + *-----------------------------------------------------------------*/ +static void convolve_tc(const float g[], const float h[], float y[], const short L_1, const short L_2); +static void correlate_tc(const float *x, float *y, const float *h, const short start, const short L_1, + const short L_2); +static void convolve_tc2(const float g[], const float h[], float y[], const short 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( + const float xn[], /* i : target signal */ + const float h_orig[], /* i : impulse response of weighted synthesis filter */ + float exc[], /* o : adaptive codebook excitation */ + float y1[], /* o : filtered adaptive codebook excitation */ + short *imp_shape, /* o : adaptive codebook index */ + short *imp_pos, /* o : position of the glotal impulse center index */ + float *gain_trans /* o : transition gain */ +) +{ + float rr[L_SUBFR]; /* criterion: nominator coeficients */ + float dd[L_SUBFR]; /* criterion: denominator coeficients */ + float gh[L_SUBFR]; /* convolution of 'g' and 'h' filters */ + float krit, krit_max; + short i, j, m; + short start1, start2, end1; + + + krit_max = -1.0e+12f; + + /* main loop */ + /* impulse */ + for( m = 0; m < NUM_IMPULSE; m++ ) + { + /* set searching ranges */ + if( *imp_posINPOL ) + { + start1 = *imp_pos-INPOL; + } + else + { + start1 = 0; + } + if( start1>L_IMPULSE2 ) + { + start2 = start1; + } + else + { + start2 = L_IMPULSE2; + } + + /*-----------------------------------------------------* + * nominator & DEnominator, gh=conv(g,h) + *-----------------------------------------------------*/ + if( start1 */ + for( i=0; i < L_SUBFR; i++ ) + { + rr[start1] += gh[i]*gh[i]; + dd[start1] += gh[i]*xn[i]; + } + for( i=start1+1; i */ + for( j=L_SUBFR-1; j > 0; j-- ) + { + gh[j] = gh[j-1] + glottal_cdbk[m*L_IMPULSE+L_IMPULSE2-i]*h_orig[j]; + rr[i] += gh[j]*gh[j]; + dd[i] += gh[j]*xn[j]; + } + gh[0] = glottal_cdbk[m*L_IMPULSE+L_IMPULSE2-i]*h_orig[0]; + rr[i] += gh[0]*gh[0]; + dd[i] += gh[0]*xn[0]; + /* move rr and dd into rr[i] and dd[i] */ + } + /* complete convolution(excitation,h_orig) */ + for( j=L_SUBFR-1; j > 0; j-- ) + { + gh[j] = gh[j-1] + glottal_cdbk[m*L_IMPULSE]*h_orig[j]; + } + } + else + { + convolve_tc( &glottal_cdbk[m*L_IMPULSE], &h_orig[0], gh, L_IMPULSE, L_SUBFR ); + } + if( end1>=start2 ) + { + /* Denominator row */ + rr[L_SUBFR-1] = 0; + for (j=0; j <= L_IMPULSE2; j++) + { + rr[L_SUBFR-1] += gh[j]*gh[j]; + } + /* move rr into rr[L_SUBFFR-1 */ + /* 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]; + } + + /* nominator rows */ + correlate_tc( xn, &dd[L_IMPULSE2], gh, (short) (start2-L_IMPULSE2), L_SUBFR, (short)(end1-L_IMPULSE2) ); + } + + /*------------------------------------------------------* + * maxim. criterion + *------------------------------------------------------*/ + for( i=start1; i < end1; i++ ) + { + krit = (float)(dd[i]*dd[i])/rr[i]; + if( krit > krit_max ) + { + krit_max = krit; + *imp_pos = i; + *imp_shape = m; + } + } + } + + /*--------------------------------------------------------* + * Build the excitation using found codeword + *--------------------------------------------------------*/ + + set_f(exc, 0, L_SUBFR); + set_f(y1, 0, L_SUBFR); + for( i=(*imp_pos-L_IMPULSE2); i<=(*imp_pos+L_IMPULSE2); i++ ) + { + if( (i >= 0) && (i < L_SUBFR) ) + { + exc[i] = glottal_cdbk[(*imp_shape)*L_IMPULSE+i-(*imp_pos)+L_IMPULSE2]; + } + } + + /*------------------------------------------------------* + * Form filtered excitation, find gain_trans + *------------------------------------------------------*/ + + convolve_tc2( exc, h_orig, y1, *imp_pos ); + + /* Find the ACELP correlations and the pitch gain (for current subframe) */ + *gain_trans = dotp( xn, y1, L_SUBFR )/(dotp( y1, y1, L_SUBFR ) + 0.01f); + + return; + +} + +/*-------------------------------------------------------------------* + * convolve_tc: + * + * convolution for different vectors' lengths + *-------------------------------------------------------------------*/ +static void convolve_tc( + const float g[], /* i : input vector */ + const float h[], /* i : impulse response (or second input vector) */ + float y[], /* o : output vetor (result of convolution) */ + const short L_1, /* i : vector h size */ + const short L_2 /* i : vector g size */ +) +{ + float temp; + short i, n; + + + for( n = 0; n < L_2; n++ ) + { + temp = g[0] * h[n]; + for( i = 1; i < ((n L_SUBFR) + { + i_end = L_SUBFR; + } + for( n = i_start; n < L_SUBFR; n++ ) + { + temp = g[0] * h[n]; + i_end2 = ((n<=i_end) ? (n+1) : i_end); + for( i = 1; i < i_end2; i++ ) + { + temp += g[i] * h[n-i]; + } + y[n] = temp; + } + return; +} + +/*-------------------------------------------------------------------* + * correlate_tc: + * + * correlation for different vectors' lengths + *-------------------------------------------------------------------*/ +static void correlate_tc( + const float *x, /* i: target signal */ + float *y, /* o: correlation between x[] and h[] */ + const float *h, /* i: impulse response (of weighted synthesis filter) */ + const short start, /* i: index of iterest */ + const short L_1, /* i: vector size */ + const short L_2 /* i: index of interest */ +) +{ + short i, j; + float s; + + + for( i = start; i < L_2; i++ ) + { + s = 0.0f; + for( j = i; j < L_1; j++ ) + { + s += x[j]*h[j-i]; + } + y[i] = s; + } + + return; +} diff --git a/lib_enc/setmodeindex.c b/lib_enc/setmodeindex.c new file mode 100644 index 000000000..4b6ff695e --- /dev/null +++ b/lib_enc/setmodeindex.c @@ -0,0 +1,41 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "options.h" +#include "prot.h" +#include "cnst.h" +#include "rom_com.h" +#include "rom_enc.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 *st, + const long total_brate, + const short bwidth) +{ + + /* Reconfigure the core coder */ + if( (st->last_total_brate != total_brate) || (st->last_bwidth != bwidth) || (st->last_codec_mode == MODE1) || (st->rf_mode_last != st->rf_mode) ) + { + core_coder_mode_switch( st, st->bwidth, total_brate ); + } + + + return; +} diff --git a/lib_enc/sig_clas.c b/lib_enc/sig_clas.c new file mode 100644 index 000000000..11ec3196c --- /dev/null +++ b/lib_enc/sig_clas.c @@ -0,0 +1,312 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ + +#define K_COR_ENC 2.857f +#define C_COR_ENC -1.286f +#define K_EE_ENC 0.04167f +#define C_EE_ENC 0.0f +#define K_ZC_ENC -0.04f +#define C_ZC_ENC 2.4f +#define K_RELE_ENC 0.05f +#define C_RELE_ENC 0.45f +#define K_PC_ENC -0.07143f +#define C_PC_ENC 1.857f +#define K_SNR_ENC 0.1111f +#define C_SNR_ENC -0.3333f + +/*-------------------------------------------------------------------* + * signal_clas() + * + * Classification state machine for FEC + * Coder type modification + *-------------------------------------------------------------------*/ + +short signal_clas( /* o : classification for current frames */ + Encoder_State *st, /* i/o: encoder state structure */ + short *coder_type, /* i/o: coder type */ + const float voicing[3], /* i : normalized correlation for 3 half-frames */ + const float *speech, /* i : pointer to speech signal for E computation */ + const short localVAD, /* i : vad without hangover */ + const short pit[3], /* i : open loop pitch values for 3 half-frames */ + const float *ee, /* i : lf/hf E ration for 2 half-frames */ + const float relE, /* i : frame relative E to the long term average */ + const short L_look, /* i : look-ahead */ + short *uc_clas /* o : flag for unvoiced class used in sp/mus classifier */ +) +{ + float mean_voi2, mean_ee2, tmp; + float een, corn, zcn, relEn, pcn, fmerit1; + short i, clas, pc, zc; + short 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 */ + mean_voi2 = 0.5f * (voicing[1] + voicing[2]); + + /* average spectral tilt in dB */ + tmp = ee[0] * ee[1]; + if( tmp < 1.0f ) + { + tmp = 1.0f; + } + + mean_ee2 = 0.5f * 20.0f * (float)log10( tmp ); + + /* compute zero crossing rate */ + zc = 0; + for( i = L_look; i < L_FRAME + L_look; i++ ) + { + if( speech[i] <= 0.0f && speech[i-1] > 0.0f ) + { + zc++; + } + } + + /* compute pitch stability */ + pc = (short)(abs(pit[1] - pit[0]) + abs(pit[2] - pit[1])); + + /*-----------------------------------------------------------------* + * Transform parameters to the range <0:1> + * Compute the merit function + *-----------------------------------------------------------------*/ + + een = K_EE_ENC * mean_ee2 + C_EE_ENC; + if( een > 1.0f ) + { + een = 1.0f; + } + else if( een < 0.0f ) + { + een = 0.0f; + } + + corn = K_COR_ENC * mean_voi2 + C_COR_ENC; + if( corn > 1.0f ) + { + corn = 1.0f; + } + else if( corn < 0.0f ) + { + corn = 0.0f; + } + + zcn = K_ZC_ENC * zc + C_ZC_ENC; + if( zcn > 1.0f ) + { + zcn = 1.0f; + } + else if( zcn < 0.0f ) + { + zcn = 0.0f; + } + + relEn = K_RELE_ENC * relE + C_RELE_ENC; + if( relEn > 1.0f ) + { + relEn = 1.0f; + } + else if( relEn < 0.5f ) + { + relEn = 0.5f; + } + + pcn = K_PC_ENC * pc + C_PC_ENC; + if( pcn > 1.0f ) + { + pcn = 1.0f; + } + else if( pcn < 0.0f ) + { + pcn = 0.0f; + } + + fmerit1 = (1.0f/6.0f) * (een + 2.0f*corn + zcn + relEn + pcn); + + /*-----------------------------------------------------------------* + * FEC classification + * Onset classification + *-----------------------------------------------------------------*/ + + + /* FEC classification */ + if( localVAD == 0 || *coder_type == UNVOICED || relE < -6.0f ) + { + clas = UNVOICED_CLAS; + } + else + { + switch( st->last_clas ) + { + case VOICED_CLAS: + case ONSET: + case VOICED_TRANSITION: + if( fmerit1 < 0.49f ) + { + clas = UNVOICED_CLAS; + } + else if( fmerit1 < 0.66f ) + { + clas = VOICED_TRANSITION; + } + else + { + clas = VOICED_CLAS; + } + + break; + + case UNVOICED_CLAS: + case UNVOICED_TRANSITION: + if( fmerit1 > 0.63f ) + { + clas = ONSET; + } + else if( fmerit1 > 0.585f ) + { + clas = UNVOICED_TRANSITION; + } + else + { + clas = UNVOICED_CLAS; + } + + break; + + default: + clas = UNVOICED_CLAS; + + break; + } + } + + /* set flag for unvoiced class, it will be used in sp/mus classifier */ + *uc_clas = clas; + if( ( ( *coder_type == UNVOICED ) || + ( st->input_bwidth != NB && fmerit1 < 0.41f && st->mold_corr > 0.65f ) || /* WB case */ + ( st->input_bwidth == NB && fmerit1 * 0.88f < 0.41f && st->mold_corr > 0.55f ) ) && /* NB case */ + relE > -15.0f && st->lt_dec_thres < 1.5f ) + { + *uc_clas = UNVOICED_CLAS; + } + + /* 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( clas == UNVOICED_CLAS ) + { + st->tc_cnt = 0; + } + + if( clas >= VOICED_TRANSITION && st->tc_cnt >= 0 ) + { + st->tc_cnt += 1; + } + + if( st->tc_cnt > 2 ) + { + st->tc_cnt = -1; + } + + if ( 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 */ + if( st->total_brate > ACELP_9k60 && *coder_type == UNVOICED ) + { + *coder_type = GENERIC; + } + + /* Prevent UC coding on mixed content at 9.6 kb/s */ + if( st->total_brate == ACELP_9k60 && *coder_type == UNVOICED && st->audio_frame_cnt != 0 ) + { + *coder_type = GENERIC; + } + + unmod_coder_type = *coder_type; + + /* Enforce GC mode on inactive signal (this can be later overwritten to INACTIVE) */ + if( localVAD == 0 && ( (*coder_type == UNVOICED && (!st->Opt_SC_VBR || + ( st->Opt_SC_VBR && st->vbr_generic_ho == 0 && st->last_coder_type > UNVOICED )) ) + || *coder_type == TRANSITION || *coder_type == VOICED ) + ) + { + *coder_type = GENERIC; + } + if( *coder_type == GENERIC && unmod_coder_type == UNVOICED && st->Opt_SC_VBR ) + { + st->vbr_generic_ho = 1; + } + + if ( *coder_type > UNVOICED && st->Opt_SC_VBR ) + { + st->vbr_generic_ho = 0; + } + + if( localVAD == 0 && *coder_type == UNVOICED ) + { + st->last_7k2_coder_type = GENERIC; + } + else + { + st->last_7k2_coder_type = *coder_type; + } + + /* Select TC mode for appropriate frames which is in general MODE1_VOICED_TRANSITION, VOICED_CLAS or MODE1_ONSET frames following UNVOICED_CLAS frames */ + if( localVAD != 0 && st->tc_cnt >= 1 ) + { + if ( st->tc_cnt == 1 ) + { + /* onset/transition frame is always coded using GC mode */ + *coder_type = GENERIC; + } + else + { + /* frame after onset/transition frame is coded by TC mode */ + *coder_type = TRANSITION; + } + } + + /* At higher rates and with 16kHz core, allow only GC and TC mode */ + if( st->total_brate >= ACELP_24k40 && *coder_type != GENERIC && *coder_type != TRANSITION ) + { + *coder_type = GENERIC; + } + + /* Patch for certain low-level signals for which the gain quantizer sometimes goes out of its dynamic range */ + if( *coder_type == VOICED && st->input_bwidth == NB && relE < -10.0f && st->total_brate <= ACELP_8k00 ) + { + *coder_type = GENERIC; + } + } + + return clas; +} diff --git a/lib_enc/spec_center.c b/lib_enc/spec_center.c new file mode 100644 index 000000000..59dd5b52c --- /dev/null +++ b/lib_enc/spec_center.c @@ -0,0 +1,62 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "prot.h" +#include "wmc_auto.h" +#include "rom_enc.h" +#include "cnst.h" + + +/*-------------------------------------------------------------------* + * spec_center() + * + * + *-------------------------------------------------------------------*/ + +void spec_center( + float spec_power[], /*(i) energy of sub-band divided uniformly*/ + float sp_center[], /*(o) spectral centroid*/ + int bandwidth /*(i) band width*/ +) +{ + int i; + float t_sp_center,frame_power; + + short sp_center_band_num = SP_CENTER_BAND_NUM_TAB[bandwidth]; + float sp_center_mem; + + t_sp_center = 0; + frame_power = 0; + + for(i=1; i +#include "wmc_auto.h" +#include "prot.h" + +#include + + +/*-------------------------------------------------------------------* + * spec_flatness() + * + * + *-------------------------------------------------------------------*/ + +void spec_flatness( + float spec_amp[], /*(i) spectral amplitude*/ + float smooth_spec_amp[], /*(i) smoothed spectral amplitude*/ + float sSFM[] /*(o) spectral flatness rate*/ +) +{ + int i; + double prods,sums; + + float SFM; + for(i=MIN_AMP_ID; i<=MAX_AMP_ID; i++) + { + smooth_spec_amp[i-MIN_AMP_ID] = smooth_spec_amp[i-MIN_AMP_ID]*0.7f + spec_amp[i]*0.3f; + } + /* sSFM1 */ + prods = 1; + sums = 0; + assert(MIN_AMP_ID<=5); + for(i=(5-MIN_AMP_ID); i<(20-MIN_AMP_ID); i++) + { + prods = smooth_spec_amp[i]*prods; + sums = sums + smooth_spec_amp[i]; + } + + if(prods>0) + { + prods = pow(prods,1.0/15); + } + else + { + prods=0; + } + sums = sums/15; + + SFM = (float)((prods+3276.8f)/(sums+3276.8f)); + sSFM[0] = 0.85f*sSFM[0] + 0.15f*SFM; + + /* sSFM2 */ + prods = 1; + sums = 0; + for(i=(20-MIN_AMP_ID); i<(40-MIN_AMP_ID); i++) + { + prods = smooth_spec_amp[i]*prods; + sums = sums + smooth_spec_amp[i]; + } + + if(prods>0) + { + prods = pow(prods,1.0/20); + } + else + { + prods =0; + } + sums = sums/20; + SFM= (float)((prods+3276.8f)/(sums+3276.8f)); + sSFM[1] = 0.85f*sSFM[1] + 0.15f*SFM; + /* sSFM3 */ + prods = 1; + sums = 0; + for(i=(40-MIN_AMP_ID); i<=(MAX_AMP_ID-MIN_AMP_ID); i++) + { + prods = smooth_spec_amp[i]*prods; + sums = sums + smooth_spec_amp[i]; + } + + if(prods>0) + { + prods = pow(prods,0.04); + } + else + { + prods =0; + } + sums = sums/25; + SFM = (float)((prods+3276.8f)/(sums+3276.8f)); + sSFM[2] = 0.85f*sSFM[2] + 0.15f*SFM; + + + return; +} diff --git a/lib_enc/speech_music_classif.c b/lib_enc/speech_music_classif.c new file mode 100644 index 000000000..9c981169b --- /dev/null +++ b/lib_enc/speech_music_classif.c @@ -0,0 +1,1900 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_enc.h" +#include "rom_com.h" /* Common static table prototypes */ + + +/*---------------------------------------------------------------------* + * 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 (short)((4.0f * ATT_NSEG / (float)NB_SUBFR16k) + 0.5f) + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ + +static short sp_mus_classif_1st( Encoder_State *st, const short localVAD, const short pitch[3], const float voicing[3], const float lsp_new[M], + const float cor_map_sum, const float epsP[M+1], const float PS[], float non_sta, float relE, + float *voi_fv, float *cor_map_sum_fv, float *LPCErr, short *high_lpn_flag ); + +static void music_mixed_classif_improv( Encoder_State *st, const float *new_inp, short *sp_aud_decision1, + const short vad_flag, const float *voicing, const float *epsP, const float etot, + const float old_cor, const float cor_map_sum ); + +static void spec_analysis( float *Bin_E, float *p2v_map ); + +static void flux( float *Bin_E, float *p2v_map, float *old_Bin_E, float *buf_flux, short attack_hangover, float dec_mov ); + +static void tonal_dist( float *p2v_map, float *buf_pkh, float *buf_Ntonal, float *buf_Ntonal2, float *buf_Ntonal_lf ); + +static short mode_decision( Encoder_State *st, short len, float *dec_mov, float *buf_flux, float *buf_epsP_tilt, float *buf_pkh, float *buf_cor_map_sum, + float *buf_Ntonal, float *buf_Ntonal2, float *buf_Ntonal_lf, float *buf_dlp ); + + +static void sp_mus_classif_2nd( Encoder_State *st, const short sp_aud_decision1, short *sp_aud_decision2, const short pitch[], + const float Etot, short *coder_type, short *attack_flag, + const float *inp, const short localVAD, const short vad_flag ); + +static void var_cor_calc( const float old_corr, float *mold_corr, float var_cor_t[], short *high_stable_cor ); + +static short attack_det( const float *inp, const short last_clas, const short localVAD, const short coder_type, const int total_brate ); + +static void tonal_context_improv( Encoder_State *st, const float PS[], short *sp_aud_decision1, short *sp_aud_decision2, + const short vad_flag, const short pitch[3], const float voicing[3], const float voi_fv, + const float cor_map_sum_fv, const float LPCErr ); +static void order_spectrum( float *vec, short len ); + +static void detect_sparseness( Encoder_State *st, const short localVAD_HE_SAD, short *sp_aud_decision1, + short *sp_aud_decision2, const float 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( /* o : 1st stage decision (1-music, 0-speech or noise) */ + Encoder_State *st, /* i/o: state structure */ + short *sp_aud_decision0, /* o : 1st stage speech/music decision */ + short *sp_aud_decision1, /* o : 1st stage speech/music decision */ + short *sp_aud_decision2, /* o : 2nd stage speech/music decision */ + const float *new_inp, /* i : new input signal */ + const float *inp, /* i : input signal to locate attach position */ + const short vad_flag, + const short localVAD, + const short localVAD_HE_SAD, /* i : HE-SAD flag without hangover */ + const short pitch[3], /* i : open-loop pitch estimate in three subframes */ + const float voicing[3], /* i : voicing estimate in three subframes */ + const float lsp_new[M], /* i : LSPs in current frame */ + const float cor_map_sum, /* i : correlation map sum (from multi-harmonic anal.) */ + const float epsP[M+1], /* i : LP prediciton error */ + const float PS[], /* i : energy spectrum */ + const float Etot, /* i : total frame energy */ + const float old_cor, /* i : max correlation from previous frame */ + short *coder_type, /* i/o: coding type */ + short *attack_flag, /* o : flag to indicate if attack is to be treated by TC or GSC */ + const float non_sta, /* i : unbound non-stationarity for sp/mus classifier */ + const float relE, /* i : relative frame energy */ + short *high_lpn_flag, + const short flag_spitch /* i : flag to indicate very short stable pitch */ +) +{ + float voi_fv, cor_map_sum_fv, LPCErr; + + /* 1st stage speech/music classification based on the GMM model */ + *sp_aud_decision1 = sp_mus_classif_1st( st, localVAD_HE_SAD, pitch, voicing, lsp_new, cor_map_sum, + epsP, PS, non_sta, relE, &voi_fv, &cor_map_sum_fv, &LPCErr, high_lpn_flag ); + + if( st->codec_mode == MODE1 || st->sr_core == 12800) + { + + /* Improvement of the 1st stage decision for mixed/music content */ + if ( !st->Opt_SC_VBR && (st->total_brate != ACELP_24k40) ) + { + music_mixed_classif_improv( st, new_inp, sp_aud_decision1, vad_flag, voicing, epsP, Etot, old_cor, cor_map_sum ); + } + + *sp_aud_decision0 = *sp_aud_decision1; + + /* 2nd stage speech/music classification (rewrite music to speech in onsets) */ + *sp_aud_decision2 = *sp_aud_decision1; + + if( st->bwidth > NB ) + { + sp_mus_classif_2nd( st, *sp_aud_decision1, sp_aud_decision2, pitch, Etot, coder_type, attack_flag, + inp, localVAD, vad_flag ); + + if ( flag_spitch && st->bwidth == WB && st->total_brate < ACELP_13k20 ) + { + /* avoid switch to AUDIO/MUSIC class for very short stable high pitch + and/or stable pitch with high correlation at low bitrates*/ + *sp_aud_decision2 = 0; + } + } + + /* Context-based improvement of 1st and 2nd stage decision on stable tonal signals */ + if( !st->Opt_SC_VBR && (st->total_brate != ACELP_24k40) ) + { + tonal_context_improv( st, PS, sp_aud_decision1, sp_aud_decision2, vad_flag, pitch, voicing, + voi_fv, cor_map_sum_fv, LPCErr ); + } + + /* Avoid using LR-MDCT on sparse spectra, use GSC instead at 13.2 kbps (WB/SWB) */ + if ( !st->Opt_SC_VBR && st->total_brate == 13200 && vad_flag == 1 && + ( st->bwidth == WB || st->bwidth == SWB ) ) + { + detect_sparseness( 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 ( st->lp_noise > 12.0f ) + { + *sp_aud_decision1 = 0; + *sp_aud_decision2 = 0; + } + + /* set GSC noisy speech flag on unvoiced SWB segments */ + st->GSC_noisy_speech = 0; + if ( vad_flag == 1 && st->total_brate >= ACELP_13k20 && st->total_brate < ACELP_24k40 && + st->lp_noise > 12.0f && *sp_aud_decision1 == 0 && st->bwidth >= SWB && + st->coder_type_raw == UNVOICED ) + { + st->GSC_noisy_speech = 1; + } + + /* Select AUDIO frames */ + if ( st->codec_mode == MODE1 && (*sp_aud_decision2 || st->GSC_noisy_speech) ) + { + *coder_type = AUDIO; + st->noise_lev = NOISE_LEVEL_SP0; + } + + } + else + { + *sp_aud_decision0 = *sp_aud_decision1; + } + + + return; +} + + +/*---------------------------------------------------------------------* + * sp_mus_classif_1st() + * + * 1st stage speech/music classification (based on the GMM model) + *---------------------------------------------------------------------*/ + +static short sp_mus_classif_1st( /* o : decision flag (1-music, 0-speech or noise) */ + Encoder_State *st, /* i/o: state structure */ + const short localVAD, + const short pitch[3], /* i : open-loop pitch estimate in three subframes */ + const float voicing[3], /* i : voicing estimate in three subframes */ + const float lsp_new[M], /* i : LSPs in current frame */ + const float cor_map_sum, /* i : correlation map sum (from multi-harmonic anal.) */ + const float epsP[M+1], /* i : LP prediciton error */ + const float PS[], /* i : energy spectrum */ + float non_sta, /* i : unbound non-stationarity */ + float relE, /* i : relative frame energy */ + float *voi_fv, /* o : scaled voicing feature */ + float *cor_map_sum_fv, /* o : scaled correlation map feature */ + float *LPCErr, /* o : scaled LP prediction error feature */ + short *high_lpn_flag + +) +{ + short i, k, p, dec, vad; + float dlp, ftmp, lepsP1, sum_PS, ps_diff, ps_sta, wrelE, wdrop, wght, mx; + float FV[N_FEATURES], *pFV = FV, PS_norm[128], dPS[128], lsp[M]; + float pys, pym, xm[N_FEATURES], py, lps = 0, lpm = 0; + const float *pSF; + float pyn, lpn = 0; + + /*------------------------------------------------------------------* + * Initialization + *------------------------------------------------------------------*/ + + vad = localVAD; + + /*------------------------------------------------------------------* + * Preparation of the feature vector + *------------------------------------------------------------------*/ + + /* [0] OL pitch */ + if ( st->tc_cnt == 1 || st->tc_cnt == 2 ) + { + *pFV++ = (float)pitch[2]; + } + else + { + *pFV++ = (float)(pitch[0] + pitch[1] + pitch[2]) / 3.0f; + } + + /* [1] voicing */ + if ( st->tc_cnt == 1 || st->tc_cnt == 2 ) + { + *pFV++ = voicing[2]; + } + else + { + *pFV++ = (float)(voicing[0] + voicing[1] + voicing[2]) / 3.0f; + } + + /* [2,3,4,5,6] LSFs */ + mvr2r( lsp_new, lsp, M ); + + ftmp = (float)acos(lsp[1]); + *pFV++ = ftmp + st->last_lsp[1]; + st->last_lsp[1] = ftmp; + + ftmp = (float)acos(lsp[2]); + *pFV++ = ftmp + st->last_lsp[2]; + st->last_lsp[2] = ftmp; + + ftmp = (float)acos(lsp[3]); + *pFV++ = ftmp + st->last_lsp[3]; + st->last_lsp[3] = ftmp; + + ftmp = (float)acos(lsp[4]); + *pFV++ = ftmp + st->last_lsp[4]; + st->last_lsp[4] = ftmp; + + ftmp = (float)acos(lsp[5]); + *pFV++ = ftmp + st->last_lsp[5]; + st->last_lsp[5] = ftmp; + + /* [7] cor_map_sum */ + *pFV++ = cor_map_sum + st->last_cor_map_sum; + st->last_cor_map_sum = cor_map_sum; + + /* [8] non_sta */ + *pFV++ = non_sta + st->last_non_sta; + st->last_non_sta = non_sta; + + /* [9] epsP */ + if ( st->bwidth == NB ) + { + /* do not take into account (statistics are too different) */ + *pFV++ = -1.647f; + } + else + { + lepsP1 = (float)log(epsP[1] + 1e-5f); + ftmp = (float)log(epsP[13]) - lepsP1; + *pFV++ = ftmp + st->past_epsP2; + st->past_epsP2 = ftmp; + } + + /* calculation of differential normalized power spectrum */ + sum_PS = 1e-5f; + for ( i = LOWEST_FBIN; i < HIGHEST_FBIN; i++ ) + { + sum_PS += PS[i]; + } + + 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-LOWEST_FBIN]); + } + + /* [10] ps_diff (spectral difference) */ + ps_diff = 0; + for ( i = LOWEST_FBIN; i < HIGHEST_FBIN; i++ ) + { + ps_diff += dPS[i]; + } + + ps_diff = (float)log(ps_diff + 1e-5f); + *pFV++ = ps_diff + st->past_ps_diff; + st->past_ps_diff = ps_diff; + + /* [11] ps_sta (spectral stationarity) */ + ps_sta = 0; + for ( i = LOWEST_FBIN; i < HIGHEST_FBIN; i++ ) + { + mx = PS_norm[i] > st->past_PS[i-LOWEST_FBIN] ? PS_norm[i] : st->past_PS[i-LOWEST_FBIN]; + ps_sta += mx / (dPS[i] + 1e-5f); + } + + *pFV++ = (float)log(ps_sta + 1e-5f); + mvr2r( &PS_norm[LOWEST_FBIN], st->past_PS, HIGHEST_FBIN-LOWEST_FBIN ); + + /*------------------------------------------------------------------* + * Scaling of the feature vector + *------------------------------------------------------------------*/ + + pFV = FV; + if ( st->bwidth == NB ) + { + pSF = SF_8k; + } + else + { + pSF = SF; + } + + for ( i=0; i lps && lpn > lpm ) + { + *high_lpn_flag = 1; + } + if ( !vad ) + { + /* artificially increase log-probability of noise */ + lps = lpn * 1.2f; + } + + st->lpm = lpm; + st->lps = lps; + + /* determine HQ Generic speech class */ + if ( lps > lpm + 0.5f ) + { + st->hq_generic_speech_class = 1; + } + else + { + st->hq_generic_speech_class = 0; + } + + /*------------------------------------------------------------------* + * State machine (sp_mus_state < 0 .. inactive, > 0 .. entry, = 0 .. active ) + *------------------------------------------------------------------*/ + + if ( vad ) + { + if ( relE < -20 || (lps <= -5 && lpm <= -5) ) + { + if ( st->sp_mus_state > 0 ) + { + if ( st->sp_mus_state < HANG_LEN ) + { + /* energy is too low but we are in entry period -> reset the inactive counter to allow new entry later */ + st->inact_cnt = 0; + } + + /* energy is too low -> we are going to instable state */ + st->sp_mus_state = 0; + } + else if ( st->sp_mus_state > -HANG_LEN ) + { + /* energy is still too low -> we are still in instable state */ + st->sp_mus_state--; + } + } + else if ( st->sp_mus_state <= 0 ) + { + if ( st->inact_cnt == 0 ) + { + + st->sp_mus_state = 1; + } + else + { + + st->sp_mus_state = HANG_LEN; + } + + st->inact_cnt = 12; + } + else if ( st->sp_mus_state > 0 && st->sp_mus_state < HANG_LEN ) + { + /* we are inside an entry period -> increment the counter of entry frames */ + st->sp_mus_state++; + } + + if ( st->sp_mus_state < 0 && st->inact_cnt > 0 ) + { + st->inact_cnt--; + } + } + else + { + if ( st->sp_mus_state > 0 && st->sp_mus_state < HANG_LEN ) + { + st->inact_cnt = 0; + } + else if ( st->inact_cnt > 0 ) + { + st->inact_cnt--; + } + + if ( st->sp_mus_state > 0 && st->sp_mus_state < HANG_LEN ) + { + + st->sp_mus_state = -HANG_LEN; + } + else if ( st->sp_mus_state > 0 ) + { + + st->sp_mus_state = -1; + } + else if ( st->sp_mus_state > -HANG_LEN ) + { + /* we are in inactive state */ + st->sp_mus_state--; + } + + } + + /*------------------------------------------------------------------* + * Decision without hangover + * Weighted decision + *------------------------------------------------------------------*/ + + /* decision without hangover (0 - speech/noise, 1 - music) */ + dec = lpm > lps; + dlp = lpm - lps; + + if ( !vad ) + { + dec = 0; + dlp = 0; + } + + /* 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; + + if ( wrelE > 1.0f ) + { + wrelE = 1.0f; + } + else if ( wrelE < 0.01f ) + { + wrelE = 0.01f; + } + + /* calculate weight based on drops of dlp (close to 1 during sudden drops of dlp, close to 0 otherwise) */ + if ( dlp < 0 && dlp < st->past_dlp[0] ) + { + if ( st->past_dlp[0] > 0 ) + { + st->wdrop = -dlp; + } + else + { + st->wdrop += st->past_dlp[0] - dlp; + } + } + else + { + st->wdrop = 0; + } + + wdrop = st->wdrop/20; + + if ( wdrop > 1.0f ) + { + wdrop = 1.0f; + } + else if ( wdrop < 0.1f ) + { + wdrop = 0.1f; + } + + /* combine weights into one */ + wght = wrelE * wdrop; + if ( wght < 0.01f ) + { + wght = 0.01f; + } + + /* calculate weighted decision */ + st->wdlp_0_95_sp = wght * dlp + (1 - wght) * st->wdlp_0_95_sp; + + if ( st->sp_mus_state == -HANG_LEN ) + { + st->wdlp_0_95_sp = 0; + } + + /*------------------------------------------------------------------* + * Final speech/music decision + *------------------------------------------------------------------*/ + + if ( !vad && st->sp_mus_state == -HANG_LEN ) + { + /* inactive state */ + dec = 0; + } + else if ( st->sp_mus_state <= 0 ) + { + /* transition from active to inactive state or instable state */ + dec = st->past_dec[0]; + } + else if ( st->sp_mus_state > 0 && st->sp_mus_state < HANG_LEN ) + { + /* entry state -> final decision is calculated based on weighted average of past non-binary decisions */ + ftmp = w_spmus[st->sp_mus_state-1][0] * dlp; + ftmp += dotp( &w_spmus[st->sp_mus_state-1][1], st->past_dlp, HANG_LEN-1 ); + dec = ftmp > 2.0f; + } + else + { + /* stable active state */ + if ( st->wdlp_0_95_sp > 0 && st->past_dec[0] == 0 && st->past_dec[1] == 0 && st->past_dec[2] == 0 ) + { + /* switching from speech to music */ + dec = 1; + } + else if ( st->past_dec[0] == 1 && st->wdlp_0_95_sp < 0 ) + { + /* switching from music to speech */ + dec = 0; + } + else + { + dec = st->past_dec[0]; + } + } + + /*------------------------------------------------------------------* + * Updates + *------------------------------------------------------------------*/ + + /* update buffer of past non-binary decisions */ + mvr2r( &st->past_dlp[0], &st->past_dlp[1], HANG_LEN-2 ); + st->past_dlp[0] = dlp; + + /* update buffer of past binary decisions */ + mvs2s( &st->past_dec[0], &st->past_dec[1], HANG_LEN-2 ); + st->past_dec[0] = dec; + + return dec; +} + + +/*---------------------------------------------------------------------* + * sp_mus_classif_2nd() + * + * 2nd stage speech/music classifier (convert music to speech for onsets) + *---------------------------------------------------------------------*/ + +static void sp_mus_classif_2nd( + Encoder_State *st, /* i/o: encoder state structure */ + const short sp_aud_decision1, /* i : 1st stage decision flag */ + short *sp_aud_decision2, /* o : 2nd stage decision flag */ + const short pitch[3], /* i : open-loop pitch estimate in three subframes */ + const float Etot, /* i : total frame energy */ + short *coder_type, /* i/o: coder type */ + short *attack_flag, /* i/o: attack flag (GSC or TC) */ + const float *inp, /* i : input signal */ + const short localVAD, + const short vad_flag +) +{ + short attack; + + /* initialization */ + *attack_flag = 0; + + /* signal stability estimation */ + stab_est( Etot, st->gsc_lt_diff_etot, &st->gsc_mem_etot, + &st->gsc_nb_thr_3, &st->gsc_nb_thr_1, st->gsc_thres, &st->gsc_last_music_flag, vad_flag ); + + /* calculate variance of correlation */ + var_cor_calc( st->old_corr, &st->mold_corr, st->var_cor_t, &st->high_stable_cor ); + + /* attack detection */ + attack = attack_det( inp, st->clas, localVAD, *coder_type, st->total_brate ); + + /* change decision from music hto speech in certain special cases */ + if( sp_aud_decision1 == 1 ) + { + if( st->ener_RAT < 0.18f && st->lt_dec_thres > 15.0f ) + { + /* strong music decision but almost no content below 1kHz */ + *sp_aud_decision2 = 0; + } + else if( st->high_stable_cor && 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; + + if ( st->codec_mode == MODE1 && *coder_type == TRANSITION ) + { + *coder_type = GENERIC; + } + } + else if( st->gsc_lt_diff_etot[MAX_LT-1] > 4.5f && + (st->gsc_lt_diff_etot[MAX_LT-1] - st->gsc_lt_diff_etot[MAX_LT-2] > 10.0f) ) + { + if ( st->tc_cnt == 1 ) + { + /* do TC coding instead of GC/VC if onset has been already declared before */ + *sp_aud_decision2 = 0; + if ( st->codec_mode == MODE1 ) + { + *coder_type = TRANSITION; + } + } + else + { + if( attack >= ATT_3LSUB_POS ) + { + /* do TC coding if attack is located in the last subframe */ + *sp_aud_decision2 = 0; + *attack_flag = 1; + if ( st->codec_mode == MODE1 ) + { + *coder_type = TRANSITION; + } + } + else if( 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; + } + } + } + } + else if ( localVAD == 1 && *coder_type == GENERIC && + ( (attack >= ATT_3LSUB_POS && st->total_brate < ACELP_24k40) || + (attack >= ATT_3LSUB_POS_16k && st->total_brate >= ACELP_24k40 && st->total_brate < ACELP_48k) ) + ) + { + /* do TC coding an attack is located in the last subframe */ + *attack_flag = 1; + if ( st->codec_mode == MODE1 ) + { + *coder_type = TRANSITION; + } + } + + return; +} + +/*---------------------------------------------------------------------* + * var_cor_calc() + * + * Calculate variance of correlation + *---------------------------------------------------------------------*/ + +static void var_cor_calc( + const float old_corr, + float *mold_corr, + float var_cor_t[], + short *high_stable_cor +) +{ + short i; + float 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]; + } + var_cor_t[i] = old_corr; + + /* calculate variance of correlation */ + var_cor = var( var_cor_t, VAR_COR_LEN ); + + /* set flag in case of highly-correlated stable signal */ + if( *mold_corr > 0.8f && var_cor < 5e-4f ) + { + *high_stable_cor = 1; + } + else + { + *high_stable_cor = 0; + } + + /* update average correlation */ + *mold_corr = 0.1f * old_corr + 0.9f * *mold_corr; + + return; +} + +/*---------------------------------------------------------------------* + * attack_det() + * + * Attack detection + *---------------------------------------------------------------------*/ + +static short attack_det( + const float *inp, /* i : input signal */ + const short last_clas, /* i : last signal clas */ + const short localVAD, + const short coder_type, /* i : coder type */ + const int total_brate /* i : total bit-rate */ +) +{ + short i, attack; + float etmp, etmp2, finc[ATT_NSEG]; + short att_3lsub_pos; + + att_3lsub_pos = ATT_3LSUB_POS; + if( total_brate >= ACELP_24k40 ) + { + att_3lsub_pos = ATT_3LSUB_POS_16k; + } + + /* compute energy per section */ + for( i=0; i etmp2 ) + { + /* stop, if the attack is not sufficiently strong */ + attack = 0; + } + + if( last_clas == VOICED_CLAS && etmp * 20 > etmp2 ) + { + /* stop, if the signal was voiced and the attack is not sufficiently strong */ + attack = 0; + } + + /* compare wrt. other sections (reduces miss-classification) */ + if( attack > 0 ) + { + etmp2 = finc[attack]; + + for( i=2; i etmp2 ) + { + /* stop, if the attack is not sufficiently strong */ + attack = 0; + break; + } + } + } + } + + /* compare wrt. other sections (reduces miss-classification) */ + else if( attack > 0 ) + { + etmp2 = finc[attack]; + + for( i=2; i etmp2 ) + { + /* stop, if the attack is not sufficiently strong */ + attack = 0; + break; + } + } + } + + return attack; +} + + +/*------------------------------------------------------------------------* + * music_mixed_classif_improv() + * + * Improve 1st stage speech/music decision for mixed&music signals + *------------------------------------------------------------------------*/ + +static void music_mixed_classif_improv( + Encoder_State *st, /* i/o: Encoder state structure */ + const float *new_inp, /* i : new input signal */ + short *sp_aud_decision1, /* i/o: improved 1st stage speech/music decision */ + const short vad_flag, + const float *voicing, /* i : voicing estimate */ + const float *epsP, /* i : LP prediction error */ + const float etot, /* i : total frame energy */ + const float old_cor, /* i : normalized correlation */ + const float cor_map_sum /* i : correlation map sum */ +) +{ + short i, dec, len, percus_flag; + float p2v_map[128], ftmp, ftmp1, lt_diff, log_max_spl, epsP_tilt, max_spl; + + /* find sample with maximum absolute amplitude */ + max_spl = 0; + for ( i=0; i max_spl ) + { + max_spl = (float)fabs(new_inp[i]); + } + } + + /* music is considered only appearing in high SNR condition and active signal */ + if ( vad_flag == 0 || st->lp_speech - st->lp_noise < 25 ) + { + st->dec_mov = 0.5f; + st->dec_mov1 = 0.5f; + + if ( vad_flag == 0 ) + { + st->onset_cnt = 0; + } + + return; + } + + st->onset_cnt++; + + if ( st->onset_cnt > 9 ) + { + st->onset_cnt = 9; + } + + if ( st->onset_cnt == 1 ) + { + set_f( st->buf_flux, -100, BUF_LEN ); + } + + /* spectral analysis */ + spec_analysis( st->Bin_E, p2v_map ); + + /* percussive music detection */ + log_max_spl = 20 * (float)log(max_spl + 0.0001f); + lt_diff = log_max_spl - st->mov_log_max_spl; + + for ( i=0; i<3; i++ ) + { + st->buf_etot[i] = st->buf_etot[i+1]; + } + st->buf_etot[i] = etot; + + percus_flag = 0; + if ( st->buf_etot[1] - st->buf_etot[0] > 6 && st->buf_etot[2] < st->buf_etot[1] && st->buf_etot[1] - st->lp_speech > 3 ) + { + if ( st->buf_etot[1] - st->buf_etot[3] > 3 && st->buf_etot[3] < st->buf_etot[2] && 0.5f * (0.5f * (voicing[0] + voicing[1]) + old_cor) < 0.75f ) + { + if ( st->dec_mov > 0.8f ) + { + percus_flag = 1; + } + else if ( old_cor < 0.75f && voicing[0] < 0.75f && voicing[1] < 0.75f && st->old_lt_diff[0] > 10 ) + { + percus_flag = 1; + } + } + } + + /* sound attack detection */ + if ( st->buf_etot[3] - st->buf_etot[2] > 6 && st->dec_mov > 0.9f && etot - st->lp_speech > 5 && st->old_lt_diff[0] > 5 ) + { + st->attack_hangover = 3; + } + + if ( voicing[0] > 0.9f && voicing[1] > 0.9f ) + { + if ( log_max_spl > st->mov_log_max_spl ) + { + st->mov_log_max_spl = 0.75f * st->mov_log_max_spl + (1 - 0.75f) * log_max_spl; + } + else + { + st->mov_log_max_spl = 0.995f * st->mov_log_max_spl + (1 - 0.995f) * log_max_spl; + } + } + + st->old_lt_diff[0] = st->old_lt_diff[1]; + st->old_lt_diff[1] = lt_diff; + + /* calculate and buffer spectral energy fluctuation */ + flux( st->Bin_E, p2v_map, st->old_Bin_E, st->buf_flux, st->attack_hangover, st->dec_mov ); + + st->attack_hangover--; + if ( st->attack_hangover < 0 ) + { + st->attack_hangover = 0; + } + + /* identify flux buffer status */ + len = 0; + for ( i = BUF_LEN-1; i >= 0 && st->buf_flux[i] >= 0; i-- ) + { + len++; + } + + /* reset flux buffer if percussive music is detected */ + if ( percus_flag == 1 ) + { + set_f( &st->buf_flux[BUF_LEN-len], 5, len ); + } + + /* calculate and buffer the tilt of residual LP analysis energies */ + ftmp = 0.00001f; + ftmp1 = 0; + for ( i=1; i<16; i++ ) + { + ftmp += epsP[i] * epsP[i]; + ftmp1 += epsP[i] * epsP[i+1]; + } + + epsP_tilt = ftmp1/ftmp; + + for ( i=0; ibuf_epsP_tilt[i] = st->buf_epsP_tilt[i+1]; + } + st->buf_epsP_tilt[i] = epsP_tilt; + + /* calculate and buffer highband spectral peakness */ + tonal_dist( p2v_map, st->buf_pkh, st->buf_Ntonal, st->buf_Ntonal2, st->buf_Ntonal_lf ); + + /* buffer sum of correlation map */ + for ( i=0; ibuf_cor_map_sum[i] = st->buf_cor_map_sum[i+1]; + } + st->buf_cor_map_sum[i] = cor_map_sum; + + /* buffer voicing metric */ + for ( i=0; i<9; i++ ) + { + st->buf_dlp[i] = st->buf_dlp[i+1]; + } + st->buf_dlp[i] = st->lps - st->lpm; + + /* classification */ + dec = mode_decision( st, len, &st->dec_mov, st->buf_flux, st->buf_epsP_tilt, st->buf_pkh, st->buf_cor_map_sum, + st->buf_Ntonal, st->buf_Ntonal2, st->buf_Ntonal_lf, st->buf_dlp ); + + /* update long term moving average of the classification decisions */ + if ( len > 30 ) + { + st->dec_mov = 0.97f * st->dec_mov + (1 - 0.97f) * dec; + st->dec_mov1 = 0.97f * st->dec_mov1 + (1 - 0.97f) * dec; + } + + /* update long-term unvoiced counter */ + if ( (st->coder_type_raw == UNVOICED || st->coder_type_raw == INACTIVE) && etot > 1.5f && st->buf_Ntonal2[59] < 2 ) + { + st->UV_cnt1 -= 8; + } + else + { + st->UV_cnt1++; + } + + if ( st->UV_cnt1 > 300 ) + { + st->UV_cnt1 = 300; + } + else if ( st->UV_cnt1 < 0 ) + { + st->UV_cnt1 = 0; + } + + st->LT_UV_cnt1 = 0.9f * st->LT_UV_cnt1 + 0.1f * st->UV_cnt1; + + /* revert classification decision due to long-term unvoiced counter */ + if ( dec == 1 && st->dec_mov1 < 0.2f && st->LT_UV_cnt1 < 200 ) + { + dec = 0; + } + + /* overwrite 1st stage speech/music decision to music */ + if ( dec == 1 ) + { + *sp_aud_decision1 = 1; + } + + return; +} + + +/*---------------------------------------------------------------------* + * spec_analysis() + * + * Spectral analysis for mixed/music classification improvement + *---------------------------------------------------------------------*/ + +static void spec_analysis( + float *Bin_E, /* i : log energy spectrum of the current frame */ + float *p2v_map /* o : spectral peakiness map */ +) +{ + short i, k, m; + float peak[L_FFT/4+1]; + float valley[L_FFT/4+1]; + short peak_idx[L_FFT/4+1]; + short valey_idx[L_FFT/4+1]; + float p2v[L_FFT/4+1]; + + /* find spectral peaks */ + k = 0; + for ( i=1; i Bin_E[i-1] && Bin_E[i] > Bin_E[i+1] ) + { + peak[k] = Bin_E[i]; + peak_idx[k] = i; + k++; + } + } + assert(k+1= 0 && Bin_E[i+1] > Bin_E[i]; i-- ) + { + k = i; + } + + for ( i=1; i valey_idx[i] && peak_idx[k] < valey_idx[i+1] ) + { + p2v[k] = 2*peak[k] - valley[i] - valley[i+1]; + k++; + } + } + + for ( i=0; i 20 && dec_mov > 0.8f ) + { + flux = 20; + } + + /* update old Bin_E buffer */ + pt1 = old_Bin_E; + pt2 = old_Bin_E + N_OLD_BIN_E; + pt3 = Bin_E; + pt4 = old_Bin_E + N_OLD_BIN_E; + pt5 = old_Bin_E + 2*N_OLD_BIN_E; + pt6 = old_Bin_E + 2*N_OLD_BIN_E; + + for ( i=0; i 55 ) + { + Ntonal++; + } + + if ( p2v_map[i] > 80 ) + { + Ntonal2++; + Ntonal_lf++; + } + } + + for ( i=64; i<127; i++ ) + { + if ( p2v_map[i] != 0 ) + { + pk += p2v_map[i]; + } + + if ( p2v_map[i] > 55 ) + { + Ntonal++; + } + + if ( p2v_map[i] > 80 ) + { + Ntonal2++; + } + } + + /* update buffers */ + for ( i=0; i 0.5f; + + if ( len <= 5 ) + { + return ( mode ); + } + else if ( len < 10 ) + { + M_pkh = mean( buf_pkh+BUF_LEN-len, len ); + M_cor_map_sum = mean( buf_cor_map_sum+BUF_LEN-len, len ); + M_Ntonal = mean( buf_Ntonal+BUF_LEN-len, len ); + V_epsP_tilt = var( buf_epsP_tilt+BUF_LEN-len, len ); + + voiced_cnt = 0; + for ( i=9; i>3; i-- ) + { + if ( buf_dlp[i] > 0.0f ) + { + voiced_cnt++; + } + } + + if ( (M_pkh > 1100 || V_epsP_tilt < 0.00008f || M_cor_map_sum > 100) && voiced_cnt < 4 ) + { + mode = 1; + } + else if ( M_Ntonal > 27 && voiced_cnt < 4 ) + { + mode = 1; + } + } + else + { + voiced_cnt = 0; + for ( i=0; i<10; i++ ) + { + if ( buf_dlp[i] > 0.0f ) + { + voiced_cnt++; + } + } + + M_flux = mean( &buf_flux[BUF_LEN-10], 10 ); + M_pkh = mean( buf_pkh+BUF_LEN-10, 10 ); + M_cor_map_sum = mean( buf_cor_map_sum+BUF_LEN-10, 10 ); + V_epsP_tilt = var( buf_epsP_tilt+BUF_LEN-10, 10 ); + + if ( (M_flux < 8.5f || (V_epsP_tilt < 0.001f && M_flux < 12.0f) || M_pkh > 1050 || M_cor_map_sum > 100) + && voiced_cnt < 3 && mean( &buf_flux[55], 5 ) < 15 ) + { + mode = 1; + *dec_mov = 1; + return ( mode ); + } + + if ( M_flux > 16.0f || (M_flux > 15 && voiced_cnt > 2) || mean( &buf_flux[55], 5 ) > 19.0f || (buf_flux[59] >= 20 && st->lps-st->lpm > 0) ) + { + *dec_mov = 0; + mode = 0; + return ( mode ); + } + + for ( i=10; i 1050-5.0f*(len-10) || M_cor_map_sum > 95-0.3f*(len-10)) && voiced_cnt < 3 ) + { + mode = 1; + return( mode ); + } + } + + if ( len == BUF_LEN ) + { + M_Ntonal = mean( buf_Ntonal, BUF_LEN ); + lf_Ntonal_ratio = sum_f(buf_Ntonal_lf, BUF_LEN)/(sum_f(buf_Ntonal2, BUF_LEN) + 0.0001f); + + if ( M_Ntonal > 18 || lf_Ntonal_ratio < 0.2f ) + { + mode = 1; + } + else if ( M_Ntonal < 1 ) + { + mode = 0; + } + } + } + + return( mode ); +} + +/*----------------------------------------------------------------------------------* + * tonal_context_improv() + * + * Context-based improvement of 1st/2nd stage speech/music decision on stable tonal signals + *----------------------------------------------------------------------------------*/ + +static void tonal_context_improv( + Encoder_State *st, /* i/o: encoder state structure */ + const float PS[], /* i : energy spectrum */ + short *sp_aud_decision1, /* i/o: 1st stage speech/music decision */ + short *sp_aud_decision2, /* i/o: 2nd stage speech/music decision */ + const short vad_flag, + const short pitch[3], /* i : open-loop pitch estimate in three subframes */ + const float voicing[3], /* i : voicing estimate in three subframes */ + const float voi_fv, /* i : scaled voicing feature */ + const float cor_map_sum_fv, /* i : scaled correlation map feature */ + const float LPCErr /* i : scaled LP prediction error feature */ +) +{ + short lt_pitch_diff; + float sort_max, sort_avg, sort_val[80]; + float tonality, tonality1, tonality2, tonality3, t2, t3, tL, err, cor, dft; + + /* reset in case of codec mode swithing */ + if( st->last_codec_mode == MODE2 ) + { + set_f( st->tonality2_buf, 0, HANG_LEN_INIT ); + set_f( st->tonality3_buf, 0, HANG_LEN_INIT ); + set_f( st->LPCErr_buf, 0, HANG_LEN_INIT ); + st->lt_music_hangover = 0; + st->lt_music_state = 0; + st->lt_speech_state = 0; + st->lt_speech_hangover= 0; + } + + /* estimate maximum tonality in bands [0-1 kHz], [1-2kHz] and [2-4kHz] */ + mvr2r( PS, sort_val, 80 ); + + /* tonality in band 0-1 kHz */ + v_sort(sort_val, 0, 19); + sort_max = sort_val[19]; + sort_avg = sum_f(&sort_val[0], 10); + tonality1 = sort_max / sort_avg; + + /* tonality in band 1-2 kHz */ + v_sort(sort_val, 20, 39); + sort_max = sort_val[39]; + sort_avg = sum_f(&sort_val[20], 10); + tonality2 = sort_max / sort_avg; + + /* tonality in band 2-4 kHz */ + v_sort(sort_val, 40, 79); + sort_max = sort_val[79]; + sort_avg = sum_f(&sort_val[40], 20); + tonality3 = sort_max / sort_avg; + + tonality = max(max(tonality1, tonality2), tonality3); + + if( st->hangover_cnt == 10 && vad_flag == 1 ) + { + /* long-term voicing parameter */ + st->lt_voicing = 0.1f * st->lt_voicing + 0.9f * *voicing; + + /* long-term correlation value */ + st->lt_corr = 0.1f * st->lt_corr + 0.9f * st->old_corr; + + /* long-term tonality measure */ + st->lt_tonality = 0.1f * st->lt_tonality + 0.9f * tonality; + } + else + { + /* long-term voicing parameter */ + st->lt_voicing = 0.7f * st->lt_voicing + 0.3f * *voicing; + + /* long-term correlation value */ + st->lt_corr = 0.7f * st->lt_corr + 0.3f * st->old_corr; + + /* long-term tonality measure */ + st->lt_tonality = 0.5f * st->lt_tonality + 0.5f * tonality; + } + + /* pitch difference w.r.t to past 3 frames */ + lt_pitch_diff = (short)abs(st->lt_corr_pitch[0] - pitch[0]); + lt_pitch_diff += (short)abs(st->lt_corr_pitch[1] - pitch[0]); + lt_pitch_diff += (short)abs(st->lt_corr_pitch[2] - pitch[0]); + + st->lt_corr_pitch[0] = st->lt_corr_pitch[1]; + st->lt_corr_pitch[1] = st->lt_corr_pitch[2]; + st->lt_corr_pitch[2] = pitch[0]; + + st->lt_old_mode[0] = st->lt_old_mode[1]; + st->lt_old_mode[1] = st->lt_old_mode[2]; + + if ( *sp_aud_decision1 == 1 && + ( min(min(tonality1, tonality2), tonality3) > 50.0f ) && + ( tonality1+tonality2 > 200.0f && tonality2 + tonality3 > 200.0f && tonality1 + tonality3 > 200.0f ) && + ( st->lt_tonality < 20000.0f ) && + ( ( st->lt_tonality > 1000 && max(st->lt_voicing, *voicing) > 0.99f ) || + ( st->lt_tonality > 1500 && st->lt_corr > 0.99f ) || + ( st->lt_tonality > 3000 && st->lowrate_pitchGain > 0.96f ) || + ( lt_pitch_diff == 0 && st->lowrate_pitchGain > 0.89f ) ) ) + { + if( sum_s(st->lt_old_mode, 2) < 2 ) + { + /* probably speech - change the decision to speech */ + *sp_aud_decision1 = 0; + *sp_aud_decision2 = 0; + + if( st->lt_hangover == 0 ) + { + st->lt_hangover = 6; + } + } + } + else + { + /* not speech, but still in the hangover period - change the decision to speech */ + if( st->lt_hangover > 0 ) + { + *sp_aud_decision1 = 0; + *sp_aud_decision2 = 0; + st->lt_hangover--; + } + } + + /* calculate standard deviation of log-tonality */ + mvr2r( st->tonality2_buf + 1, st->tonality2_buf, HANG_LEN_INIT - 1 ); + st->tonality2_buf[HANG_LEN_INIT - 1] = 0.2f*(float)log10(tonality2); + t2 = std_dev( st->tonality2_buf, HANG_LEN_INIT ); + + mvr2r( st->tonality3_buf + 1, st->tonality3_buf, HANG_LEN_INIT - 1 ); + st->tonality3_buf[HANG_LEN_INIT - 1] = 0.2f*(float)log10(tonality3); + t3 = std_dev( st->tonality3_buf, HANG_LEN_INIT ); + + tL = 0.2f*(float)log10(st->lt_tonality); + + /* calculate standard deviation of residual LP energy */ + mvr2r( st->LPCErr_buf + 1, st->LPCErr_buf, HANG_LEN_INIT - 1 ); + st->LPCErr_buf[HANG_LEN_INIT - 1] = LPCErr; + err = std_dev( st->LPCErr_buf, HANG_LEN_INIT ); + + cor = max( voi_fv - cor_map_sum_fv, 0.0f ); + dft = 0.2f * (float) fabs( log10(tonality2) - log10(tonality3) ); + + /* state machine for strong music */ + if( *sp_aud_decision1 == 1 && st->lt_music_state == 0 && st->lt_music_hangover == 0 && + t2 < 0.54f && t2 > 0.26f && t3 > 0.22f && tL < 0.54f && tL > 0.26f && err > 0.5f ) + { + st->lt_music_state = 1; + st->lt_music_hangover = 6; + } + else if( st->lt_music_state == 1 && st->lt_music_hangover == 0 && + t2 < 0.34 && t3 < 0.26f && tL < 0.45f) + { + st->lt_music_state = 0; + st->lt_music_hangover = 6; + } + + if( st->lt_music_hangover > 0 ) + { + st->lt_music_hangover--; + } + + /* state machine for strong speech */ + if( *sp_aud_decision1 == 1 && st->lt_speech_state == 0 && st->lt_speech_hangover == 0 && + cor > 0.40f && dft < 0.1f && voi_fv > 2 * cor_map_sum_fv + 0.12f && + t2 < cor && t3 < cor && tL < cor && cor_map_sum_fv < cor && voi_fv > cor && voi_fv > 0.76f ) + { + st->lt_speech_state = 1; + st->lt_speech_hangover = 6; + } + else if( st->lt_speech_state == 1 && st->lt_speech_hangover == 0 && cor < 0.40f ) + { + st->lt_speech_state = 0; + st->lt_speech_hangover = 6; + } + + if( st->lt_speech_hangover > 0 ) + { + st->lt_speech_hangover--; + } + + /* final decision */ + if ( *sp_aud_decision1 == 1 && st->lt_speech_state == 1 ) + { + /* strong speech - probably error in speech/music classification */ + *sp_aud_decision1 = 0; + *sp_aud_decision2 = 0; + } + else if ( *sp_aud_decision1 == 0 && st->lt_music_state == 1 ) + { + /* strong music - probably error in speech/music classification */ + *sp_aud_decision1 = 1; + *sp_aud_decision2 = 1; + } + + /* update the buffer of past decisions */ + st->lt_old_mode[2] = *sp_aud_decision1; + + return; +} + +/*---------------------------------------------------------------------* + * detect_sparseness() + * + * + *---------------------------------------------------------------------*/ + +static void detect_sparseness( + Encoder_State *st, /* i/o: encoder state structure */ + const short localVAD_HE_SAD, /* i : HE-SAD flag without hangover */ + short *sp_aud_decision1, /* i/o: 1st stage speech/music decision */ + short *sp_aud_decision2, /* i/o: 2nd stage speech/music decision */ + const float voi_fv /* i : scaled voicing feature */ +) +{ + float sum; + float ftmp; + float ftmp1; + float S1[128]; + short i,j; + short hb_sp_high_flag = 0; + short lb_sp_high_flag = 0; + float sumh; + float sparse; + float tmp_buf[4]; + float Mlpe = 0.0f; + float Mv = 0.0f; + float Msp; + + mvr2r( st->Bin_E, S1, 128 ); + + sum = 0; + for ( i=0; i<80; i++ ) + { + if ( S1[i] < 0 ) + { + S1[i] = 0; + } + sum += S1[i]; + } + + sumh = 0; + for ( i=80; i<128; i++ ) + { + if ( S1[i] < 0 ) + { + S1[i] = 0; + } + sumh += S1[i]; + } + + sum += sumh; + + /* order spectral from max to min */ + order_spectrum(S1, 128); + + /* calculate spectral sparseness in the range 0 - 6.4 kHz */ + j = 0; + ftmp = 0.0f; + ftmp1 = 0.75f * sum; + for ( i=0; i<128; i++ ) + { + ftmp += S1[i]; + if ( ftmp > ftmp1 ) + { + j = i; + break; + } + } + + for ( i=0; isparse_buf[i] = st->sparse_buf[i+1]; + } + + sparse = (float)j; + st->sparse_buf[i] = sparse; + + if ( st->bwidth == WB ) + { + Msp = mean(st->sparse_buf, 8); + + /* find long-term smoothed sparseness */ + if ( st->last_vad_spa == 0 ) + { + set_f( &st->sparse_buf[0], sparse, HANG_LEN_INIT-1 ); + st->LT_sparse = sparse; + } + else + { + set_f(tmp_buf, 0.0f, 4); + + for ( i=0; isparse_buf[i] > tmp_buf[j] ) + { + mvr2r(&tmp_buf[j], &tmp_buf[j+1], 3-j); + tmp_buf[j] = st->sparse_buf[i]; + break; + } + } + } + + ftmp = 0.25f*(HANG_LEN_INIT*Msp - sum_f(tmp_buf, 4)) - st->LT_sparse; + + st->LT_sparse = st->LT_sparse + 0.25f * ftmp; + } + + /* find high-band sparseness */ + mvr2r(st->Bin_E+80, S1, 48); + order_spectrum(S1, 48); + + for ( i=0; ihf_spar_buf[i] = st->hf_spar_buf[i+1]; + } + st->hf_spar_buf[i] = sum_f(S1, 5)/(sumh + 0.1f); + if ( mean(st->hf_spar_buf, 8) > 0.2f ) + { + hb_sp_high_flag = 1; + } + + /* find low-band sparseness */ + mvr2r(st->Bin_E, S1, 60); + order_spectrum(S1, 60); + + if ( sum_f(S1, 5)/sum_f(S1,60) > 0.18f ) + { + lb_sp_high_flag = 1; + } + + /* find smoothed linear prediction efficiency */ + for ( i=0; i<7; i++ ) + { + st->lpe_buf[i] = st->lpe_buf[i+1]; + } + + st->lpe_buf[i] = st->past_epsP2; + Mlpe = mean(st->lpe_buf, 8); + + /* find smoothed voicing */ + for ( i=0; ivoicing_buf[i] = st->voicing_buf[i+1]; + } + + st->voicing_buf[i] = voi_fv; + Mv = mean(st->voicing_buf, 8); + } + + /* avoid using LR-MDCT on sparse spectra */ + if ( *sp_aud_decision1 == 1 ) + { + if ( st->bwidth == WB ) + { + ftmp = 90; + } + else + { + ftmp = 91; + } + if ( sparse > ftmp ) + { + *sp_aud_decision1 = 0; + *sp_aud_decision2 = 1; + st->gsc_hangover = 1; + } + else if ( st->gsc_hangover == 1 ) + { + if ( sparse > 85 ) + { + *sp_aud_decision1 = 0; + *sp_aud_decision2 = 1; + } + else if ( fabs(sparse - mean(&st->sparse_buf[HANG_LEN_INIT-1-st->gsc_cnt], st->gsc_cnt)) < 7.0f ) + { + *sp_aud_decision1 = 0; + *sp_aud_decision2 = 1; + } + } + + if ( st->bwidth == WB ) + { + if ( st->LT_sparse > 60 && sparse > 50 && Mlpe < -1.3f && Mv > 0.85f && + lb_sp_high_flag == 0 && ( (hb_sp_high_flag == 0 && sumh > 0.15f * sum) || sumh <= 0.15f * sum ) ) + { + *sp_aud_decision1 = 0; + *sp_aud_decision2 = 1; + st->gsc_hangover = 1; + } + else if ( st->gsc_hangover == 1 && !( *sp_aud_decision1 == 0 && *sp_aud_decision2 == 1) ) + { + if ( fabs(sparse - mean(&st->sparse_buf[HANG_LEN_INIT-1-st->gsc_cnt], st->gsc_cnt)) < 7.0f ) + { + *sp_aud_decision1 = 0; + *sp_aud_decision2 = 1; + } + } + } + } + + /* update the counter of consecutive GSC frames with sparse spectrum */ + if ( *sp_aud_decision1 == 0 && *sp_aud_decision2 == 1 ) + { + (st->gsc_cnt)++; + if ( st->gsc_cnt > 7 ) + { + st->gsc_cnt = 7; + } + } + else + { + st->gsc_cnt = 0; + st->gsc_hangover = 0; + } + + st->last_vad_spa = localVAD_HE_SAD; + + return; +} + + +static void order_spectrum( float *vec, short len ) +{ + short i, j, imax, imin; + float temp; + + for (i = 0; i vec[imax]) + { + imax = j; + } + else + { + if (vec[j] < vec[imin]) + { + imin = j; + } + } + } + + temp = vec[i]; + vec[i] = vec[imax]; + vec[imax] = temp; + + if (imin == i) + { + imin = imax; + } + + temp = vec[len - i - 1]; + vec[len - i - 1] = vec[imin]; + vec[imin] = temp; + } + + return; +} diff --git a/lib_enc/stat_enc.h b/lib_enc/stat_enc.h new file mode 100644 index 000000000..f3589714a --- /dev/null +++ b/lib_enc/stat_enc.h @@ -0,0 +1,1230 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#ifndef STAT_ENC_H +#define STAT_ENC_H +#include "options.h" +#include "stat_com.h" /* Common structures */ +#include "cnst.h" + + +/*------------------------------------------------------------------------------------------* + * Indice + *------------------------------------------------------------------------------------------*/ + +typedef struct +{ + unsigned short value; /* value of the quantized indice */ + short nb_bits; /* number of bits used for the quantization of the indice */ +} Indice; + +typedef struct +{ + /* signal memory */ + float syn[1+M]; /* Synthesis memory (non-pe) */ + + /* ACELP memories*/ + float old_exc[L_EXC_MEM]; /* ACELP exc memory (Aq) */ + float mem_w0; + float mem_syn[M]; /* ACELP synthesis memory (pe) before post-proc */ + float mem_syn2[M]; /* ACELP synthesis memory (pe) after post-proc */ + float mem_syn_r[L_SYN_MEM]; /* ACELP synthesis memory for 1.25ms */ + float mem_syn3[M]; + + float tilt_code; + float gc_threshold; /* Noise enhancer - threshold for gain_code */ + + /* TCX memory */ + float Txnq[L_FRAME32k/2+64];/* Q target (overlap or ACELP+ZIR, use Aq) */ + float *acelp_zir; + float tcx_target_bits_fac; + + +} LPD_state; + +typedef struct PLC_ENC_EVS +{ + + int nBits; /* number of bits */ + + int enableGplc; + int T0_4th; + int T0; + int calcOnlylsf; + int pit_min; + int pit_max; + + float mem_MA[M]; + float mem_AR[M]; + + float lsfold[M]; /* old lsf (frequency domain) */ + float lspold[M]; /* old lsp (immittance spectral pairs) */ + + float lsfoldbfi0[M]; /* Previous frame lsf */ + float lsfoldbfi1[M]; /* Past previous frame lsf */ + float lsf_adaptive_mean[M]; /* Mean lsf for bfi cases */ + float stab_fac; + + LPD_state *LPDmem; + float old_exc[8]; /* ACELP exc memory (Aq) */ + + float lsf_con[M]; + float last_lsf_ref[M]; + float last_lsf_con[M]; +} PLC_ENC_EVS; + +/* Arrays and variables specific to encoder */ +typedef struct +{ + HANDLE_FD_CNG_COM hFdCngCom; + + float msPeriodog[NPART]; /* Periodogram */ + float msBminWin[NPART]; + float msBminSubWin[NPART]; + float msPsd[NPART]; /* Power Spectral Density estimate (i.e., smoothed periodogram) */ + float msAlpha[NPART]; /* Optimal smoothing parameter */ + float msMinBuf[MSNUMSUBFR*NPART]; /* Buffer of minima */ + float msCurrentMinOut[NPART]; + float msCurrentMin[NPART]; + float msCurrentMinSubWindow[NPART]; + int msLocalMinFlag[NPART]; + int msNewMinFlag[NPART]; + float msPsdFirstMoment[NPART]; + float msPsdSecondMoment[NPART]; + float msNoiseFloor[NPART]; /* Estimated noise floor */ + float msNoiseEst[NPART]; /* Estimated noise level */ + float energy_ho[NPART]; + float msNoiseEst_old[NPART]; + float msLogPeriodog[NPART]; /* Periodogram */ + float msLogNoiseEst[NPART]; /* Estimated noise level */ + + float msPeriodogBuf[MSBUFLEN*NPART]; + int msPeriodogBufPtr; + + int stopFFTbinDec; + int startBandDec; + int stopBandDec; + int npartDec; + int midbandDec[NPART]; + int nFFTpartDec; + int partDec[NPART]; +} +FD_CNG_ENC; +typedef FD_CNG_ENC *HANDLE_FD_CNG_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. */ + int nSubblockSize; + /** Delay buffer */ + float buffer[L_FRAME_MAX/NSUBBLOCKS]; + /** Size of the delay buffer in use. Maximum delay from all users of this buffer. */ + int 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. */ + float 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. */ + float accSubblockNrg[NSUBBLOCKS+MAX_TD_DELAY+1]; + /** subblockNrgChange[i] = max(subblockNrg[i]/subblockNrg[i-1], subblockNrg[i-1]/subblockNrg[i]) */ + float subblockNrgChange[NSUBBLOCKS+MAX_TD_DELAY]; + /** Size of the delay buffer in use, as number of subblocks. Maximum delay from all users of this buffer. */ + int nDelay; + /* Delay of the input (modulo pDelayBuffer->nSubblockSize), nPartialDelay <= pDelayBuffer->nDelay. */ + int nPartialDelay; + + /** Decay factor for the recursive accumulation */ + float facAccSubblockNrg; + + /** High-pass filter states (delay line) */ + float firState1; + float 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)(float const * pSubblockNrg, float const * pAccSubblockNrg, int nSubblocks, int nPastSubblocks, float attackRatioThreshold, int * pbIsAttackPresent, int * 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. */ + int nDelay; + /** Number of subblocks to check for transients. */ + int nSubblocksToCheck; + /** Function for checking a presence of an attack. */ + TCheckSubblocksForAttack CheckSubblocksForAttack; + /** Attack ratio threshold. */ + float attackRatioThreshold; + /** True when an attack was detected. */ + int bIsAttackPresent; + /** The index of an attack. */ + int 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; + + +typedef struct +{ + int bw_index; /* index of band width */ + + /* feature */ + float sp_center[SP_CENTER_NUM]; /* spectral center*/ + float ltd_stable_rate[STABLE_NUM]; /* time-domain stable rate*/ + float sfm[SFM_NUM]; /* spectral flatness*/ + float f_tonality_rate[TONA_NUM]; /* tonality rate*/ + float frame_sb_energy[BG_ENG_NUM]; /* energy of sub-band divided non-uniformly*/ + float frames_power[POWER_NUM]; /* energy of several frames*/ + float pre_spec_low_dif[PRE_SPEC_DIF_NUM]; /* low frequency spectral different*/ + float t_bg_energy; /* time background energy of several frames*/ + float t_bg_energy_sum; /* number of time background energy*/ + int tbg_energy_count; /* sum of time background energy of several frames*/ + int bg_update_count; /* time of background update*/ + float frame_energy_smooth; /* smoothed energy of several frames*/ + + + /************************************************************************/ + /* history parameters */ + /************************************************************************/ + float smooth_spec_amp[SPEC_AMP_NUM]; /* smoothed spectral amplitude*/ + float sb_bg_energy[BG_ENG_NUM]; /* sub-band background energy*/ + float pre_snr[PRE_SNR_NUM]; /* previous time SNR*/ + float lt_snr_org; /* original long time SNR*/ + float lf_snr_smooth; /* smoothed lf_snr*/ + float l_silence_snr; /* sum of snr's of non active frames*/ + float l_speech_snr; /* sum of snr's of active frames*/ + int l_silence_snr_count; /* number of non active frames*/ + int l_speech_snr_count; /* number of active frames*/ + float fg_energy ; /* foreground energy sum */ + float bg_energy ; /* background energy sum */ + int fg_energy_count ; /* number of the foreground energy frame */ + int bg_energy_count ; /* number of the background energy frame */ + int fg_energy_est_start; /* flag by that indicate whether if estimate energy*/ + int speech_flag; /* residual number of hangover 1 */ + int continuous_noise_num; /* time of continuous noise frames*/ + int continuous_speech_num; /* time of continuous speech frames*/ + int continuous_speech_num2; /* time 2 of continuous speech frames*/ + int frameloop; /* number of frame*/ + float tonality_rate3 ; /* tonality rate*/ + float music_background_rate; /* music background rate*/ + float lt_noise_sp_center_diff_sum; /* different sum of long time noise sp_center*/ + float lt_noise_sp_center_diff_counter; /* number of the member lt_noise_sp_center_diff_sum*/ + float lt_noise_sp_center0 ; /* long time noise sp_center0*/ + float lt_noise_sp_center3 ; /* long time noise sp_center3*/ + float lt_bg_highf_eng; /* average of long time high frequency energy*/ + int update_num_with_snr; /* the number of the background update with SNR*/ + int update_count; + short warm_hang_num; /* the number of hangover for warm up*/ + short vad_flag_for_bk_update; +} T_CldfbVadState; + + +typedef struct igfscfenc_public_data_struct +{ + int ptrBitIndex; + int bitCount; + int prev[64]; /* no more than 64 SCFs for the IGF energy envelope of one block */ + int prevSave[64]; + int scfCountLongBlock; + int t; + int Tsave; + int contex_saved; + const unsigned short *cf_se00; + const unsigned short *cf_se01; + short cf_off_se01; + const unsigned short *cf_se02; + const short *cf_off_se02; + const unsigned short *cf_se10; + short cf_off_se10; + const unsigned short *cf_se11; + const short *cf_off_se11; + Tastat acState; +} IGFSCFENC_INSTANCE, *IGFSCFENC_INSTANCE_HANDLE; + + +typedef struct igf_enc_private_data_struct +{ + IGF_INFO igfInfo; + int igfScfQuantized[IGF_MAX_SFB]; + IGFSCFENC_INSTANCE hIGFSCFArithEnc; + + + int igfCurrWhiteningLevel[IGF_MAX_TILES]; + int igfPrevWhiteningLevel[IGF_MAX_TILES]; + + float prevSFM_FIR[IGF_MAX_TILES]; + float prevSFM_IIR[IGF_MAX_TILES]; + int wasTransient; + + UWord8 igfBitstream[BITBUFSIZE/8]; + short igfBitstreamBits; + + +} IGF_ENC_PRIVATE_DATA, *IGF_ENC_PRIVATE_DATA_HANDLE; + +/**********************************************************************/ /** +Definition of public data for this module +**************************************************************************/ +typedef struct igf_enc_instance_struct +{ + IGF_ENC_PRIVATE_DATA igfData; + int infoSamplingRate; + int infoStartFrequency; + int infoStopFrequency; + int infoStartLine; + int infoStopLine; + int infoTotalBitsWritten; + int infoTotalBitsPerFrameWritten; + int infoFrameCount; + int flatteningTrigger; + float spec_be_igf[N_MAX_TCX-IGF_START_MN]; + float tns_predictionGain; +} IGF_ENC_INSTANCE, *IGF_ENC_INSTANCE_HANDLE; + +/*----------------------------------------------------------------------------------* + * + * Main encoder structure + * + *----------------------------------------------------------------------------------*/ + +typedef struct +{ + + /*----------------------------------------------------------------------------------* + * Common parameters + *----------------------------------------------------------------------------------*/ + + short codec_mode; /* Mode1 or Mode2 */ + short last_codec_mode; /* previous frame Mode 1 or 2 */ + short last_codec_mode_cng; /* previous inactive frame Mode 1 or 2 */ + short mdct_sw_enable; /* MDCT switching enable flag */ + short mdct_sw; /* MDCT switching indicator */ + float prev_hi_ener; + short prev_hi_sparse; + float clas_sec_old; + short clas_final_old; + float last_gain1; + float last_gain2; + + short nb_bits_tot; /* total number of bits already written */ + Indice *ind_list; /* list of indices */ + short bitstreamformat; /* Bitstream format flag (G.192/MIME) */ + short next_ind; /* pointer to the next empty slot in the list of indices */ + short last_ind; /* last written indice */ + + int input_Fs; /* input signal sampling frequency in Hz */ + long total_brate; /* total bitrate in kbps of the codec */ + long last_total_brate; /* last frame's total bitrate in kbps of the codec */ + long last_total_brate_cng; /* last inactive frame's total bitrate in kbps of the codec */ + short core; /* core (ACELP_CORE, TCX_20_CORE, TCX_10_CORE, HQ_CORE, AMR_WB_CORE) */ + long core_brate; /* core bitrate */ + long last_core_brate; /* previous frame core bitrate */ + short extl; /* extension layer */ + short last_extl; /* previous extension layer */ + long extl_brate; /* extension layer bitrate */ + short input_bwidth; /* input signal bandwidth */ + short bwidth; /* encoded bandwidth NB, WB, SWB or FB */ + short max_bwidth; /* maximum encoded bandwidth */ + short last_input_bwidth; /* input signal bandwidth in the previous frame */ + short last_bwidth; /* coded bandwidth in the previous frame */ + short last_bwidth_cng; /* coded bandwidth in the previous inactive frame */ + short L_frame; /* ACELP core internal frame length */ + short Opt_AMR_WB; /* flag indicating AMR-WB IO mode */ + short Opt_DTX_ON; /* flag indicating DTX operation */ + short cng_type; /* flag indicating LP or CLDFB based SID/CNG */ + short active_cnt; /* counter of active frames */ + short Opt_SC_VBR; /* flag indicating SC-VBR mode */ + short last_Opt_SC_VBR; /* flag indicating prev frame's SC-VBR mode */ + short lp_cng_mode2; + /*----------------------------------------------------------------------------------* + * ACELP core parameters + *----------------------------------------------------------------------------------*/ + + LPD_state LPDmem; /* ACELP memories */ + + short clas; /* current frame clas */ + short last_clas; /* previous frame signal classification */ + float Bin_E[L_FFT]; /* per bin energy of two frames */ + float Bin_E_old[L_FFT/2]; /* per bin energy of old 2nd frames */ + float lsp_old1[M]; /* old unquantized LSP vector at the end of the frame at 12k8 */ + float lsf_old1[M]; /* old unquantized LSF vector at the end of the frame at 12k8 */ + float lsp_old[M]; /* old LSP vector at the end of the frame */ + float lsf_old[M]; /* old LSF vector at the end of the frame */ + float lsp_old16k[M]; /* old LSP vector at the end of the frame @16kHz */ + float lspold_enc[M]; /* old lsp (immittance spectral pairs) */ + short pstreaklen; /* LSF quantizer */ + float streaklimit; /* LSF quantizer */ + unsigned int offset_scale1[MAX_NO_MODES+1][MAX_NO_SCALES+1]; /* offsets for LSF LVQ structure 1st 8-dim subvector*/ + unsigned int offset_scale2[MAX_NO_MODES+1][MAX_NO_SCALES+1]; /* offsets for LSF LVQ structure 2nd 8-dim subvector*/ + unsigned int offset_scale1_p[MAX_NO_MODES_p+1][MAX_NO_SCALES+1]; /* offsets for LSF LVQ structure, pred. case, 1st 8-dim subvector*/ + unsigned int offset_scale2_p[MAX_NO_MODES_p+1][MAX_NO_SCALES+1]; /* offsets for LSF LVQ structure, pred. case, 2nd 8-dim subvector*/ + short no_scales[MAX_NO_MODES][2]; /* LSF LVQ structure */ + short no_scales_p[MAX_NO_MODES_p][2]; /* LSF LVQ structure */ + float stab_fac; /* LSF stability factor */ + float mem_decim[2*L_FILT_MAX]; /* decimation filter memory */ + float mem_deemph; /* deemphasis filter memory */ + float mem_preemph; /* preemphasis filter memory */ + float mem_hp20_in[4]; /* HP filter memory */ + float old_inp_12k8[L_INP_MEM]; /* memory of input signal at 12.8kHz */ + float old_wsp[L_WSP_MEM]; /* old weighted signal vector */ + float old_wsp2[(L_WSP_MEM - L_INTERPOL)/OPL_DECIM]; /* old decimated weighted signal vector */ + float fr_bands1[NB_BANDS]; /* spectrum per critical bands of the previous frame */ + float fr_bands2[NB_BANDS]; /* spectrum per critical bands 2 frames ago */ + float mem_wsp; /* weighted signal vector memory */ + float mem_decim2[3]; /* weighted signal decimation filter memory */ + float mem_syn1[M]; /* synthesis filter memory (for core switching and FD BWE) */ + + float clip_var[6]; /* pitch gain clipping memory */ + float past_qua_en[4]; /* gain quantization memory (used also in AMR-WB IO mode) */ + float mem_AR[M]; /* AR memory of LSF quantizer (past quantized LSFs without mean) */ + float mem_MA[M]; /* MA memory of LSF quantizer (past quantized residual) (used also in AMR-WB IO mode) */ + short mCb1; /* LSF quantizer - counter of stationary frames after a transition frame */ + short coder_type_raw; /* raw coder_type (before UNVOICED is lost) */ + short last_coder_type_raw; /* raw last_coder_type (coming from the sigal classification) */ + short last_coder_type; /* previous coding type */ + short ini_frame; /* initialization frames counter */ + float old_thres; /* normalized correlation weighting in open-loop pitch */ + float old_corr; /* normalized correlation in previous frame (mean value) */ + short old_pitch; /* previous pitch for open-loop pitch search */ + short delta_pit; /* open-loop pitch extrapolation correction */ + float ee_old; /* previous frame low/high frequency energy ratio */ + short min_band; /* minimum critical band of useful bandwidth */ + short max_band; /* maximum critical band of useful bandwidth */ + short tc_cnt; /* TC frame counter */ + short audio_frame_cnt; /* Counter of relative presence of audio frames */ + float old_dE1; /* Maximum energy increase in previous frame */ + short old_ind_deltaMax; /* Index of the sub-subframe of maximum energy in previous frame */ + float old_enr_ssf[2*NB_SSF]; /* Maxima of energies per sub-subframes of previous frame */ + short spike_hyst; /* Hysteresis to prevent UC after sharp energy spike */ + short music_hysteresis; /* Counter of frames after AUDIO coding mode to prevent UC */ + short last_harm_flag_acelp; /* harmonicity flag for ACELP @32kbps rate */ + float old_Aq_12_8[M+1]; /* old Aq[] for core switching */ + float old_Es_pred; /* old Es_pred for core switching */ + short high_stable_cor; + + short seed_tcx; /* AC mode (GSC) - seed for noise fill*/ + short cor_strong_limit; /* AC mode (GSC) - Indicator about high spectral correlation per band */ + short GSC_noisy_speech; /* AC mode (GSC) - flag to indicate GSC on SWB noisy speech */ + short mem_last_pit_band; /* AC mode (GSC) - memory of the last band where pitch contribution was significant */ + float mem_w0_tmp; + float mem_syn_tmp[M]; + float var_cor_t[VAR_COR_LEN]; + float mid_dyn; /* AC mode (GSC) - signal dynamic */ + short noise_lev; /* AC mode (GSC) - noise level */ + short past_dyn_dec; /* AC mode (GSC) - Past noise level decision */ + float Last_frame_ener; /* AC mode (GSC) - Last frame energy */ + short pit_exc_hangover; /* AC mode (GSC) - Hangover for the time contribution switching*/ + + float last_exc_dct_in[L_FRAME]; /* AC mode (GSC) - previous excitation */ + float last_ener; /* AC mode (GSC) - previous energy */ + short last_bitallocation_band[6]; /* AC mode (GSC) - previous bit allocation of each band */ + + + short last_act_dec_hang; /* Speech/music classifier - decision from the last active frame */ + float past_PS[HIGHEST_FBIN-LOWEST_FBIN]; + float past_ps_diff; + float past_epsP2; + short inact_cnt; + float wdrop; + float wdlp_0_95_sp; + short sp_mus_state; + short past_dec[HANG_LEN-1]; /* Speech/music classifier - buffer of past binary decisions */ + float past_dlp[HANG_LEN-1]; /* Speech/music classifier - buffer of past non-binary decisions */ + float last_lsp[M_LSP_SPMUS]; + float last_cor_map_sum; + float last_non_sta; + float past_log_enr[NB_BANDS_SPMUS]; /* Speech/music classifier - last average per-band log energy used for non_staX */ + float gsc_thres[4]; /* Speech/music classifier - classification threshold */ + float gsc_lt_diff_etot[MAX_LT]; /* Speech/music classifier - long-term total energy variation */ + float gsc_mem_etot; /* Speech/music classifier - total energy memory */ + short gsc_last_music_flag; /* Speech/music classifier - last music flag */ + short gsc_nb_thr_1; /* Speech/music classifier - number of consecutives frames of level 1 */ + short gsc_nb_thr_3; /* Speech/music classifier - number of consecutives frames of level 3 */ + float mold_corr; + float lt_gpitch; + float mean_avr_dyn; /* Speech/music classifier - long term average dynamic */ + float last_sw_dyn; /* Speech/music classifier - last dynamic */ + float lt_dec_thres; /* Speech/music classifier - Long term speech/music thresold values */ + float ener_RAT; /* Speech/music classifier - LF/to total energy ratio */ + + /* speech/music classifier improvement parameters */ + float old_Bin_E[3*N_OLD_BIN_E]; + float buf_flux[BUF_LEN]; + float buf_pkh[BUF_LEN]; + float buf_epsP_tilt[BUF_LEN]; + float buf_cor_map_sum[BUF_LEN]; + float buf_Ntonal[BUF_LEN]; + float buf_Ntonal2[BUF_LEN]; + float buf_Ntonal_lf[BUF_LEN]; + float buf_dlp[10]; + short onset_cnt; + float buf_etot[4]; + short attack_hangover; + float dec_mov; + float dec_mov1; + float mov_log_max_spl; + float old_lt_diff[2]; + short UV_cnt1; + float LT_UV_cnt1; + + short lt_music_hangover; + float tonality2_buf[HANG_LEN_INIT]; + float tonality3_buf[HANG_LEN_INIT]; + float LPCErr_buf[HANG_LEN_INIT]; + short lt_music_state; + short lt_speech_state; + short lt_speech_hangover; + float lpe_buf[HANG_LEN_INIT]; + float voicing_buf[HANG_LEN_INIT]; + short gsc_hangover; + float sparse_buf[HANG_LEN_INIT]; + float hf_spar_buf[HANG_LEN_INIT]; + float LT_sparse; + short gsc_cnt; + + short Last_pulse_pos; /* FEC - last position of the first glottal pulse in the frame */ + float lsfoldbfi0[M]; /* FEC - LSF vector of the previous frame */ + float lsfoldbfi1[M]; /* FEC - LSF vector of the past previous frame */ + float lsf_adaptive_mean[M]; /* FEC - adaptive mean LSF vector for FEC */ + short next_force_safety_net; /* FEC - flag to force safety net in next frame */ + float old_S[L_FFT/2]; /* Tonal detector - prev. log-energy spectrum with subtracted floor */ + float cor_map[L_FFT / 2]; /* Tonal detector - LT correlation map */ + float noise_char; /* Tonal detector - LT noise character */ + float ave_enr2[NB_BANDS]; /* Tonal detector - LT average E per crit. band (for non_sta2) */ + float act_pred; /* Tonal detector - prediction of speech activity from 0 to 1 (0-inactive, 1-active) */ + float multi_harm_limit; /* Tonal detector - adaptive threshold */ + float enrO[NB_BANDS]; /* Noise estimator - previous energy per critical band */ + float bckr[NB_BANDS]; /* Noise estimator - background noise estimation per critical band */ + float ave_enr[NB_BANDS]; /* Noise estimator - long-term average energy per critical band */ + short pitO; /* Noise estimator - previous open-loop pitch value */ + short aEn; /* Noise estimator - noise estimator adaptation flag */ + float totalNoise; /* Noise estimator - total noise energy */ + short first_noise_updt; /* Noise estimator - flag used to determine if the first noise update frame */ + short harm_cor_cnt; /* Noise estimator - 1st memory counter of harm or correlation frame */ + short bg_cnt; /* Noise estimator - pause length counter */ + float prim_act_quick; /* Noise estimator - primary activity quick */ + float prim_act_slow; /* Noise estimator - primary activity slow */ + float prim_act; /* Noise estimator - primary activity slow rise quick fall */ + float prim_act_quick_he; /* Noise estimator - primary activity quick */ + float prim_act_slow_he; /* Noise estimator - primary activity slow */ + float prim_act_he; /* Noise estimator - primary activity slow rise quick fall */ + float Etot_l; /* Noise estimator - Track energy from below */ + float Etot_h; /* Noise estimator - Track energy from above */ + float Etot_l_lp; /* Noise estimator - Smoothed low energy */ + float Etot_last; /* Noise estimator - Energy of last frame */ + float Etot_lp; /* Noise estimator - Filtered input energy */ + float lt_tn_track; + float lt_tn_dist; + float lt_Ellp_dist; + float lt_haco_ev; + short low_tn_track_cnt; + float epsP_0_2_lp; + float epsP_0_2_ad_lp; + float epsP_2_16_lp; + float epsP_2_16_lp2; + float epsP_2_16_dlp_lp; + float epsP_2_16_dlp_lp2; + float lt_aEn_zero; + + float Etot_st_est; /* Noise estimation - short term estimate of E{ Etot } */ + float Etot_sq_st_est; /* Noise estimation - short term estimate of E{ Etot^2 } */ + + + short nb_active_frames; + short hangover_cnt; + float lp_speech; + float Etot_v_h2; + float sign_dyn_lp; + short nb_active_frames_he; + short hangover_cnt_he; + short nb_active_frames_HE_SAD; + long vad_flag_reg_H; + long vad_flag_reg_L; + long vad_prim_reg; + + short vad_flag_cnt_50; + short vad_prim_cnt_16; + + short hangover_cnt_dtx; + short hangover_cnt_music; + + float bcg_flux; + short soft_hangover; + short voiced_burst; + short bcg_flux_init; + float voicing_old; + short nb_active_frames_he1; + short hangover_cnt_he1; + + float bckr_tilt_lt; + + short var_SID_rate_flag; /* CNG and DTX - flag for variable SID rate */ + float lp_ener; /* CNG and DTX - low-pass filtered energy for CNG */ + short cng_seed; /* CNG and DTX - seed for white noise random generator */ + float lspCNG[M]; /* CNG and DTX - LP filtered ISPs */ + short first_CNG; /* CNG and DTX - first CNG frame flag */ + float lp_noise; /* CNG and DTX - LP filterend total noise estimation */ + short cnt_SID; /* CNG and DTX - counter of SID update for the interop. mode or dtx, if enabled */ + short max_SID; /* CNG and DTX - max allowed number of CNG FRAME_NO_DATA frames */ + short interval_SID; /* CNG and DTX - interval of SID update, default 8 */ + short old_enr_index; /* CNG and DTX - index of last encoded CNG energy */ + float Enew; /* CNG and DTX - CNG target residual energy */ + short VarDTX_cnt_voiced; /* CNG and DTX - counter for variable DTX activation (speech) */ + float lt_ener_voiced; /* CNG and DTX - long-term energy of signal (measured on voiced parts) */ + short VarDTX_cnt_noise; /* CNG and DTX - counter for variable DTX activation (noise) */ + float lt_ener_noise; /* CNG and DTX - long-term energy of background noise */ + float lt_ener_last_SID; /* CNG and DTX - long-term energy of last SID frame */ + short cng_hist_size; /* CNG and DTX - size of CNG history buffer for averaging, <0,DTX_HIST_SIZE> */ + short cng_hist_ptr; /* CNG and DTX - pointer for averaging buffers */ + float cng_lsp_hist[DTX_HIST_SIZE*M]; /* CNG and DTX - old LSP buffer for averaging */ + float cng_ener_hist[DTX_HIST_SIZE]; /* CNG and DTX - log energy buffer for averaging */ + short cng_cnt; /* CNG and DTX - counter of CNG frames for averaging */ + short cng_ener_seed; /* CNG and DTX - seed for random generator for variation of excitation energy */ + short cng_ener_seed1; + float frame_ener; + float lp_sp_enr; + short last_allow_cn_step; + short ho_hist_size; /* CNG and DTX - size of DTX hangover history buffer for averaging, <0,HO_HIST_SIZE> */ + short ho_hist_ptr; /* CNG and DTX - pointer for averaging buffers */ + long ho_sid_bw; /* CNG and DTX - SID bandwidth flags */ + float ho_lsp_hist[HO_HIST_SIZE*M]; /* CNG and DTX - old LSP buffer for averaging */ + float ho_ener_hist[HO_HIST_SIZE]; /* CNG and DTX - energy buffer for averaging */ + float ho_env_hist[HO_HIST_SIZE*NUM_ENV_CNG]; + short act_cnt; /* CNG and DTX - counter of active frames */ + short ho_circ_size; /* CNG and DTX - size of DTX hangover history buffer for averaging, <0,HO_HIST_SIZE> */ + short ho_circ_ptr; /* CNG and DTX - pointer for averaging buffers */ + float ho_lsp_circ[HO_HIST_SIZE*M]; /* CNG and DTX - old LSP buffer for averaging */ + float ho_ener_circ[HO_HIST_SIZE]; /* CNG and DTX - energy buffer for averaging */ + float ho_env_circ[HO_HIST_SIZE*NUM_ENV_CNG]; + short burst_ho_cnt; /* CNG and DTX - counter of hangover frames at end of active burst */ + short cng_buf_cnt; /* CNG and DTX - Counter of buffered CNG parameters */ + float cng_exc2_buf[HO_HIST_SIZE*L_FFT]; /* CNG and DTX - exc2 buffer for storing */ + long cng_brate_buf[HO_HIST_SIZE]; /* CNG and DTX - buffer for storing last_active_brate */ + + short CNG_mode; /* CNG and DTX - mode for DTX configuration */ + long last_active_brate; /* CNG and DTX - last active frame bitrate used for CNG_mode control */ + short ho_16k_lsp[HO_HIST_SIZE]; /* CNG and DTX - 16k LSPs flags */ + short last_CNG_L_frame; /* CNG and DTX - last CNG frame length */ + short act_cnt2; /* CNG and DTX - counter of active frames for CNG_mode switching */ + float ho_lsp_circ2[HO_HIST_SIZE*M]; /* CNG and DTX - second buffer of LSPs */ + short num_ho; /* CNG and DTX - number of selected hangover frames */ + short hangover_terminate_flag; /* CNG and DTX - flag indicating whether to early terminate DTX hangover */ + float old_env[NUM_ENV_CNG]; + float lp_env[NUM_ENV_CNG]; + float cng_res_env[NUM_ENV_CNG*HO_HIST_SIZE]; + float exc_mem[24]; + float exc_mem1[30]; + float exc_mem2[30]; + + float dispMem[8]; /* Noise enhancer - phase dispersion algorithm memory */ + + short uv_count; /* Stationary noise UV modification - unvoiced counter */ + short act_count; /* Stationary noise UV modification - activation counter */ + float ge_sm; /* Stationary noise UV modification - smoothed excitation gain */ + float lspold_s[M]; /* Stationary noise UV modification - old LSP vector */ + short noimix_seed; /* Stationary noise UV modification - mixture seed */ + float min_alpha; /* Stationary noise UV modification - minimum alpha */ + float exc_pe; /* Stationary noise UV modification - memory of the preemphasis filter */ + + short last_L_frame; /* ACELP@16kHz - last L_frame value */ + float mem_decim16k[2*L_FILT_MAX]; /* ACELP@16kHz - decimation filter memory @16kHz */ + float mem_preemph16k; /* ACELP@16kHz - preemphasis filter memory @16kHz */ + float old_inp_16k[L_INP_MEM]; /* ACELP@16kHz - memory of input signal @16 kHz */ + float mem_deemp_preQ; /* ACELP@16kHz - prequantizer deemhasis memory */ + float mem_preemp_preQ; /* ACELP@16kHz - prequantizer preemhasis memory */ + short last_nq_preQ; /* ACELP@16kHz - AVQ subquantizer number of the last sub-band of the last subframe */ + short use_acelp_preq; /* ACELP@16kHz - flag of prequantizer usage */ + + short bpf_off; /* Bass post-filter - do not use BPF when this flag is set to 1 */ + float old_pitch_buf[2*NB_SUBFR16k]; /* Bass post-filter - buffer of old subframe pitch values */ + float pst_mem_deemp_err; /* Bass post-filter - filter memory of noise LP filter */ + float pst_lp_ener; /* Bass post-filter - long-term energy */ + float lps; + float lpm; + + /* stable short pitch detection */ + float voicing0_sm; + float voicing_sm; + float LF_EnergyRatio_sm; + short predecision_flag; + float diff_sm; + float energy_sm; + + + /*----------------------------------------------------------------------------------* + * HF WB BWE for AMR-WB IO mode at 23.85 kbps + *----------------------------------------------------------------------------------*/ + + float gain_alpha; + float mem_hf2_enc[L_FIR-1]; + float mem_hp400_enc[4]; + float mem_hf_enc[L_FIR-1]; + float mem_syn_hf_enc[M]; + short seed2_enc; + + /*----------------------------------------------------------------------------------* + * CLDFB analysis + *----------------------------------------------------------------------------------*/ + + HANDLE_CLDFB_FILTER_BANK cldfbAnaEnc; /* main analysis filter bank handle */ + HANDLE_CLDFB_FILTER_BANK cldfbSynTd; + + + /*----------------------------------------------------------------------------------* + * FD CNG handle + *----------------------------------------------------------------------------------*/ + + HANDLE_FD_CNG_ENC hFdCngEnc; + short fd_cng_reset_flag; + float last_totalNoise; + float totalNoise_increase_hist[TOTALNOISE_HIST_SIZE]; + short totalNoise_increase_len; + + /*----------------------------------------------------------------------------------* + * SC-VBR parameters + *----------------------------------------------------------------------------------*/ + + float vadsnr; + float vadnoise; + + /* NELP variables */ + float shape1_filt_mem[20]; + float shape2_filt_mem[20]; + float shape3_filt_mem[20]; + float txlpf1_filt1_mem[20]; + float txlpf1_filt2_mem[20]; + float txhpf1_filt1_mem[20]; + float txhpf1_filt2_mem[20]; + float bp1_filt_mem_wb[8]; + float nelp_lp_fit_mem[NELP_LP_ORDER*2]; + float bp1_filt_mem_nb[14]; + short nelp_enc_seed; + float nelp_gain_mem; + short last_nelp_mode; + short nelp_mode; + + /* PPP variables */ + short pppcountE; + short bump_up; + short last_ppp_mode; + short last_last_ppp_mode; + short ppp_mode; + float prev_ppp_gain_pit; + float prev_tilt_code; + + /* voiced encoder variables */ + int firstTime_voicedenc; + + /* DTFS variables */ + float dtfs_enc_a[MAXLAG_WI]; + float dtfs_enc_b[MAXLAG_WI]; + int dtfs_enc_lag; + int dtfs_enc_nH; + int dtfs_enc_nH_4kHz; + float dtfs_enc_upper_cut_off_freq_of_interest; + float dtfs_enc_upper_cut_off_freq; + + float prev_cw_en; + float ph_offset_E; + float lastLgainE; /* Previous gain value for the low band */ + float lastHgainE; /* Previous gain value for the high band */ + float lasterbE[NUM_ERB_WB]; /* Previous Amplitude spectrum (ERB) */ + + short mode_QQF; + short rate_control; + float SNR_THLD; + short Q_to_F; + short pattern_m; + short patterncount; + short Last_Resort; + short numactive; /* keep the count of the frames inside current 600 frame block */ + float sum_of_rates; /* sum of the rates of past 600 active frames */ + float global_avr_rate; /* global rate up to current time. recorded a (rate in kbps) * 6000 */ + int global_frame_cnt; /* 600 active frame block count. Used to update the global rate */ + short set_ppp_generic; + short avoid_HQ_VBR_NB; + + /*----------------------------------------------------------------------------------* + * HQ core parameters + *----------------------------------------------------------------------------------*/ + + float input_buff[L_FRAME48k+L_FRAME48k+NS2SA(48000, DELAY_FIR_RESAMPL_NS)]; + float * input; + float * old_input_signal; + + float old_hpfilt_in; + float old_hpfilt_out; + float EnergyLT; + float Energy_Old; + short TransientHangOver; + float old_out[L_FRAME32k]; /* buffer for OLA; at the encoder, the maximum length is L_FRAME32k (corresponds to maximum internal L_frame length) */ + short last_core; + short hq_generic_speech_class; + short mode_count; /* HQ_HARMONIC mode count */ + short mode_count1; /* HQ_NORMAL mode count */ + short Nb_ACELP_frames; + short prev_Npeaks; /* number of peaks in previous frame */ + short prev_peaks[HVQ_MAX_PEAKS]; /* indices of the peaks in previous frame */ + short hvq_hangover; + short prev_hqswb_clas; + short prev_SWB_peak_pos[SPT_SHORTEN_SBNUM]; + + /* speech/music classification */ + short last_vad_spa; + short lt_old_mode[3]; + float lt_voicing; + float lt_corr; + float lt_tonality; + short lt_corr_pitch[3]; + short lt_hangover; + float lowrate_pitchGain; + + short prev_frm_index[NB_SWB_SUBBANDS_HAR_SEARCH_SB]; + short prev_frm_hfe2; + short prev_stab_hfe2; + float prev_ni_ratio; + float prev_En_sb[NB_SWB_SUBBANDS]; + short last_bitalloc_max_band[2]; + float last_ni_gain[BANDS_MAX]; + float last_env[BANDS_MAX]; + short last_max_pos_pulse; + + /* PVQ range coder state */ + unsigned int rc_low; + unsigned int rc_range; + short rc_cache; + short rc_carry; + short rc_carry_count; + short rc_num_bits; + short rc_tot_bits; + short rc_offset; + /*----------------------------------------------------------------------------------* + * TBE parameters + *----------------------------------------------------------------------------------*/ + + float old_speech_shb[L_LOOK_16k + L_SUBFR16k]; /* Buffer memories */ + float old_speech_wb[(L_LOOK_12k8 + L_SUBFR) * 5/16]; /* Buffer memories */ + float old_input_fhb[NS2SA(48000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS) - L_FRAME48k/2]; + float prev_lsp_shb[LPC_SHB_ORDER]; + float state_ana_filt_shb[ 2 * ALLPASSSECTIONS_STEEP + 1 ]; /* states for the analysis filters */ + float cldfbHBLT; + /* states for the filters used in generating SHB excitation from WB excitation*/ + float mem_csfilt[2]; + + /* states for the filters used in generating SHB signal from SHB excitation*/ + float state_syn_shbexc[L_SHB_LAHEAD]; + float state_lpc_syn[LPC_SHB_ORDER]; + float old_bwe_exc[PIT16k_MAX * 2]; /* old excitation */ + short bwe_seed[2]; + float bwe_non_lin_prev_scale; + float old_bwe_exc_extended[NL_BUFF_OFFSET]; + float syn_overlap[L_SHB_LAHEAD]; /* overlap buffer used to Adjust SHB Frame Gain*/ + float decim_state1[(2*ALLPASSSECTIONS_STEEP+1)]; + float decim_state2[(2*ALLPASSSECTIONS_STEEP+1)]; + float mem_genSHBexc_filt_down_wb2[(2*ALLPASSSECTIONS_STEEP+1)]; + float mem_genSHBexc_filt_down_wb3[(2*ALLPASSSECTIONS_STEEP+1)]; + float mem_genSHBexc_filt_down_shb[(2*ALLPASSSECTIONS_STEEP+1)]; + + float elliptic_bpf_2_48k_mem[4][4]; + float prev_fb_energy; + float prev_gainFr_SHB; + float lsp_shb_slow_interpl[LPC_SHB_ORDER]; + float lsp_shb_fast_interpl[LPC_SHB_ORDER]; + float shb_inv_filt_mem[LPC_SHB_ORDER]; + float lsp_shb_spacing[3]; + float prev_swb_GainShape; + short prev_frGainAtten; + + short spectral_tilt_reset; + short consec_inactive; + float ra_deltasum; + short trigger_SID; + float running_avg; + float snr_sum_vad; + + float prev_wb_GainShape; + float swb_lsp_prev_interp[LPC_SHB_ORDER]; + float fb_state_lpc_syn[LPC_SHB_ORDER]; + float fb_tbe_demph; + float tilt_mem; + + + short prev_coder_type; + float prev_lsf_diff[LPC_SHB_ORDER-2]; + float prev_tilt_para; + float cur_sub_Aq[M+1]; + + /* quantized data */ + short lsf_idx[NUM_Q_LSF]; + short m_idx; + short grid_idx; + short idxSubGains; + short idxFrameGain; + short idx_shb_fr_gain; + short idx_res_gs[NB_SUBFR16k]; + short idx_mixFac; + + short lsf_WB; + short gFrame_WB; + + short idxGain; + float dec_2_over_3_mem[12]; + float dec_2_over_3_mem_lp[6]; + + + /*----------------------------------------------------------------------------------* + * SWB BWE parameters + *----------------------------------------------------------------------------------*/ + + float new_input_hp[NS2SA(16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS)]; + float old_input[NS2SA(48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS)]; + float old_input_wb[NS2SA(16000, DELAY_FD_BWE_ENC_NS)]; + float old_input_lp[NS2SA(16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_NS)]; + float old_syn_12k8_16k[NS2SA(16000, DELAY_FD_BWE_ENC_NS)]; + float old_fdbwe_speech[L_FRAME48k]; + float mem_deemph_old_syn; + short prev_mode; + float old_wtda_swb[L_FRAME48k]; + short prev_L_swb_norm1; + float prev_global_gain; + short modeCount; + float EnergyLF; + float tbe_demph; + float tbe_premph; + float mem_stp_swb[LPC_SHB_ORDER]; + float *ptr_mem_stp_swb; + float gain_prec_swb; + float mem_zero_swb[LPC_SHB_ORDER]; + + /*----------------------------------------------------------------------------------* + * WB, SWB and FB bandwidth detector + *----------------------------------------------------------------------------------*/ + + float lt_mean_NB; + float lt_mean_WB; + float lt_mean_SWB; + short count_WB; + short count_SWB; + short count_FB; + + /*----------------------------------------------------------------------------------* + * SWB DTX/CNG parameters + *----------------------------------------------------------------------------------*/ + + short last_vad; + float last_wb_cng_ener; + float last_shb_cng_ener; + float mov_wb_cng_ener; + float mov_shb_cng_ener; + short shb_cng_ini_cnt; + short last_SID_bwidth; + short shb_NO_DATA_cnt; + + /*----------------------------------------------------------------------------------* + * Channel-aware mode + *----------------------------------------------------------------------------------*/ + + short rf_mode; /* flag to signal the RF mode */ + short rf_mode_last; + short last_rf_mode_cng; + short Opt_RF_ON; + short rf_frame_type; + + short rf_target_bits_write; + short rf_fec_offset; + short rf_targetbits_buff[MAX_RF_FEC_OFFSET]; + int rf_indx_frametype[MAX_RF_FEC_OFFSET]; + + float rf_mem_w0; + float rf_clip_var[6]; + float rf_tilt_code; + float rf_mem_syn2[M]; + float rf_dispMem[8]; + float rf_gc_threshold; + + short rf_target_bits; + float rf_tilt_buf[NB_SUBFR16k]; + + short rf_indx_lsf[MAX_RF_FEC_OFFSET][3]; + int rf_indx_pitch[MAX_RF_FEC_OFFSET][NB_SUBFR16k]; + int rf_indx_fcb[MAX_RF_FEC_OFFSET][NB_SUBFR16k]; + int rf_indx_gain[MAX_RF_FEC_OFFSET][NB_SUBFR16k]; + int rf_indx_EsPred[MAX_RF_FEC_OFFSET]; + int rf_indx_ltfMode[MAX_RF_FEC_OFFSET][NB_SUBFR16k]; + + short rf_indx_nelp_fid[MAX_RF_FEC_OFFSET]; + short rf_indx_nelp_iG1[MAX_RF_FEC_OFFSET]; + short rf_indx_nelp_iG2[MAX_RF_FEC_OFFSET][2]; + + short rf_indx_tbeGainFr[MAX_RF_FEC_OFFSET]; + + int rf_tcxltp_pitch_int_past; + int rf_last_tns_active; + int rf_second_last_tns_active; + int rf_second_last_core; + short rf_clas[MAX_RF_FEC_OFFSET]; + int rf_gain_tcx[MAX_RF_FEC_OFFSET]; + int rf_tcxltp_param[MAX_RF_FEC_OFFSET]; + + short rf_fec_indicator; + short RF_bwe_gainFr_ind; + + /*----------------------------------------------------------------------------------* + * Local synthesis parameters + *----------------------------------------------------------------------------------*/ + + + /*----------------------------------------------------------------------------------* + * + * Mode2 + * + *----------------------------------------------------------------------------------*/ + + int frame_size_index; /*0-FRAME_SIZE_NB-1: index determining the frame size*/ + int bits_frame_nominal; /*avg bits per frame on active frame*/ + int bits_frame; /*bits per frame overall */ + int bits_frame_core; /*bits per frame for the core*/ + int narrowBand; + + /*ACELP config*/ + ACELP_config acelp_cfg; /*configuration set for each frame*/ + + ACELP_config acelp_cfg_rf; /* configuration for RF frame */ + + /*TCX config*/ + TCX_config tcx_cfg; + int L_frameTCX; + + /* cod_main.c */ + float mem_preemph_enc; /* speech preemph filter memory (at encoder-sampling-rate) */ + + /* Signal Buffers and Pointers at encoder-sampling-rate */ + float *speech_enc; + float *speech_enc_pe; + float *new_speech_enc; + float *new_speech_enc_pe; + float buf_speech_enc[L_PAST_MAX_32k+L_FRAME32k+L_NEXT_MAX_32k]; + float buf_speech_enc_pe[L_PAST_MAX_32k+L_FRAME32k+L_NEXT_MAX_32k]; + float *wspeech_enc; + float buf_wspeech_enc[L_FRAME16k+L_SUBFR+L_FRAME16k+L_NEXT_MAX_16k]; + float *synth; + float buf_synth[OLD_SYNTH_SIZE_ENC+L_FRAME32k]; /*can be reduced to PIT_MAX_MAX+L_FRAME_MAX if no rate switching*/ + float *speech_TCX; + float *new_speech_TCX; + + /* Core Signal Analysis Outputs */ + float *spectrum[2]; /* MDCT output for a short block */ + float spectrum_long[N_MAX]; /* MDCT output for a long block. Points to spectrum */ + float noiseTiltFactor; /* compensation for LPC tilt in noise filling */ + int noiseLevelMemory; /* counter of consecutive low TCX noise levels */ + STnsData tnsData[2]; + int fUseTns[2]; + + int enableTcxLpc; /* global toggle for the TCX LPC quantizer */ + int envWeighted; /* are is{p,f}_old_q[] weighted or not? */ + + int acelpEnabled; /* Flag indicating if ACELP can be used */ + int tcx10Enabled; /* Flag indicating if TCX 10 can be used */ + int tcx20Enabled; /* Flag indicating if TCX 20 can be used */ + + short tcxMode; /* Chosen TCX mode for this frame */ + + float mem_wsp_enc; /* wsp vector memory */ + + int nb_bits_header_ace; /* number of bits for the header */ + int nb_bits_header_tcx; /* number of bits for the header */ + + /* 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*/ + short restrictedMode; + + + + + /* Framing */ + int nb_subfr; + + float preemph_fac; /*Preemphasis factor*/ + float gamma; + + TransientDetection transientDetection; + int transient_info[3]; + + int acelpFramesCount; + float prevTempFlatness; + + float prevEnergyHF; + float currEnergyHF; + float currEnergyLookAhead; + + int lpcQuantization; + + int encoderLookahead_enc; + int encoderPastSamples_enc; + int encoderLookahead_FB; + + /* pitch_ol for adaptive lag window */ + int old_pitch_la; /* past open loop pitch lag from look-ahead */ + float old_voicing_la; /* past open loop pitch gain from look-ahead */ + + + int tcxonly; + + short flag_noisy_speech_snr; /* encoder detector for noisy speech */ + short Pos_relE_cnt; /* Number of frames between relE */ + + int fscale; + int sr_core; + int acelp_autocorr; /* Optimize acelp in 0 covariance or 1 correlation domain */ + + int pit_min; + int pit_fr1; + int pit_fr1b; + int pit_fr2; + int pit_max; + int pit_res_max; + + /* for FAC */ + int L_frame_past; + + int memQuantZeros[L_FRAME_PLUS]; /* Quantization deadzone flags */ + + /*Adaptive BPF*/ + int bpf_gain_param; + float mem_bpf[2*L_FILT16k]; + float mem_error_bpf[2*L_FILT16k]; + + /* TCX-LTP */ + int tcxltp; + int tcxltp_pitch_int; + int tcxltp_pitch_fr; + float tcxltp_gain; + int tcxltp_pitch_int_past; + int tcxltp_pitch_fr_past; + float tcxltp_gain_past; + float tcxltp_norm_corr_past; + float buf_speech_ltp[L_PAST_MAX_32k+L_FRAME32k+L_NEXT_MAX_32k]; + float *speech_ltp; + float *new_speech_ltp; + short tcxltp_filt_idx; + int tcxltp_bits; + int tcxltp_param[LTPSIZE]; + + float measuredBwRatio; /* measured bw; used for TCX noise-filling */ + int nmStartLine; /* Starting line for the noise measurement */ + + short glr; + short glr_idx[2]; + float mean_gc[2]; + float prev_lsf4_mean; + short glr_reset; + int last_sr_core; + float last_stab_fac; + + /*for rate switching*/ + short rate_switching_reset; /*Rate switching flag requiring a reset of memories at least partially */ + short rate_switching_reset_16kHz; + + short enablePlcWaveadjust; + short Tonal_SideInfo; + + short seed_acelp; + + short tcx_lpc_shaped_ari; + + PLC_ENC_EVS plcExt; + T_CldfbVadState vad_st; + + IGF_ENC_INSTANCE hIGFEnc; + short igf; + + short tec_tfa; + TEMPORAL_ENVELOPE_CODING_ENCODER tecEnc; + short tec_flag; + short tfa_flag; + float tfa_enr[N_TEC_TFA_SUBFR]; + + short vbr_generic_ho; + short last_7k2_coder_type; + + short sharpFlag; + + + short Local_VAD; + +} Encoder_State; + + +/*---------------------------------------------------------------* + * Encoder Static RAM * + *---------------------------------------------------------------*/ + +typedef struct GainItemStr +{ + float nmrValue; + short gainIndex; +} GainItem; + +/* Structure for storing correlations between ACELP codebook components and target */ +typedef struct +{ + float xx; /* energy of target x */ + float y1y1; /* energy of adaptive cbk contribution y1 */ + float y2y2; /* energy of fixed cbk contribution y2 */ + float xy1; /* correlation of x and y1 */ + float xy2; /* correlation of x and y2 */ + float y1y2; /* correlation of y1 and y2 */ +} ACELP_CbkCorr; + +struct PLC_ENC_EVS; +typedef struct PLC_ENC_EVS * HANDLE_PLC_ENC_EVS; + + +#endif diff --git a/lib_enc/stat_noise_uv_enc.c b/lib_enc/stat_noise_uv_enc.c new file mode 100644 index 000000000..6e4f8cb9b --- /dev/null +++ b/lib_enc/stat_noise_uv_enc.c @@ -0,0 +1,72 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "prot.h" +#include "rom_com.h" + +/*-----------------------------------------------------------------* + * stat_noise_uv_enc() + * + * Modifies excitation signal when the noise is stationary + *-----------------------------------------------------------------*/ + +void stat_noise_uv_enc( + Encoder_State *st, /* i/o: state structure */ + const short coder_type, /* i : coding type */ + const float *epsP, /* i : LP prediction errors */ + float *isp_new, /* i : immittance spectral pairs at 4th sfr */ + float *isp_mid, /* i : immittance spectral pairs at 2nd sfr */ + float *Aq, /* i : A(z) quantized for the 4 subframes */ + float *exc2 /* i/o: excitation buffer */ +) +{ + short noisiness = 0; + + /*-----------------------------------------------------------------* + * Calculate and write the noisiness parameter + *-----------------------------------------------------------------*/ + + if ( coder_type == UNVOICED || ( coder_type == INACTIVE && st->core_brate <= ACELP_9k60 ) ) + { + if ( st->bwidth != NB ) + { + /* WB case */ + noisiness = (short)(((epsP[2] / epsP[16]) - 1) * 2.0f * 32); + } + else if ( coder_type == INACTIVE && st->bwidth == NB ) + { + /* NB GSC case */ + noisiness = (short)(((epsP[2] / epsP[16]) - 1) * 0.25f * 32); + } + else + { + /* NB case */ + noisiness = (short)(((epsP[2] / epsP[16]) - 1) * 0.5f * 32); + } + + if( noisiness < 0 ) + { + noisiness = 0; + } + + if( noisiness > 31 ) + { + noisiness = 31; + } + + push_indice( st, IND_NOISINESS, noisiness, 5 ); + } + + /*-----------------------------------------------------------------* + * Modify the stationary noise excitation signal + *-----------------------------------------------------------------*/ + + stat_noise_uv_mod( coder_type, noisiness, st->lsp_old, isp_new, isp_mid, Aq, exc2, 0, &st->ge_sm, + &st->uv_count, &st->act_count, st->lspold_s, &st->noimix_seed, &st->min_alpha, &st->exc_pe, + st->core_brate, st->bwidth ); + + return; +} diff --git a/lib_enc/subband_fft.c b/lib_enc/subband_fft.c new file mode 100644 index 000000000..96859a9c5 --- /dev/null +++ b/lib_enc/subband_fft.c @@ -0,0 +1,183 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "prot.h" +#include "rom_enc.h" + + + + +/*-------------------------------------------------------------------* + * fft16() + * + * + *-------------------------------------------------------------------*/ + +static void fft16(float *r_samp, float *i_samp) +{ + int i,j,N,Nv2,nm1,k; + float tmpr[16],tmpi[16]; + float r1,s1,r2,s2; + + + for (i = 0; i < 16; i++) + { + tmpr[i] = r_samp[i]*M_inr[i] - i_samp[i]*M_ini[i]; + tmpi[i] = r_samp[i]*M_ini[i] + i_samp[i]*M_inr[i]; + } + + for (i = 0; i < 8; i++) + { + s1 = tmpr[i] - tmpr[8+i]; + r1 = tmpi[i] - tmpi[8+i]; + + tmpr[i] = tmpr[i] + tmpr[8+i]; + tmpi[i] = tmpi[i] + tmpi[8+i]; + + tmpr[i+8] = s1*M_r[i] - r1*M_i[i]; + tmpi[i+8] = s1*M_i[i] + r1*M_r[i]; + } + + for (i = 0; i < 4; i++) + { + s1 = tmpr[i] - tmpr[4+i]; + r1 = tmpi[i] - tmpi[4+i]; + + tmpr[i] = tmpr[i] + tmpr[4+i]; + tmpi[i] = tmpi[i] + tmpi[4+i]; + + tmpr[i+4] = s1*M_r[2*i] - r1*M_i[2*i]; + tmpi[i+4] = s1*M_i[2*i] + r1*M_r[2*i]; + + } + for (i = 0; i < 4; i++) + { + s1 = tmpr[i+8] - tmpr[12+i]; + r1 = tmpi[i+8] - tmpi[12+i]; + + tmpr[i+8] = tmpr[i+8] + tmpr[12+i]; + tmpi[i+8] = tmpi[i+8] + tmpi[12+i]; + + tmpr[i+12] = s1*M_r[2*i] - r1*M_i[2*i]; + tmpi[i+12] = s1*M_i[2*i] + r1*M_r[2*i]; + + } + + + for (i = 0; i< 16; i=i+4) + { + s1 = tmpr[i] - tmpr[2+i]; + r1 = tmpi[i] - tmpi[2+i]; + s2 = tmpr[i+1] - tmpr[3+i]; + r2 = tmpi[i+1] - tmpi[3+i]; + + tmpr[i] = tmpr[i] + tmpr[2+i]; + tmpi[i] = tmpi[i] + tmpi[2+i]; + tmpr[i+1] = tmpr[i+1] + tmpr[3+i]; + tmpi[i+1] = tmpi[i+1] + tmpi[3+i]; + + tmpr[i+2] = s1*M_r[0] - r1*M_i[0]; + tmpi[i+2] = s1*M_i[0] + r1*M_r[0]; + tmpr[i+3] = s2*M_r[4] - r2*M_i[4]; + tmpi[i+3] = s2*M_i[4] + r2*M_r[4]; + } + + for (i = 0; i < 16; i= i+2) + { + s1 = tmpr[i] - tmpr[1+i]; + r1 = tmpi[i] - tmpi[1+i]; + + tmpr[i] = tmpr[i] + tmpr[1+i]; + tmpi[i] = tmpi[i] + tmpi[1+i]; + + tmpr[i+1] = s1*M_r[0] - r1*M_i[0]; + tmpi[i+1] = s1*M_i[0] + r1*M_r[0]; + } + + + N = 16; + Nv2=N>>1; + nm1=N-1; + j=0; + for(i=0; i>=1; + } + j+=k; + } + + r_samp[15] = tmpr[15]*M_Wr[15] - tmpi[15]*M_Wi[15]; + i_samp[15] = tmpr[15]*M_Wi[15] + tmpi[15]*M_Wr[15]; + + return; +} + +/*-------------------------------------------------------------------* + * subband_FFT() + * + * + *-------------------------------------------------------------------*/ + +void subband_FFT( + float Sr[16][60], /*(i) real part of the cldfb*/ + float Si[16][60], /*(i) imag part of the cldfb*/ + float *spec_amp /*(o) spectral amplitude*/ +) +{ + int i,j; + float tmpr[16],tmpi[16]; + float ptmp[16],tmp1; + for(i=0; i<10; i++) + { + for(j=0; j<16; j++) + { + tmpr[j] = Sr[j][i]; + tmpi[j] = Si[j][i]; + } + + fft16(tmpr,tmpi); + + for(j=0; j<16; j++) + { + ptmp[j] = tmpr[j]*tmpr[j] + tmpi[j]*tmpi[j]; + } + if(i%2==0) + { + for(j=0; j<8; j++) + { + tmp1 = ptmp[j] + ptmp[15-j] ; + spec_amp[i*8+j] = (float)sqrt(tmp1); + } + } + else + { + for(j=0; j<8; j++) + { + tmp1 = ptmp[j] + ptmp[15-j] ; + spec_amp[i*8+7-j] =(float)sqrt(tmp1); + } + } + } + + return; +} diff --git a/lib_enc/swb_bwe_enc.c b/lib_enc/swb_bwe_enc.c new file mode 100644 index 000000000..19b55aecd --- /dev/null +++ b/lib_enc/swb_bwe_enc.c @@ -0,0 +1,1728 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include "rom_enc.h" +#include "basop_util.h" +#include "basop_proto_func.h" + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ +static short SWB_BWE_encoding( Encoder_State *st, const float *insig, const float *insig_lp, const float *insig_hp, const float *synth, + const float *yos, float *SWB_fenv, const float tilt_nb, const short st_offset, const short coder_type ); +static void MSVQ_Interpol_Tran( float *SWB_env_energy, short *indice ); +static void calculate_tonality( const float *org, const float *gen, float *SFM_org, float *SFM_gen, const short length ); +static short WB_BWE_encoding( const short coder_type, const float *yos, float *WB_fenv, Encoder_State *st ); +static void energy_control( Encoder_State *st, const short core, const short mode, const short coder_type, const float *org, const short offset, float *energy_factor ); +static short decision_hq_generic_class (const float *coefs, const short hq_generic_offset ); + +/*-------------------------------------------------------------------* + * wb_bwe_enc() + * + * WB BWE encoder + *-------------------------------------------------------------------*/ + +void wb_bwe_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const float *new_wb_speech, /* i : original input signal at 16kHz */ + short coder_type /* i : coding type */ +) +{ + float old_input[NS2SA(16000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS) + L_FRAME16k]; + float *new_input; /* pointer to original input signal */ + float yorig[L_FRAME16k]; /* MDCT spectrum of weighted original */ + short mode = 0; + float wtda_old_input[2*L_FRAME16k]; + float WB_fenv[SWB_FENV]; + short Sample_Delay_WB_BWE; + + if( st->total_brate == ACELP_13k20 ) + { + /*---------------------------------------------------------------------* + * Delay the original input signal to be synchronized with ACELP core synthesis + *---------------------------------------------------------------------*/ + + set_f( old_input, 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 = old_input + Sample_Delay_WB_BWE; + mvr2r( st->old_input_wb, old_input, Sample_Delay_WB_BWE ); + mvr2r( new_wb_speech, new_input, L_FRAME16k ); + mvr2r( old_input + L_FRAME16k, st->old_input_wb, Sample_Delay_WB_BWE ); + + /*---------------------------------------------------------------------* + * WB BWE encoding + *---------------------------------------------------------------------*/ + + /* MDCT of the original signal */ + wtda( old_input, wtda_old_input, st->old_wtda_swb, ALDO_WINDOW, ALDO_WINDOW, L_FRAME16k ); + + direct_transform( wtda_old_input, yorig, 0, L_FRAME16k ); + + mode = WB_BWE_encoding( coder_type, yorig, WB_fenv, st ); + + push_indice( st, IND_WB_CLASS, mode - 2, 1 ); + } + + + st->prev_mode = mode; + + return; +} + +/*-------------------------------------------------------------------* + * get_normalize_spec() + * + *-------------------------------------------------------------------*/ + +static void get_normalize_spec( + const short core, /* i : core selected */ + const short extl, /* i : extension layer selected */ + const short mode, /* i : SHB BWE class */ + const short core_type, /* i : coding type */ + const float *org, /* i : input spectrum */ + float *SWB_signal, /* o : output spectrum */ + short *prev_L_swb_norm, /* i : previous norm. len */ + const short offset /* i : frequency offset */ +) +{ + short n_freq, L_swb_norm; + float envelope[L_FRAME32k]; + short frq_end; + + set_f( SWB_signal, 0, HQ_GENERIC_HIGH0+offset ); + calc_normal_length(core, org, mode, extl, &L_swb_norm, prev_L_swb_norm); + if( extl == SWB_BWE || extl == FB_BWE ) + { + if( mode == HARMONIC ) + { + mvr2r( org, &SWB_signal[240+offset], 240 ); + mvr2r( &org[128], &SWB_signal[480+offset], 80 ); + } + else + { + mvr2r( &org[112], &SWB_signal[240+offset], 128 ); + mvr2r( &org[112], &SWB_signal[368+offset], 128 ); + mvr2r( &org[176], &SWB_signal[496+offset], 64 ); + } + frq_end = 560+offset; + } + else if (extl == WB_BWE) + { + if( core_type == 0 ) + { + mvr2r(&org[160], &SWB_signal[240], 80); + } + else + { + mvr2r(&org[80], &SWB_signal[240], 80); + } + frq_end = L_FRAME16k; + } + else + { + mvr2r( org+HQ_GENERIC_OFFSET, SWB_signal+HQ_GENERIC_HIGH0+offset, HQ_GENERIC_LEN0 ); + mvr2r( org+HQ_GENERIC_OFFSET, SWB_signal+HQ_GENERIC_HIGH1+offset, HQ_GENERIC_LEN0 ); + if ( offset == HQ_GENERIC_FOFFSET_24K4 ) + { + mvr2r( org+HQ_GENERIC_LOW0, SWB_signal+HQ_GENERIC_HIGH2+offset, HQ_GENERIC_END_FREQ-HQ_GENERIC_HIGH2 ); + } + frq_end = L_FRAME32k; + } + + /* calculate envelope */ + calc_norm_envelop( SWB_signal, envelope, L_swb_norm, frq_end - offset, offset ); + + /* Normalize with envelope */ + for( n_freq = swb_bwe_subband[0]+offset; n_freqextl == SWB_BWE || st->extl == FB_BWE ) + { + input_hi = &fSpectrum[256]; + numsharp = NUM_SHARP; + if ( ( st->last_extl == SWB_BWE && st->extl == SWB_BWE ) || ( st->last_extl == FB_BWE && st->extl == FB_BWE ) ) + { + gain_tmp = fGain / (st->prev_global_gain + EPSILON); + if (st->prev_mode == TRANSIENT) + { + numharmonic = numharmonic * 2; + } + else if (st->prev_mode == NORMAL || st->prev_mode == NOISE) + { + numharmonic = 3 * numharmonic / 2; + } + } + else + { + gain_tmp = 1; + if (st->prev_mode == HARMONIC) + { + numharmonic = numharmonic / 2; + sharplimit = sharplimit / 2; + } + else + { + numharmonic = numharmonic * 2; + sharplimit = sharplimit * 2; + } + } + } + else if (st->extl == WB_BWE) + { + input_hi = &fSpectrum[224]; + numsharp = NUM_SHARP / 3; + if (st->prev_mode == HARMONIC) + { + numharmonic = numharmonic / 4; + } + else + { + numharmonic = numharmonic / 2; + } + if (st->last_extl != WB_BWE) + { + if (st->prev_mode == HARMONIC) + { + sharplimit = sharplimit / 2; + } + else + { + sharplimit = sharplimit * 2; + } + } + } + + meanH = EPSILON; + for(i = 0; i < numsharp; i ++) + { + peak = 0.0f; + mean[i] = 0; + + for(j = 0; j < SHARP_WIDTH; j ++) + { + mag = (float) fabs(*input_hi); + if (mag > peak) + { + peak = mag; + } + mean[i] += mag; + input_hi ++; + } + meanH += mean[i]; + + if(mean[i] != peak) + { + sharp = (float) (peak * (SHARP_WIDTH - 1) / (mean[i] - peak)); + } + else + { + sharp = 0.0f; + } + + if (sharp > 4.5 && peak > 8) + { + k += 1; + } + else if (sharp < 3.0) + { + noise += 1; + } + + if (sharp > sharpPeak) + { + sharpPeak = sharp; + } + } + + if ( st->extl == SWB_BWE || st->extl == FB_BWE ) + { + if(k >= numharmonic && gain_tmp > 0.5f && gain_tmp < 1.8f && sharpPeak > sharplimit) + { + sharpMod = 1; + } + else + { + sharpMod = 0; + } + meanH /= 288; + mean_d = 0.0f; + for(i=0; iextl == WB_BWE) + { + if (k >= numharmonic && sharpPeak > sharplimit) + { + sharpMod = 1; + } + else + { + sharpMod = 0; + } + } + + if (sharpMod && st->modeCount < 12) + { + st->modeCount++; + } + else if (sharpMod == 0 && st->modeCount > 0) + { + st->modeCount--; + } + + if (st->modeCount >= 2) + { + sharpMod = 1; + } + + if (sharpMod) + { + mode = HARMONIC; + } + else if ( st->extl == SWB_BWE || st->extl == FB_BWE ) + { + if (noise > 4 && mean_d < 4.8f*meanH && tilt_nb < 5) + { + mode = NOISE; + } + } + + return mode; +} + +/*-------------------------------------------------------------------* + * WB_BWE_encoding() + * + * WB BWE main encoder + *-------------------------------------------------------------------*/ + +static short WB_BWE_encoding( /* o : classification of wb signal */ + const short coder_type, + const float *yos, /* i : MDCT coefficients of weighted original */ + float *WB_fenv, /* i/o: energy of WB envelope */ + Encoder_State *st /* i/o: Encoder structure */ +) +{ + short mode; + float global_gain; + float energy; + short i, n_coeff, n_band; + short index; + float energy_factor[4]; + + /* Energy for the different bands and global energies */ + global_gain = EPSILON; + + for (i = 0, n_band = 0; i < 2; i++) + { + energy = EPSILON; + for (n_coeff = swb_bwe_subband[n_band]; n_coeff < swb_bwe_subband[n_band+2]; n_coeff++) + { + energy += yos[n_coeff] * yos[n_coeff]; + } + + WB_fenv[i] = energy; + n_band += 2; + global_gain += energy; + } + + mode = FD_BWE_class(yos, global_gain, 0, st); + + energy_control( st, ACELP_CORE, mode, coder_type, yos, 0, energy_factor ); + + for (i = 0; i < 2; i++) + { + WB_fenv[i] = (float)(log10( WB_fenv[i]*energy_factor[i<<1]/40 )*FAC_LOG2); + } + + index = WB_BWE_fenv_q( WB_fenv, F_2_5, 32, 2 ); + + push_indice( st, IND_WB_FENV, index, 5 ); + + + return (mode); + +} + + +/*-------------------------------------------------------------------* + * swb_bwe_enc() + * + * SWB BWE encoder (only for 32kHz signals) + *-------------------------------------------------------------------*/ + +void swb_bwe_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const float *old_input_12k8, /* i : input signal @12.8kHz for SWB BWE */ + const float *old_input_16k, /* i : input signal @16kHz for SWB BWE */ + const float *old_syn_12k8_16k, /* i : ACELP core synthesis at 12.8kHz or 16kHz*/ + const float *new_swb_speech, /* i : original input signal at 32kHz */ + const float *shb_speech, /* i : SHB target signal (6-14kHz) at 16kHz */ + const short coder_type /* i : coding type */ +) +{ + short i, inner_frame, idxGain; + float *new_input; + long inner_Fs; + float old_input[NS2SA(48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS) + L_FRAME48k]; + float old_input_lp[L_FRAME16k], new_input_hp[L_FRAME16k]; + float yorig[L_FRAME48k]; + float wtda_old_input[2*L_FRAME48k]; + float SWB_fenv[SWB_FENV]; + float tilt_nb; + short Sample_Delay_SWB_BWE, Sample_Delay_HP, Sample_Delay_LP; + float ener_low, energy_fbe_fb, fb_ener_adjust, ener_adjust_quan; + + ener_adjust_quan = 0.0f; + idxGain = 0; + + /*---------------------------------------------------------------------* + * Delay the original input signal to be synchronized with ACELP core synthesis + *---------------------------------------------------------------------*/ + + if( st->extl == FB_BWE ) + { + inner_frame = L_FRAME48k; + inner_Fs = 48000; + } + else + { + inner_frame = L_FRAME32k; + inner_Fs = 32000; + } + + set_f( old_input, 0.0f, NS2SA(inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS) + inner_frame ); + + if( st->L_frame == 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); + + mvr2r( st->old_input_lp, old_input_lp, Sample_Delay_LP ); + mvr2r( old_input_12k8 + L_INP_MEM, &old_input_lp[Sample_Delay_LP], L_FRAME-Sample_Delay_LP ); + mvr2r( old_input_12k8 + L_INP_MEM + L_FRAME - Sample_Delay_LP, st->old_input_lp, Sample_Delay_LP ); + } + 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); + + mvr2r( st->old_input_lp, old_input_lp, Sample_Delay_LP ); + mvr2r( old_input_16k + L_INP_MEM, &old_input_lp[Sample_Delay_LP], L_FRAME16k-Sample_Delay_LP ); + mvr2r( old_input_16k + L_INP_MEM + L_FRAME16k - Sample_Delay_LP, st->old_input_lp, Sample_Delay_LP ); + } + + mvr2r( st->new_input_hp, new_input_hp, Sample_Delay_HP ); + mvr2r( shb_speech, new_input_hp + Sample_Delay_HP, L_FRAME16k - Sample_Delay_HP ); + mvr2r( shb_speech + L_FRAME16k - Sample_Delay_HP, st->new_input_hp, Sample_Delay_HP ); + + new_input = old_input + Sample_Delay_SWB_BWE; + mvr2r( st->old_input, old_input, Sample_Delay_SWB_BWE ); + mvr2r( new_swb_speech, new_input, inner_frame ); + mvr2r( old_input + inner_frame, st->old_input, Sample_Delay_SWB_BWE ); + + /*----------------------------------------------------------------------* + * Calculate tilt of the input signal and the ACELP core synthesis + *----------------------------------------------------------------------*/ + + calc_tilt_bwe( old_input_lp, &tilt_nb, L_FRAME ); + + /*---------------------------------------------------------------------* + * SWB BWE encoding + * FB BWE encoding + *---------------------------------------------------------------------*/ + + /* windowing of the original input signal */ + wtda( old_input, wtda_old_input, st->old_wtda_swb, ALDO_WINDOW,ALDO_WINDOW,inner_frame ); + + /* DCT of the original input signal */ + direct_transform( wtda_old_input, yorig, 0, inner_frame ); + + /* FB BWE encoding */ + if ( st->extl == FB_BWE ) + { + energy_fbe_fb = sum2_f( yorig + FB_BAND_BEGIN, FB_BAND_WIDTH ) + EPSILON; + ener_low = EPSILON; + for( i=FB_BAND_BEGIN - FB_BAND_WIDTH; iL_frame == L_FRAME16k) + { + SWB_BWE_encoding( st, old_input, old_input_lp, new_input_hp, old_syn_12k8_16k, yorig, SWB_fenv, tilt_nb, 80, coder_type ); + } + else + { + SWB_BWE_encoding( st, old_input, old_input_lp, new_input_hp, old_syn_12k8_16k, yorig, SWB_fenv, tilt_nb, 6, coder_type ); + } + + /* write FB BWE frame gain to the bitstream */ + if( st->extl == FB_BWE ) + { + push_indice( st, IND_FB_SLOPE, idxGain, NUM_BITS_FB_FRAMEGAIN ); + } + + + return; +} + +/*-------------------------------------------------------------------* + * Freq_weights() + * + *-------------------------------------------------------------------*/ +static +void freq_weights( + const float Band_Ener[], /* i : Band energy */ + const float f_weighting[], /* i : weigting coefs. */ + float w_env[], /* o : Freq. weighting */ + const short Nbands /* i : Number of bands */ +) +{ + short i; + float tmp, w1[SWB_FENV], w2[SWB_FENV]; + float min_b, max_b; + + /* Find Max band energy */ + min_b = Band_Ener[0]; + max_b = Band_Ener[0]; + for( i=1; i max_b ) + { + max_b = Band_Ener[i]; + } + } + + /* Find weighting function */ + tmp = 1.f/(max_b-min_b); + for( i=0; i k; l-- ) + { + dist_min[l] = dist_min[l - 1]; + index[l] = index[l - 1]; + } + dist_min[k] = dist; + index[k] = i; + break; + } + } + } + } + else + { + set_f( dist_min, 3.402823466e+38F, surv ); /* FLT_MAX */ + + for (i = 0; i < surv; i++) + { + index[i] = i; + } + + p_E_ROM_dico = E_ROM_dico; + + for( i = 0; i < E_ROM_dico_size; i++ ) + { + dist = x[0] - *p_E_ROM_dico++; + dist *= dist; + + for( j = 1; j < dim; j++ ) + { + temp1 = x[j] - *p_E_ROM_dico++; + dist += temp1 * temp1; + } + + for( k = 0; k < surv; k++ ) + { + if( dist < dist_min[k] ) + { + for( l = surv - 1; l > k; l-- ) + { + dist_min[l] = dist_min[l-1]; + index[l] = index[l-1]; + } + dist_min[k] = dist; + index[k] = i; + break; + } + } + } + } + + return; +} + +/*-------------------------------------------------------------------* + * vqSimple_w() + * + *-------------------------------------------------------------------*/ +static +short vqSimple_w( + const float *x, /* i : input for quantizer */ + float *y, /* i : quantized value */ + const float *cb, /* i : codebooks */ + const float *w, /* i : weight */ + const short dim, /* i : dimension */ + const short l, /* i : number of candidates */ + const short flag /* i : flag indicationg weighted distortion metric */ +) +{ + short i, j, index; + const float *cbP; + float dist_min, dist, temp; + + index = 0; + dist_min = FLT_MAX; + cbP = cb; + + if( flag ) + { + for( i = 0; i < l; i++ ) + { + dist = x[0] - *cbP++; + dist *= (dist * w[0]); + for( j = 1; j < dim; j++ ) + { + temp = x[j] - *cbP++; + dist += temp * temp * w[j]; + } + + if( dist < dist_min ) + { + dist_min = dist; + index = i; + } + } + } + else + { + for( i = 0; i < l; i++ ) + { + dist = x[0] - *cbP++; + dist *= dist; + for( j = 1; j < dim; j++ ) + { + temp = x[j] - *cbP++; + dist += temp * temp; + } + + if( dist < dist_min ) + { + dist_min = dist; + index = i; + } + } + } + + /* Reading the selected vector */ + mvr2r( &cb[index * dim], y, dim ); + + return(index); +} + +/*-------------------------------------------------------------------* + * MSVQ_Interpol_Tran() + * + *-------------------------------------------------------------------*/ + +static void MSVQ_Interpol_Tran( + float *SWB_env_energy, /* i/o : (original/quantized) energy */ + short *indice /* o : quantized index */ +) +{ + short k, n_band, candInd[N_CAND_TR], ind_tmp[2]; + float env_temp11[SWB_FENV_TRANS/2], env_temp12[SWB_FENV_TRANS/2]; + float dist, minDist, tmp_q; + float quant_tmp[SWB_FENV_TRANS], quant_tmp2[SWB_FENV_TRANS]; + float distCand[N_CAND_TR], quant_select[SWB_FENV_TRANS]; + + /* Extract target vector */ + for( n_band = 0; n_band < DIM_TR1; n_band++ ) + { + env_temp11[n_band] = SWB_env_energy[2*n_band]; + env_temp12[n_band] = SWB_env_energy[2*n_band+1]; + } + + vqWithCand_w( env_temp11, Env_TR_Cdbk1, DIM_TR1, N_CB_TR1, candInd, N_CAND_TR, distCand, NULL, 0 ); + + minDist = FLT_MAX; + for( k=0; ktotal_brate <= ACELP_8k00 ) + { + core_type = 0; + } + else + { + core_type = 1; + } + + get_normalize_spec( core, st->extl, mode, core_type, org, SWB_signal, &(st->prev_L_swb_norm1), offset ); + + if ( st->extl == WB_BWE) + { + max_band = 4; + band_step = 2; + } + } + else /* HQ core */ + { + gamma = 0.55f; + get_normalize_spec( core, -1, mode, -1, org, SWB_signal, &(st->prev_L_swb_norm1), offset ); + + if ( offset == HQ_GENERIC_FOFFSET_32K ) + { + max_band = 12; + } + } + + for( n_band=0; n_bandL_frame == L_FRAME ) + { + L = L_SUBFR; + } + else + { + L = L_SUBFR16k; + } + + /* HF transient detect */ + IsTransient = detect_transient( insig_hp, st, L_FRAME16k, coder_type ); + + /* LF transient detect */ + IsTransient_LF = 0; + for ( n_band = 0; n_band < 4; n_band++ ) + { + energy = EPSILON; + for ( i = 0; i < L; i++ ) + { + energy += insig_lp[i + n_band*L] * insig_lp[i + n_band*L]; + } + + if( energy > 5.5f * st->EnergyLF ) + { + IsTransient_LF = 1; + } + + st->EnergyLF = energy; + } + calc_tilt_bwe(insig, &tilt, L_FRAME32k); + if( IsTransient == 1 && (tilt > 8.0 || st->clas > 1) ) + { + IsTransient = 0; + st->TransientHangOver = 0; + } + + if( IsTransient == 1 ) + { + mode = IsTransient; + push_indice( st, IND_SWB_CLASS, mode, 2 ); + + /* Energy for the different bands and global energies */ + global_gain = 0; + for (n_band = 0; n_band < SWB_FENV_TRANS; n_band++) + { + energy = EPSILON; + for (n_coeff = swb_bwe_trans_subband[n_band]+st_offset; n_coeff < swb_bwe_trans_subband[n_band+1]+st_offset; n_coeff++) + { + energy += yos[n_coeff] * yos[n_coeff]; + } + global_gain += energy; + SWB_fenv[n_band] = energy; + } + global_gain *= 0.5f; + + for (n_band = 0; n_band < SWB_FENV_TRANS; n_band++) + { + SWB_fenv[n_band] = 10.0f * (float)log10( SWB_fenv[n_band]/swb_bwe_trans_subband_width[n_band] ) - Mean_env_tr[n_band]; + } + + WB_tenv_orig = EPSILON; + WB_tenv_syn = EPSILON; + for(n_band = 0; n_band < SWB_TENV; n_band++) + { + SWB_tenv[n_band] = EPSILON; + + for(i = 0; i < L_SUBFR16k; i++) + { + SWB_tenv[n_band] += insig_hp[i + n_band*L_SUBFR16k] * insig_hp[i + n_band*L_SUBFR16k]; + } + + for(i=0; i 1) + { + Rat_tenv = 1.0f; + } + + for(n_band = 0; n_band < SWB_TENV; n_band++) + { + SWB_tenv[n_band] *= Rat_tenv; + } + + max = SWB_tenv[0]; + pos = 0; + for(n_band = 1; n_band < SWB_TENV; n_band++) + { + if(SWB_tenv[n_band] > max) + { + max = SWB_tenv[n_band]; + pos = n_band; + } + } + + max = SWB_tenv[0]; + for(n_band = 1; n_band < SWB_TENV; n_band++) + { + if(SWB_tenv[n_band] > 5.0f*SWB_tenv[n_band-1]) + { + break; + } + } + + if(n_band < SWB_TENV) + { + energy = 0.0f; + for(n_band = (pos+1); n_band < SWB_TENV; n_band++) + { + energy += SWB_tenv[n_band]; + } + if(pos == SWB_TENV-1) + { + energy = 0.0f; + } + else + { + energy /= (SWB_TENV-pos-1); + } + + for(n_band = 0; n_band < pos; n_band++) + { + SWB_tenv[n_band] *= 0.5f; + } + + SWB_tenv[pos] *= 1.005f; + if(energy < SWB_tenv[pos]) + { + for(n_band = pos+1; n_band < SWB_TENV; n_band++) + { + SWB_tenv[n_band] *= 0.9f; + } + } + } + else + { + for(n_band = 1; n_band < SWB_TENV; n_band++) + { + if(SWB_tenv[n_band-1] > SWB_tenv[n_band]) + { + SWB_tenv[n_band-1] = 0.5f*(SWB_tenv[n_band-1]+SWB_tenv[n_band]); + } + else + { + SWB_tenv[n_band] = 0.5f*(SWB_tenv[n_band-1]+SWB_tenv[n_band]); + } + } + + for(n_band = 0; n_band < SWB_TENV; n_band++) + { + SWB_tenv[n_band] *= 0.9f; + } + } + + if(IsTransient_LF == 0 && coder_type == INACTIVE && st->TransientHangOver == 1) + { + for(n_band = 0; n_band < SWB_TENV; n_band++) + { + SWB_tenv[n_band] *= 0.5f; + } + for(n_band = 0; n_band < SWB_FENV_TRANS; n_band++) + { + SWB_fenv[n_band] *= 0.05f; + } + } + else + { + SWB_fenv[2] *= 0.1f; + SWB_fenv[3] *= 0.05f; + } + + for(n_band = 0; n_band < SWB_TENV; n_band++) + { + SWB_tenv_tmp[n_band] = (float) log10( SWB_tenv[n_band] + EPSILON ) * FAC_LOG2; + if (SWB_tenv_tmp[n_band] > 15) + { + index = 15; + } + else if (SWB_tenv_tmp[n_band] < 0) + { + index = 0; + } + else + { + index = (short)(SWB_tenv_tmp[n_band]+0.5f); + } + + push_indice( st, IND_SWB_TENV, index, 4 ); + + } + + MSVQ_Interpol_Tran(SWB_fenv, indice); + + push_indice( st, IND_SWB_FENV, indice[0], 7 ); + push_indice( st, IND_SWB_FENV, indice[1], 6 ); + + } + else + { + /* Energy for the different bands and global energies */ + global_gain = 0; + for (n_band = 0; n_band < SWB_FENV; n_band++) + { + energy = EPSILON; + for (n_coeff = swb_bwe_subband[n_band]+st_offset; n_coeff < swb_bwe_subband[n_band+1]+st_offset; n_coeff++) + { + energy += yos[n_coeff] * yos[n_coeff]; + } + + if (n_bandprev_mode = mode; + st->prev_global_gain = global_gain; + + return mode; +} + +static short decision_hq_generic_class ( + const float *coefs, /* i: original MDCT spectrum */ + const short hq_generic_offset /* i: frequency offset of high frequency spectrum */ +) +{ + short i, k; + float p, a, e; + float p2a; + float avgp2a; + short nband; + + if ( hq_generic_offset == HQ_GENERIC_FOFFSET_24K4 ) + { + nband = 10; + } + else + { + nband = 8; + } + + avgp2a = 0.f; + for (k = 0; k < nband; k++) + { + a = 0.0f; + p = 0.0f; + for (i = swb_bwe_subband[k]+hq_generic_offset; i p) + { + p = e; + } + + a += e; + } + + if (a > 0.0f) + { + a *= swb_inv_bwe_subband_width[k]; + p2a = 10.0f * (float) log10 (p / a); + avgp2a += p2a; + } + } + + avgp2a /= (float)(nband); + + if ( avgp2a > 8.6f ) + { + return HQ_GENERIC_EXC1; + } + else + { + return HQ_GENERIC_EXC0; + } +} + +/*-------------------------------------------------------------------* + * hq_generic_hf_encoding() + * + *-------------------------------------------------------------------*/ + +void hq_generic_hf_encoding( + const float *coefs, /* i : MDCT coefficients of weighted original */ + float *hq_generic_fenv, /* i/o: energy of SWB envelope */ + const short hq_generic_offset, /* i : frequency offset for extracting energy */ + Encoder_State *st, /* i/o: encoder state structure */ + short *hq_generic_exc_clas /* o : HF excitation class */ +) +{ + short n_coeff, n_band; + float energy; + float energy_factor[SWB_FENV], w_env[SWB_FENV]; + short indice[HQ_GENERIC_NVQIDX]; + short nenv; + + if ( hq_generic_offset <= HQ_GENERIC_FOFFSET_24K4 ) + { + nenv = SWB_FENV; + } + else + { + nenv = SWB_FENV-2; + } + + for( n_band = 0; n_band < nenv; n_band++ ) + { + energy = EPSILON; + for( n_coeff = swb_bwe_subband[n_band]+hq_generic_offset; n_coeff < swb_bwe_subband[n_band+1] + hq_generic_offset; n_coeff++ ) + { + energy += coefs[n_coeff] * coefs[n_coeff]; + } + + hq_generic_fenv[n_band] = energy; + } + + if ( st->bwidth == FB ) + { + for( n_band = 0; n_band < DIM_FB; n_band++ ) + { + energy = EPSILON; + for( n_coeff = fb_bwe_subband[n_band]; n_coeff < fb_bwe_subband[n_band+1]; n_coeff++ ) + { + energy += coefs[n_coeff] * coefs[n_coeff]; + } + + hq_generic_fenv[n_band+nenv] = energy; + } + } + + energy_control( st, HQ_CORE, -1, -1, coefs, hq_generic_offset, energy_factor ); + + if ( st->hq_generic_speech_class == 1 ) + { + push_indice( st, IND_HQ_SWB_EXC_SP_CLAS, 1, 1 ); + *hq_generic_exc_clas = HQ_GENERIC_SP_EXC; + } + else + { + *hq_generic_exc_clas = decision_hq_generic_class(coefs, hq_generic_offset); + push_indice( st, IND_HQ_SWB_EXC_SP_CLAS, 0, 1 ); + push_indice( st, IND_HQ_SWB_EXC_CLAS, *hq_generic_exc_clas, 1 ); + } + + for( n_band = 0; n_band < nenv; n_band++ ) + { + hq_generic_fenv[n_band] *= energy_factor[n_band]; + hq_generic_fenv[n_band] = 10.0f * (float)log10( hq_generic_fenv[n_band]*swb_inv_bwe_subband_width[n_band] ); + } + + if ( st->bwidth == FB ) + { + for( n_band = 0; n_band < DIM_FB; n_band++ ) + { + hq_generic_fenv[n_band+nenv] = 10.0f * (float)log10( hq_generic_fenv[n_band+nenv]*fb_inv_bwe_subband_width[n_band] ); + } + } + + freq_weights( hq_generic_fenv, w_NOR, w_env, nenv ); + + for( n_band = 0; n_band < nenv; n_band++ ) + { + hq_generic_fenv[n_band] -= Mean_env[n_band]; + } + + if ( st->bwidth == FB ) + { + for( n_band = 0; n_band < DIM_FB; n_band++ ) + { + hq_generic_fenv[n_band+nenv] -= Mean_env_fb[n_band]; + } + } + + /* Energy VQ */ + if ( hq_generic_offset <= HQ_GENERIC_FOFFSET_24K4 ) + { + msvq_interpol( hq_generic_fenv, w_env, indice ); + } + else + { + msvq_interpol_2( hq_generic_fenv, w_env, indice, nenv ); + } + + if ( st->bwidth == FB ) + { + indice[5] = vqSimple_w( hq_generic_fenv+nenv, hq_generic_fenv+nenv, EnvCdbkFB, NULL, DIM_FB, N_CB_FB, 0 ); + } + + push_indice( st, IND_SWB_FENV_HQ, indice[0], 5 ); + push_indice( st, IND_SWB_FENV_HQ, indice[1], 7 ); + push_indice( st, IND_SWB_FENV_HQ, indice[2], 6 ); + push_indice( st, IND_SWB_FENV_HQ, indice[3], 5 ); + + if ( hq_generic_offset <= HQ_GENERIC_FOFFSET_24K4 ) + { + push_indice( st, IND_SWB_FENV_HQ, indice[4], 6 ); + } + else + { + push_indice( st, IND_SWB_FENV_HQ, indice[4], 5 ); + } + + if ( st->bwidth == FB ) + { + push_indice( st, IND_FB_FENV_HQ, indice[5], 5 ); + } + + for( n_band = 0; n_band < nenv; n_band++ ) + { + Word16 tmp,frac,exp; + Word32 L_tmp; + tmp = add((short)(hq_generic_fenv[n_band]*256),(short)(Mean_env[n_band]*256)); /*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); + tmp = shl(tmp, add(exp,1)); /*Q1 */ + hq_generic_fenv[n_band] = (float)tmp*0.5f; /*Q1 */ + } + + if ( st->bwidth == FB ) + { + for( n_band = 0; n_band < DIM_FB; n_band++ ) + { + Word16 tmp,frac,exp; + Word32 L_tmp; + + tmp = add((short)(hq_generic_fenv[n_band + nenv]*128),(short)(Mean_env_fb[n_band]*128)); /*Q7 */ + 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); + tmp = shl(tmp, add(exp, 1));/*Q1 */ + hq_generic_fenv[add(n_band,nenv)] = (float)tmp*0.5f; + } + } + + return; +} diff --git a/lib_enc/swb_bwe_enc_hr.c b/lib_enc/swb_bwe_enc_hr.c new file mode 100644 index 000000000..d74f2e84a --- /dev/null +++ b/lib_enc/swb_bwe_enc_hr.c @@ -0,0 +1,474 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "prot.h" +#include "rom_com.h" + +/*-------------------------------------------------------------------* + * en_band_quant() + * + * Quantize the band envelop + *-------------------------------------------------------------------*/ + +static short en_band_quant( /* o : quantization index */ + float *en_band, /* i/o: (un)quantized envelope value */ + const float *env_code, /* i : envelope codebook */ + const short N /* i : codebook dimension */ +) +{ + float maxerr, err; + short i, j, ind; + + maxerr = FLT_MAX; + ind = 0; + + for( i = 0; i < N; i++ ) + { + err = FLT_MIN; + for (j = 0; j < 2; j++) + { + err += (en_band[j] - env_code[i*2+j]) * (en_band[j] - env_code[i*2+j]); + } + if (err < maxerr) + { + maxerr = err; + ind = i; + } + } + + en_band[0] = env_code[2*ind]; + en_band[1] = env_code[2*ind+1]; + + return( ind ); +} + +/*-------------------------------------------------------------------* + * swb_bwe_enc_hr() + * + * HR SWB BWE encoder + *-------------------------------------------------------------------*/ + +void swb_bwe_enc_hr( + Encoder_State *st, /* i/o: encoder state structure */ + const float *new_input, /* i : input signal */ + const short input_frame, /* i : frame length */ + const short coder_type, /* i : coding type */ + const short unbits /* i : number of core unused bits */ +) +{ + short i, j, k, nBits, nBits_total, nBits_block, Nsv, Nsv2, width_noncoded; + short is_transient, pos; + int x_norm[NSV_MAX*(WIDTH_BAND+1)], x_norm1[NSV_MAX*(WIDTH_BAND+1)]; + float t_audio[L_FRAME48k], t_audio_tmp[L_FRAME48k]; + float gain, gain2, en_band[N_BANDS_BWE_HR]; + short ind1, ind2; + short nq[NSV_MAX], nq2[NSV_MAX]; + float tmpF, min_env; + float en_noncoded; + + /*---------------------------------------------------------------------* + * initializations + *---------------------------------------------------------------------*/ + + ind2 = 0; /* only to suppress warnings */ + Nsv2 = 0; /* only to suppress warnings */ + gain2 = 0 ; /* only to suppress warnings */ + en_noncoded = 0;/* only to suppress warnings */ + + /* reset memories in case that last frame was a different technology */ + if( st->last_core == HQ_CORE || st->last_extl != st->extl ) + { + set_f( st->old_wtda_swb, 0, L_FRAME48k ); + } + + /* calculate SWB BWE bit-budget (extension layer bit-rate + AVQ unused bits from the core layer) */ + nBits = (short)(st->extl_brate) / 50 + unbits; + nBits_total = nBits; + + + /*---------------------------------------------------------------------* + * detect transient frames + *---------------------------------------------------------------------*/ + + is_transient = detect_transient( new_input, st, input_frame, coder_type ); + push_indice( st, IND_HR_IS_TRANSIENT, is_transient, 1 ); + + /*---------------------------------------------------------------------* + * OLA and MDCT + *---------------------------------------------------------------------*/ + + wtda( new_input, t_audio_tmp, st->old_wtda_swb, ALDO_WINDOW, ALDO_WINDOW, input_frame ); + + direct_transform( t_audio_tmp, t_audio, is_transient, input_frame ); + + if( is_transient ) + { + nBits = -1; /* is_transient flag */ + nBits_block = nBits_total / NUM_TIME_SWITCHING_BLOCKS; + nBits += nBits_total % NUM_TIME_SWITCHING_BLOCKS; + + /* set width of noncoded (blind estimated) spectrum */ + if( st->extl == SWB_BWE_HIGHRATE ) + { + width_noncoded = L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_END_FREQ_COEF; + } + else /* st->extl == FB_BWE_HIGHRATE */ + { + width_noncoded = (2*END_FREQ_BWE_FULL_FB/50)/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_END_FREQ_COEF; + } + + /*---------------------------------------------------------------------* + * transient frames: processing in blocks (subframes) + *---------------------------------------------------------------------*/ + + for( k = 0; k < NUM_TIME_SWITCHING_BLOCKS; k++ ) + { + nBits += nBits_block; + + /* compute energy of noncoded (14.4-20kHz) spectrum */ + if( st->extl == FB_BWE_HIGHRATE ) + { + en_noncoded = sum2_f( t_audio + k*input_frame/NUM_TIME_SWITCHING_BLOCKS + NUM_TRANS_END_FREQ_COEF, width_noncoded ) + 0.001f; + en_noncoded = (float)sqrt( en_noncoded / width_noncoded ); + } + + /* keep only frequencies in interest */ + set_f( t_audio + k*input_frame/NUM_TIME_SWITCHING_BLOCKS, 0, NUM_TRANS_START_FREQ_COEF ); + set_f( t_audio + k*input_frame/NUM_TIME_SWITCHING_BLOCKS + L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS, 0, (input_frame-L_FRAME32k)/NUM_TIME_SWITCHING_BLOCKS ); + + /*---------------------------------------------------------------------* + * global gain coding + *---------------------------------------------------------------------*/ + + /* compute and quantize global energy */ + gain = sum2_f( t_audio + k*input_frame/NUM_TIME_SWITCHING_BLOCKS + NUM_TRANS_START_FREQ_COEF, WIDTH_TRANS_FREQ_COEF*N_BANDS_TRANS_BWE_HR ) + 0.001f; + gain = (float)sqrt( gain ) / (WIDTH_TRANS_FREQ_COEF*N_BANDS_TRANS_BWE_HR); + ind1 = gain_quant( &gain, MIN_GLOB_GAIN_BWE_HR, MAX_GLOB_GAIN_BWE_HR, NBITS_GLOB_GAIN_BWE_HR ); + + push_indice( st, IND_HR_GAIN, ind1, NBITS_GLOB_GAIN_BWE_HR ); + nBits -= NBITS_GLOB_GAIN_BWE_HR; + + /* normalization with global gain */ + tmpF = 1/gain; + for( i=0; iextl == SWB_BWE_HIGHRATE ) + { + en_noncoded = en_band[N_BANDS_TRANS_BWE_HR-1]; + } + else /* st->extl == FB_BWE_HIGHRATE */ + { + en_noncoded /= (gain * en_band[N_BANDS_TRANS_BWE_HR-1]); + + ind1 = 0; + if( en_noncoded < BWE_HR_TRANS_EN_LIMIT1 ) + { + ind1 = 1; + en_noncoded = en_band[N_BANDS_TRANS_BWE_HR-1] * BWE_HR_TRANS_EN_LIMIT1; + } + else if( en_noncoded < BWE_HR_TRANS_EN_LIMIT2 ) + { + ind1 = 2; + en_noncoded = en_band[N_BANDS_TRANS_BWE_HR-1] * BWE_HR_TRANS_EN_LIMIT2; + } + else if( en_noncoded < BWE_HR_TRANS_EN_LIMIT3 ) + { + ind1 = 3; + en_noncoded = en_band[N_BANDS_TRANS_BWE_HR-1] * BWE_HR_TRANS_EN_LIMIT3; + } + else + { + en_noncoded = en_band[N_BANDS_TRANS_BWE_HR-1]; + } + push_indice( st, IND_HR_HF_GAIN, ind1, NBITS_HF_GAIN_BWE_HR ); + nBits -= NBITS_HF_GAIN_BWE_HR; + } + + /*---------------------------------------------------------------------* + * AVQ coding (quantize normalized spectrum) + *---------------------------------------------------------------------*/ + + Nsv = (NUM_TRANS_END_FREQ_COEF - NUM_TRANS_START_FREQ_COEF) / WIDTH_BAND; + AVQ_cod( t_audio + k*input_frame/NUM_TIME_SWITCHING_BLOCKS + NUM_TRANS_START_FREQ_COEF, x_norm, nBits, Nsv ); + AVQ_encmux( st, st->extl, x_norm, &nBits, Nsv, nq ); + + } + } + else /* !is_transient */ + { + nBits--; /* is_transient flag */ + + /*---------------------------------------------------------------------* + * processing of normal (non-transient) frames + *---------------------------------------------------------------------*/ + + /* set width of noncoded (blind estimated) spectrum */ + if( st->extl == SWB_BWE_HIGHRATE ) + { + width_noncoded = L_FRAME32k - NUM_NONTRANS_END_FREQ_COEF; + } + else /* st->extl == FB_BWE_HIGHRATE */ + { + width_noncoded = 2*END_FREQ_BWE_FULL_FB/50 - NUM_NONTRANS_END_FREQ_COEF; + } + + /* compute energy of noncoded (14.4-20kHz) spectrum */ + if( st->extl == FB_BWE_HIGHRATE ) + { + en_noncoded = sum2_f( t_audio + NUM_NONTRANS_END_FREQ_COEF, width_noncoded ) + 0.001f; + en_noncoded = (float)sqrt( en_noncoded / width_noncoded ); + } + + /* keep only frequencies in interest */ + set_f( t_audio, 0, NUM_NONTRANS_START_FREQ_COEF ); + set_f( t_audio + NUM_NONTRANS_END_FREQ_COEF, 0, input_frame-NUM_NONTRANS_END_FREQ_COEF ); + + /*---------------------------------------------------------------------* + * global gain coding + *---------------------------------------------------------------------*/ + + /* compute and quantize global gain */ + gain = sum2_f( t_audio + NUM_NONTRANS_START_FREQ_COEF, WIDTH_NONTRANS_FREQ_COEF*N_BANDS_BWE_HR ) + 0.001f; + gain = (float)sqrt(gain) / (WIDTH_NONTRANS_FREQ_COEF*N_BANDS_BWE_HR); + ind1 = gain_quant( &gain, MIN_GLOB_GAIN_BWE_HR, MAX_GLOB_GAIN_BWE_HR, NBITS_GLOB_GAIN_BWE_HR ); + + push_indice( st, IND_HR_GAIN, ind1, NBITS_GLOB_GAIN_BWE_HR ); + nBits -= NBITS_GLOB_GAIN_BWE_HR; + + /* normalization with global gain */ + tmpF = 1/gain; + for( i=0; i NBITS_THRESH_BWE_HR ) + { + i = NUM_NONTRANS_END_FREQ_COEF - NUM_NONTRANS_START_FREQ_COEF; + mvr2r( t_audio + NUM_NONTRANS_START_FREQ_COEF, t_audio_tmp, NUM_NONTRANS_END_FREQ_COEF - NUM_NONTRANS_START_FREQ_COEF ); + } + else + { + /* reorder the spectrum */ + ind1 = (pos*64 + pos/2 * WIDTH_BAND); + mvr2r( t_audio + NUM_NONTRANS_START_FREQ_COEF, t_audio_tmp, ind1 ); + + ind2 = ((pos+1)*64 + (pos+1)/2 * WIDTH_BAND); + mvr2r( t_audio + NUM_NONTRANS_START_FREQ_COEF + ind2, t_audio_tmp + ind1, NUM_NONTRANS_END_FREQ_COEF - NUM_NONTRANS_START_FREQ_COEF - ind2 ); + + i = ind1 + NUM_NONTRANS_END_FREQ_COEF - NUM_NONTRANS_START_FREQ_COEF - ind2; + } + + /*---------------------------------------------------------------------* + * estimate energy of noncoded spectrum (14.4-20kHz) + *---------------------------------------------------------------------*/ + + if( st->extl == SWB_BWE_HIGHRATE ) + { + en_noncoded = 0.5f * min_env; + } + else /* st->extl == FB_BWE_HIGHRATE */ + { + en_noncoded /= (gain * min_env); + + ind1 = 0; + if( en_noncoded < BWE_HR_NONTRANS_EN_LIMIT1 ) + { + ind1 = 1; + en_noncoded = 0.5f * min_env * BWE_HR_NONTRANS_EN_LIMIT1; + } + else if( en_noncoded > BWE_HR_NONTRANS_EN_LIMIT2 ) + { + ind1 = 2; + en_noncoded = min_env * BWE_HR_NONTRANS_EN_LIMIT2; + } + else if( en_noncoded > BWE_HR_NONTRANS_EN_LIMIT3 ) + { + ind1 = 3; + en_noncoded = min_env * BWE_HR_NONTRANS_EN_LIMIT3; + } + else + { + en_noncoded = 0.5f * min_env; + } + + push_indice( st, IND_HR_HF_GAIN, ind1, NBITS_HF_GAIN_BWE_HR ); + nBits -= NBITS_HF_GAIN_BWE_HR; + } + + /*---------------------------------------------------------------------* + * AVQ coding (quantize normalized spectrum) + *---------------------------------------------------------------------*/ + + Nsv = i / WIDTH_BAND; + AVQ_cod( t_audio_tmp, x_norm, nBits, Nsv ); + AVQ_encmux( st, st->extl, x_norm, &nBits, Nsv, nq ); + + /*---------------------------------------------------------------------* + * second stage coding + *---------------------------------------------------------------------*/ + + if( nBits >= 9 + NBITS_GLOB_GAIN_BWE_HR && sum_s( nq, Nsv) > 0 ) + { + /* select spectrum of the second stage coding */ + k = 0; + for( i=0; i 396 ) + { + Nsv2 = 33; + } + else + { + Nsv2 = nBits/12; + } + + /* second stage global gain estimation and coding */ + gain2 = sum2_f( t_audio, Nsv2*WIDTH_BAND ) + 0.001f; + gain2 = (float)(16*sqrt( gain2 / (Nsv2*WIDTH_BAND) )); + ind1 = gain_quant( &gain2, MIN_GLOB_GAIN_BWE_HR, MAX_GLOB_GAIN_BWE_HR, NBITS_GLOB_GAIN_BWE_HR ); + + push_indice( st, IND_HR_GAIN, ind1, NBITS_GLOB_GAIN_BWE_HR ); + nBits -= NBITS_GLOB_GAIN_BWE_HR; + + /* normalize with global gain */ + gain2 *= 0.0625f; /* 1/16 */ + tmpF = 1/gain2; + for( i=0; iextl, x_norm1, &nBits, Nsv2, nq2 ); + } + + } + + /* write unused bits */ + while( nBits > 0 ) + { + i = min( nBits, 16 ); + push_indice( st, IND_UNUSED, 0, i ); + nBits -= i; + } + + + return; +} diff --git a/lib_enc/swb_bwe_enc_lr.c b/lib_enc/swb_bwe_enc_lr.c new file mode 100644 index 000000000..224cfea90 --- /dev/null +++ b/lib_enc/swb_bwe_enc_lr.c @@ -0,0 +1,673 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include "stat_com.h" + +/*--------------------------------------------------------------------------* + * GetSubbandCorrIndex2_har() + * + * Finds the index of best correlation between highband (*inBuf) and lowband (*predBuf) for current subband of length (fLen) + *--------------------------------------------------------------------------*/ + +static short GetSubbandCorrIndex2_har( /* o : best correlation index */ + const float *inBuf, /* i : target buffer (i.e., highband signal) */ + const float *predBuf, /* i : prediction buffer (i.e., lowband) */ + const short fLen, /* i : window length */ + const short maxLag, /* i : search length */ + const GainItem *G_item, /* i : nZero nonzero components (value+index) */ + const short nZero, /* i : number of nonzero components used in */ + short *prev_frame_bstindx /* i : previous frame best Indices */ +) +{ + short bestIdx, i, j; + float corr, energy, corr_sq; + float lagCorr_sq, lagEnergy, eOld; + short absPos; + short N1, N2; + + + absPos = 0; + bestIdx = 0; + lagCorr_sq = 0.0f; + lagEnergy = 1e30f; + + for( i = 0, energy = 0.0f; i < fLen - 1; i++, predBuf++ ) + { + energy += *predBuf **predBuf; + } + + predBuf -= fLen-1; + eOld = 0.0f; + N1 = max(0, *prev_frame_bstindx-maxLag/2); + if( *prev_frame_bstindx < 0 ) + { + N2 = maxLag-1; + } + else + { + N2 = min(maxLag-1, *prev_frame_bstindx+maxLag/2); + } + + predBuf +=N1; + + /* find the best lag */ + for( i = N1; i <= N2; i++ ) + { + corr = 0.0f; + + /* get the energy, remove the old and update with the new energy index */ + for(j = 0, energy = 0.0f; j < fLen; j++, predBuf++) + { + energy += *predBuf **predBuf; + } + + predBuf -= fLen; + + /* energy to be removed in the next lag */ + eOld = *predBuf; + eOld *= eOld; + + /* get cross-correlation */ + if( energy ) + { + for(j = 0, corr = 0.0f; j < nZero; j++) + { + corr += inBuf[G_item[j].gainIndex]* predBuf[G_item[j].gainIndex]; + } + + corr_sq = corr*corr; + + if( (double)lagCorr_sq*(double)energy < (double)corr_sq*(double)lagEnergy ) + { + bestIdx = i; + lagCorr_sq = corr_sq; + lagEnergy = energy; + } + } + + predBuf++; + absPos++; + } + + if( lagCorr_sq == 0.0f && *prev_frame_bstindx < 0 ) + { + bestIdx = 0; + } + else + { + if( lagCorr_sq == 0.0f ) + { + bestIdx = *prev_frame_bstindx; + } + } + + *prev_frame_bstindx = bestIdx; + + return bestIdx; +} + + + +/*--------------------------------------------------------------------------* + * 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( + float *yos, /* i : original input spectrum */ + float *y2, /* i : decoded spectrum */ + const short nBands_search, /* i : number of bands */ + short *lagIndices, /* o : pulse index */ + short *prev_frame_bstindx, /* i/o: prev frame index */ + const short swb_lowband, /* i : length of the LF spectrum */ + const short *subband_offsets, + const short *sbWidth, + const short *subband_search_offset + +) +{ + GainItem Nbiggest[(NB_SWB_SUBBANDS_HAR_SEARCH_SB)*N_NBIGGEST_PULSEARCH]; + const float *refBuf,*predBuf; + short search_offset[NB_SWB_SUBBANDS_HAR_SEARCH_SB]; + short nlags[NB_SWB_SUBBANDS_HAR_SEARCH_SB]; + short j, k, sb; + short n_nbiggestsearch[NB_SWB_SUBBANDS_HAR]; + float low_freqsgnl[L_FRAME32k]; + + /* Initializations */ + predBuf = y2; + + /* Get the number of HF groups for performing Similarity search */ + for( sb = 0; sb < nBands_search; sb++ ) + { + nlags[sb] = (short)pow(2, bits_lagIndices_mode0_Har[sb]); + } + + for( sb=0; sb search_offset[sb] - sbWidth[sb] - nlags[sb]/2; j-- ) + { + low_freqsgnl[k] = predBuf[j]; + k++; + } + } + /* correlation b/w HF spectrum Group1 of length sbLen and decoded LF spectrum */ + lagIndices[sb] = GetSubbandCorrIndex2_har( yos + swb_lowband + subband_offsets[sb], low_freqsgnl, + sbWidth[sb], nlags[sb], Nbiggest+(sb*N_NBIGGEST_PULSEARCH), + n_nbiggestsearch[sb], &prev_frame_bstindx[sb] ); + } + + return; +} + +static short GetSubbandCorrIndex2_pulsestep( + const float *inBuf, + const float *predBuf, + const float *predBufMa, + const short fLen, + const short maxLag, + const GainItem *G_item, + const short nZero, + short ssearch_buflim, + const float *predBuf_ni +) +{ + short bestIdx, i, j; + float corr, energy, corr_sq; + float lagCorr_sq, lagEnergy; + short absPos; + short ib_flag = 0; + + + absPos = 0; + bestIdx = -1; + lagCorr_sq = 0.0f; + lagEnergy = 1e30f; + + /* Get the initial energy for zero lag */ + while( *predBuf == 0.0f && absPos < ssearch_buflim ) + { + predBuf++; + absPos++; + predBuf_ni++; + } + + if( absPos == ssearch_buflim ) + { + predBuf--; + absPos--; + predBuf_ni--; + } + for( i = 0, energy = 0.0f; i < fLen; i++, predBuf_ni++ ) + { + energy += *predBuf_ni **predBuf_ni; + } + + predBuf_ni -= fLen; + lagEnergy = energy; + + /* Find the best lag */ + for( i = 0; i < maxLag; i++ ) + { + corr = 0.0f; + + /* Get the energy, remove the old and update with the new energy index */ + for(j = 0, energy = 0.0f; j < fLen; j++, predBuf_ni++) + { + energy += *predBuf_ni **predBuf_ni; + } + predBuf_ni -= fLen; + + /* Get cross-correlation */ + if( energy ) + { + for(j = 0, corr = 0.0f; j < nZero; j++) + { + corr += inBuf[G_item[j].gainIndex]* predBufMa[G_item[j].gainIndex]; + } + + corr_sq = corr*corr; + + if( (lagCorr_sq == 0.0f && corr_sq == 0.0f) || (double)lagCorr_sq*(double)energy < (double)corr_sq*(double)lagEnergy ) + { + bestIdx = i; + lagCorr_sq = corr_sq; + lagEnergy = energy; + } + } + + predBuf++; + absPos++; + predBuf_ni++; + while( *predBuf == 0.0f && absPos < ssearch_buflim ) + { + predBuf++; + absPos++; + predBuf_ni++; + } + + if( absPos >= ssearch_buflim ) + { + if( bestIdx == -1 ) + { + ib_flag = 1; + } + + break; + } + } + if( ib_flag ) + { + bestIdx = 0; + } + return bestIdx; +} + + +/*--------------------------------------------------------------------------* + * GetSWBIndices() + * + * Finds the subband lags for subband coding. Each lag corresponds to + * the section that is copied and scaled from the low-frequency band + * to form the high-frequency subband. + * + * The subbands are searched in two steps to reduce the complexity of + * the search relative to full search. In first step, a most representative + * subband is selected based on the similarity of the subbands.Full search + * is performed for the selected subband.Based on the lagIndice value for + * this subband, the region of highest interest is selected. A partial + * search is performed for rest of the subbands around this region of the + * low-frequency range. + *--------------------------------------------------------------------------*/ + +static void GetSWBIndices( + const float *predBuf, /* i : low-frequency band */ + const float *targetBuf, /* i : high-frequency band */ + const short nBands_search, /* i : number of search subbands */ + const short *sbWidth, /* i : subband lengths */ + short *lagIndices, /* o : selected lags for subband coding */ + const short predBufLen, /* i : low-frequency band length */ + GainItem *Nbiggest, /* o : most representative region */ + const short *subband_offsets, /* o : N biggest components */ + float *predBuf_ni /* i : low-frequency band filled noise */ +) +{ + const float *refBuf; + short search_offset[NB_SWB_SUBBANDS]; + short nlags[NB_SWB_SUBBANDS]; + short sbLen; + short j, sb; + short n_nbiggestsearch[NB_SWB_SUBBANDS]; + short ssearch_buflim; + float sspectra_ma[L_FRAME32k]; + + /* Initializations */ + for (sb = 0; sb < nBands_search; sb++) + { + j = sb * N_NBIGGEST_PULSEARCH; + sbLen = sbWidth[sb]; + refBuf = targetBuf + subband_offsets[sb]; + FindNBiggest2_simple(refBuf, Nbiggest+j, sbLen, &n_nbiggestsearch[sb],N_NBIGGEST_PULSEARCH); + } + + /* Selection of most representative subband (full search) */ + for ( sb = 0; sb < nBands_search; sb++ ) + { + nlags[sb] = (short)pow(2, bits_lagIndices_modeNormal[sb]); + } + + for ( sb = 0; sb < nBands_search; sb++ ) + { + search_offset[sb] = subband_search_offsets[sb]; + } + sspectra_ma[0] = (predBuf_ni[0]+predBuf_ni[1])/2.0f; + + for( sb=1; sb < predBufLen-1; sb++ ) + { + sspectra_ma[sb] = (predBuf_ni[sb-1] + predBuf_ni[sb] + predBuf_ni[sb+1])/3.0f; + } + + sspectra_ma[sb] = (predBuf_ni[sb-1]+predBuf_ni[sb])/2.0f; + /* Partial search for rest of subbands except the last which is fixed */ + for( sb = 0; sb < nBands_search; sb++ ) + { + sbLen = sbWidth[sb]; + ssearch_buflim = predBufLen - (sbLen + search_offset[sb]); + lagIndices[sb] = GetSubbandCorrIndex2_pulsestep( targetBuf + subband_offsets[sb], predBuf + search_offset[sb], + sspectra_ma + search_offset[sb], sbLen, nlags[sb], Nbiggest+(sb*N_NBIGGEST_PULSEARCH),n_nbiggestsearch[sb], + ssearch_buflim, predBuf_ni + search_offset[sb]); + } + + return; +} + + + +static void gethar_noisegn( + Encoder_State *st, + float spectra[], + float noise_flr[], + float xSynth_har[], + const short sbWidth[], + const short lagIndices[], + const short bands, + const short har_bands, + const short fLenLow, + const short fLenHigh, + const short subband_offsets[], + const short subband_search_offset[], + short band_start[], + short band_end[], + short band_width[], + float band_energy[], + float be_tonal[], + float *sspectra, + const short har_freq_est2, + const short pos_max_hfe2, + short *pul_res, + GainItem pk_sf[] +) +{ + GainItem get_pk[N_NBIGGEST_SEARCH_LRG_B]; + short n_nbiggestsearch,imin,gqlevs; + short i; + float hfspec[L_FRAME32k]; + float g,g1,g2,dmin,d; + + /*Generate HF noise*/ + genhf_noise( noise_flr, xSynth_har, sspectra, bands, har_bands, har_freq_est2, pos_max_hfe2, pul_res, pk_sf, fLenLow, + fLenHigh, sbWidth, lagIndices, subband_offsets, subband_search_offset ); + + mvr2r(spectra+fLenLow,hfspec,fLenHigh); + FindNBiggest2_simple(hfspec, get_pk, fLenHigh, &n_nbiggestsearch,N_NBIGGEST_SEARCH_LRG_B); + for(i=0; iprev_hqswb_clas, &st->prev_ni_ratio ); + + /* Find best indices for each group */ + getswbindices_har(spectra, sspectra_ni,nBands_search, lagIndices, prev_frm_index,fLenLow,subband_offsets, sbWidth , subband_search_offset); + /* Write the indices into the bitstream */ + for (k = 0; k < nBands_search; k++) + { + push_indice( st,IND_LAGINDICES, lagIndices[k], bits_lagIndices_mode0_Har[k]); + } + + if(flag_dis == 0) + { + if(har_freq_est2 != SWB_HAR_RAN1 || har_freq_est2 != *prev_frm_hfe2) + { + har_freq_est2 += lagIndices[0]; + } + } + + /*noise generation*/ + gethar_noisegn( st, spectra, sspectra_diff, xSynth_har, sbWidth, lagIndices, BANDS, har_bands, fLenLow, fLenHigh, subband_offsets, subband_search_offset, + band_start, band_end, band_width, band_energy, be_tonal, sspectra, har_freq_est2, pos_max_hfe2, pul_res, pk_sf ); + + /*HF Spectrum Generation*/ + Gettonl_scalfact( xSynth_har, spectra_ni, fLenLow, fLenHigh, har_bands, BANDS, band_energy, band_start, band_end, p2a_flags, be_tonal, pk_sf, pul_res ); + + if(flag_dis == 0) + { + *prev_frm_hfe2 = 0; + } + else + { + *prev_frm_hfe2 = har_freq_est2; + } + + for( k = har_bands; k < BANDS; k++ ) + { + for( i = band_start[k]; i <= band_end[k]; i++ ) + { + spectra[i] = xSynth_har[i-fLenLow]; + } + } + } + else + { + /* Spectrum normalization for the corecoder*/ + ss_min = spectrumsmooth_noiseton(spectra,spectra_ni,sspectra,sspectra_diff,sspectra_ni,fLenLow, ni_seed); + + /* Get lag indices */ + GetSWBIndices( sspectra, spectra + fLenLow, nBands, sbWidth, lagIndices, fLenLow, + Nbiggest, subband_offsets, sspectra ); + /* Bitstream operations */ + for (k = 0; k < nBands; k++) + { + if( p2a_flags[BANDS-NB_SWB_SUBBANDS+k] == 0 ) + { + push_indice( st,IND_LAGINDICES,lagIndices[k], bits_lagIndices_modeNormal[k] ); + } + else + { + lagIndices[k] = 0; + } + } + convert_lagIndices_pls2smp( lagIndices, nBands, lagIndices, sspectra, sbWidth, fLenLow ); + /*get levels for missing bands*/ + GetlagGains( sspectra_ni, &band_energy[BANDS-NB_SWB_SUBBANDS], nBands, sbWidth, lagIndices, fLenLow, lagGains ); + for(k=0; kprev_En_sb, p2a_flags, BANDS, band_start, band_end, fLenLow ); + + for( k = BANDS - NB_SWB_SUBBANDS; k < BANDS; k++ ) + { + if( p2a_flags[k] == 0 ) + { + for( i = band_start[k]; i <= band_end[k]; i++ ) + { + spectra[i] = xSynth_har[i-fLenLow]; + } + } + else + { + for( i = band_start[k]; i <= band_end[k]; i++ ) + { + spectra[i] = spectra_ni[i]; + } + } + } + } + + return; +} + +/*--------------------------------------------------------------------------* + * swb_bwe_enc_lr() + * + * Main encoding routine of SWB BWE for the LR MDCT core + *--------------------------------------------------------------------------*/ + +void swb_bwe_enc_lr( + Encoder_State *st, /* i/o: encoder state structure */ + const float m_core[], /* i : lowband synthesis */ + const float m_orig[], /* i/o: scaled orig signal (MDCT) */ + float m[], /* o : highband synthesis with lowband zeroed */ + const long total_brate, /* i : total bitrate for selecting subband pattern */ + short BANDS, /* i : Total number of Subbands in a frame */ + short *band_start, /* i : band start of each SB */ + short *band_end, /* i : band end of each SB */ + float *band_energy, /* i : band_energy of each SB */ + short *p2a_flags, /* i : HF tonal indicator */ + const short hqswb_clas, /* i : HQ_NORMAL or HQ_HARMONIC mode */ + short lowlength, /* i : lowband length */ + short highlength, /* i : highband length */ + short *prev_frm_index, /* i/o: previous frame lag index for harmonic mode */ + const short har_bands, /* i : Number of LF harmonic bands */ + short *prev_frm_hfe2, + short *prev_stab_hfe2, + short band_width[], /* i : subband bandwidths */ + const float y2_ni[], /* i/o: Sparse filled core coder */ + short *ni_seed /* i/o: random seed for search buffer NI */ +) +{ + short k; + short nBands; + short nBands_search; + short wBands[NB_SWB_SUBBANDS]; + short lagIndices[NB_SWB_SUBBANDS]; + float lagGains[NB_SWB_SUBBANDS]; + const short *subband_offsets; + short swb_lowband, swb_highband; + const short *subband_search_offset; + subband_search_offset = subband_search_offsets_13p2kbps_Har; + subband_offsets = subband_offsets_sub5_13p2kbps_Har; + hf_parinitiz(total_brate,hqswb_clas,lowlength,highlength,wBands,&subband_search_offset,&subband_offsets,&nBands,&nBands_search,&swb_lowband,&swb_highband); + /* Prepare m[], low part from WB core, high part from 32k input */ + mvr2r( m_core, m, swb_lowband ); + mvr2r( m_orig + swb_lowband, m + swb_lowband, swb_highband ); + + /* SWB BWE encoding */ + EncodeSWBSubbands( st, m, swb_lowband, swb_highband, nBands, nBands_search, wBands, subband_offsets, + lagIndices, lagGains, BANDS, band_start, band_end, band_energy, p2a_flags, + hqswb_clas, prev_frm_index, har_bands, subband_search_offset, prev_frm_hfe2, prev_stab_hfe2,band_width, y2_ni, ni_seed ); + m[swb_lowband+swb_highband-1] *= 0.0625f; + m[swb_lowband+swb_highband-2] *= 0.125f; + m[swb_lowband+swb_highband-3] *= 0.25f; + m[swb_lowband+swb_highband-4] *= 0.5f; + + /* set frequencies below 6.4 kHz to zero */ + if(hqswb_clas == HQ_NORMAL) + { + for (k=0; k < swb_lowband; k++) + { + m[k] = 0.0f; + } + } + + return; +} diff --git a/lib_enc/swb_pre_proc.c b/lib_enc/swb_pre_proc.c new file mode 100644 index 000000000..11b2566d0 --- /dev/null +++ b/lib_enc/swb_pre_proc.c @@ -0,0 +1,314 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include "rom_enc.h" + + +/*-------------------------------------------------------------------* + * Local constants + * + *-------------------------------------------------------------------*/ + +#define CLDFB_NO_CHANNELS_HB 20 + + +/*-------------------------------------------------------------------* + * wb_pre_proc() + * + * - Resampling of input signal when input signal sampling rate + * is above 16kHz + * - Common WB TBE and WB BWE pre-processing + *-------------------------------------------------------------------*/ + +void wb_pre_proc( + Encoder_State *st, /* i/o: encoder state structure */ + const float *new_inp_resamp16k, /* i : original input signal */ + float *hb_speech /* o : HB target signal (6-8kHz) at 16kHz */ +) +{ + short Sample_Delay_WB_BWE, ramp_flag; + float old_input[NS2SA(16000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS) + L_FRAME16k]; + float *highband_new_speech, highband_old_speech [(L_LOOK_12k8 + L_SUBFR + L_FRAME) * 5/16]; + short fSwitchFromIO = 0; + + if ( (st->last_total_brate == ACELP_6k60) || + (st->last_total_brate == ACELP_8k85) || + (st->last_total_brate == ACELP_12k65) || + (st->last_total_brate == ACELP_14k25) || + (st->last_total_brate == ACELP_15k85) || + (st->last_total_brate >= ACELP_18k25 && st->last_total_brate <= ACELP_23k85) ) + { + fSwitchFromIO = 1; + } + + set_f( old_input, 0, NS2SA(16000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS) + L_FRAME16k ); + + if ( st->extl == WB_BWE || st->extl == WB_TBE || st->igf ) + { + ramp_flag = 0; + if( (st->last_extl != WB_TBE && st->last_extl != WB_BWE && !st->igf) || (st->igf && fSwitchFromIO) ) + { + ramp_flag = 1; + } + + if ( !st->ppp_mode) + { + flip_spectrum_and_decimby4( new_inp_resamp16k, hb_speech, L_FRAME16k, st->decim_state1, st->decim_state2, ramp_flag ); + + if( st->extl != WB_TBE ) + { + /* Update the previous wideband speech buffer in case of a WB_BWE frame - this code is in wb_tbe_enc */ + Sample_Delay_WB_BWE = (L_LOOK_12k8 + L_SUBFR) * 5/16; + + highband_new_speech = highband_old_speech + Sample_Delay_WB_BWE; + mvr2r( hb_speech, highband_new_speech, L_FRAME16k / 4 ); + mvr2r( highband_old_speech + L_FRAME16k / 4, st->old_speech_wb, Sample_Delay_WB_BWE ); + } + } + } + else + { + set_f( st->decim_state1, 0.0f, (2*ALLPASSSECTIONS_STEEP+1) ); + set_f( st->decim_state2, 0.0f, (2*ALLPASSSECTIONS_STEEP+1) ); + set_f( st->old_speech_wb, 0.0f, (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 */ + if ( (st->extl != WB_BWE || (st->extl == WB_BWE && st->total_brate <= ACELP_8k00)) && !st->ppp_mode ) + { + Sample_Delay_WB_BWE = NS2SA( 16000, DELAY_FD_BWE_ENC_12k8_NS ); + + mvr2r( new_inp_resamp16k, &old_input[Sample_Delay_WB_BWE], L_FRAME16k ); + mvr2r( st->old_input_wb, old_input, Sample_Delay_WB_BWE ); + mvr2r( new_inp_resamp16k + L_FRAME16k - Sample_Delay_WB_BWE, st->old_input_wb, Sample_Delay_WB_BWE ); + if ((st->extl != SWB_BWE) && (st->extl != FB_BWE)) + { + mvr2r( old_input, st->old_wtda_swb, L_FRAME16k ); + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * swb_pre_proc() + * + * - 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 + *-------------------------------------------------------------------*/ + +void swb_pre_proc( + Encoder_State *st, /* i/o: encoder state structure */ + const float *input, /* i : original input signal */ + float *new_swb_speech, /* o : original input signal at 32kHz */ + float *shb_speech, /* o : SHB target signal (6-14kHz) at 16kHz */ + float realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : real buffer */ + float imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] /* i : imag buffer */ +) +{ + short Sample_Delay_SWB_BWE, inner_frame, delay; + long inner_Fs; + float old_input[NS2SA(48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS) + L_FRAME48k]; + float spchTmp[640]; + short i, j; + short startB, endB; + float *realBufferFlipped[CLDFB_NO_COL_MAX]; + float *imagBufferFlipped[CLDFB_NO_COL_MAX]; + float realBufferTmp[CLDFB_NO_COL_MAX][20]; + float imagBufferTmp[CLDFB_NO_COL_MAX][20]; + short ts, nB, uB; + float sign; + + for( j=0; j < CLDFB_NO_COL_MAX; j++ ) + { + set_f( realBufferTmp[j], 0, 20 ); + set_f( imagBufferTmp[j], 0, 20 ); + realBufferFlipped[j] = realBufferTmp[j]; + imagBufferFlipped[j] = imagBufferTmp[j]; + } + + set_f( old_input, 0.0f, NS2SA(48000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS) + L_FRAME48k ); + + if( st->input_Fs == 32000 ) + { + mvr2r( input, new_swb_speech, L_FRAME32k ); + if (st->last_extl != SWB_BWE && st->last_extl != FB_BWE && st->extl != SWB_BWE_HIGHRATE) + { + Sample_Delay_SWB_BWE = NS2SA(32000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS); + mvr2r(st->old_fdbwe_speech, &old_input[Sample_Delay_SWB_BWE], L_FRAME32k); + set_f(old_input, 0, Sample_Delay_SWB_BWE); + mvr2r(st->old_fdbwe_speech + L_FRAME32k - Sample_Delay_SWB_BWE, st->old_input, Sample_Delay_SWB_BWE); + if (st->extl != WB_BWE) + { + mvr2r(old_input, st->old_wtda_swb, L_FRAME32k); + } + } + + if( st->extl != SWB_BWE && st->extl != FB_BWE ) + { + mvr2r( input, st->old_fdbwe_speech, L_FRAME32k ); + } + } + else /* 48 kHz */ + { + if( st->codec_mode == MODE1 ) + { + if( st->extl != SWB_BWE && st->extl != FB_BWE && st->core == ACELP_CORE) + { + /* move the resampling out of the TDBWE path as new_swb_speech is not needed for TDBWE. */ + mvr2r( input, st->old_fdbwe_speech, L_FRAME48k ); + } + else + { + if( st->last_extl != SWB_BWE && st->last_extl != FB_BWE ) + { + /* resample 48 kHz to 32kHz */ + if( st->last_bwidth == FB ) + { + inner_frame = L_FRAME48k; + inner_Fs = 48000; + mvr2r( st->old_fdbwe_speech, new_swb_speech, L_FRAME48k ); + } + else + { + inner_frame = L_FRAME32k; + inner_Fs = 32000; + decimate_2_over_3_allpass( st->old_fdbwe_speech, L_FRAME48k, new_swb_speech, st->dec_2_over_3_mem, allpass_poles_3_ov_2, + decimate_3_ov_2_lowpass_num, decimate_3_ov_2_lowpass_den, st->dec_2_over_3_mem_lp ); + } + + Sample_Delay_SWB_BWE = NS2SA( inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ); + mvr2r( new_swb_speech, &old_input[Sample_Delay_SWB_BWE], inner_frame ); + set_f( old_input, 0, Sample_Delay_SWB_BWE ); + mvr2r( new_swb_speech + inner_frame - Sample_Delay_SWB_BWE, st->old_input, Sample_Delay_SWB_BWE ); + mvr2r( old_input, st->old_wtda_swb, inner_frame ); + } + /* resample 48 kHz to 32kHz */ + if( st->bwidth == FB ) + { + mvr2r( input, new_swb_speech, L_FRAME48k ); + } + else + { + decimate_2_over_3_allpass( input, L_FRAME48k, new_swb_speech, st->dec_2_over_3_mem, allpass_poles_3_ov_2, + decimate_3_ov_2_lowpass_num, decimate_3_ov_2_lowpass_den, st->dec_2_over_3_mem_lp ); + } + } + } + else + { + /* resample 48 kHz to 32kHz */ + if( st->bwidth == FB ) + { + mvr2r( input, new_swb_speech, L_FRAME48k ); + } + else + { + decimate_2_over_3_allpass( input, L_FRAME48k, new_swb_speech, st->dec_2_over_3_mem, allpass_poles_3_ov_2, + decimate_3_ov_2_lowpass_num, decimate_3_ov_2_lowpass_den, st->dec_2_over_3_mem_lp ); + } + } + } + + if( ( st->core == ACELP_CORE && st->extl != SWB_BWE_HIGHRATE && st->extl != FB_BWE_HIGHRATE ) || + ( ( st->total_brate == ACELP_9k60 || st->rf_mode ) && st->bwidth == SWB ) ) + { + if( st->L_frame == L_FRAME ) + { + startB= 34; + endB= 14; + for( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) + { + for( nB = startB, uB=0; nB > endB; nB--,uB++ ) + { + sign = (ts%2) ? 1.0f : -1.0f; + realBufferFlipped[ts][uB] = -sign*realBuffer[ts][nB]; + imagBufferFlipped[ts][uB] = sign*imagBuffer[ts][nB]; + } + } + } + else + { + startB = 39; + endB = 19; + for( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) + { + for( nB = startB, uB=0; nB > endB; nB--,uB++ ) + { + realBufferFlipped[ts][uB] = -realBuffer[ts][nB]; + imagBufferFlipped[ts][uB] = imagBuffer[ts][nB]; + } + } + } + + { + float CldfbHB = 0; + for (nB = 0; nB < 10; nB++) + { + for (ts = 0; ts < CLDFB_NO_COL_MAX; ts++) + { + CldfbHB += (realBufferFlipped[ts][nB] * realBufferFlipped[ts][nB] + imagBufferFlipped[ts][nB] * imagBufferFlipped[ts][nB]); + } + } + if( CldfbHB <= 0 ) + { + CldfbHB = 1.0f; + } + st->cldfbHBLT = 0.9f * st->cldfbHBLT + 0.1f * ( 0.221462f /*=1/log10(32768)*/ * (log10(CldfbHB) - 1.0f) ); + } + cldfbSynthesis( realBufferFlipped, imagBufferFlipped, shb_speech, -1, st->cldfbSynTd ); + + if( st->extl != WB_TBE && st->extl != SWB_TBE && st->extl != 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; + mvr2r( shb_speech + L_FRAME16k - delay, st->old_speech_shb, delay ); + } + } + else + { + if( st->bwidth == FB || st->core == ACELP_CORE) + { + set_f( st->old_speech_shb, 0, L_LOOK_16k + L_SUBFR16k ); + set_f( shb_speech, 0, L_FRAME16k ); /* shb_speech for FB/SWB BWE_HIGHRATE is not used at 64kbps */ + } + else + { + /* flip the spectrm */ + mvr2r( new_swb_speech, spchTmp, L_FRAME32k ); + + for( i = 0; i < L_FRAME32k; i = i+2 ) + { + spchTmp[i] = -spchTmp[i]; + } + + Decimate_allpass_steep( spchTmp, st->state_ana_filt_shb, L_FRAME32k, shb_speech ); + mvr2r( shb_speech + L_FRAME16k - (L_LOOK_16k + L_SUBFR16k), st->old_speech_shb, L_LOOK_16k + L_SUBFR16k ); + } + + /* Reset CLDFB synthesis buffer */ + set_f( st->cldfbSynTd->cldfb_state, 0.0f, st->cldfbSynTd->p_filter_length + st->cldfbSynTd->no_channels*st->cldfbSynTd->no_col ); + } + + /* Memory reset to compensate for 0.9375 ms offset when transitioning from IO to SWB */ + if( st->last_extl == -1 ) + { + delay = NS2SA(st->input_Fs, DELAY_FIR_RESAMPL_NS); + for( i = 0; i < delay; i++ ) + { + shb_speech[i] = (float)i * (0.03f * shb_speech[2*delay-1-i]); + } + } + + return; +} diff --git a/lib_enc/swb_tbe_enc.c b/lib_enc/swb_tbe_enc.c new file mode 100644 index 000000000..6a05b7df0 --- /dev/null +++ b/lib_enc/swb_tbe_enc.c @@ -0,0 +1,2044 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" +#include "rom_enc.h" + +/*-----------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------*/ + +static void return_M_Least( const float *inp, const short n_cols, const float *codebook, const short num_grp, + const float *weight, const short interNum, short *least ); +static void singlevectortest_gain( const float *inp, const short dimen, const short cb_size, short *index, + const float *weight, float *recon, const float *codebook ); +static void determine_gain_weights( const float *gain, float *weights, const short dims ); +static void QuantizeSHBsubgains( Encoder_State *st, float *subgains, const short extl ); +static void QuantizeSHBframegain( Encoder_State *st, float *GainFrame, const short extl, long extl_brate, short *rf_gainFrame_ind ); +static short closest_centroid( const float *data, const float *weights, const float *quantizer, const short centroids, const short length); +static void EstimateSHBFrameGain( const short length, const float *oriSHB, const float *synSHB, float *subgain, float *GainFrame, const float *win_shb, const float *subwin ); +static void EstimateSHBGainShape( const short length, const float *oriSHB, const float *synSHB, float *subgain, const float *subwin ); +static float pow_off_pk(float a[], short len, short step); +static void Quant_lower_LSF( const float lsf[], float lsf_q[], short lsf_idx[] ); +static short Quant_mirror_point(const float lsf[], const float lsf_q[], float *m); +static short Find_LSF_grid(const float lsf[], float lsf_q[], const float m); +static void gainFrSmooth_En(Encoder_State *st, float *shb_frame, const float *lpc_shb, const float *lsp_shb, float *MA_lsp_shb_spacing, short *frGainAttenuate, short *frGainSmoothEn ); +static void Quant_BWE_LSF( Encoder_State *st, const float lsp_shb[], float Q_lsfs[] ); +static void Quant_shb_ener_sf( Encoder_State *st, float *shb_ener_sf ); +static void Quant_shb_res_gshape( Encoder_State *st, float *shb_res_gshape ); + + +/*-------------------------------------------------------------------* + * InitSWBencBuffer() + * + * Initialize SWB buffers + *-------------------------------------------------------------------*/ + +void InitSWBencBuffer( + Encoder_State *st /* i/o: SHB encoder structure */ +) +{ + set_f( st->old_speech_shb, 0.0f, L_LOOK_16k + L_SUBFR16k ); + set_f(st->old_bwe_exc, 0.0f, (PIT16k_MAX * 2)); + st->bwe_seed[0] = 23; + st->bwe_seed[1] = 59; + set_f( st->old_bwe_exc_extended, 0.0f, NL_BUFF_OFFSET ); + st->bwe_non_lin_prev_scale = 0; + + + set_f( st->state_ana_filt_shb, 0.0f, (2*ALLPASSSECTIONS_STEEP+1) ); + + set_f( st->elliptic_bpf_2_48k_mem[0], 0.0f, 4 ); + set_f( st->elliptic_bpf_2_48k_mem[1], 0.0f, 4 ); + set_f( st->elliptic_bpf_2_48k_mem[2], 0.0f, 4 ); + set_f( st->elliptic_bpf_2_48k_mem[3], 0.0f, 4 ); + st->prev_fb_energy = 0.0f; + + return; +} + + +/*-------------------------------------------------------------------* + * ResetSHBbuffer_Enc() + * + *-------------------------------------------------------------------*/ + +void ResetSHBbuffer_Enc( + Encoder_State *st /* i/o: SHB encoder structure */ +) +{ + /* states for the filters used in generating SHB excitation from WB excitation*/ + set_f( st->mem_genSHBexc_filt_down_shb,0, (2*ALLPASSSECTIONS_STEEP+1) ); + set_f( st->mem_csfilt, 0, 2 ); + + /* states for the filters used in generating SHB signal from SHB excitation*/ + set_f( st->state_syn_shbexc, 0, L_SHB_LAHEAD ); + set_f( st->state_lpc_syn, 0, LPC_SHB_ORDER ); + if( sub(st->extl, FB_TBE) == 0 ) + { + set_f( st->fb_state_lpc_syn, 0, LPC_SHB_ORDER ); + st->fb_tbe_demph = 0; + } + /* states for the filters used in generating WB signal from WB excitation*/ + set_f( st->decim_state1, 0.0f, (2*ALLPASSSECTIONS_STEEP+1) ); + set_f( st->decim_state2, 0.0f, (2*ALLPASSSECTIONS_STEEP+1) ); + set_f( st->mem_genSHBexc_filt_down_wb2, 0, (2*ALLPASSSECTIONS_STEEP+1) ); + set_f( st->mem_genSHBexc_filt_down_wb3, 0, (2*ALLPASSSECTIONS_STEEP+1) ); + + + /* overlap buffer used to Adjust SHB Frame Gain */ + set_f( st->mem_stp_swb, 0, LPC_SHB_ORDER ); + st->gain_prec_swb = 1.0f; + set_f( st->syn_overlap,0,L_SHB_LAHEAD ); + st->tbe_demph = 0.0f; + st->tbe_premph = 0.0f; + + return; +} + + +/*-------------------------------------------------------------------* +* wb_tbe_enc() +* +* WB TBE encoder, 6 - 8 kHz band encoding module +*-------------------------------------------------------------------*/ + +void wb_tbe_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const short coder_type, /* i : coding type */ + const float *hb_speech, /* i : HB target signal (6-8kHz) at 16kHz */ + const float *bwe_exc_extended, /* i : bandwidth extended exciatation */ + const float voice_factors[], /* i : voicing factors */ + const float pitch_buf[], /* i : pitch for each subframe */ + const float voicing[] /* i : OL maximum normalized correlation */ +) +{ + short i, j, k, delay; + float hb_old_speech[(L_LOOK_12k8 + L_SUBFR + L_FRAME) * 5/16]; + float shaped_wb_excitation [ (L_FRAME16k + L_SHB_LAHEAD)/4]; + float exc4kWhtnd [L_FRAME16k / 4]; + short ana_align_delay = - L_SHB_LAHEAD / 4 - 5; + float GainFrame, GainShape[NUM_SHB_SUBFR]; + float lpc_wb[LPC_SHB_ORDER_WB+1]; + float lsp_wb[LPC_SHB_ORDER_WB], weights_lsp[LPC_SHB_ORDER_WB] = {1.0, 1.0}; + float *hb_new_speech, *hb_frame; + float R[LPC_SHB_ORDER_WB+2], ervec[LPC_SHB_ORDER_WB+1]; + float prev_pow, curr_pow, scale; + float p2m_in, p2m_out; + short uv_flag; + float pitBufAvg, voicingBufAvg; + float vf_modified[NB_SUBFR16k]; + float temp_wb_fac, feedback; + float lsp_spacing; + float ervec_temp[LPC_SHB_ORDER_WB+1]; + float lsp_wb_temp[LPC_SHB_ORDER_WB], lpc_wb_temp[LPC_SHB_ORDER_WB+1]; + + /* delay alignment */ + delay = (L_LOOK_12k8 + L_SUBFR) * 5/16; + + hb_new_speech = hb_old_speech + delay; + hb_frame = hb_old_speech + L_SUBFR * 5/16 + ana_align_delay; + + mvr2r( st->old_speech_wb, hb_old_speech, delay ); + mvr2r( hb_speech, hb_new_speech, L_FRAME16k / 4 ); + mvr2r( hb_old_speech + L_FRAME16k / 4, st->old_speech_wb, delay ); + if( ( st->last_extl != WB_TBE && st->last_extl != WB_BWE ) && + ( st->clas == UNVOICED_CLAS || ( voicing[0] < 0.5f && voicing[1] < 0.5f && voicing[2] < 0.5f ) ) && + ( !st->igf ) ) + { + /* In case of unvoiced signals after switching cores, back-propagate the target signal */ + mvr2r( hb_speech, hb_old_speech, delay ); + + for( i = (L_LOOK_12k8 + L_SUBFR) * 5/16, j = k = 0; j < L_SUBFR16k; i--, j+=4, k++ ) + { + hb_old_speech[i] *= ola_win_shb_switch_fold[j]; + hb_old_speech[i] += hb_speech[k] * ola_win_shb_switch_fold[L_SUBFR16k-4-j]; + } + } + + autocorr( hb_old_speech, R, LPC_SHB_ORDER_WB+1, (NS2SA(INT_FS_12k8, 5000000L) + L_SUBFR + L_FRAME) * 5/16, win_lpc_hb_wb, 0, 1, 1 ); /* VE2QC: to be tuned later */ + lev_dur( lpc_wb_temp, R, LPC_SHB_ORDER_WB, ervec_temp ); + a2lsp( lsp_wb_temp, lpc_wb_temp, LPC_SHB_ORDER_WB ); + lsp_spacing = 0.5f; + + for( i = 0; i < LPC_SHB_ORDER_WB; i++ ) + { + lsp_spacing = min(lsp_spacing, (float)( i == 0 ? lsp_wb_temp[0] : (lsp_wb_temp[i] - lsp_wb_temp[i -1]))); + } + + /* Spectral smoothing of autocorrelation coefficients */ + for (i = 0; i <= LPC_SHB_ORDER_WB; i++) + { + R[i] = R[i] * wac[i]; + } + R[0] = max( R[0], 1.0e-8f ); + + if ( st->rf_mode == 1 || st->extl_brate == WB_TBE_0k35 ) + { + lev_dur( lpc_wb, R, LPC_SHB_ORDER_LBR_WB, ervec ); + + /* Expand bandwidth of the LP coeffs */ + for (i = 0; i <= LPC_SHB_ORDER_LBR_WB; i++) + { + lpc_wb[i] *= lpc_weights[i]; + } + + /* convert into lsps and calculate weights */ + a2lsp(lsp_wb,lpc_wb, LPC_SHB_ORDER_LBR_WB); + lsp_weights(lsp_wb, weights_lsp, LPC_SHB_ORDER_LBR_WB); + + /* Quantization of LSFs */ + i = closest_centroid( lsp_wb, weights_lsp, lbr_wb_bwe_lsfvq_cbook_2bit, 4, LPC_SHB_ORDER_LBR_WB ); + if( st->codec_mode == MODE2 ) + { + st->lsf_WB = i; + } + else + { + push_indice( st, IND_SHB_LSF, i, NUM_BITS_LBR_WB_LSF ); + } + + mvr2r( lbr_wb_bwe_lsfvq_cbook_2bit + i*LPC_SHB_ORDER_LBR_WB, lsp_wb, LPC_SHB_ORDER_LBR_WB); + + lsp2a( lpc_wb, lsp_wb, LPC_SHB_ORDER_LBR_WB ); + set_f( lpc_wb + LPC_SHB_ORDER_LBR_WB+1, 0.0f, (LPC_SHB_ORDER_WB - LPC_SHB_ORDER_LBR_WB) ); + } + else + { + lev_dur( lpc_wb, R, LPC_SHB_ORDER_WB, ervec ); + + /* Expand bandwidth of the LP coeffs */ + for (i = 0; i <= LPC_SHB_ORDER_WB; i++) + { + lpc_wb[i] *= lpc_weights[i]; + } + + /* convert into lsps and calculate weights */ + a2lsp(lsp_wb,lpc_wb, LPC_SHB_ORDER_WB); + lsp_weights(lsp_wb, weights_lsp, LPC_SHB_ORDER_WB); + + /* Quantization of LSFs */ + i = closest_centroid( lsp_wb, weights_lsp, wb_bwe_lsfvq_cbook_8bit, 256, LPC_SHB_ORDER_WB ); + push_indice( st, IND_SHB_LSF, i, NUM_BITS_WB_LSF ); + + mvr2r( wb_bwe_lsfvq_cbook_8bit + i*LPC_SHB_ORDER_WB, lsp_wb, LPC_SHB_ORDER_WB); + + lsp2a( lpc_wb, lsp_wb, LPC_SHB_ORDER_WB ); + } + + uv_flag = 0; + if ( st->extl_brate == WB_TBE_1k05 && st->coder_type_raw == UNVOICED ) + { + uv_flag = 1; + } + + mvr2r( voice_factors, vf_modified, NB_SUBFR16k ); + if( coder_type == VOICED ) + { + for ( i = 1; i < NB_SUBFR; i++ ) + { + vf_modified[i] = 0.8f * voice_factors[i] + 0.2f * voice_factors[i-1]; + } + + if(st->L_frame != L_FRAME ) + { + vf_modified[4] = 0.8f * voice_factors[4] + 0.2f * voice_factors[3]; + } + } + + /* From low band excitation, generate highband excitation */ + mvr2r( st->state_syn_shbexc, shaped_wb_excitation, L_SHB_LAHEAD/4 ); + GenShapedWBExcitation( shaped_wb_excitation + L_SHB_LAHEAD/4, lpc_wb, exc4kWhtnd, st->mem_csfilt, st->mem_genSHBexc_filt_down_shb, + st->mem_genSHBexc_filt_down_wb2, st->mem_genSHBexc_filt_down_wb3, st->state_lpc_syn, coder_type, + bwe_exc_extended, st->bwe_seed, vf_modified, uv_flag, st->igf ); + + prev_pow = sum2_f( shaped_wb_excitation, L_SHB_LAHEAD/4 ); + curr_pow = sum2_f( shaped_wb_excitation + L_SHB_LAHEAD/4, L_SHB_LAHEAD/4 ); + + if( voice_factors[0] > 0.75f ) + { + curr_pow *= 0.25; + } + + if( prev_pow == 0 ) + { + scale = 0; + } + else + { + scale = sqrt(curr_pow/prev_pow); + } + + for( i = 0; i < (L_SHB_LAHEAD/4 - 1); i++ ) + { + shaped_wb_excitation[i] *= scale; + } + + scale = sqrt( scale ); + + shaped_wb_excitation[L_SHB_LAHEAD/4 - 1] *= scale; + + /* Update WB excitation */ + mvr2r( shaped_wb_excitation + L_FRAME16k/4, st->state_syn_shbexc, L_SHB_LAHEAD/4 ); + + /* estimate the gain shape parameter */ + EstimateSHBGainShape( SHB_OVERLAP_LEN/2, hb_frame, shaped_wb_excitation, GainShape, subwin_wb ); + + /* Gain frame adjustment factor */ + temp_wb_fac = (float)log( (GainShape[0]+0.00001f) / (st->prev_wb_GainShape+0.0001f) ); + feedback = temp_wb_fac * temp_wb_fac ; + for (i = 1; i < NUM_SHB_SUBFR/4; i++) + { + temp_wb_fac = (float)log( (GainShape[i]+0.00001f) / (GainShape[i-1]+0.0001f) ); + feedback += (temp_wb_fac * temp_wb_fac); + } + feedback = 0.4f / (1 + 0.5f * feedback); + + temp_wb_fac = st->prev_wb_GainShape; + for (i = 0; i < NUM_SHB_SUBFR/4; i++) + { + GainShape[i] = (1 - feedback) * GainShape[i] + feedback * temp_wb_fac; + temp_wb_fac = GainShape[i]; + } + st->prev_wb_GainShape = GainShape[NUM_SHB_SUBFR/4-1]; + + /* Compute the power of gains away from the peak gain prior to quantization */ + p2m_in = pow_off_pk(GainShape, NUM_SHB_SUBFR / 4, 1); + + if ( st->extl_brate == WB_TBE_0k35 ) + { + for (i=0; i<8; i++) + { + GainShape[i] = RECIP_ROOT_EIGHT; + } + } + else + { + push_indice( st, IND_UV_FLAG, uv_flag, 1 ); + + /* Quantization of the subframe gain parameter */ + QuantizeSHBsubgains( st, GainShape, st->extl ); + } + + /* Compute the power of gains away from the peak gain after quantization */ + p2m_out = pow_off_pk(GainShape, NUM_SHB_SUBFR/2, 2); + + /* Estimate the gain parameter */ + EstimateSHBFrameGain( SHB_OVERLAP_LEN/2, hb_frame, shaped_wb_excitation, GainShape, &GainFrame, window_wb, subwin_wb ); + + /* 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 ( p2m_out > 2.0f * p2m_in ) + { + float temp = 0; + if(p2m_in >= 0 && p2m_out > 0) + { + temp = sqrt((2.0f * p2m_in) / p2m_out); + } + GainFrame *= temp; + } + + pitBufAvg = 0.0025f * sum_f( pitch_buf, NB_SUBFR ); + voicingBufAvg = 0.333f * sum_f( voicing, 3 ); + if(voicingBufAvg <= 0.0f && (pitBufAvg != 0)) + { + voicingBufAvg = pitBufAvg/1.001f; + } + else if(voicingBufAvg <= 0.0f) + { + voicingBufAvg = 1.0f; + } + + GainFrame *= max(min((float)(pitBufAvg/voicingBufAvg), 1.0f), 0.7f); + + if( lsp_spacing < 0.01f ) + { + GainFrame *= 0.65f; + } + + /* Quantization of the frame gain parameter */ + if( st->igf && coder_type == VOICED ) + { + GainFrame *= 0.5f; + } + else if( st->igf && (0.25f*sum_f(voice_factors, NB_SUBFR) > 0.35f) ) + { + GainFrame *= 0.75f; + } + + QuantizeSHBframegain( st, &GainFrame, st->extl, st->extl_brate, &st->RF_bwe_gainFr_ind ); + + /* Adjust the subframe and frame gain of the synthesized SHB signal */ + /* Scale the shaped excitation*/ + ScaleShapedSHB( SHB_OVERLAP_LEN/2, shaped_wb_excitation, st->syn_overlap, GainShape, GainFrame, window_wb, subwin_wb ); + + + return; +} + + +/*-------------------------------------------------------------------* + * swb_tbe_enc() + * + * SWB TBE encoder, 6 - 14 kHz (or 7.5 - 15.5 kHz) band encoding module + *-------------------------------------------------------------------*/ + +void swb_tbe_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const short coder_type, /* i : coding type */ + float *shb_speech, /* i : SHB target signal (6-14kHz) at 16kHz */ + const float *bwe_exc_extended, /* i : bandwidth extended exciatation */ + const float voice_factors[], /* i : voicing factors */ + float *White_exc16k, /* o : shaped white excitation for the FB TBE */ + const float voicing[], /* i : OL maximum normalized correlation */ + const float pitch_buf[] /* i : pitch for each subframe */ +) +{ + short i, j, delay; + float shb_old_speech[L_LOOK_16k + L_SUBFR16k + L_FRAME16k]; + float shaped_shb_excitation [L_FRAME16k + L_SHB_LAHEAD]; + float GainFrame, GainShape[NUM_SHB_SUBFR]; + float lpc_shb[LPC_SHB_ORDER+1]; + float weights_lsp[LPC_SHB_ORDER]; + float *shb_frame, *shb_new_speech; + float lsf_shb_orig[LPC_SHB_ORDER]; + float lsp_shb_1[LPC_SHB_ORDER], lsp_shb_2[LPC_SHB_ORDER], lsp_temp[LPC_SHB_ORDER]; + float lpc_shb_sf[4*(LPC_SHB_ORDER+1)]; + const float *ptr_lsp_interp_coef; + short tmp; + float shb_ener_sf; + float lsf_shb[LPC_SHB_ORDER]; + float shb_res[L_FRAME16k]; + float shb_res_gshape[NB_SUBFR16k], normFac; + short vf_ind; + float sd_uq_q, vf_modified[NB_SUBFR16k]; + float pitBufAvg, voicingBufAvg; + float R[LPC_SHB_ORDER+2], ervec[LPC_SHB_ORDER+1]; + short ana_align_delay[2] = {-L_SHB_LAHEAD - (NL_BUFF_OFFSET/2), -L_SHB_LAHEAD - (NL_BUFF_OFFSET/2)}; + + float prev_pow, curr_pow, scale; + float p2m_in, p2m_out; + short frGainAttenuate, frGainSmoothEn; + float MA_lsp_shb_spacing; + float temp_swb_fac, feedback; + float shaped_shb_excitationTemp[L_FRAME16k]; + float lsf_diff[LPC_SHB_ORDER], w[LPC_SHB_ORDER]; + float refl[M]; + float tilt_para; + float formant_fac; + float temp; + short stab_check = 1; + + /* initializations */ + set_f( shaped_shb_excitationTemp, 0.0f, L_FRAME16k ); + + /* compensate for the delay in target generation and subframe LA */ + shb_frame = shb_old_speech + L_SUBFR16k + ana_align_delay[0]; + + /* set up the speech buffers for TBE processing*/ + delay = L_LOOK_16k + L_SUBFR16k; + shb_new_speech = shb_old_speech + delay; + mvr2r( st->old_speech_shb, shb_old_speech, delay ); + mvr2r( shb_speech, shb_new_speech, L_FRAME16k ); + mvr2r( shb_old_speech + L_FRAME16k, st->old_speech_shb, delay ); + + autocorr( shb_old_speech, + R, + LPC_SHB_ORDER+1, + NS2SA(INT_FS_16k, ACELP_LOOK_NS) + L_SUBFR16k + L_FRAME16k, + win_lpc_shb, 0, 1, 1 ); + + /* Spectral smoothing of autocorrelation coefficients */ + if(st->rf_mode || st->total_brate == ACELP_9k60) + { + for (i = 0; i <= LPC_SHB_ORDER; i++) + { + R[i] = R[i] * wac_swb[i]; + } + } + /* Set the autocorr[0] element to a non-negative value */ + R[0] = max( R[0], 1.0e-8f); + + lev_dur( lpc_shb, R, LPC_SHB_ORDER, ervec ); + { + float enerG, lpc_shb1[M+1]; + + /* extend the lpc_shb to a 16th order gain calc */ + set_f(lpc_shb1, 0, M+1); + mvr2r(lpc_shb, lpc_shb1, LPC_SHB_ORDER + 1); + + /* estimate the LP gain */ + enerG = enr_1_Az(lpc_shb1, 2*L_SUBFR); + + /* if the LP gain is greater than a threshold, avoid saturation. + The function 'is_numeric_float' used to check for infinity enerG */ + if(enerG > 32 || !(is_numeric_float(enerG)) ) + { + set_f(lpc_shb, 0, LPC_SHB_ORDER+1); + lev_dur( lpc_shb, R, 2, ervec ); + } + } + + /* Expand bandwidth of the LP coeffs */ + if(st->rf_mode || st->total_brate == ACELP_9k60) + { + for( i = 0; i <= LPC_SHB_ORDER; i++ ) + { + lpc_shb[i] *= lpc_weights[i]; + } + } + + /* convert to LSFs */ + stab_check = a2lsp( lsf_shb, lpc_shb, LPC_SHB_ORDER ); + + if( (st->last_extl != SWB_TBE && st->last_extl != FB_TBE) || st->ini_frame == 0 ) + { + for( i=0; i < LPC_SHB_ORDER; i++ ) + { + st->prev_lsp_shb[i] = i/20.0f; + } + } + + if( stab_check == 0 ) + { + mvr2r( st->prev_lsp_shb, lsf_shb, LPC_SHB_ORDER ); + } + + mvr2r( lsf_shb, st->prev_lsp_shb, LPC_SHB_ORDER ); + + mvr2r(lsf_shb, lsf_shb_orig, LPC_SHB_ORDER); + + gainFrSmooth_En( st, shb_frame, lpc_shb, lsf_shb, &MA_lsp_shb_spacing, &frGainAttenuate, &frGainSmoothEn); + + if(st->rf_mode || st->total_brate == ACELP_9k60) + { + lsp_weights( lsf_shb, weights_lsp, LPC_SHB_ORDER ); + + /* to compensate for the 1.1* weighting done inside the function lsp_weights */ + weights_lsp[3]*=0.909091f; + weights_lsp[4]*=0.909091f; + + /* 8-bit VQ, 10 dimension */ + i = closest_centroid(lsf_shb, weights_lsp, swb_tbe_lsfvq_cbook_8b, 256, LPC_SHB_ORDER); + mvr2r(swb_tbe_lsfvq_cbook_8b + i * LPC_SHB_ORDER, lsf_shb, LPC_SHB_ORDER); + + set_s(st->lsf_idx, 0, NUM_Q_LSF); + st->lsf_idx[0] = i; + } + else + { + /* Quantization of LSFs */ + Quant_BWE_LSF( st, lsf_shb, lsf_shb ); + } + + space_lsfs( lsf_shb, LPC_SHB_ORDER ); + + /* voice factor adjustment and gainframe attenuation factor */ + sd_uq_q = 0; + for( i = 0; i < LPC_SHB_ORDER; i++ ) + { + /* Estimate the QD in lsps between UQ and Q*/ + sd_uq_q += (lsf_shb[i] - lsf_shb_orig[i]) * (lsf_shb[i] - lsf_shb_orig[i]); + } + + mvr2r(voice_factors, vf_modified, NB_SUBFR16k); + + if( coder_type == VOICED || mean(voice_factors, 4) > 0.4f ) + { + for( i = 1; i < NB_SUBFR; i++ ) + { + vf_modified[i] = 0.8f * voice_factors[i] + 0.2f * voice_factors[i-1]; + } + + if( st->L_frame != L_FRAME ) + { + vf_modified[4] = 0.8f * voice_factors[4] + 0.2f * voice_factors[3]; + } + } + + /* SHB LSF from current frame; and convert to LSP for interpolation */ + lsf2lsp( lsf_shb, lsp_shb_2, LPC_SHB_ORDER, 1.0f ); + + if( st->last_extl == SWB_TBE || st->last_extl == FB_TBE ) + { + /* SHB LSP values from prev. frame for interpolation */ + mvr2r( st->swb_lsp_prev_interp, lsp_shb_1, LPC_SHB_ORDER ); + } + else + { + /* Use current frame's LSPs; in effect no interpolation */ + mvr2r( lsp_shb_2, lsp_shb_1, LPC_SHB_ORDER ); + } + + lsf_diff[0] = lsf_diff[LPC_SHB_ORDER-1] = 0.5f; + for( i=1; i<(LPC_SHB_ORDER-1); i++ ) + { + lsf_diff[i] = lsf_shb[i] - lsf_shb[i-1]; + } + a2rc (st->cur_sub_Aq+1, refl, (short) 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; + if( st->last_extl != SWB_TBE ) + { + for( i=1; iprev_lsf_diff[i-1] = 0.5f*lsf_diff[i]; + } + } + + if( st->total_brate <= ACELP_16k40 ) + { + if(!(st->prev_tilt_para > 5.0f && (coder_type == TRANSITION || tilt_para < 1.0f)) && !(((st->prev_tilt_para < 3.0f && st->prev_coder_type >= VOICED)) && tilt_para > 5.0f)) + { + for( i = 1; i < (LPC_SHB_ORDER-1); i++ ) + { + w[i] = (lsf_diff[i] < st->prev_lsf_diff[i-1]) ? min(max(0.8f*lsf_diff[i]/st->prev_lsf_diff[i-1], 0.5f), 1.0f) : min(max(0.8f*st->prev_lsf_diff[i-1]/lsf_diff[i], 0.5f), 1.0f); + } + w[0] = w[1]; + w[LPC_SHB_ORDER-1] = w[LPC_SHB_ORDER-2]; + + for( i = 0; i < LPC_SHB_ORDER; i++ ) + { + lsp_temp[i] = lsp_shb_1[i]*(1.0f-w[i]) + lsp_shb_2[i]*w[i]; + } + } + else + { + mvr2r(lsp_shb_2, lsp_temp, LPC_SHB_ORDER); + } + } + + mvr2r( lsf_diff+1, st->prev_lsf_diff, LPC_SHB_ORDER-2 ); + st->prev_tilt_para = tilt_para; + + if( st->total_brate == ACELP_24k40 || st->total_brate == ACELP_32k ) + { + /* SHB LSP interpolation */ + ptr_lsp_interp_coef = interpol_frac_shb; + for( j = 0; j < 4; j++ ) + { + for( i = 0; i < LPC_SHB_ORDER; i++ ) + { + lsp_temp[i] = lsp_shb_1[i]*(*ptr_lsp_interp_coef) + + lsp_shb_2[i]*(*(ptr_lsp_interp_coef+1)); + } + ptr_lsp_interp_coef += 2; + + tmp = j*(LPC_SHB_ORDER+1); + /* convert from lsp to lsf */ + lsp2lsf( lsp_temp, lpc_shb_sf+tmp, LPC_SHB_ORDER, 1.0f ); + /* convert lsf to lpc for SHB synthesis */ + lsp2a( lpc_shb_sf+tmp, lpc_shb_sf+tmp, LPC_SHB_ORDER ); + lpc_shb_sf[j*(LPC_SHB_ORDER+1)] = 1.0f; + } + + /* -------- Calculate the SHB Energy -------- */ + shb_ener_sf = 0.003125f * sum2_f( shb_frame + L_SHB_LAHEAD, L_FRAME16k ); + Quant_shb_ener_sf( st, &shb_ener_sf ); + + /* -------- calculate the residuals using the FOUR subframe LPCs -------- */ + + set_f( shb_res, 0, L_FRAME16k ); + residu( lpc_shb_sf, LPC_SHB_ORDER, shb_frame + L_SHB_LAHEAD, shb_res, 80 ); + residu( lpc_shb_sf + (LPC_SHB_ORDER+1), LPC_SHB_ORDER, shb_frame + L_SHB_LAHEAD + 80, shb_res + 80, 80 ); + residu( lpc_shb_sf + 2*(LPC_SHB_ORDER+1), LPC_SHB_ORDER, shb_frame + L_SHB_LAHEAD + 160, shb_res + 160, 80 ); + residu( lpc_shb_sf + 3*(LPC_SHB_ORDER+1), LPC_SHB_ORDER, shb_frame + L_SHB_LAHEAD + 240, shb_res + 240, 80 ); + + set_f( shb_res_gshape, 0, NB_SUBFR16k ); + for( i = 0; i < NB_SUBFR16k; i++ ) + { + shb_res_gshape[i] = sum2_f( shb_res+i*64, 64 ); + } + + maximum(shb_res_gshape, NB_SUBFR16k, &normFac); + normFac = (float)1.0f/(0.0001f + normFac); + for( i = 0; i < NB_SUBFR16k; i++ ) + { + shb_res_gshape[i] = sqrt(shb_res_gshape[i]*normFac); + } + + Quant_shb_res_gshape(st, shb_res_gshape); + } + + /* Save the SWB LSP values from current frame for interpolation */ + mvr2r( lsp_shb_2, st->swb_lsp_prev_interp, LPC_SHB_ORDER ); + + + + /* For 13.2 and 16.4kbps, convert LSPs back into LP coeffs */ + /* convert from lsp to lsf */ + lsp2lsf( lsp_temp, lpc_shb, LPC_SHB_ORDER, 1.0f ); + /* convert lsf to lpc for SHB synthesis */ + lsp2a( lpc_shb, lpc_shb, LPC_SHB_ORDER ); + lpc_shb[0] = 1.0f; + + /* Save the SWB LSP values from current frame for interpolation */ + mvr2r( lsp_shb_2, st->swb_lsp_prev_interp, LPC_SHB_ORDER ); + mvr2r( st->state_syn_shbexc, shaped_shb_excitation, L_SHB_LAHEAD ); + + /* Determine formant PF strength */ + formant_fac = swb_formant_fac( lpc_shb[1], &st->tilt_mem ); + + vf_ind = 20; + GenShapedSHBExcitation( shaped_shb_excitation + L_SHB_LAHEAD, lpc_shb, White_exc16k, st->mem_csfilt, + st->mem_genSHBexc_filt_down_shb, st->state_lpc_syn, coder_type, bwe_exc_extended, st->bwe_seed, + vf_modified, st->extl, &(st->tbe_demph), &(st->tbe_premph), lpc_shb_sf, &shb_ener_sf, shb_res_gshape, + shb_res, &vf_ind, formant_fac, st->fb_state_lpc_syn,&(st->fb_tbe_demph), st->total_brate, 0 ); + + if( st->total_brate == ACELP_24k40 || st->total_brate == ACELP_32k ) + { + if(st->codec_mode == MODE2) + st->idx_mixFac = vf_ind; + else + push_indice( st, IND_SHB_VF, vf_ind, NUM_BITS_SHB_VF); + } + + for( i=0; imem_stp_swb, + st->ptr_mem_stp_swb, &(st->gain_prec_swb), st->mem_zero_swb, formant_fac ); + } + + mvr2r( shaped_shb_excitationTemp, &shaped_shb_excitation[L_SHB_LAHEAD], L_FRAME16k ); + + prev_pow = sum2_f( shaped_shb_excitation, L_SHB_LAHEAD + 10 ); + curr_pow = sum2_f( shaped_shb_excitation + L_SHB_LAHEAD + 10, L_SHB_LAHEAD + 10 ); + + if( voice_factors[0] > 0.75f ) + { + curr_pow *= 0.25; + } + + if( prev_pow == 0 ) + { + scale = 0; + } + else + { + scale = sqrt( curr_pow/ prev_pow ); + } + for( i=0; istate_syn_shbexc, L_SHB_LAHEAD ); + /* Estimate the gain-shape parameter */ + EstimateSHBGainShape( SHB_OVERLAP_LEN, shb_frame, shaped_shb_excitation, GainShape, subwin_shb ); + + /* Gain shape BWS/high band low energy fix */ + if( st->cldfbHBLT < 1.0f ) + { + /* 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]; + } + } + /* Gain frame adjustment factor */ + temp_swb_fac = (float)log( (GainShape[0]+0.00001f) / (st->prev_swb_GainShape+0.0001f) ); + feedback = temp_swb_fac * temp_swb_fac ; + for (i = 1; i < NUM_SHB_SUBGAINS; i++) + { + temp_swb_fac = (float)log( (GainShape[i]+0.00001f) / (GainShape[i-1]+0.0001f) ); + feedback += (temp_swb_fac * temp_swb_fac); + } + feedback = 0.4f / (1 + 0.5f * feedback); + + if( frGainAttenuate == 1 || ( sum_f(voicing, 3) > 2.4f && sum_f(voice_factors, 4) > 0.8f ) ) + { + temp_swb_fac = st->prev_swb_GainShape; + for( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + GainShape[i] = (1 - feedback) * GainShape[i] + feedback * temp_swb_fac; + temp_swb_fac = GainShape[i]; + } + } + st->prev_swb_GainShape = GainShape[3]; + + /* Compute the power of gains away from the peak gain prior to quantization */ + p2m_in = pow_off_pk(GainShape, NUM_SHB_SUBGAINS, 1); + + /* Quantization of the gain shape parameter */ + QuantizeSHBsubgains( st, GainShape, st->extl ); + + /* Compute the power of gains away from the peak gain after quantization */ + p2m_out = pow_off_pk(GainShape, NUM_SHB_SUBFR, 4); + + /* Estimate the gain parameter */ + EstimateSHBFrameGain( SHB_OVERLAP_LEN, shb_frame, shaped_shb_excitation, GainShape, &GainFrame, window_shb, subwin_shb ); + + if( st->tec_tfa == 1 ) + { + tfaCalcEnv( shb_frame, st->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( p2m_out > 2.0f * p2m_in ) + { + temp = 0.f; + if(p2m_in >= 0 && p2m_out > 0) + { + temp = sqrt((2.0f * p2m_in)/p2m_out); + } + GainFrame *= temp; + } + + if( frGainSmoothEn == 1 && st->prev_gainFr_SHB < GainFrame ) + { + GainFrame = 0.5f * (st->prev_gainFr_SHB + GainFrame); + } + + if( frGainAttenuate == 1 && MA_lsp_shb_spacing <= 0.0024f ) + { + GainFrame = (float)pow( GainFrame, 0.8f ); + } + else if( st->prev_frGainAtten == 1 && GainFrame > 3.0f * st->prev_gainFr_SHB ) + { + GainFrame *= (0.8f + 0.5f*feedback); + } + st->prev_frGainAtten = frGainAttenuate; + + st->prev_gainFr_SHB = GainFrame; + + /* Gain attenuation when the SWB LSF quantization error is larger than a threshold */ + sd_uq_q = (sd_uq_q/0.0025f); + if( st->L_frame == L_FRAME ) + { + sd_uq_q = 1 - 0.2f* (sd_uq_q * sd_uq_q); + } + else + { + sd_uq_q = 1 - 0.1f* (sd_uq_q * sd_uq_q); + } + + sd_uq_q = max(min(sd_uq_q, 1.0f), 0.5f); + + pitBufAvg = 0.0025f * sum_f(pitch_buf, 4); + voicingBufAvg = (sum_f(voice_factors, 4) > 0.6f) ? 0.333f : 0.1667f; + voicingBufAvg = voicingBufAvg * sum_f(voicing, 3); + + if(voicingBufAvg <= 0.0f && (sd_uq_q*pitBufAvg != 0)) + { + voicingBufAvg = sd_uq_q*pitBufAvg/1.001f; + } + else if(voicingBufAvg <= 0.0f) + { + voicingBufAvg = 1.0f; + } + + /* Controlled gain evolution in SWB for stronger voiced segments */ + GainFrame *= max(min((float)(sd_uq_q*pitBufAvg/voicingBufAvg), 1.0f), 0.6f); + if( st->L_frame == L_FRAME16k || st->rf_mode == 1 ) + { + /* Compensate for energy increase mismatch due to memory-less synthesis*/ + GainFrame *= 0.85f; + } + + /* Quantization of the frame gain parameter */ + QuantizeSHBframegain( st, &GainFrame, st->extl, 0, &st->RF_bwe_gainFr_ind ); + + /* Adjust the subframe and frame gain of the synthesized SHB signal */ + /* Scale the shaped excitation */ + + + if( st->extl == FB_TBE) + { + for( i=0; i a[j]) + { + j = i; + } + } + + sum -= a[j] * a[j]; + + return (sum); +} + + +/*-------------------------------------------------------------------* + * EstimateSHBGainShape() + * + * Estimate temporal gain parameters + *-------------------------------------------------------------------*/ + +static void EstimateSHBGainShape( + const short length, /* i : SHB overlap length */ + const float *oriSHB, /* i : target original SHB frame */ + const float *synSHB, /* i : shaped SHB excitation */ + float *subgain, /* o : estimate of gain shape */ + const float *subwin /* i : SHB subframe window */ +) +{ + const short *skip; + short i, k; + float sum_gain, oriNrg, synNrg, sig; + short num_join, num_gains, join_length; + + float normFact; + + num_join = NUM_SHB_SUBFR/NUM_SHB_SUBGAINS; + num_gains = NUM_SHB_SUBGAINS; + skip = skip_bands_SWB_TBE; + + if( length == SHB_OVERLAP_LEN/2 ) + { + num_gains = NUM_SHB_SUBFR/4; + skip = skip_bands_WB_TBE; + } + + /* calculate and normalize the subgain */ + sum_gain = (float)1e-10; + oriNrg = 0.0f; + synNrg = 0.0f; + + if( length == SHB_OVERLAP_LEN/2 ) + { + for( i=0; i MAX_LSF/2) + { + offset = lsf_map[0]; + scale = (MAX_LSF - m)/m; + for (i = 0; i < NUM_MAP_LSF; i++) + { + lsf_map[i] = (lsf_map[i] - offset)*scale + offset; + } + } + + last_q_lsf = lsf_q[NUM_Q_LSF - 1]; + scale = MAX_LSF - last_q_lsf; + + for (i = 0; i < NUM_LSF_GRIDS; i++) + { + for (j = 0; j < NUM_MAP_LSF; j++) + { + grid[i][j] = lsf_grid[i][j]*scale + last_q_lsf; + } + } + + D_best = QUANT_DIST_INIT; + for (i = 0; i < NUM_LSF_GRIDS; i++) + { + D = EPSILON; + for (j = 0; j < NUM_MAP_LSF; j++) + { + lsf_t[j] = (1 - grid_smoothing[j])*lsf_map[j] + grid_smoothing[j]*grid[i][j]; + D += (lsf_t[j] - lsf[NUM_Q_LSF + j])*(lsf_t[j] - lsf[NUM_Q_LSF + j]); + } + + if (D < D_best) + { + mvr2r(lsf_t, lsf_smooth, NUM_MAP_LSF); + D_best = D; + I_best = i; + } + } + + for (i = 0; i < NUM_MAP_LSF; i++) + { + lsf_q[NUM_Q_LSF + i] = lsf_smooth[i]; + } + + return I_best; +} + +/*-------------------------------------------------------------------* +* gainFrSmooth_En() +* +* Gain frame smoothing and attenuation control +*-------------------------------------------------------------------*/ +static void gainFrSmooth_En( + Encoder_State *st, + float *shb_frame, + const float *lpc_shb, + const float *lsp_shb, + float *MA_lsp_shb_spacing, + short *frGainAttenuate, + short *frGainSmoothEn +) +{ + float lsp_slow_evol_rate = 0, lsp_fast_evol_rate = 0, lsp_spacing = 0.5f; + float temp_shb_frame[L_FRAME16k+L_SHB_LAHEAD]; + int i; + + for( i = 0; i < LPC_SHB_ORDER; i++ ) + { + lsp_spacing = min(lsp_spacing, (float)( i == 0 ? lsp_shb[0] : (lsp_shb[i] - lsp_shb[i -1]))); + + /* estimate the mean square error in lsps from current frame to past frames */ + lsp_slow_evol_rate += (lsp_shb[i] - st->lsp_shb_slow_interpl[i]) * (lsp_shb[i] - st->lsp_shb_slow_interpl[i]); + lsp_fast_evol_rate += (lsp_shb[i] - st->lsp_shb_fast_interpl[i]) * (lsp_shb[i] - st->lsp_shb_fast_interpl[i]); + + /* update the slow and fast interpolation lsps for next frame */ + st->lsp_shb_slow_interpl[i] = 0.7f * st->lsp_shb_slow_interpl[i] + 0.3f * lsp_shb[i]; + st->lsp_shb_fast_interpl[i] = 0.3f * st->lsp_shb_fast_interpl[i] + 0.7f * lsp_shb[i]; + } + + if( st->last_extl != SWB_TBE && st->last_extl != FB_TBE && lsp_spacing < 0.008f ) + { + st->lsp_shb_spacing[0] = lsp_spacing; + st->lsp_shb_spacing[1] = lsp_spacing; + st->lsp_shb_spacing[2] = lsp_spacing; + st->prev_frGainAtten = 1; + } + + *MA_lsp_shb_spacing = 0.1f*st->lsp_shb_spacing[0] + 0.2f*st->lsp_shb_spacing[1] + 0.3f*st->lsp_shb_spacing[2] + 0.4f*lsp_spacing; + + st->lsp_shb_spacing[0] = st->lsp_shb_spacing[1]; + st->lsp_shb_spacing[1] = st->lsp_shb_spacing[2]; + st->lsp_shb_spacing[2] = lsp_spacing; + + *frGainAttenuate = 0; + *frGainSmoothEn = 0; + + if( (lsp_spacing < 0.008f && (*MA_lsp_shb_spacing < 0.005f || st->prev_frGainAtten == 1)) || lsp_spacing <= 0.0032f ) + { + *frGainAttenuate = 1; + mvr2r(shb_frame, temp_shb_frame, L_FRAME16k+L_SHB_LAHEAD); + + fir( temp_shb_frame, lpc_shb, shb_frame, st->shb_inv_filt_mem, L_FRAME16k+L_SHB_LAHEAD, LPC_SHB_ORDER, 1 ); + + if( lsp_slow_evol_rate < 0.001f && lsp_fast_evol_rate < 0.001f ) + { + *frGainSmoothEn = 1; + } + } +} + +/*-------------------------------------------------------------------* + * Quant_BWE_LSF() + * + * Quantize super highband spectral envolope + *-------------------------------------------------------------------*/ + +static void Quant_BWE_LSF( + Encoder_State *st, /* i/o: encoder state structure */ + const float lsf_shb[], /* i : unquanitzed LSFs */ + float Q_lsfs[] /* o : quanitzed LSFs */ +) +{ + float lsf[LPC_SHB_ORDER]; + float lsf_q[LPC_SHB_ORDER]; + short lsf_idx[NUM_Q_LSF]; + short i; + short m_idx; + float m; + short grid_idx; + + for (i = 0; i < LPC_SHB_ORDER; i++) + { + lsf[i] = 0.5f - lsf_shb[LPC_SHB_ORDER - 1 - i]; + } + + Quant_lower_LSF( lsf, lsf_q, lsf_idx ); + + for (i = 0; i < NUM_Q_LSF; i++) + { + if(st->codec_mode == MODE2) + { + st->lsf_idx[i] = lsf_idx[i]; + } + else + { + push_indice( st, IND_SHB_LSF, lsf_idx[i], lsf_q_num_bits[i] ); + } + } + + m_idx = Quant_mirror_point(lsf, lsf_q, &m); + + if(st->codec_mode == MODE2) + st->m_idx = m_idx; + else + push_indice( st,IND_SHB_MIRROR, m_idx, MIRROR_POINT_BITS); + + grid_idx = Find_LSF_grid(lsf, lsf_q, m); + + if(st->codec_mode == MODE2) + st->grid_idx = grid_idx; + else + push_indice( st,IND_SHB_GRID, grid_idx, NUM_LSF_GRID_BITS); + + for (i = 0; i < LPC_SHB_ORDER; i++) + { + Q_lsfs[i] = 0.5f - lsf_q[LPC_SHB_ORDER - 1 - i]; + } + + return; +} + +/*-------------------------------------------------------------------* + * closest_centroid() + * + * Determine a set of closest VQ centroids for a given input + *-------------------------------------------------------------------*/ + +static short closest_centroid( + const float *data, /* i : input data */ + const float *weights, /* i : weights */ + const float *quantizer, /* i : quantizer table */ + const short centroids, /* i : number of centroids */ + const short length) /* i : dimension of quantiser */ +{ + short i,j, index; + float tmp, werr, best_werr; + + index = 0; + best_werr = 1.0E20f; + + for( i=0; i best_werr) + { + break; + } + } + + if( werr < best_werr ) + { + best_werr = werr; + index = i; + } + } + + return index; +} + +/*-------------------------------------------------------------------* + * QuantizeSHBsubgains() + * + * Quantize super highband temporal gains + *-------------------------------------------------------------------*/ + +static void QuantizeSHBsubgains( + Encoder_State *st, /* i/o: encoder state structure */ + float subgains[], /* i/o: super highband temporal gains */ + const short extl /* i : extension layer */ +) +{ + short i, idxSubGain; + float Unit_weights10[NUM_SHB_SUBFR]; + + if( extl == WB_TBE ) + { + set_f( Unit_weights10, 1.0f, (short)NUM_SHB_SUBFR/4 ); + + for( i=0; i=0; i-- ) + { + subgains[i] = subgains[i/2]; + } + } + else + { + for(i = 0; i < NUM_SHB_SUBGAINS; i++) + { + subgains[i] = (float) log10(subgains[i] + 0.001f); + } + + idxSubGain = (short)vquant(subgains, 0, subgains, SHBCB_SubGain5bit, NUM_SHB_SUBGAINS, 1<= 0; i--) + { + subgains[i] = subgains[i*NUM_SHB_SUBGAINS/NUM_SHB_SUBFR]; + } + + if( st->codec_mode == MODE2 ) + { + st->idxSubGains = idxSubGain; + } + else + { + push_indice(st, IND_SHB_SUBGAIN, idxSubGain, NUM_BITS_SHB_SUBGAINS); + } + } + + return; +} + +/*-------------------------------------------------------------------* + * Quant_shb_ener_sf() + * + * Quantize SHB subframe energies + *-------------------------------------------------------------------*/ + +static void Quant_shb_ener_sf( + Encoder_State *st, /* i/o: encoder state structure */ + float *shb_ener_sf /* i/o: super highband subframe energies */ +) +{ + short idxSubEner; + + float temp_shb_ener_sf, sum; + + sum = *shb_ener_sf; + *shb_ener_sf = (float)log10(sum); + + temp_shb_ener_sf = 0; + idxSubEner = usquant(*shb_ener_sf, &temp_shb_ener_sf, 0, 0.042f, 1<codec_mode == MODE2) + st->idx_shb_fr_gain = idxSubEner; + else + push_indice( st, IND_SHB_ENER_SF, idxSubEner, NUM_BITS_SHB_ENER_SF); + + return; +} + +/*-------------------------------------------------------------------* +* Quant_shb_res_gshape() +* +* Quantize SHB gain shapes in residual domain +*-------------------------------------------------------------------*/ + +static void Quant_shb_res_gshape( + Encoder_State *st, /* i/o: encoder state structure */ + float shb_res_gshape[] /* i/o: super highband gain shapes */ +) +{ + short i, idxSubGain[NB_SUBFR16k]; + + for(i = 0; i < NB_SUBFR16k; i++) + { + idxSubGain[i] = usquant(shb_res_gshape[i], &shb_res_gshape[i], 0.125, 0.125f, 1<codec_mode == MODE2) + st->idx_res_gs[i] = idxSubGain[i]; + else + push_indice( st, IND_SHB_RES_GS1+i, idxSubGain[i], NUM_BITS_SHB_RES_GS); + } +} + +/*-------------------------------------------------------------------* + * QuantizeSHBframegains() + * + * Quantize super highband frame gain + *-------------------------------------------------------------------*/ + +static void QuantizeSHBframegain( + Encoder_State *st, /* i/o: encoder state structure */ + float *GainFrame, /* i/o: Gain */ + const short extl, /* i : extension layer */ + long extl_brate /* i : extension layer bitrate */ + ,short *rf_gainFrame_ind +) +{ + short idxFrameGain; + float Q_GainFrame; + float Unit_weights1 = 1.0f; + + float GainFrameLog; + + if ( extl == WB_TBE ) + { + determine_gain_weights( GainFrame, &(Unit_weights1), 1 ); + + if( extl_brate == WB_TBE_0k35 ) + { + singlevectortest_gain( GainFrame, 1, 1< *GainFrame * 1.06f && idxFrameGain > 0 ) /* 1.06 = +0.5 dB */ + { + idxFrameGain--; + Q_GainFrame = SHBCB_FrameGain16[idxFrameGain]; + } + + st->gFrame_WB = idxFrameGain; + *rf_gainFrame_ind = idxFrameGain; + } + else + { + singlevectortest_gain( GainFrame, 1, 1< GainFrameLog + 0.495*SHB_GAIN_QDELTA && idxFrameGain != 0) + { + idxFrameGain = idxFrameGain - 1; + Q_GainFrame = idxFrameGain*SHB_GAIN_QDELTA + SHB_GAIN_QLOW; + } + + Q_GainFrame = (float) pow(10.0, Q_GainFrame ); + if( st->codec_mode == MODE2 ) + { + st->idxFrameGain = idxFrameGain; + } + else + { + push_indice( st, IND_SHB_FRAMEGAIN, idxFrameGain, NUM_BITS_SHB_FRAMEGAIN ); + } + *rf_gainFrame_ind = idxFrameGain; + } + if( st->rf_mode ) + { + /*Currently intended for SWB only. Modify for WB is needed later!*/ + if( st->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 <= 1.25 ) /* [0 to 1.25] range --> 0.5*/ + *rf_gainFrame_ind = 0; + else if ( *GainFrame <= 3 ) /* (1.25 to 3] --> 2 */ + *rf_gainFrame_ind = 1; + else if ( *GainFrame <= 6 ) /* (3 to 6] --> 4 */ + *rf_gainFrame_ind = 2; + else /* (6 to Inf) --> 8 */ + *rf_gainFrame_ind = 3; + } + } + + *GainFrame = Q_GainFrame; + + return; +} + + + +/*-------------------------------------------------------------------* + * determine_gain_weights() + * + * Determine weights for gain quantization + *-------------------------------------------------------------------*/ + +static void determine_gain_weights ( + const float *gain, /* i : Gain parameter */ + float *weights, /* o : gain weights */ + const short dims /* i : number of gains */ +) +{ + short j; + + for( j = 0; j < dims; j++ ) + { + if( gain[j] > 1e-6 ) + { + weights[j] = (float)(pow (fabs (gain[j]), -0.9f)); + } + else + { + weights[j] = 501.187233628f; + } + } + + return; +} + +/*-------------------------------------------------------------------* + * singlevectortest_gain() + * + * VQ for coding superhigh band gain + *-------------------------------------------------------------------*/ + +static void singlevectortest_gain ( + const float *inp, /* i : input gain vector */ + const short dimen, /* i : dimension of the input vector */ + const short cb_size, /* i : codebook size */ + short *index, /* o : quanitzation index */ + const float *weight, /* i : Weights for the quanitzation */ + float *recon, /* o : Reconstruction */ + const float *codebook /* i : Codebook */ +) +{ + short k, interNum, flag; + float meanU, meanQ; + short least[4]; + + interNum = 4; + + return_M_Least( inp, dimen, codebook, cb_size, weight, interNum, least ); + + meanU = sum_f( inp, dimen ); + mvr2r( codebook + dimen*least[0], recon, dimen ); + + index[0] = least[0]; + flag = 0; + for( k = 0; k < interNum; k++ ) + { + if( flag == 0 ) + { + meanQ = sum_f( codebook + dimen*least[k], dimen ); + + if( meanQ <= 1.1 * meanU ) + { + flag = 1; + mvr2r( codebook + dimen*least[k], recon, dimen ); + index[0] = least[k]; + } + } + } + + return; +} + +static void return_M_Least( + const float *inp, /* i: input */ + const short n_cols, /* i: vector size */ + const float *codebook, /* i: codebook */ + const short num_grp, /* i: number of centroids */ + const float *weight, /* i: gain weights */ + const short interNum, /* i: number on short list prior to 2nd stage search*/ + short *least /* o: return value */ +) +{ + short i, k; + float distance[1024], mindist, tmp; + + mindist = QUANT_DIST_INIT; + for( i = 0; i < num_grp; i++ ) + { + distance[i] = 0; + for( k = 0; k < n_cols; k++ ) + { + tmp = inp[k] - codebook[n_cols*i + k]; + distance[i] += weight[k] * tmp * tmp; + } + + if( distance[i] < mindist ) + { + mindist = distance[i]; + least[0] = i; + } + } + + distance[least[0]] = QUANT_DIST_INIT; + + for( k = 1; k < interNum; k++ ) + { + mindist = QUANT_DIST_INIT; + for( i = 0; i < num_grp; i++ ) + { + if( distance[i] < mindist ) + { + mindist = distance[i]; + least[k] = i; + } + } + + distance[least[k]] = QUANT_DIST_INIT; + } + + return; +} + + +/*-------------------------------------------------------------------* + * fb_tbe_reset_enc() + * + * Reset the extra parameters needed for FB TBE encoding + *-------------------------------------------------------------------*/ + +void fb_tbe_reset_enc( + float elliptic_bpf_2_48k_mem[][4], + float *prev_fb_energy +) +{ + set_f( elliptic_bpf_2_48k_mem[0], 0.0f, 4 ); + set_f( elliptic_bpf_2_48k_mem[1], 0.0f, 4 ); + set_f( elliptic_bpf_2_48k_mem[2], 0.0f, 4 ); + set_f( elliptic_bpf_2_48k_mem[3], 0.0f, 4 ); + *prev_fb_energy = 0.0f; + + return; +} + +/*-------------------------------------------------------------------* + * fb_tbe_enc() + * + * FB TBE encoder, 14(resp. 15.5) - 20 kHz band encoding module + *-------------------------------------------------------------------*/ + +void fb_tbe_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const float new_input[], /* i : input speech at 48 kHz sample rate */ + const float fb_exc[] /* i : FB excitation from the SWB part */ +) +{ + float fb_exc_energy, ratio, temp2; + float tmp_vec[L_FRAME48k]; + short idxGain; + float input_fhb[L_FRAME48k]; + short Sample_Delay_HP; + + elliptic_bpf_48k_generic( new_input, tmp_vec, st->elliptic_bpf_2_48k_mem, full_band_bpf_2 ); + + Sample_Delay_HP = NS2SA(48000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS) - L_FRAME48k/2 ; + + if( st->last_extl != FB_TBE ) + { + set_f( st->old_input_fhb, 0.0f, Sample_Delay_HP ); + set_f(tmp_vec, 0.0f, 320); + } + + mvr2r( st->old_input_fhb, input_fhb, Sample_Delay_HP ); + mvr2r( tmp_vec, input_fhb + Sample_Delay_HP, L_FRAME48k-Sample_Delay_HP ); + mvr2r( tmp_vec + L_FRAME48k - Sample_Delay_HP, st->old_input_fhb, Sample_Delay_HP ); + + /* Compute the energy of the Fullband component over 4kHz (16kHz to 20kHz) */ + temp2 = sum2_f( input_fhb, L_FRAME48k/2 ) + st->prev_fb_energy; + st->prev_fb_energy = sum2_f( input_fhb + L_FRAME48k/2, L_FRAME48k/2 ); + fb_exc_energy = sum2_f( fb_exc, L_FRAME16k ) + EPSILON; + ratio = (float) sqrt( temp2 / fb_exc_energy ); + idxGain = (short)( log2_f ((float)ratio) + 0.5f ); + idxGain = max( 0, min(15,idxGain) ); + ratio = (float)(1 << idxGain); + + if( st->codec_mode == MODE2 ) + { + st->idxGain = idxGain; + } + else + { + push_indice( st, IND_FB_SLOPE, idxGain, 4 ); + } + + + return; +} + + +/*---------------------------------------------------------------------* + * tbe_write_bitstream() + * + * Write TBE bitstream. + *---------------------------------------------------------------------*/ +void tbe_write_bitstream( + Encoder_State *st +) +{ + short i; + + if ( (st->rf_mode || st->total_brate == ACELP_9k60) && st->bwidth == WB) + { + /* WB LSF */ + push_next_indice( st, st->lsf_WB, NUM_BITS_LBR_WB_LSF ); + + /* WB frame */ + push_next_indice( st, st->gFrame_WB, NUM_BITS_SHB_FrameGain_LBR_WB ); + } + else if (st->total_brate >= ACELP_9k60 && st->total_brate <= ACELP_32k && (st->bwidth == SWB || st->bwidth == FB)) + { + /* LSF coefficients */ + + if(st->rf_mode || st->total_brate == ACELP_9k60) + { + push_next_indice( st, st->lsf_idx[0], 8 ); + } + else + { + for (i = 0; i < NUM_Q_LSF; i++) + { + push_next_indice( st, st->lsf_idx[i], lsf_q_num_bits[i] ); + } + + /* LSF mirror points */ + push_next_indice( st, st->m_idx, MIRROR_POINT_BITS ); + + /* LSF grid points */ + push_next_indice( st, st->grid_idx, NUM_LSF_GRID_BITS ); + } + + /* Gain shape */ + push_next_indice( st, st->idxSubGains, NUM_BITS_SHB_SUBGAINS ); + + /* frame gain */ + push_next_indice( st, st->idxFrameGain, NUM_BITS_SHB_FRAMEGAIN ); + + if (st->total_brate >= ACELP_24k40) + { + /* sub frame energy*/ + push_next_indice( st, st->idx_shb_fr_gain, NUM_BITS_SHB_ENER_SF ); + + /* gain shapes residual */ + for (i = 0; i < NB_SUBFR16k; i++) + { + push_next_indice( st, st->idx_res_gs[i], NUM_BITS_SHB_RES_GS ); + } + + /* voicing factor */ + push_next_indice( st, st->idx_mixFac, NUM_BITS_SHB_VF ); + } + + if( st->tec_tfa == 1 ) + { + push_next_indice( st, st->tec_flag, BITS_TEC ); + push_next_indice( st, st->tfa_flag, BITS_TFA ); + } + } + + if (st->bwidth == FB) + { + push_next_indice( st, st->idxGain, 4 ); + } +} + + + +void TBEreset_enc( + Encoder_State *st, /* i/o: encoder state structure */ + short bandwidth /* i : bandwidth mode */ +) +{ + if(st->last_core != ACELP_CORE) + { + set_f( st->old_bwe_exc, 0.0f, PIT16k_MAX * 2 ); + st->bwe_non_lin_prev_scale = 0.f; + } + + if( bandwidth == WB ) + { + wb_tbe_extras_reset( st->mem_genSHBexc_filt_down_wb2, st->mem_genSHBexc_filt_down_wb3 ); + set_f( st->mem_genSHBexc_filt_down_shb, 0, 7 ); + set_f( st->state_lpc_syn, 0, 10 ); + set_f( st->state_syn_shbexc, 0, L_SHB_LAHEAD/4 ); + set_f( st->syn_overlap, 0, L_SHB_LAHEAD ); + set_f( st->mem_csfilt, 0, 2 ); + } + else if( bandwidth == SWB || bandwidth == FB ) + { + set_f( st->state_ana_filt_shb, 0.0f, (2*ALLPASSSECTIONS_STEEP+1) ); + + swb_tbe_reset( st->mem_csfilt, st->mem_genSHBexc_filt_down_shb, st->state_lpc_syn, + st->syn_overlap, st->state_syn_shbexc, &(st->tbe_demph), &(st->tbe_premph), + st->mem_stp_swb, &(st->gain_prec_swb) ); + + + if( bandwidth == FB ) + { + set_f(st->fb_state_lpc_syn, 0, LPC_SHB_ORDER); + st->fb_tbe_demph = 0; + fb_tbe_reset_enc( st->elliptic_bpf_2_48k_mem, &st->prev_fb_energy ); + } + + } + + return; +} diff --git a/lib_enc/tcq_core_enc.c b/lib_enc/tcq_core_enc.c new file mode 100644 index 000000000..877e8ea0d --- /dev/null +++ b/lib_enc/tcq_core_enc.c @@ -0,0 +1,439 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include "options.h" +#include "rom_com.h" +#include "prot.h" +#include "cnst.h" +#include "basop_util.h" +#include "basop_proto_func.h" + + +/*---------------------------------------------------------------------* + * tcq_core_LR_enc() + * + * Main Generic Audio Encoder Routine for LR-MDCT + *---------------------------------------------------------------------*/ + +void tcq_core_LR_enc( + Encoder_State *st, + int inp_vector[], + const float coefs_norm[], + float coefs_quant[], + const short bit_budget, /* number of bits */ + const short BANDS, + const short *sfm_start, + const short *sfm_end, + const short *sfmsize, + Word32 *Rk_fx, + int *npulses, + short *k_sort, + const short *p2a_flags, + const short p2a_bands, + const short *last_bitalloc, + const short input_frame, + const short adjustFlag, + const short is_transient +) +{ + short i, j, k, size, nb_bytes; + int nzp; + + float gain; + float step_scale[NB_SFM]; + + short pos_index[NB_SFM]; + float Rk_sort[NB_SFM]; + int USQ_TCQ[NB_SFM]; /* TCQ is selected by default*/ + float coefs_norm_dec[L_FRAME32k]; /* New output buffer (TCQ+USQ)*/ + + float pulses, crosscorr, selfcorr; + int savedstates[TCQ_MAX_BAND_SIZE]; + ARCODEC arenc, *parenc; + BITSTREAM bs, *pbs; + short k_num[2]; + + int flag_wbnb = 0; + int lsbtcq_bits = TCQ_AMP; + int tcq_arbits = 2; + int nzbands = 0; + short bcount = 0; + float abuffer[560]; + float mbuffer[560]; + float sbuffer[560]; + short dpath[280]; + /*Word32 Rk_fx[NB_SFM];*/ /* Q16 */ + Word32 Rk_sort_fx[NB_SFM]; /* Q16 */ + Word32 bsub_fx = 0; + Word32 est_frame_bits_fx; + + Word16 nzb = 0; + Word32 delta_fx; + Word32 surplus_fx; + Word32 bit_surplus_fx[2]; + + Word32 leftbits = 0; + Word32 sepbits = 0; + Word32 divider = 0; + + set_s(dpath, 0, 280); + set_f(abuffer, 0.f, 560); + set_f(mbuffer, 0.f, 560); + + set_f(sbuffer, FLT_MAX, 560); + + /* initialization */ + set_f( Rk_sort, 0.f, NB_SFM ); + set_i( USQ_TCQ, 0, NB_SFM ); + set_f( coefs_norm_dec, 0.f, L_FRAME32k ); + InitLSBTCQ(&bcount); + + if( input_frame <= L_FRAME16k && adjustFlag == 0 && is_transient == 0 ) + { + flag_wbnb = 1; + lsbtcq_bits = 0; + tcq_arbits = 0; + } + + parenc = &arenc; + pbs = &bs; + + pbs->curPos = 7; + pbs->numbits = 0; + pbs->numByte = 0; + memset(pbs->buf, 0, MAX_SIZEBUF_PBITSTREAM); + ar_encoder_start(parenc, pbs, bit_budget); + + /* TCQ Index initialize */ + memset( pos_index, 0, sizeof(short)*NB_SFM ); + + /* Bits distribution analysis */ + for( i = 0; i < BANDS; i++ ) + { + if ( L_sub(ar_div(Rk_fx[i], sfmsize[i]), 49152) >= 0 ) + { + /* USQ used for high importance bands*/ + USQ_TCQ[i] = 1; + } + else + { + /* TCQ used for usual bands */ + USQ_TCQ[i] = 0; + } + if( Rk_fx[i] > 0 ) + { + nzbands++; + } + } + + for( j = 0; j < BANDS; j++ ) + { + if( Rk_fx[j] > 0 ) + { + nzb++; + } + } + +#define WMC_TOOL_SKIP + 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] = 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); +#undef WMC_TOOL_SKIP + /* Quantize spectral band shapes using TCQ */ + /* Select ISC */ + set_f( coefs_quant, 0.0, sfm_end[BANDS-1]+1 ); + + mvr2r( coefs_norm, coefs_quant,sfm_end[BANDS-1]+1 ); + + delta_fx = 0; + est_frame_bits_fx = 0; + if( input_frame <= L_FRAME16k && adjustFlag == 0 && is_transient == 0 ) + { + surplus_fx = -131072; + bit_allocation_second_fx( Rk_fx, Rk_sort_fx, BANDS, sfmsize, k_sort, k_num, p2a_flags, p2a_bands, last_bitalloc, input_frame ); + + nzbands = 0; + for ( j = 0; j < BANDS; j++ ) + { + if( sub(j, k_num[0]) != 0 && sub(j, k_num[1]) != 0) + { + leftbits = L_add( leftbits, Rk_fx[k_sort[j]]); + if( Rk_fx[k_sort[j]] > 0 ) + { + nzbands = add(nzbands, 1); + } + } + else + { + sepbits = L_add( sepbits, Rk_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 */ + { + if( k != k_num[0] && k != k_num[1]) + { + if( Rk_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]]; + /* Determine scale step, ISC and TCQ quantizer */ + GetISCScale( &coefs_quant[sfm_start[k_sort[k]]], size, L_add( Rk_fx[k_sort[k]], delta_fx), + &coefs_norm_dec[ sfm_start[ k_sort[k]]], &step_scale[k_sort[k]], &surplus_fx, &pulses, savedstates, 0, &nzp, 0, 0, 0, 0 ); + leftbits = L_sub( leftbits, L_add( Rk_fx[k_sort[k]], delta_fx) ); + + npulses[ k_sort[k]] = (int)pulses; + + encode_position_ari_fx( parenc, &coefs_norm_dec[ sfm_start[ k_sort[k]]], size, &est_frame_bits_fx ); + encode_magnitude_tcq_fx( parenc, &coefs_norm_dec[ sfm_start[ k_sort[k]]], size, npulses[k_sort[k]], nzp, savedstates, &est_frame_bits_fx ); + encode_signs_fx( parenc, &coefs_norm_dec[ sfm_start[ k_sort[k]]], size, nzp, &est_frame_bits_fx ); + nzbands--; + + } + /* Have USQ coded band */ + else if( Rk_fx[k_sort[k]] > 0 && sub(USQ_TCQ[k_sort[k]], 1) == 0 ) + { + size = sfmsize[k_sort[k]]; + GetISCScale( &coefs_quant[ sfm_start[ k_sort[k]]], size, L_add( Rk_fx[k_sort[k]], delta_fx), + &coefs_norm_dec[ sfm_start[ k_sort[k]]], &step_scale[k_sort[k]], &surplus_fx, &pulses, savedstates, 1, &nzp, 0, 0, 0, 0 ); + leftbits = L_sub( leftbits, L_add( Rk_fx[k_sort[k]], delta_fx) ); + + npulses[ k_sort[ k]] = (int)pulses; + + encode_position_ari_fx( parenc, &coefs_norm_dec[sfm_start[k_sort[k]]], size, &est_frame_bits_fx ); + encode_magnitude_usq_fx( parenc, &coefs_norm_dec[sfm_start[k_sort[k]]], size, npulses[k_sort[k]], nzp, &est_frame_bits_fx ); + encode_signs_fx( parenc, &coefs_norm_dec[ sfm_start[ k_sort[ k]]], size, nzp, &est_frame_bits_fx ); + + nzbands--; + } + else /* Then have zero block */ + { + npulses[ k_sort[ k]] = 0; + size = sfmsize[k_sort[k]]; + } + +#define WMC_TOOL_SKIP + 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); + } + else + { + delta_fx = 0; + } +#undef WMC_TOOL_SKIP + } + } +#define WMC_TOOL_SKIP + if (( L_sub(surplus_fx,524288) > 0 && sub(input_frame,L_FRAME8k) == 0 ) || ( L_sub(surplus_fx,786432) > 0 && sub(input_frame,L_FRAME16k) == 0 )) + { + 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; + bit_surplus_fx[1] = 0; + } +#undef WMC_TOOL_SKIP + for( k = 0; k < BANDS; k++ ) + { + for( j = 0; j < 2; j++ ) + { + if( k == k_num[j] ) + { +#define WMC_TOOL_SKIP + Rk_fx[k_sort[k]] = L_add(Rk_fx[k_sort[k]],bit_surplus_fx[j]); + + if( Rk_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]]; + + /* Determine scale step, ISC and TCQ quantizer */ + GetISCScale( &coefs_quant[sfm_start[k_sort[k]]], size, Rk_fx[k_sort[k]], &coefs_norm_dec[ sfm_start[ k_sort[k]]], + &step_scale[k_sort[k]], &surplus_fx, &pulses, savedstates, 0, &nzp, 0, 0, 0, 0 ); + + npulses[ k_sort[k]] = pulses; + + encode_position_ari_fx( parenc, &coefs_norm_dec[ sfm_start[ k_sort[k]]], size, &est_frame_bits_fx ); + encode_magnitude_tcq_fx( parenc, &coefs_norm_dec[ sfm_start[ k_sort[k]]], size, npulses[k_sort[k]], nzp, savedstates, &est_frame_bits_fx ); + encode_signs_fx( parenc, &coefs_norm_dec[ sfm_start[ k_sort[k]]], size, nzp, &est_frame_bits_fx ); + } + /* Have USQ coded band */ + else if( Rk_fx[k_sort[k]] > 0 && sub(USQ_TCQ[k_sort[k]], 1) == 0 ) + { + size = sfmsize[k_sort[k]]; + + GetISCScale( &coefs_quant[ sfm_start[ k_sort[k]]], size, Rk_fx[k_sort[k]], &coefs_norm_dec[ sfm_start[ k_sort[k]]], + &step_scale[k_sort[k]], &surplus_fx, &pulses, savedstates, 1, &nzp, 0, 0, 0, 0 ); + + npulses[ k_sort[k]] = pulses; + + encode_position_ari_fx( parenc, &coefs_norm_dec[sfm_start[k_sort[k]]], size, &est_frame_bits_fx ); + encode_magnitude_usq_fx( parenc, &coefs_norm_dec[sfm_start[k_sort[k]]], size, npulses[k_sort[k]], nzp, &est_frame_bits_fx ); + encode_signs_fx( parenc, &coefs_norm_dec[ sfm_start[ k_sort[k]]], size, nzp, &est_frame_bits_fx ); + } + else /* Then have zero block */ + { + npulses[ k_sort[k]] = 0; + size = sfmsize[k_sort[k]]; + } +#undef WMC_TOOL_SKIP + } + } + } + } + else + { + surplus_fx = 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( Rk_fx[k_sort[k]] > 0 ) + { + size = sfmsize[k_sort[k]]; + GetISCScale( &coefs_quant[ sfm_start[ k_sort[k]]], size, L_add( Rk_fx[k_sort[k]], delta_fx), &coefs_norm_dec[ sfm_start[ k_sort[k]]], &step_scale[k_sort[k]], &surplus_fx, &pulses, savedstates, 1, &nzp, &bcount, abuffer, mbuffer, sbuffer); + + npulses[ k_sort[k]] = pulses; + encode_position_ari_fx(parenc, &coefs_norm_dec[sfm_start[k_sort[k]]], size, &est_frame_bits_fx); + encode_magnitude_usq_fx(parenc, &coefs_norm_dec[sfm_start[k_sort[k]]], size, npulses[k_sort[k]], nzp, &est_frame_bits_fx); + encode_signs_fx(parenc, &coefs_norm_dec[ sfm_start[ k_sort[k]]], size, nzp, &est_frame_bits_fx); + + /* nzbands--; */ + nzbands = sub(nzbands, 1); + } + else /* Then have zero block */ + { + npulses[ k_sort[k]] = 0; + size = sfmsize[k_sort[k]]; + } + + /* Surplus distribution */ + if( surplus_fx > 0 && nzbands > 0 ) + { + delta_fx = ar_div(surplus_fx, nzbands); + surplus_fx = L_sub(surplus_fx, delta_fx); + } + } + } + + TCQLSB( bcount, abuffer, mbuffer, sbuffer, dpath ); + + /* Save TCQ path to bitstream */ + SaveTCQdata( parenc, dpath, lsbtcq_bits ); + + /* Add tcq sequence to decoding buffer */ + InitLSBTCQ( &bcount ); + + ar_encoder_done( parenc ); + + /* Loop through non-zero blocks */ + if( !flag_wbnb ) + { + for( k = 0; k < BANDS; k++ ) + { + if( Rk_fx[k_sort[k]] > 0 ) + { + size = sfmsize[k_sort[k]]; + RestoreTCQ( &coefs_norm_dec[ sfm_start[ k_sort[k]]], size, &bcount, mbuffer ); + } + } + } + + nb_bytes = bit_budget >> 3; + j = bit_budget - (nb_bytes << 3); + for( i = 0; i < nb_bytes; i++ ) + { + push_indice(st, IND_HQ2_SUBBAND_TCQ, pbs->buf[i], 8); + } + if( j > 0 ) + { + push_indice(st, IND_HQ2_SUBBAND_TCQ, (pbs->buf[nb_bytes] >> (8 - j)), j); + } + + /* Clear decoding buffer */ + set_f( coefs_quant, 0.0, sfm_end[BANDS-1]+1 ); + /* New analysis of decoded frame */ + for( i = 0; i < BANDS; i++ ) + { + if( Rk_fx[ k_sort[i]] > 0 ) + { + gain = 0.0f; + + crosscorr = 0.0f; + selfcorr = EPSILON; + for( j = 0; j < sfmsize[k_sort[i]]; j++ ) + { + crosscorr += (coefs_norm[sfm_start[k_sort[i]]+j] * coefs_norm_dec[sfm_start[k_sort[i]]+j]); + selfcorr += (coefs_norm_dec[sfm_start[k_sort[i]]+j] * coefs_norm_dec[sfm_start[k_sort[i]]+j]); + } + + gain = crosscorr / selfcorr; + + if( gain == 0 ) + { + gain = 1e-10f; + } + + /* Use optimal gain */ + for( j = 0; j < sfmsize[k_sort[i]]; j++ ) + { + inp_vector[sfm_start[k_sort[i]]+j] = round_f( ((1.0f/QTCQ)*coefs_norm_dec[sfm_start[k_sort[i]]+j]) ); + coefs_quant[sfm_start[k_sort[i]]+j] = gain*coefs_norm_dec[sfm_start[k_sort[i]]+j]; + } + } + } + + + return; + +} diff --git a/lib_enc/tcx_ltp_enc.c b/lib_enc/tcx_ltp_enc.c new file mode 100644 index 000000000..55a99d4c8 --- /dev/null +++ b/lib_enc/tcx_ltp_enc.c @@ -0,0 +1,421 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "prot.h" +#include "rom_enc.h" +#include "rom_com.h" + + + + +static float interpolate_corr( /* o : interpolated value */ + const float *x, /* i : input vector */ + const short frac, /* i : fraction of lag */ + const short frac_max /* i : max fraction */ +) +{ + short i; + float s; + const float *c1, *c2, *x1, *x2, *win; + + + if ( frac_max == 6 ) + { + win = E_ROM_inter6_1; + } + else + { + win = E_ROM_inter4_1; + } + + x1 = &x[0]; + x2 = &x[1]; + c1 = &win[frac]; + c2 = &win[frac_max-frac]; + s = 0.0f; + for(i=0; i<4; i++, c1+=frac_max, c2+=frac_max) + { + s+= (*x1--) * (*c1) + (*x2++) * (*c2); + } + + + return s; +} + +static void tcx_ltp_pitch_search( + int pitch_ol, + int *pitch_int, + int *pitch_fr, + int *index, + float *norm_corr, + const short len, + float *wsp, + int pitmin, + int pitfr1, + int pitfr2, + int pitmax, + int pitres +) +{ + short i, t, t0, t1, step, fraction, t0_min, t0_max, t_min, t_max, delta; + float temp, cor_max, cor[256], *pt_cor; + + + if ( pitres == 6 ) + { + delta = 8; + } + else + { + delta = 16; + } + + t0_min = (short)pitch_ol - (delta>>1); + t0_max = (short)pitch_ol + (delta>>1) - 1; + + if( t0_min < pitmin ) + { + t0_min = pitmin; + t0_max = t0_min + delta - 1; + } + if( t0_max > pitmax ) + { + t0_max = pitmax; + t0_min = t0_max - delta + 1; + } + t_min = t0_min - L_INTERPOL1; + t_max = t0_max + L_INTERPOL1; + + pt_cor = cor; + for ( t=t_min; t<=t_max; t++ ) + { + *pt_cor++ = dotp( wsp, wsp-t, len ); + } + + pt_cor = cor + L_INTERPOL1; + cor_max = *pt_cor++; + t1 = t0_min; + for ( t=t0_min+1; t<=t0_max; t++ ) + { + if ( *pt_cor > cor_max ) + { + cor_max = *pt_cor; + t1 = t; + } + pt_cor++; + } + temp = dotp( wsp, wsp, len ) * dotp( wsp-t1, wsp-t1, len ); + *norm_corr = cor_max / (float)sqrt( temp + 0.1f ); + if ( t1 >= pitfr1 ) + { + *pitch_int = t1; + *pitch_fr = 0; + *index = t1 - pitfr1 + ((pitfr2-pitmin)*pitres) + ((pitfr1-pitfr2)*(pitres>>1)); + 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 + L_INTERPOL1 - t0_min; + t0 = t1; + if ( t0 >= pitfr2 ) + { + step = 2; + fraction = 2; + } + else + { + step = 1; + fraction = 1; + } + + if (t0 == t0_min) /* Limit case */ + { + fraction = 0; + cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres ); + } + else /* Process negative fractions */ + { + t0--; + cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres ); + for ( i=(fraction+step); i<=pitres-1; i=i+step ) + { + temp = interpolate_corr( &pt_cor[t0], i, pitres ); + if (temp > cor_max) + { + cor_max = temp; + fraction = i; + } + } + } + + for ( i=0; i<=pitres-1; i=i+step ) /* Process positive fractions */ + { + temp = interpolate_corr( &pt_cor[t1], i, pitres ); + if (temp > cor_max) + { + cor_max = temp; + fraction = i; + t0 = t1; + } + } + *pitch_int = t0; + *pitch_fr = fraction; + if ( t0 >= pitfr2 ) + { + *index = t0*(pitres>>1) + (fraction>>1) - (pitfr2*(pitres>>1)) + ((pitfr2-pitmin)*pitres); + } + else + { + *index = t0*pitres + fraction - (pitmin*pitres); + } + + +} + +static void tcx_ltp_find_gain( float *speech, float *pred_speech, int L_frame, float *gain, int *gain_index ) +{ + int gainbits = 2; + + + /* Find gain */ + *gain = get_gain( speech, pred_speech, L_frame, NULL); + + /* Quantize gain */ + if (*gain >= 0.875f) + { + *gain_index = 3; /* 1.00/2 */ + } + else if (*gain >= 0.625f) + { + *gain_index = 2; /* 0.75/2 */ + } + else if (*gain >= 0.375f) + { + *gain_index = 1; /* 0.50/2 */ + } + else if (*gain >= 0.125f) + { + *gain_index = 0; /* 0.25/2 */ + } + else + { + *gain_index = -1; /* escape */ + } + /* Dequantize gain */ + *gain = (float)(*gain_index + 1) * 0.625f/(float)(1< 0.25f && tempFlatness < 3.5f ) || + ( tcxOnly == 1 && tcxMode == TCX_10 && max(norm_corr, *norm_corr_past) > 0.5f && maxEnergyChange < 3.5f ) || + /* 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 == 1 && norm_corr > 0.44f && L_frameTCX*(1.2f-norm_corr) < *pitch_int) || + ( tcxOnly == 1 && tcxMode == TCX_20 && norm_corr > 0.44f && (tempFlatness < 6.0f || (tempFlatness < 7.0f && maxEnergyChange < 22.0f)) ) ) + { + { + ltp_param[0] = 1; + } + } + } + if ( ltp_param[0] ) + { + /* Find predicted signal */ + predict_signal( speech, pred_speech, *pitch_int, *pitch_fr, pitres, L_frameTCX ); + + /* Find gain */ + tcx_ltp_find_gain( speech, pred_speech, L_frameTCX, gain, <p_param[2] ); + + /* Total number of bits for LTP */ + if (ltp_param[2] + 1) /* gain > 0 */ + { + *ltp_bits = 12; + } + else /* gain <= 0 -> turn off LTP */ + { + ltp_param[0] = 0; + } + } + if (!ltp_param[0]) + { + /* No LTP -> set everything to zero */ + *pitch_int = L_frameTCX; + *pitch_fr = 0; + ltp_param[1] = 0; + set_zero( pred_speech, L_frameTCX ); + *gain = 0.f; + ltp_param[2] = 0; + if ( tcxltp_on || SideInfoOnly) + { + *ltp_bits = 1; + } + else + { + *ltp_bits = 0; + } + } + + if (SideInfoOnly) + { + *gain = 0.f; + } + + if ( *gain_past==0.f && *gain==0.f ) + { + mvr2r( speech, speech_ltp, L_subfr ); + } + else if ( *gain_past==0.f ) + { + alpha = 0.f; + step = 1.f/(float)(L_subfr); + for ( n=0; n0.f ) + { + predict_signal( speech-lpcorder, buf_zir, *pitch_int, *pitch_fr, pitres, lpcorder ); + } + else + { + set_f( buf_zir, 0.0f, lpcorder ); + } + for ( n=0; n +#include "wmc_auto.h" +#include +#include +#include +#include "options.h" +#include "prot.h" +#include "rom_com.h" +#include "cnst.h" + + + +/* compute noise-measure flags for spectrum filling and quantization (0: tonal, 1: noise-like) */ +static void ComputeSpectrumNoiseMeasure( + const float *powerSpec, + int L_frame, + int startLine, + int resetMemory, + int *noiseFlags, + int lowpassLine +) +{ + int i, lastTone; + float s; + if (resetMemory) + { + for (i = 0; i < lowpassLine; i++) + { + noiseFlags[i] = 0; + } + } + for (i = lowpassLine; i < L_frame; i++) + { + noiseFlags[i] = 1; + } + if (powerSpec && startLine+6= (1.75f - 0.5f * noiseFlags[i]) * c) + { + noiseFlags[i] = 1; + } + else + { + noiseFlags[i] = 0; + lastTone = i; + } + } + /* lower L_frame*startRatio lines are tonal (0), upper 7 lines are processed separately */ + for (; i < lowpassLine - 1; i++) + { + float c = powerSpec[i-1] + powerSpec[i] + powerSpec[i+1]; /**/ + /* running sum can't be updated any more, just use the latest one */ + if (s >= (1.75f - 0.5f * noiseFlags[i]) * c) + { + noiseFlags[i] = 1; + } + else + { + noiseFlags[i] = 0; + /* lastTone = i; */ + } + } + noiseFlags[i] = 1; /* uppermost line is defined as noise-like (1) */ + + if (lastTone > 0) /* spread uppermost tonal line one line upward */ + { + noiseFlags[lastTone+1] = 0; + } + } +} + +static void detectLowpassFac(const float *powerSpec, int L_frame, int rectWin, float *pLpFac, int lowpassLine) +{ + int i; + float threshold; + + threshold = 0.1f * 2*NORM_MDCT_FACTOR; + if (rectWin) + { + /* compensate for bad side-lobe attenuation with asymmetric windows */ + threshold *= 2.f; + } + for (i = lowpassLine-1; i >= lowpassLine/2; i--) + { + if (powerSpec[i] > threshold) + { + break; + } + } + *pLpFac = + (0.3f * (*pLpFac)) + + (0.7f * ((float) (i+1) / (float) L_frame)); +} + +/*-----------------------------------------------------------* + * Compute noise-measure flags for spectrum filling * + * and quantization (0: tonal, 1: noise-like). * + * Detect low pass if present. * + *-----------------------------------------------------------*/ +void AnalyzePowerSpectrum( + Encoder_State *st, /* i/o: encoder states */ + int L_frame, /* input: frame length */ + int L_frameTCX, /* input: full band frame length */ + int left_overlap, /* input: left overlap length */ + int right_overlap, /* input: right overlap length */ + float const mdctSpectrum[], /* input: MDCT spectrum */ + float const signal[], /* input: windowed signal corresponding to mdctSpectrum */ + float powerSpec[] /* output: Power spectrum. Can point to signal */ +) +{ + int i, iStart, iEnd, lowpassLine; + + lowpassLine = L_frameTCX; + { + TCX_MDST(signal, powerSpec, left_overlap, L_frameTCX-(left_overlap+right_overlap)/2, right_overlap); + } + iStart = 0; + iEnd = L_frameTCX; + + if(st->narrowBand) + { + attenuateNbSpectrum(L_frameTCX, powerSpec); + } + + /* power spectrum: MDCT^2 + MDST^2 */ + for (i = iStart; i < iEnd; i++) + { + powerSpec[i] *= powerSpec[i]; + powerSpec[i] += mdctSpectrum[i] * mdctSpectrum[i]; + } + ComputeSpectrumNoiseMeasure(powerSpec, L_frameTCX, st->nmStartLine*L_frame/st->L_frame, (st->L_frame*st->last_sr_core != st->L_frame_past*st->sr_core) || (st->last_core != TCX_20_CORE), st->memQuantZeros, lowpassLine); + if( st->total_brate <= ACELP_24k40 ) + { + lowpassLine = (int)(2.0f*st->tcx_cfg.bandwidth*L_frame); + detectLowpassFac(powerSpec, L_frame, (st->last_core == ACELP_CORE), &st->measuredBwRatio, lowpassLine); + } + else + { + st->measuredBwRatio = 1.0f; + } +} + +void mdct_preShaping(float x[], int lg, const float gains[]) +{ + int i, j, k, l; + float g; + int m, n, k1, k2; + + j = 0; /* not counted, is included in ptr init */ + /* FDNS_NPTS = 64 !!! */ + k = lg/FDNS_NPTS; + m = lg%FDNS_NPTS; + if (m) + { + if ( m <= (FDNS_NPTS/2) ) + { + n = FDNS_NPTS/m; + k1 = k; + k2 = k + 1; + } + else + { + n = FDNS_NPTS/(FDNS_NPTS-m); + k1 = k + 1; + k2 = k; + } + for (i=0; i= 2)) && + ((invGain * x[i] <= -3.625f) || (invGain * x[i] >= 3.625f))) + { + xq[i] += (xq[i] < 0) ? -2 : 2; + i_max = i; + break; + } + } + /* 2. compress value range of all xq up to i_max: add two steps */ + for (i = 0; i < i_max; i++) + { + if (x[i] < 0.0f) + { + xq[i] = (int)(invGain * x[i] - 0.375f); + } + else + { + xq[i] = (int)(invGain * x[i] + 0.375f); + } + } + /* 3. find first mag. maximum below i_max which is half as high */ + i_max_old = i_max; + if (i_max_old > -1) + { + invGain *= 2.0f; + i_max = -1; /* reset first maximum, update inverse gain */ + for (i = 0; i < lg/4; i++) + { + if (((xq[i] <= -2) || (xq[i] >= 2)) && + ((invGain * x[i] <= -3.625f) || (invGain * x[i] >= 3.625f))) + { + xq[i] += (xq[i] < 0) ? -2 : 2; + i_max = i; + break; + } + } + } + /* 4. re-compress and quantize all xq up to half-height i_max+1 */ + for (i = 0; i < i_max; i++) + { + if (x[i] < 0.0f) + { + xq[i] = (int)(invGain * x[i] - 0.375f); + } + else + { + xq[i] = (int)(invGain * x[i] + 0.375f); + } + } + /* 5. always compress 2 lines; lines could be at index 0 and 1! */ + if (i_max_old > -1) + { + invGain *= 0.5f; /* reset inverse gain */ + if (i_max < i_max_old) + { + i_max = i_max_old; + } + } + i = i_max + 1; + if (x[i] < 0.0f) + { + xq[i] = (invGain * x[i] <= -3.625f) ? xq[i] - 2 : (int)(invGain * x[i] - 0.375f); + } + else + { + xq[i] = (invGain * x[i] >= 3.625f) ? xq[i] + 2 : (int)(invGain * x[i] + 0.375f); + } + i++; + if (x[i] < 0.0f) + { + xq[i] = (invGain * x[i] <= -3.625f) ? xq[i] - 2 : (int)(invGain * x[i] - 0.375f); + } + else + { + xq[i] = (invGain * x[i] >= 3.625f) ? xq[i] + 2 : (int)(invGain * x[i] + 0.375f); + } + } + else /*if(!tcx_lpc_shaped_ari)*/ + { + PsychAdaptLowFreqEmph(x, lpcGains); + }/*if(!tcx_lpc_shaped_ari)*/ +} + +void PsychAdaptLowFreqEmph(float x[], + const float lpcGains[] + ) +{ + int i; + float max, fac, tmp; + max = tmp = lpcGains[0]; + + /* find minimum (tmp) and maximum (max) of LPC gains in low frequencies */ + for (i = 1; i < 9; i++) + { + if (tmp > lpcGains[i]) + { + tmp = lpcGains[i]; + } + if (max < lpcGains[i]) + { + max = lpcGains[i]; + } + } + tmp *= 32.0f; + if ((max < tmp) && (max > FLT_MIN)) + { + fac = tmp = (float)pow(tmp / max, 0.0078125f); + + /* gradual boosting of lowest 32 bins; DC is boosted by (tmp/max)^1/4 */ + for (i = 31; i >= 0; i--) + { + x[i] *= fac; + fac *= tmp; + } + } + +} + +float SQ_gain( /* output: SQ gain */ + float x[], /* input: vector to quantize */ + int nbitsSQ, /* input: number of bits targeted */ + int lg) /* input: vector size (2048 max) */ +{ + int i, iter; + float ener, tmp, target, fac, offset; + float en[N_MAX/4]; + + + /* energy of quadruples with 9dB offset */ + for (i=0; i>2] = (float)log10(ener); /* saves a MAC */ + } + + /* SQ scale: 4 bits / 6 dB per quadruple */ + target = 0.15f * (float)(nbitsSQ - (lg>>4)); + fac = 12.8f; + offset = fac; + + /* find offset (0 to 128 dB with step of 0.125dB) */ + for (iter=0; iter<10; iter++) + { + fac *= 0.5f; + offset -= fac; + ener = 0.0f; + + for (i=0; i 0.3f) + { + ener += tmp; + + /* if ener is above target -> break and increase offset */ + if (ener > target) + { + offset += fac; + break; + } + } + } + } + + /* return gain */ + + + return (float)pow(10.0f, 0.45f + 0.5f*offset); +} + +void tcx_scalar_quantization( + float *x, /* i: input coefficients */ + int *xq, /* o: quantized coefficients */ + int L_frame, /* i: frame length */ + float gain, /* i: quantization gain */ + float offset, /* i: rounding offset (deadzone) */ + int *memQuantZeros, /* o: coefficients set to 0 */ + const int alfe_flag +) +{ + int i; + float gainInv, rounding, rounding2; + + + /* Init scalar quantizer */ + gainInv = 1.0f/gain; + rounding = offset; + rounding2 = -offset; + + for (i = L_frame - 1; (memQuantZeros[i]) && ((float)fabs(x[i]) * gainInv < 1.0f); i--) + { + xq[i] = 0; + } + for (; i >= 0; i--) + { + if (x[i]>0.f) + { + xq[i] = ((int) (rounding + x[i]*gainInv)); + } + else + { + xq[i] = ((int) (rounding2 + x[i]*gainInv)); + } + } + + /* don't instrument; BASOP code restricts to 16 bit by using 16 bit operators only*/ + for(i=0; i= 1) + { + stopFlag = 0; + } + else + { + stopFlag = 1; + } + + sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC( xq, L_frame, + &lastnz, + nEncoded, target, &stopFlag, hm_cfg); + + if( tcxRateLoopOpt >= 1 ) + { + if((*nEncoded>=old_nEncoded && (stopFlag>=old_stopFlag)) || (*nEncoded>old_nEncoded && (stopFlag==0 && old_stopFlag>0)) || (stopFlag==0 && old_stopFlag==0)) + { + *gain = sqGain; + old_nEncoded=*nEncoded; + old_stopFlag=stopFlag; + old_sqBits = sqBits; + *lastnz_out = lastnz; + } + } + } /* for ( iter=0 ; iter= 1 ) + { + /* Quantize spectrum */ + tcx_scalar_quantization( x, xq, L_frame, *gain, offset, memQuantZeros, tcxonly ); + + /* Output */ + *nEncoded = old_nEncoded; + sqBits = old_sqBits; + *stop = old_stopFlag; + } + else + { + /* Output */ + *gain = sqGain; + *stop = stopFlag; + *lastnz_out = lastnz; + } + + + + return sqBits; +} + +void QuantizeGain(int n, float * pGain, int * pQuantizedGain) +{ + float ener, gain; + int quantizedGain; + + ener = (float)sqrt((float)n / (float)NORM_MDCT_FACTOR); + + gain = *pGain * ener; + + assert(gain > 0); + + /* quantize gain with step of 0.714 dB */ + quantizedGain = (int)floor(0.5f + 28.0f * (float)log10(gain)); + + if (quantizedGain < 0) + { + quantizedGain = 0; + } + if (quantizedGain > 127) + { + quantizedGain = 127; + } + + *pQuantizedGain = quantizedGain; + *pGain = (float)pow(10.0f, ((float)quantizedGain)/28.0f) / ener; +} + +void tcx_noise_factor( + float *x_orig, /* i: unquantized mdct coefficients */ + float *sqQ, /* i: quantized mdct coefficients */ + int iFirstLine, /* i: first coefficient to be considered */ + int lowpassLine, /* i: last nonzero coefficients after low-pass */ + int nTransWidth, /* i: minimum size of hole to be checked */ + int L_frame, /* i: frame length */ + float gain_tcx, /* i: tcx gain */ + float tiltCompFactor, /* i: LPC tilt compensation factor */ + float *fac_ns, /* o: noise factor */ + int *quantized_fac_ns /* o: quantized noise factor */ +) +{ + int i, k, win, segmentOffset; + float inv_gain2, sqErrorNrg, n, tilt_factor, tmp; + float att; /* noise level attenuation factor for transient windows */ + + + /*Adjust noise filling level*/ + sqErrorNrg = 0.0f; + n = 0.0f; + /* max() */ + tilt_factor = 1.0f /(float)pow(max(0.375f, tiltCompFactor), 1.0f/(float)L_frame); /* 1/(a^b) = a^-b */ + inv_gain2 = 1.0f / ((float)(nTransWidth * nTransWidth) * gain_tcx); + + /* find last nonzero line below iFirstLine, use it as start offset */ + for (i = iFirstLine; i > iFirstLine/2; i--) + { + if (sqQ[i] != 0.0f) + { + break; + } + } + inv_gain2 *= (float)pow(tilt_factor, (float)i); + + segmentOffset = ++i; + if (nTransWidth <= 3) + { + att = tmp = FLT_MIN; + for (k = i & 0xFFFE; k < lowpassLine; k++) + { + att += x_orig[k] * x_orig[k]; /* even-index bins, left sub-win */ + k++; + tmp += x_orig[k] * x_orig[k]; /* odd-index bins, right sub-win */ + } + att = (float)sqrt((min(att, tmp)*2.0f) / (att + tmp)); + } + else + { + att = 1.0f; + } + win = 0; + for (; i < lowpassLine; i++) + { + inv_gain2 *= tilt_factor; + if (sqQ[i] != 0) /* current line is not zero, so reset pointers */ + { + if (win > 0) /* add segment sum to sum of segment magnitudes */ + { + k = i - segmentOffset; + if (nTransWidth <= 3) + { + n += (k > 2 * nTransWidth - 4) ? (float)(k - nTransWidth + 1) + : (float)(k*k) * 0.28125f/nTransWidth; /* table lookup instead of */ + } + else + { + n += (k > 12) ? (float)k - 7.0f : (float)(k*k) * 0.03515625f; + } + for (k = segmentOffset; k < i-win; k++) + { + sqErrorNrg += sqQ[k] * (float)nTransWidth; + sqQ[k] = 0; + } + for (; win > 0; win--) + { + sqErrorNrg += sqQ[k] * (float)win; + sqQ[k++] = 0; + } + } + segmentOffset = i + 1; /* new segment might start at next line */ + } + else /* current line is zero, so update pointers & segment sum */ + { + if (win < nTransWidth) + { + win++; + } + /* update segment sum: magnitudes scaled by smoothing function */ + sqQ[i] = (float)fabs(x_orig[i]) * (float)win * inv_gain2; + } + } + if (win > 0) /* add last segment sum to sum of segment magnitudes */ + { + k = i - segmentOffset; + if (nTransWidth <= 3) + { + n += (k > 2 * nTransWidth - 4) ? (float)(k - nTransWidth + 1) + : (float)(k*k) * 0.28125f/nTransWidth; /* table lookup instead of */ + } + else + { + n += (k > 12) ? (float)k - 7.0f : (float)(k*k) * 0.03515625f; + } + for (k = segmentOffset; k < i-win; k++) + { + sqErrorNrg += sqQ[k] * (float)nTransWidth; + sqQ[k] = 0; + } + for (; win > 0; win--) + { + sqErrorNrg += sqQ[k] * (float)win; + sqQ[k++] = 0; + } + } + + /* noise level factor: average of segment magnitudes of noise bins */ + if (n > 0.0f) + { + *fac_ns = (sqErrorNrg * att) / n; + } + else + { + *fac_ns = 0.0f; + } + + /* quantize, dequantize noise level factor (range 0.09375 - 0.65625) */ + *quantized_fac_ns = (int)(0.5f + *fac_ns * 1.34375f*(1< (1<syn, buf, 1+m); + + mvr2r(xn_buf, synth, L_frame_glob); + mvr2r(synth+L_frame_glob-m-1, LPDmem->syn, 1+m); + + if(!st->tcxonly) + { + /* Update weighted synthesis */ + residu(Ai+(st->nb_subfr-1)*(M+1), M,synth+L_frame_glob-1, &tmp, 1); + LPDmem->mem_w0=wsig[L_frame_glob-1]-tmp; + } + + + /* Emphasis of synth -> synth_pe */ + tmp = synth[-m-1]; + preemph(synth-m, preemph_f, m+L_frame_glob, &tmp); + mvr2r(synth+L_frame_glob-m, LPDmem->mem_syn, m); + mvr2r(synth+L_frame_glob-m, LPDmem->mem_syn2, m); + mvr2r( synth+L_frame_glob-L_SYN_MEM, LPDmem->mem_syn_r, L_SYN_MEM); + + if ( !st->tcxonly || (L_frame_glob==L_FRAME16k)) + { + /* Update excitation */ + if (L_frame_glob < L_EXC_MEM) + { + mvr2r( LPDmem->old_exc+(L_frame_glob), LPDmem->old_exc, L_EXC_MEM-(L_frame_glob) ); + residu(A, M,synth, LPDmem->old_exc+L_EXC_MEM-(L_frame_glob), (L_frame_glob)); + } + else + { + residu(A, M,synth+(L_frame_glob)-L_EXC_MEM, LPDmem->old_exc, L_EXC_MEM); + } + } +} + + + +/*--------------------------------------------------------------- + * Residual Quantization + *--------------------------------------------------------------*/ + +/* Returns: number of bits used (including "bits") */ +int tcx_ari_res_Q_spec( + const float x_orig[], /* i: original spectrum */ + const int signs[], /* i: signs (x_orig[.]<0) */ + float x_Q[], /* i/o: quantized spectrum */ + int L_frame, /* i: number of lines */ + float gain, /* i: TCX gain */ + int prm[], /* o: bit-stream */ + int target_bits, /* i: number of bits available */ + int bits, /* i: number of bits used so far */ + float deadzone, /* i: quantizer deadzone */ + const float x_fac[] /* i: spectrum post-quantization factors */ +) +{ + int i, j, num_zeros; + int zeros[L_FRAME_PLUS]; + float fac_m, fac_p, thres, sign, x_Q_m, x_Q_p; + + + /* Limit the number of residual bits */ + target_bits = 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; + for (i=0; i= target_bits) + { + /* no bits left */ + break; + } + if (x_Q[i] != 0) + { + sign = (1-2*signs[i])*x_fac[i]; + + x_Q_m = x_Q[i] - sign*fac_m; + x_Q_p = x_Q[i] + sign*fac_p; + if (fabs(x_orig[i] - gain * x_Q_m) < fabs(x_orig[i] - gain * x_Q_p)) /* Decrease magnitude */ + { + x_Q[i] = x_Q_m; + prm[bits++] = 0; + } + else /* Increase magnitude */ + { + x_Q[i] = x_Q_p; + prm[bits++] = 1; + } + } + else + { + zeros[num_zeros++] = i; + } + } + + /* Requantize zeroed-lines of the spectrum */ + fac_p = (1.0f - deadzone)*0.33f; + --target_bits; /* reserve 1 bit for the check below */ + for (j=0; j= target_bits) + { + /* 1 or 0 bits left */ + break; + } + + i = zeros[j]; + + thres = fac_p * x_fac[i]; + if (fabs(x_orig[i]) > thres * gain) + { + prm[bits++] = 1; + prm[bits++] = 1-signs[i]; + x_Q[i] = (2-4*signs[i]) * thres; + } + else + { + prm[bits++] = 0; + } + } + + return bits; +} + +#define kMaxEstimatorOvershoot 5 +#define kMaxEstimatorUndershoot 0 + + +int tcx_res_Q_gain( + float sqGain, + float *gain_tcx, + int *prm, + int sqTargetBits +) +{ + int bits; + float gain_reQ; + + /*Refine the gain quantization : Normal greedy gain coding */ + gain_reQ=*gain_tcx; + for(bits=0; bits thres * sqGain) + { + /* was (b > thres) */ + prm[(*bits)++] = 1; + prm[(*bits)++] = 1; + *x_Q = 2.f*thres; + } + else if (x_orig < -thres * sqGain) + { + /* was (b < -thres) */ + prm[(*bits)++] = 1; + prm[(*bits)++] = 0; + *x_Q = -2.f*thres; + } + else + { + prm[(*bits)++] = 0; + } + + return; +} + + +int tcx_res_Q_spec( + float *x_orig, + float *x_Q, + int L_frame, + float sqGain, + int *prm, + int sqTargetBits, + int bits, + float sq_round, + const float lf_deemph_factors[] +) +{ + int i; + float fac_m, fac_p; + + /* Limit the number of residual bits */ + sqTargetBits = min(sqTargetBits, NPRM_RESQ); + + /* Requantize the spectrum line-by-line */ + fac_p = 0.5f - sq_round * 0.5f; + fac_m = sq_round * 0.5f; + if (!lf_deemph_factors) + { + for (i = 0; i < L_frame; i++) + { + if (bits >= sqTargetBits-kMaxEstimatorUndershoot) + { + fac_m=fac_p=0; + if (bits >= min(NPRM_RESQ,sqTargetBits+kMaxEstimatorOvershoot)) + { + break; + } + } + + if (x_Q[i] != 0.0f) + { + if(x_orig[i]<(sqGain)*x_Q[i]) + { + prm[bits++]=0; + x_Q[i]-=(x_Q[i]>0)? fac_m : fac_p; + } + else + { + prm[bits++]=1; + x_Q[i]+=(x_Q[i]>0)? fac_p : fac_m; + } + } + } + sqTargetBits -= 2; /* Quantize zeroed lines of the spectrum */ + for (i = 0; (i < L_frame) && (bits < sqTargetBits); i++) + { + /* bits < sqTargetBits */ + if (x_Q[i] == 0.0f) + { + refine_0(x_orig[i], &x_Q[i], sqGain, prm, &bits, sq_round, 1.0f); /* inlined */ + } + } + /* Make sure that all possible bits are initialized */ + for (i = bits; i < NPRM_RESQ; i++) + { + prm[i] = 0; + } + return bits; + } + for (i = 0; i < L_frame; i++) + { + if (bits >= sqTargetBits-kMaxEstimatorUndershoot) + { + fac_m=fac_p=0; + if (bits >= min(NPRM_RESQ,sqTargetBits+kMaxEstimatorOvershoot)) + { + break; + } + } + + if (x_Q[i] != 0 && lf_deemph_factors[i] > 0.5f) + { + if(x_orig[i]<(sqGain)*x_Q[i]) + { + prm[bits++]=0; + x_Q[i]-=(x_Q[i]>0)? fac_m*lf_deemph_factors[i]: fac_p*lf_deemph_factors[i]; + } + else + { + prm[bits++]=1; + x_Q[i]+=(x_Q[i]>0)? fac_p*lf_deemph_factors[i]: fac_m*lf_deemph_factors[i]; + } + } + } + + /*Quantize zeroed-line of the spectrum*/ + for (i = 0; (i < L_frame) && (bits < (sqTargetBits-2)); i++) + { + /* For (bits >= (sqTargetBits-2)) */ + if (x_Q[i] == 0 && lf_deemph_factors[i] > 0.5f) + { + refine_0(x_orig[i], &x_Q[i], sqGain, prm, &bits, sq_round, lf_deemph_factors[i]); + } + } + + /*Be sure that every possible bits are initialized*/ + for (i = bits; i < NPRM_RESQ; i++) + { + prm[i]=0; + } + + return bits; +} + + +void ProcessIGF( + IGF_ENC_INSTANCE_HANDLE const hInstance, /**< in: instance handle of IGF Encoder */ + Encoder_State *st, /**< in: Encoder state */ + float *pMDCTSpectrum, /**< in: MDCT spectrum */ + float *pPowerSpectrum, /**< in: MDCT^2 + MDST^2 spectrum, or estimate */ + int isTCX20, /**< in: flag indicating if the input is TCX20 or TCX10/2xTCX5 */ + int isTNSActive, /**< in: flag indicating if the TNS is active */ + int isTransition, /**< in: flag indicating if the input is the transition from from ACELP to TCX20/TCX10 */ + int frameno /**< in: flag indicating index of current subframe */ +) +{ + int igfGridIdx; + int isIndepFlag; + int bsBits; + int pBsStart; + + isIndepFlag = 1; + if (isTransition && isTCX20) + { + igfGridIdx = IGF_GRID_LB_TRAN; + } + else if (isTCX20) + { + igfGridIdx = IGF_GRID_LB_NORM; + } + else + { + /* It is short block */ + igfGridIdx = IGF_GRID_LB_SHORT; + if (frameno == 1) + { + isIndepFlag = 0; + } + } + + IGFEncApplyMono(hInstance, /**< in: instance handle of IGF Encoder */ + igfGridIdx, /**< in: IGF grid index */ + st, /**< in: Encoder state */ + pMDCTSpectrum, /**< in: MDCT spectrum */ + pPowerSpectrum, /**< in: MDCT^2 + MDST^2 spectrum, or estimate */ + isTCX20, /**< in: flag indicating if the input is TCX20 or TCX10/2xTCX5 */ + isTNSActive, + (st->last_core == ACELP_CORE) + ); /**< in: flag indicating if the TNS is active */ + + + { + const float tns_predGain = (&st->hIGFEnc)->tns_predictionGain; + const short int startLine = (&st->hIGFEnc)->infoStartLine; + const short int endLine = (&st->hIGFEnc)->infoStopLine; + const int maxOrder = 8; + const float* spec_before = (&st->hIGFEnc)->spec_be_igf; + int curr_order = 0; + float A[ITF_MAX_FILTER_ORDER+1]; + float predictionGain = 0; + int* flatteningTrigger = &(&st->hIGFEnc)->flatteningTrigger; + ITF_Detect( spec_before, startLine, endLine, maxOrder, A, &predictionGain, &curr_order ); + + *flatteningTrigger = tns_predGain < 1.15 && predictionGain < 1.15; + } + + pBsStart = st->next_ind; + hInstance->infoTotalBitsPerFrameWritten = 0; + IGFEncWriteBitstream( hInstance, isTCX20 ? NULL : st, &hInstance->infoTotalBitsPerFrameWritten, igfGridIdx, isIndepFlag ); + + bsBits = st->next_ind - pBsStart; + if (!isTCX20) + { + IGFEncConcatenateBitstream(hInstance, bsBits, &st->next_ind, &st->nb_bits_tot, st->ind_list); + } + + return; +} + + +void attenuateNbSpectrum(int L_frame, float *spectrum) +{ + int i; + int length = L_frame / 20; + float att = (length == 8)?0.6f:0.66f; + + for(i=0; i +#include "wmc_auto.h" +#include +#include "prot.h" + + + +void tfaCalcEnv(const float* shb_speech, float* enr) +{ + int i, j, k; + for (i=0, k=0; i 0.70 && pitch_buf_sum > 4.0 * 110 && voicing_sum > 2.0 * 0.70) || + (last_core == TCX_20_CORE && flatness > 0.50 && voicing_sum < 2.0 * 0.70)) + { + tfa_flag = 1; + } + /* energy lower limit */ + if(m_a < m_a_bottom) + { + tfa_flag = 0; + } + + return tfa_flag; +} diff --git a/lib_enc/tns_base_enc.c b/lib_enc/tns_base_enc.c new file mode 100644 index 000000000..b4fc8db68 --- /dev/null +++ b/lib_enc/tns_base_enc.c @@ -0,0 +1,315 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "cnst.h" +#include "wmc_auto.h" +#include "rom_com.h" +#include "prot.h" + +#include +#include +#include + + +#define HLM_MIN_NRG (32768.0f * 2*NORM_MDCT_FACTOR / (640*640)) + +static float Autocorrelation(float const x[], int n, int lag) +{ + return dotp(x, x+lag, n-lag); +} + +/** 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(float const rxx[], int 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(float const parCoeff[], int index[], int 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 float (* TLinearPredictionFilter)(int order, float const parCoeff[], float * state, float x); + +/********************************/ +/* Interface functions */ +/********************************/ + +#define MAX_SUBDIVISIONS 3 + +int DetectTnsFilt(STnsConfig const * pTnsConfig, + float const pSpectrum[], + STnsData * pTnsData + , float* predictionGain + ) +{ + float norms[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS]; + int iFilter = 0; + short i; + + for( i=0; imaxOrder <= 0) + { + return 0; + } + + /* Calculate norms for each spectrum part */ + for (iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++) + { + int const idx0 = pTnsConfig->iFilterBorders[iFilter+1]; + int const idx1 = pTnsConfig->iFilterBorders[iFilter]; + int const nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions; + int iSubdivisions; + /* Variable initialization */ + assert(pTnsConfig->pTnsParameters[iFilter].nSubdivisions <= MAX_SUBDIVISIONS); + for (iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++) + { + int const iStartLine = idx0 + (idx1-idx0)*iSubdivisions/nSubdivisions; + int const iEndLine = idx0 + (idx1-idx0)*(iSubdivisions+1)/nSubdivisions; + /* Variable initialization */ + norms[iFilter][iSubdivisions] = sum2_f(pSpectrum+iStartLine, iEndLine-iStartLine); /* No need for indirect, PTR_INIT used instead */ + + } + } + /* Calculate normalized autocorrelation for spectrum subdivision and get TNS filter parameters based on it */ + for (iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++) + { + float rxx[TNS_MAX_FILTER_ORDER+1]; + int const idx0 = pTnsConfig->iFilterBorders[iFilter+1]; + int const idx1 = pTnsConfig->iFilterBorders[iFilter]; + int const spectrumLength = idx1 - idx0; + STnsFilter * const pFilter = pTnsData->filter + iFilter; + int const nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions; + int iSubdivisions; + + set_f( rxx, 0, TNS_MAX_FILTER_ORDER+1 ); /* WMOPS: This initialization is required */ + /* Variable initialization */ + for (iSubdivisions = 0; (iSubdivisions < nSubdivisions) && (norms[iFilter][iSubdivisions] > HLM_MIN_NRG); iSubdivisions++) + { + float const fac = 1.0f/norms[iFilter][iSubdivisions]; + int const iStartLine = idx0 + spectrumLength*iSubdivisions/nSubdivisions; + int const iEndLine = idx0 + spectrumLength*(iSubdivisions+1)/nSubdivisions; + float const * pWindow = tnsAcfWindow; + float const * pEndWindowCoeff = &tnsAcfWindow[sizeof(tnsAcfWindow)/sizeof(tnsAcfWindow[0])]; /* WMOPS: Not counted as it is used only in the assertion */ + int lag; + (void)pEndWindowCoeff; + /* For additional loop condition */ + /* Variable initialization */ + for (lag = 1; lag <= pTnsConfig->maxOrder; lag++) + { + rxx[lag] += fac * (*pWindow) * Autocorrelation(pSpectrum+iStartLine, iEndLine-iStartLine, lag); + pWindow++; + } + } + if (iSubdivisions == nSubdivisions) /* meaning there is no subdivision with low energy */ + { + rxx[0] = (float)pTnsConfig->pTnsParameters[iFilter].nSubdivisions; + pFilter->spectrumLength = spectrumLength; + /* Limit the maximum order to spectrum length/4 */ + GetFilterParameters(rxx, min(pTnsConfig->maxOrder, pFilter->spectrumLength/4), pFilter); + } + } + + if (predictionGain) + { + assert(pTnsConfig->nMaxFilters == 1); + *predictionGain = pTnsData->filter->predictionGain; + } + + /* We check the filter's decisions in the opposite direction */ + for (iFilter = pTnsConfig->nMaxFilters-1; iFilter >= 0; iFilter--) + { + STnsFilter * const pFilter = pTnsData->filter + iFilter; + struct TnsParameters const * const pTnsParameters = pTnsConfig->pTnsParameters + iFilter; + + /* TNS decision function */ + if ((pFilter->predictionGain > pTnsParameters->minPredictionGain) + || (pFilter->avgSqrCoef > pTnsParameters->minAvgSqrCoef)) + { + ++pTnsData->nFilters; + } + 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); + pFilter->order = 1; + ++pTnsData->nFilters; + } + else + { + ClearTnsFilterCoefficients(pFilter); + } + } + return (pTnsData->nFilters > 0) ? 1 : 0; +} + +TNS_ERROR EncodeTnsData(STnsConfig const * pTnsConfig, STnsData const * pTnsData, int * stream, int * pnSize, int * pnBits) +{ + *pnSize = 0; + *pnBits = 0; + if (pTnsConfig->nMaxFilters > 1) + { + if (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; +} + +TNS_ERROR WriteTnsData(STnsConfig const * pTnsConfig, int const * stream, int * pnSize, Encoder_State *st, int * pnBits) +{ + if (pTnsConfig->nMaxFilters > 1) + { + if (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 */ +/********************************/ + +/** Autocorrelation to parcor coefficients. + * Conversion of autocorrelation to parcor/reflection coefficients. + * @param input Autocorrelation function/coefficients. + * @param parCoeff output filter (PARCOR) coefficients. + * @param order filter order. + * @return prediction gain. + */ +static float AutoToParcor(const float input[], float parCoeff[], int order) +{ + int i, j; + float tmp, tmp2; + float workBuffer[2*TNS_MAX_FILTER_ORDER]; + float * const pWorkBuffer = &workBuffer[order]; /* temp pointer */ /* WMOPS: No need for counting as it can be realized as a separate buffer */ + + for(i=0; icoefIndex; + /* Variable initialization */ + /* compute TNS filter in lattice (ParCor) form with LeRoux-Gueguen algorithm */ + pTnsFilter->predictionGain = AutoToParcor(rxx, parCoeff, maxOrder); + /* non-linear quantization of TNS lattice coefficients with given resolution */ + Parcor2Index(parCoeff, indexes, maxOrder); + + /* reduce filter order by truncating trailing zeros */ + i = maxOrder - 1; + while ((i >= 0) && (indexes[i] == 0)) + { + --i; + /* Loop condition */ + } + pTnsFilter->order = i + 1; + + /* compute avg(coef*coef) */ + pTnsFilter->avgSqrCoef = 0; + for (i = pTnsFilter->order-1; i >= 0; i--) + { + float const value = values[indexes[i]+INDEX_SHIFT]; + /* Variable initialization */ + pTnsFilter->avgSqrCoef += value * value; + + } + pTnsFilter->avgSqrCoef /= maxOrder; +} + +static void Parcor2Index(const float parCoeff[], int index[], int order) +{ + int const nValues = 1 << TNS_COEF_RES; /* WMOPS: This is just a constant */ + float const * values = tnsCoeff4; + int i; + int iIndex; + float x; + for (i = 0; i < order; i++) + { + iIndex = 1; + x = parCoeff[i]; + /* Variable initialization */ + assert((x >= -1.0f) && (x <= 1.0f)); + while ((iIndex < nValues) && (x > 0.5f*(values[iIndex-1]+values[iIndex]))) + { + ++iIndex; + /* Loop condition */ + } + index[i] = (iIndex-1) - INDEX_SHIFT; + } +} diff --git a/lib_enc/transient_detection.c b/lib_enc/transient_detection.c new file mode 100644 index 000000000..a4ba637d6 --- /dev/null +++ b/lib_enc/transient_detection.c @@ -0,0 +1,600 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "stat_enc.h" +#include "cnst.h" +#include "prot.h" +#include +#include +#include +#include +#include + +#define WMC_TOOL_SKIP + + +#define MIN_BLOCK_ENERGY 107.37f + + +/************************************************/ +/* */ +/* Internal functions prototypes */ +/* */ +/************************************************/ + +static void InitDelayBuffer(int nFrameLength, int nDelay, DelayBuffer * pDelayBuffer); +static void InitSubblockEnergies(int nFrameLength, int nDelay, DelayBuffer * pDelayBuffer, SubblockEnergies * pSubblockEnergies); +static void InitTransientDetector(SubblockEnergies * pSubblockEnergies, int nDelay, int nSubblocksToCheck, + TCheckSubblocksForAttack pCheckSubblocksForAttack, + float attackRatioThreshold, TransientDetector * pTransientDetector); +static void UpdateDelayBuffer(float const * input, int nSamplesAvailable, DelayBuffer * pDelayBuffer); +static void HighPassFilter(float const * input, int length, float * pFirState1, float * pFirState2, float * output); +static void UpdateSubblockEnergies(float const * input, int nSamplesAvailable, SubblockEnergies * pSubblockEnergies); +static void CalculateSubblockEnergies(float const * input, int 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(float const * pSubblockNrg, float const * pAccSubblockNrg, int nSubblocks, int nPastSubblocks, float attackRatioThreshold, int * pbIsAttackPresent, int * pAttackIndex) +{ + int i; + int bIsAttackPresent, attackIndex; + + (void)nPastSubblocks; + (void)nSubblocks; + assert(nSubblocks >= NSUBBLOCKS); + assert(nPastSubblocks >= 2); + + bIsAttackPresent = FALSE; + attackIndex = -1; + /* Search for the last attack in the subblocks */ + if ((pSubblockNrg[-1] > pAccSubblockNrg[-1] * attackRatioThreshold) + || (pSubblockNrg[-2] > pAccSubblockNrg[-2] * attackRatioThreshold) + ) + { + bIsAttackPresent = TRUE; + attackIndex = 0; + } + /* PTR_INIT for pSubblockNrg[i-1] */ + for (i = 0; i < NSUBBLOCKS; i++) + { + if (pSubblockNrg[i] > pAccSubblockNrg[i] * attackRatioThreshold) + { + if (i < 6) + { + bIsAttackPresent = TRUE; + } + if ((attackIndex != 2) && (attackIndex != 6)) + { + attackIndex = i; + if ((pSubblockNrg[i] < pAccSubblockNrg[i] * 1.125f * attackRatioThreshold) && (i == 2 || i == 6)) + { + attackIndex++; /* avoid minimum overlap to prevent clicks */ + } + } + } + else /* no attack, but set index anyway in case of strong energy increase */ + { + if ((pSubblockNrg[i] > pSubblockNrg[i-1] * 1.5f * attackRatioThreshold) && + (pSubblockNrg[i] > pSubblockNrg[i-2] * 1.5f * attackRatioThreshold)) + { + if ((attackIndex != 2) && (attackIndex != 6)) + { + attackIndex = i; + + if (((pSubblockNrg[i] < pSubblockNrg[i-1] * 2.0f * attackRatioThreshold) || + (pSubblockNrg[i] < pSubblockNrg[i-2] * 2.0f * attackRatioThreshold)) && (i == 2 || i == 6)) + { + attackIndex++; /* avoid minimum overlap to prevent clicks */ + } + } + } + } + } + /* avoid post-echos on click sounds (very short transients) due to TNS aliasing */ + if (attackIndex == 4) + { + attackIndex = 7; + } + else if (attackIndex == 5) + { + attackIndex = 6; + } + *pAttackIndex = attackIndex; + *pbIsAttackPresent = bIsAttackPresent; +} + +/** Initialize TCX transient detector. + * See InitTransientDetector for definition of parameters. + */ +static void InitTCXTransientDetector(int nDelay, SubblockEnergies * pSubblockEnergies, TransientDetector * pTransientDetector) +{ + InitTransientDetector(pSubblockEnergies, nDelay, NSUBBLOCKS, GetAttackForTCXDecision, 8.5f, pTransientDetector); +} + +/************************************************/ +/* */ +/* Interface functions */ +/* */ +/************************************************/ + +void InitTransientDetection(int nFrameLength, + int nTCXDelay, + TransientDetection * pTransientDetection) +{ + /* Init the delay buffer. */ + InitDelayBuffer(nFrameLength, nTCXDelay, &pTransientDetection->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 += NSUBBLOCKS+1; +} + +float GetTCXAvgTemporalFlatnessMeasure(struct TransientDetection const * pTransientDetection, int nCurrentSubblocks, int nPrevSubblocks) +{ + int i; + TransientDetector const * pTransientDetector = &pTransientDetection->transientDetector; + SubblockEnergies const * pSubblockEnergies = pTransientDetector->pSubblockEnergies; + int const nDelay = pTransientDetector->nDelay; /* */ + int const nRelativeDelay = pSubblockEnergies->nDelay - nDelay; /* */ + float const * pSubblockNrgChange = NULL; + float sumTempFlatness; + int const nTotBlocks = nCurrentSubblocks+nPrevSubblocks; /* */ + /* Initialization */ + assert(nTotBlocks > 0); + sumTempFlatness = 0.0f; + + assert((nPrevSubblocks <= nRelativeDelay) && (nCurrentSubblocks <= NSUBBLOCKS+nDelay)); + pSubblockNrgChange = &pSubblockEnergies->subblockNrgChange[nRelativeDelay-nPrevSubblocks]; + for (i = 0; i < nTotBlocks; i++) + { + sumTempFlatness += pSubblockNrgChange[i]; + } + return sumTempFlatness / (float)nTotBlocks; +} + +float GetTCXMaxenergyChange(struct TransientDetection const * pTransientDetection, + const int isTCX10, + const int nCurrentSubblocks, const int nPrevSubblocks) +{ + int i; + TransientDetector const * pTransientDetector = &pTransientDetection->transientDetector; + SubblockEnergies const * pSubblockEnergies = pTransientDetector->pSubblockEnergies; + int const nDelay = pTransientDetector->nDelay; /* */ + int const nRelativeDelay = pSubblockEnergies->nDelay - nDelay; /* */ + float const * pSubblockNrgChange = NULL; + float maxEnergyChange; + int nTotBlocks = nCurrentSubblocks+nPrevSubblocks; /* */ + /* Initialization */ + assert(nTotBlocks > 0); + maxEnergyChange = 0.0f; + + assert((nPrevSubblocks <= nRelativeDelay) && (nCurrentSubblocks <= NSUBBLOCKS+nDelay)); + pSubblockNrgChange = &pSubblockEnergies->subblockNrgChange[nRelativeDelay-nPrevSubblocks]; + if (pTransientDetector->bIsAttackPresent || isTCX10) /* frame is TCX-10 */ + { + float const * pSubblockNrg = &pSubblockEnergies->subblockNrg[nRelativeDelay-nPrevSubblocks]; + float nrgMin, nrgMax = pSubblockNrg[0]; + int idxMax = 0; + /* find subblock with maximum energy */ + for (i = 1; i < nTotBlocks; i++) + { + if (nrgMax < pSubblockNrg[i]) + { + nrgMax = pSubblockNrg[i]; + idxMax = i; + } + } + nrgMin = nrgMax; + /* find minimum energy after maximum */ + for (i = idxMax + 1; i < nTotBlocks; i++) + { + if (nrgMin > pSubblockNrg[i]) + { + nrgMin = pSubblockNrg[i]; + } + } + /* lower maxEnergyChange if energy doesn't decrease much after energy peak */ + if (nrgMin > 0.375f * nrgMax) + { + nTotBlocks = idxMax - 3; + } + } + for (i = 0; i < nTotBlocks; i++) + { + maxEnergyChange = max(maxEnergyChange, pSubblockNrgChange[i]); + } + + return maxEnergyChange; +} + +/*---------------------------------------------------------------* + * RunTransientDetection() + * + * Time Domain Transient Detector for TCX + *---------------------------------------------------------------*/ + +void RunTransientDetection( + float const * input, + int nSamplesAvailable, + TransientDetection * pTransientDetection +) +{ + float filteredInput[L_FRAME_MAX]; + SubblockEnergies * pSubblockEnergies = &pTransientDetection->subblockEnergies; /* */ + TransientDetector * pTransientDetector = &pTransientDetection->transientDetector; /* */ + + assert((input != NULL) && (pTransientDetection != NULL) && (pSubblockEnergies != NULL) && (pTransientDetector != NULL)); + /* Variable initializations */ + 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); + + return; +} + + +void SetTCXModeInfo(Encoder_State *st, /* i/o: encoder state structure */ + TransientDetection const * pTransientDetection, + short * tcxModeOverlap + ) +{ + if( st->codec_mode == MODE2 ) + { + assert(pTransientDetection != NULL); + + /* determine window sequence (1 long or 2 short windows) */ + if (st->tcx10Enabled && st->tcx20Enabled) + { + /* window switching based on transient detector output */ + if ( + ((pTransientDetection->transientDetector.bIsAttackPresent) + || (st->currEnergyHF > st->prevEnergyHF * 39.0f)) && + ((st->last_core != ACELP_CORE) && (st->last_core != AMR_WB_CORE))) + { + st->tcxMode = TCX_10; + } + else + { + st->tcxMode = TCX_20; + } + } + else + { + /* window selection (non-adaptive) based on flags only */ + if (st->tcx10Enabled) + { + st->tcxMode = TCX_10; + } + else if (st->tcx20Enabled) + { + st->tcxMode = TCX_20; + } + else + { + st->tcxMode = NO_TCX; + } + } + + /* set the left window overlap */ + + if (st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE) + { + st->tcx_cfg.tcx_last_overlap_mode = TRANSITION_OVERLAP; + } + else if ((st->tcxMode == TCX_10) && (st->tcx_cfg.tcx_curr_overlap_mode == ALDO_WINDOW)) + { + st->tcx_cfg.tcx_last_overlap_mode = FULL_OVERLAP; + } + else + { + st->tcx_cfg.tcx_last_overlap_mode = st->tcx_cfg.tcx_curr_overlap_mode; + } + + /* determine the right window overlap */ + if( st->tcxMode == TCX_10 ) + { + if (pTransientDetection->transientDetector.attackIndex < 0) + { + *tcxModeOverlap = HALF_OVERLAP; + } + else + { + *tcxModeOverlap = pTransientDetection->transientDetector.attackIndex % 4; + if (*tcxModeOverlap == 1) + { + *tcxModeOverlap = FULL_OVERLAP; + } + } + } + else if (st->tcxMode == TCX_20) + { + if (pTransientDetection->transientDetector.attackIndex == 7) + { + *tcxModeOverlap = HALF_OVERLAP; + } + else if (pTransientDetection->transientDetector.attackIndex == 6) + { + *tcxModeOverlap = MIN_OVERLAP; + } + else + { + *tcxModeOverlap = ALDO_WINDOW; + } + } + else + { + /* NO_TCX */ + *tcxModeOverlap = TRANSITION_OVERLAP; + } + + /* for the ACELP -> TCX transition frames use full right window overlap */ + + if ((st->tcx_cfg.tcx_last_overlap_mode == TRANSITION_OVERLAP) && (*tcxModeOverlap == ALDO_WINDOW)) + { + *tcxModeOverlap = FULL_OVERLAP; + } + } + + return; +} + +/************************************************/ +/* */ +/* Internal functions */ +/* */ +/************************************************/ + +static void InitDelayBuffer(int nFrameLength, int nDelay, DelayBuffer * pDelayBuffer) +{ + int const nMaxBuffSize = sizeof(pDelayBuffer->buffer)/sizeof(pDelayBuffer->buffer[0]); + + assert((nFrameLength > NSUBBLOCKS) && (nFrameLength % NSUBBLOCKS == 0) && (nDelay >= 0) && (pDelayBuffer != NULL)); + pDelayBuffer->nSubblockSize = nFrameLength/NSUBBLOCKS; + assert(pDelayBuffer->nSubblockSize <= nMaxBuffSize); + set_f(pDelayBuffer->buffer, 0.0f, nMaxBuffSize); + pDelayBuffer->nDelay = nDelay % pDelayBuffer->nSubblockSize; + assert(pDelayBuffer->nDelay <= nMaxBuffSize); + + return; +} + + +static void InitSubblockEnergies(int nFrameLength, int nDelay, DelayBuffer * pDelayBuffer, SubblockEnergies * pSubblockEnergies) +{ + int const nMaxBuffSize = sizeof(pSubblockEnergies->subblockNrg)/sizeof(pSubblockEnergies->subblockNrg[0]); + (void)nFrameLength; + + assert((pDelayBuffer != NULL) && (pSubblockEnergies != NULL) && (pDelayBuffer->nSubblockSize * NSUBBLOCKS == nFrameLength) && (pDelayBuffer->nSubblockSize > 0)); + + set_f(pSubblockEnergies->subblockNrg, MIN_BLOCK_ENERGY, nMaxBuffSize); + set_f(pSubblockEnergies->accSubblockNrg, MIN_BLOCK_ENERGY, nMaxBuffSize+1); + set_f(pSubblockEnergies->subblockNrgChange, 1.0f, nMaxBuffSize); + pSubblockEnergies->nDelay = nDelay / pDelayBuffer->nSubblockSize; + assert(pSubblockEnergies->nDelay < nMaxBuffSize); + pSubblockEnergies->nPartialDelay = nDelay % pDelayBuffer->nSubblockSize; + pSubblockEnergies->facAccSubblockNrg = 0.8125f; /* Energy accumulation factor */ + pSubblockEnergies->firState1 = 0.0f; + pSubblockEnergies->firState2 = 0.0f; + + pSubblockEnergies->pDelayBuffer = pDelayBuffer; + pDelayBuffer->nDelay = max(pDelayBuffer->nDelay, pSubblockEnergies->nPartialDelay); + + return; +} + +/** 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. + * @param pTransientDetector Structure to be initialized. + */ +static void InitTransientDetector(SubblockEnergies * pSubblockEnergies, int nDelay, int nSubblocksToCheck, + TCheckSubblocksForAttack pCheckSubblocksForAttack, + float attackRatioThreshold, TransientDetector * pTransientDetector) +{ + int const nMaxBuffSize = sizeof(pSubblockEnergies->subblockNrg)/sizeof(pSubblockEnergies->subblockNrg[0]); + (void)nMaxBuffSize; + 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 = 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; + + return; +} + +/* This function should be inlined and WMOPS instrumentation takes that into account, meaning that all references are considered as local variables */ +static float InlineFilter(float inValue, float firState1, float firState2) +{ + return 0.375f * inValue - 0.5f * firState1 + 0.125f * firState2; +} + + +static void HighPassFilter(float const * input, int length, float * pFirState1, float * pFirState2, float * output) +{ + int i; + output[0] = InlineFilter(input[0], *pFirState1, *pFirState2); + output[1] = InlineFilter(input[1], input[0], *pFirState1); + for (i = 2; i < length; i++) + { + output[i] = InlineFilter(input[i], input[i-1], input[i-2]); + } + /* update filter states: shift time samples through delay line */ + *pFirState2 = input[length-2]; + *pFirState1 = input[length-1]; + + return; +} + + +static void RunTransientDetector(TransientDetector * pTransientDetector) +{ + float const attackRatioThreshold = pTransientDetector->attackRatioThreshold; /* */ + SubblockEnergies const * pSubblockEnergies = pTransientDetector->pSubblockEnergies; /* */ + int const nDelay = pTransientDetector->nDelay; /* */ + int const nRelativeDelay = pSubblockEnergies->nDelay - nDelay; /* */ + float const * pSubblockNrg = &pSubblockEnergies->subblockNrg[nRelativeDelay]; /* */ + float const * pAccSubblockNrg = &pSubblockEnergies->accSubblockNrg[nRelativeDelay]; /* */ + + assert((pTransientDetector->CheckSubblocksForAttack != NULL)); + /* Variable initialization */ + pTransientDetector->CheckSubblocksForAttack(pSubblockNrg, pAccSubblockNrg, + NSUBBLOCKS+nDelay, nRelativeDelay, + attackRatioThreshold, + &pTransientDetector->bIsAttackPresent, &pTransientDetector->attackIndex); + + return; +} + +static void UpdateDelayBuffer(float const * input, int nSamplesAvailable, DelayBuffer * pDelayBuffer) +{ + int i; + int const 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++) + { + pDelayBuffer->buffer[i] = input[i+nSamplesAvailable-nDelay]; + } + } + + return; +} + + +static void UpdateSubblockEnergies(float const * input, int nSamplesAvailable, SubblockEnergies * pSubblockEnergies) +{ + int 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++) + { + 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); + + return; +} + + +/* This function should be inlined and WMOPS instrumentation takes that into account, meaning that all references are considered as local variables */ +static void UpdatedAndStoreAccWindowNrg(float newWindowNrgF, float * pAccSubblockNrg, float facAccSubblockNrg, float * pOutAccWindowNrgF) +{ + /* Store the accumulated energy */ + *pOutAccWindowNrgF = *pAccSubblockNrg; + /* Update the accumulated energy: maximum of the current and the accumulated energy */ + *pAccSubblockNrg *= facAccSubblockNrg; + if (newWindowNrgF > *pAccSubblockNrg) + { + *pAccSubblockNrg = newWindowNrgF; + } + + return; +} + + +static void CalculateSubblockEnergies(float const * input, int nSamplesAvailable, SubblockEnergies * pSubblockEnergies) +{ + DelayBuffer * pDelayBuffer = pSubblockEnergies->pDelayBuffer; /* */ + int const nSubblockSize = pDelayBuffer->nSubblockSize; /* */ + int const nDelay = pSubblockEnergies->nDelay; /* */ + int const nPartialDelay = pSubblockEnergies->nPartialDelay; /* */ + float const * delayBuffer = &pDelayBuffer->buffer[pDelayBuffer->nDelay - nPartialDelay]; /* */ + float const facAccSubblockNrg = pSubblockEnergies->facAccSubblockNrg; /* */ + float * pSubblockNrg = &pSubblockEnergies->subblockNrg[nDelay]; /* */ + float * pAccSubblockNrg = &pSubblockEnergies->accSubblockNrg[nDelay]; /* */ + float * pSubblockNrgChange = &pSubblockEnergies->subblockNrgChange[nDelay]; /* */ + float * pAccSubblockTmp; + int nWindows; + int i, w, k; + /* Variable initializations */ + nWindows = (nSamplesAvailable+nPartialDelay)/nSubblockSize; + pAccSubblockTmp = &pAccSubblockNrg[nWindows]; + + set_f(pSubblockNrg, MIN_BLOCK_ENERGY, NSUBBLOCKS); + if (nWindows > 0) + { + /* Process left over samples from the previous frame. */ + for (k = 0; k < nPartialDelay; k++) + { + pSubblockNrg[0] += delayBuffer[k] * delayBuffer[k]; + } + k = 0; + /* Process new samples in the 0. subblock. */ + for (i = nPartialDelay; i < nSubblockSize; i++, k++) + { + pSubblockNrg[0] += input[k] * input[k]; + } + /* Set accumulated subblock energy at this point. */ + UpdatedAndStoreAccWindowNrg(pSubblockNrg[0], pAccSubblockTmp, facAccSubblockNrg, &pAccSubblockNrg[0]); + for (w = 1; w < nWindows; w++) + { + /* Process new samples in the w. subblock. */ + for (i = 0; i < nSubblockSize; i++, k++) + { + pSubblockNrg[w] += input[k] * input[k]; + } + /* 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++) + { + if (pSubblockNrg[w] > pSubblockNrg[w-1]) + { + pSubblockNrgChange[w] = pSubblockNrg[w]/pSubblockNrg[w-1]; + } + else + { + pSubblockNrgChange[w] = pSubblockNrg[w-1]/pSubblockNrg[w]; + } + } + } + + return; +} diff --git a/lib_enc/transition_enc.c b/lib_enc/transition_enc.c new file mode 100644 index 000000000..7b9544650 --- /dev/null +++ b/lib_enc/transition_enc.c @@ -0,0 +1,978 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*-----------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------*/ + +static void gain_trans_enc( float *gain_trans, float exc[], short *quant_index, short *quant_sign ); + +static void tc_enc( Encoder_State *st, const long core_brate, const short L_frame, const short i_subfr, short *tc_subfr, short *position, + const float *h1, const float *xn, float *exc, float *y1, short *T0_min, short *T0_max, short *T0, + short *T0_frac, float *gain_pit, float g_corr[], float *bwe_exc ); + +/*-----------------------------------------------------------------* + * transition_enc() + * + * Principal function for adaptive excitation construction in TC + *-----------------------------------------------------------------*/ + +void transition_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const long core_brate, /* i : core bitrate */ + const short L_frame, /* i : length of the frame */ + const short coder_type, /* i : coding type */ + const short i_subfr, /* i : subframe index */ + short *tc_subfr, /* i/o: TC subframe index */ + short *Jopt_flag, /* i : joint optimization flag */ + short *position, /* i/o: maximum of residual signal index */ + const float voicing[], /* i : normalized correlations (from OL pitch) */ + const short T_op[], /* i : open loop pitch estimates in current frame */ + short *T0, /* i/o: close loop integer pitch */ + short *T0_frac, /* i/o: close loop fractional part of the pitch */ + short *T0_min, /* i/o: lower limit for close-loop search */ + short *T0_max, /* i/o: higher limit for close-loop search */ + float *exc, /* i/o: pointer to excitation signal frame */ + float *y1, /* o : zero-memory filtered adaptive excitation */ + const float *res, /* i : pointer to the LP residual signal frame */ + const float *h1, /* i : weighted filter input response */ + const float *xn, /* i : target vector */ + float *xn2, /* o : target vector for innovation search */ + float *gp_cl, /* i/o: memory of gain of pitch clipping algorithm */ + float *gain_pit, /* o : adaptive excitation gain */ + float *g_corr, /* o : ACELP correlation values */ + short *clip_gain, /* i/o: adaptive gain clipping flag */ + float **pt_pitch, /* o : floating pitch values */ + float *bwe_exc /* o : excitation for SWB TBE */ +) +{ + short i, pit_flag, pit_start, pit_limit, index, nBits; + float temp; + short limit_flag, mult_Top; + short lp_select, lp_flag; + int offset=0; + /* set limit_flag to 0 for restrained limits, and 1 for extended limits */ + limit_flag = 0; + + pit_start = PIT_MIN; + + /*-----------------------------------------------------------------* + * 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( *tc_subfr == 3*L_SUBFR ) + { + if( L_frame == L_FRAME ) + { + *position = emaximum( res + 3*L_SUBFR,min(T_op[0]+2,L_SUBFR), &temp ) + 3*L_SUBFR; + *tc_subfr = 3*L_SUBFR; + } + else /* L_frame == L_FRAME16k */ + { + *position = emaximum( res + 4*L_SUBFR,min(T_op[0]+2,L_SUBFR), &temp ) + 4*L_SUBFR; + *tc_subfr = 4*L_SUBFR; + } + } + else + { + *position = emaximum( res, (short)(T_op[0]+2), &temp ); + + /* correction in case of possibly wrong T_op (double-pitch values) */ + if( (L_frame == L_FRAME && T_op[0] > 2*PIT_MIN) || + (L_frame == L_FRAME16k && T_op[0] > 2*PIT16k_MIN) + ) + { + short position_tmp, len; + float aver, temp2; + + len = (short)(T_op[0]/2+2); + + position_tmp = emaximum( res, len, &temp2 ); + aver = dotp( res, res, len) + 0.01f; + aver = sqrt(aver/len); + + temp = sqrt(temp); + temp2 = sqrt(temp2); + + if( temp2 > 0.8f * temp && aver < 0.25f * temp ) + { + *position = position_tmp; + } + } + + *tc_subfr = (short) floor((*position)/L_SUBFR)*L_SUBFR; + } + + mult_Top = 1; + if( limit_flag == 0 ) + { + if( L_frame == L_FRAME && T_op[1] < PIT_MIN ) + { + mult_Top = 2; + } + + if( L_frame == L_FRAME16k && T_op[1] < PIT16k_MIN ) + { + mult_Top = 2; + } + } + + limit_T0( L_frame, 8, 0, limit_flag, mult_Top*T_op[1], 0, T0_min, T0_max ); + } + + /*-----------------------------------------------------------------* + * zero adaptive excitation signal construction + *-----------------------------------------------------------------*/ + + if ( *tc_subfr > i_subfr ) + { + *gain_pit = 0.0f; + *clip_gain = 0; + g_corr[0] = 1.0f; + g_corr[1] = 1.0f; + + set_f(&exc[i_subfr], 0, L_SUBFR); /* set excitation for current subrame to 0 */ + + if( L_frame == L_FRAME ) + { + set_f(&bwe_exc[i_subfr*HIBND_ACB_L_FAC], 0, (short) (L_SUBFR*HIBND_ACB_L_FAC)); /* set past excitation buffer to 0 */ + } + else + { + set_f(&bwe_exc[i_subfr*2], 0, (short) (L_SUBFR*2)); /* set past excitation buffer to 0 */ + } + + set_f(y1, 0, L_SUBFR); /* set filtered adaptive excitation to 0 */ + mvr2r(xn, xn2, L_SUBFR); /* target vector for codebook search */ + *T0 = L_SUBFR; + *T0_frac = 0; + + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; /* save subframe pitch values */ + } + + /*-----------------------------------------------------------------* + * glottal codebook contribution construction + *-----------------------------------------------------------------*/ + + else if ( *tc_subfr == i_subfr ) + { + if( L_frame == L_FRAME ) + { + set_f( bwe_exc-PIT_MAX*HIBND_ACB_L_FAC, 0, PIT_MAX*HIBND_ACB_L_FAC); /* set past excitation buffer to 0 */ + } + else + { + set_f( bwe_exc-PIT16k_MAX*2, 0, PIT16k_MAX*2); /* set past excitation buffer to 0 */ + } + + tc_enc( st, core_brate, L_frame, i_subfr, tc_subfr, position, h1, xn, exc, y1, T0_min, T0_max, T0, T0_frac, gain_pit, g_corr, bwe_exc ); + + *clip_gain = gp_clip( core_brate, voicing, i_subfr, coder_type, xn, gp_cl ); + updt_tar( xn, xn2, y1, *gain_pit, L_SUBFR ); + + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; /* save subframe pitch values */ + *Jopt_flag = 1; + } + + /*--------------------------------------------------------------* + * 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 ( *tc_subfr < i_subfr) + { + if( L_frame == L_FRAME ) + { + *Jopt_flag = 1; + + /* pit_flag for T0 bits number coding determination */ + if( ((i_subfr - *tc_subfr) == L_SUBFR) || ((i_subfr - *tc_subfr) == L_SUBFR-TC_0_0) ) + { + pit_flag = 0; + } + else + { + pit_flag = L_SUBFR; + } + if( *tc_subfr == TC_0_0 ) + { + if( i_subfr == L_SUBFR ) + { + limit_T0( L_FRAME, 8, pit_flag, limit_flag, *T0, 0, T0_min, T0_max ); + } + pit_flag = 1; + } + + /*----------------------------------------------------------* + * if tc_subfr==0, change tc_subfr corresponding to the + * second glot. impulse position + *----------------------------------------------------------*/ + + if( (*tc_subfr == 0) && (i_subfr == L_SUBFR) ) + { + if( PIT_MIN > (*position) ) + { + pit_start = L_SUBFR - (*position); + } + else + { + pit_start = PIT_MIN; + } + if( pit_start < PIT_MIN ) + { + pit_start = PIT_MIN; + } + + pit_limit = 2*pit_start + (*position); + + /* Find the closed loop pitch period */ + *T0 = pitch_fr4( &exc[i_subfr], xn, h1, *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); + for (i=0; i(2*L_SUBFR-(*position)) ) + { + if( (*T0) + (*position) >= 3*L_SUBFR) + { + /* second glottal impulse is in the 4th subframe */ + *tc_subfr = TC_0_192; + } + else + { + /* second glottal impulse is in the 3rd subframe */ + *tc_subfr = TC_0_128; + } + } + else if( (*tc_subfr == 0) && (i_subfr == L_SUBFR) ) + { + /* second glottal impulse is in the 2nd subframe */ + *tc_subfr = TC_0_64; + } + } + + /*-----------------------------------------------------------------* + * get number of bits for pitch encoding + *-----------------------------------------------------------------*/ + + nBits = ACB_bits_tbl[BIT_ALLOC_IDX(core_brate, TRANSITION, i_subfr, TC_SUBFR2IDX(*tc_subfr))]; + + /*-----------------------------------------------------------------* + * Find adaptive part of excitation, encode pitch period + *-----------------------------------------------------------------*/ + + /* first glottal impulse is in the 1st subrame */ + if( (i_subfr == L_SUBFR) && (*tc_subfr >= TC_0_128) ) + { + /*--------------------------------------------------------* + * second glottal impulse is in the 3rd or 4th subframe + * - build exc[] in 2nd subframe + *--------------------------------------------------------*/ + + *T0 = 2*L_SUBFR; + *T0_frac = 0; + *Jopt_flag = 0; + + set_f( &exc[i_subfr], 0, (short)(L_SUBFR+1) ); + set_f( &bwe_exc[i_subfr*HIBND_ACB_L_FAC], 0, (short)(L_SUBFR*HIBND_ACB_L_FAC) ); + } + else if( (i_subfr == L_SUBFR) && (*tc_subfr == TC_0_64) ) + { + /*--------------------------------------------------------* + * second glottal impulse is in the 2nd subframe, + * - build exc[] in 2nd subframe + *--------------------------------------------------------*/ + + if( (*T0)+(*position) < L_SUBFR ) + { + /* impulse must be in the 2nd subframe (not in 1st) */ + *T0 = L_SUBFR - (*position); + *T0_frac = 0; + } + + if( (*T0)+(*position) >= 2*L_SUBFR ) + { + /* impulse must be in the 2nd subframe (not in 3rd) */ + *T0 = 2*L_SUBFR-1-(*position); + *T0_frac = 2; + } + + limit_T0( L_FRAME, 8, pit_flag, limit_flag, *T0, 0, T0_min, T0_max ); /* find T0_min and T0_max for delta search */ + + /* 7bit ENCODER */ + index = (*T0-pit_start)*2 + *T0_frac/2; + push_indice( st, IND_PITCH, index, nBits ); + + /* Find the adaptive codebook vector - ACELP long-term prediction */ + pred_lt4( &exc[i_subfr], &exc[i_subfr], *T0, *T0_frac, L_SUBFR+1, inter4_2, L_INTERPOL2, PIT_UP_SAMP); + + offset = tbe_celp_exc_offset(*T0, *T0_frac); + for (i=0; i= 3*L_SUBFR ) + { + /* impulse must be in the 3rd subframe (not in 4th) */ + *T0 = 3*L_SUBFR - 1 - (*position); + *T0_frac = 2; + } + + limit_T0( L_FRAME, 8, pit_flag, limit_flag, *T0, 0, T0_min, T0_max ); /* find T0_min and T0_max for delta search */ + + index = (*T0-pit_start)*2 + *T0_frac/2; + push_indice( st, IND_PITCH, index, nBits ); + + /* Find the adaptive codebook vector - ACELP long-term prediction */ + pred_lt4( &exc[i_subfr], &exc[i_subfr], *T0, *T0_frac, L_SUBFR+1, inter4_2, L_INTERPOL2, PIT_UP_SAMP ); + + offset = tbe_celp_exc_offset(*T0, *T0_frac); + for (i=0; i= 2*L_SUBFR) && (i_subfr == 3*L_SUBFR) ) + { + (*pt_pitch) -= 3; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + } + else if( (*tc_subfr == L_SUBFR) && (i_subfr == 2*L_SUBFR) ) + { + (*pt_pitch) -= 2; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + } + else if( (*tc_subfr == TC_0_64) && (i_subfr == L_SUBFR) ) + { + (*pt_pitch) -= 1; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + } + else if( (*tc_subfr == TC_0_128) && (i_subfr == 2*L_SUBFR) ) + { + (*pt_pitch) -= 2; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + } + else if( (*tc_subfr == TC_0_192) && (i_subfr == 3*L_SUBFR) ) + { + (*pt_pitch) -= 3; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + **pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f; + (*pt_pitch)++; + } + } + else /* L_frame == L_FRAME16k */ + { + if( i_subfr >= 2*L_SUBFR ) + { + limit_flag = 1; + } + + if( i_subfr <= 2*L_SUBFR ) + { + if( i_subfr < 2*L_SUBFR ) + { + mult_Top = 1; + if( T_op[0] < PIT16k_MIN ) + { + mult_Top = 2; + } + limit_T0( L_FRAME16k, 8, 0, limit_flag, mult_Top*T_op[0], 0, T0_min, T0_max ); /* TC0 second subfr. */ + } + else + { + limit_T0( L_FRAME16k, 8, 0, limit_flag, T_op[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(core_brate, coder_type, i_subfr, TC_SUBFR2IDX_16KHZ(*tc_subfr))]; + + /*-----------------------------------------------------------------* + * Find adaptive part of excitation, encode pitch period + *-----------------------------------------------------------------*/ + + if( nBits == 10 ) + { + *T0 = pitch_fr4( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, 0, limit_flag, PIT16k_FR2_EXTEND_10b, PIT16k_MAX, L_frame, L_SUBFR ); + pit16k_Q_enc( st, nBits, limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + else if( 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( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, 0, limit_flag, PIT16k_FR2_TC0_2SUBFR, 2*L_SUBFR, L_frame, L_SUBFR ); + + if( *T0_max > 2*L_SUBFR ) + { + *T0 = 2*L_SUBFR; + *T0_frac = 0; + } + + if( *T0 < PIT16k_FR2_TC0_2SUBFR ) + { + index = (*T0)*4 + (*T0_frac) - (PIT16k_MIN*4); + } + else + { + index = (*T0)*2 + ((*T0_frac)>>1) - (PIT16k_FR2_TC0_2SUBFR*2) + ((PIT16k_FR2_TC0_2SUBFR-PIT16k_MIN)*4); + } + + push_indice( st, IND_PITCH, index, nBits ); + } + else if( nBits == 6 ) + { + /* delta search */ + *T0 = pitch_fr4( &exc[i_subfr], xn, h1, *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( 4, *T0, *T0_frac, *T0_min ); + + push_indice( st, IND_PITCH, index, nBits ); + } + if( nBits == 6 ) + { + limit_T0( 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 + *-----------------------------------------------------------------*/ + + if( (i_subfr == L_SUBFR) && (*T0 == 2*L_SUBFR) ) + { + *gain_pit = 0.0f; + *clip_gain = 0; + g_corr[0] = 0.01f; + g_corr[1] = 0.01f; + *Jopt_flag = 0; + + set_f( &exc[i_subfr], 0, L_SUBFR+1 ); /* set excitation for current subrame to 0 */ + + push_indice( st, IND_LP_FILT_SELECT, 0, 1 ); /* this bit is actually not needed */ + + mvr2r( xn, xn2, L_SUBFR ); /* target vector for codebook search */ + set_f( y1, 0, L_SUBFR ); /* set filtered adaptive excitation to 0 */ + set_f( &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, inter4_2, L_INTERPOL2, PIT_UP_SAMP ); + + 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( + Encoder_State *st, /* i/o: encoder state structure */ + const long core_brate, /* i : core bitrate */ + const short L_frame, /* i : length of the frame */ + const short i_subfr, /* i : subrame index */ + short *tc_subfr, /* i/o: TC subframe index */ + short *position, /* i/o: index of the residual signal maximum */ + const float *h1, /* i : weighted filter input response */ + const float *xn, /* i : target signal */ + float *exc, /* o : glottal codebook contribution */ + float *y1, /* o : filtered glottal codebook contribution */ + short *T0_min, /* o : lower pitch limit */ + short *T0_max, /* o : higher pitch limit */ + short *T0, /* o : close loop integer pitch */ + short *T0_frac, /* o : close loop fractional part of the pitch */ + float *gain_pit, /* o : pitch gain (0..GAIN_PIT_MAX) */ + float g_corr[], /* o : correlations and -2 */ + float *bwe_exc /* i/o: excitation for SWB TBE */ +) +{ + short imp_shape, imp_pos, imp_sign, imp_gain, index, nBits; + float gain_trans; + + imp_pos = *position-i_subfr; + + /*-----------------------------------------------------------------* + * get number of bits for pitch encoding + *-----------------------------------------------------------------*/ + + if( L_frame == L_FRAME ) + { + nBits = ACB_bits_tbl[BIT_ALLOC_IDX(core_brate, TRANSITION, i_subfr, TC_SUBFR2IDX(*tc_subfr))]; + } + else /* L_frame == L_FRAME16k */ + { + nBits = ACB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ(core_brate, TRANSITION, i_subfr, TC_SUBFR2IDX_16KHZ(*tc_subfr))]; + } + + /*--------------------------------------------------------------* + * Closed loop pitch search + *--------------------------------------------------------------*/ + + *T0_frac = 0; + if( L_frame == L_FRAME ) + { + if( (*T0_min <= L_SUBFR) || (*tc_subfr == 3*L_SUBFR) ) + { + if( nBits == 9 ) + { + *T0 = pitch_fr4( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, 0, 0, PIT_FR2_9b, PIT_FR1_9b, L_FRAME, L_SUBFR ); + } + else if( nBits == 6 ) + { + *T0 = pitch_fr4( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, 0, 0, PIT_MIN, L_SUBFR, L_FRAME, L_SUBFR ); + } + else + { + *T0 = pitch_fr4( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, 0, 0, PIT_MAX, PIT_MIN, L_FRAME, L_SUBFR ); + } + } + else + { + *T0 = L_SUBFR; + } + + if( (*tc_subfr == L_SUBFR) && (*T0 < L_SUBFR) ) + { + *T0 = L_SUBFR; + } + } + else /* L_frame == L_FRAME16k */ + { + if( nBits == 10 ) + { + *T0 = pitch_fr4( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, 0, 1, PIT16k_FR2_EXTEND_10b, PIT16k_MAX, L_FRAME16k, L_SUBFR ); + } + else if( nBits == 6 ) + { + /* T0_frac with 1/2 sample resolution */ + *T0 = pitch_fr4( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, 0, 0, PIT16k_MIN, L_SUBFR, L_FRAME16k, L_SUBFR ); + + if( *T0 > L_SUBFR ) + { + *T0 = L_SUBFR; + *T0_frac = 0; + } + } + } + + /* set tc_subfr to TC_0_0 */ + if( i_subfr == 0 && L_frame == L_FRAME && ( *T0 < L_SUBFR || *tc_subfr == 3*L_SUBFR ) ) + { + *tc_subfr = TC_0_0; + } + + /*--------------------------------------------------------------* + * Builds glottal codebook contribution + *--------------------------------------------------------------*/ + + set_impulse( xn, h1, &exc[i_subfr], y1, &imp_shape, &imp_pos, &gain_trans ); + + /*--------------------------------------------------------------* + * quantize gain_trans and scale glottal codebook contribution + *--------------------------------------------------------------*/ + + gain_trans_enc( &gain_trans, &exc[i_subfr], &imp_gain, &imp_sign ); + + /* set past excitation buffer to zeros */ + set_f( exc-L_EXC_MEM, 0, L_EXC_MEM ); + + /*--------------------------------------------------------------* + * adapt. search of the second impulse in the same subframe + * (when appears) + *--------------------------------------------------------------*/ + + pred_lt4_tc( exc, *T0, *T0_frac, inter4_2, imp_pos, i_subfr); + + if( L_frame == L_FRAME ) + { + interp_code_5over2(&exc[i_subfr], &bwe_exc[i_subfr * HIBND_ACB_L_FAC], L_SUBFR); + } + else + { + interp_code_4over2(&exc[i_subfr], &bwe_exc[i_subfr * 2], L_SUBFR); + } + + /*--------------------------------------------------------------* + * compute glottal-shape codebook excitation + *--------------------------------------------------------------*/ + + /* create filtered glottal codebook contribution */ + conv( &exc[i_subfr], h1, y1, L_SUBFR ); + + /* gain_pit computation */ + *gain_pit = corr_xy1( xn, y1, g_corr, L_SUBFR,0); + + /*--------------------------------------------------------------* + * Encode parameters and write indices + *--------------------------------------------------------------*/ + + if( L_frame == L_FRAME ) + { + if( ( (i_subfr != 0) || (*tc_subfr == TC_0_0) ) + && (*tc_subfr != L_SUBFR)) + { + /* write pitch index */ + if( (*T0 >= L_SUBFR) && (*tc_subfr != 3*L_SUBFR) ) + { + push_indice( st, IND_PITCH, 0, nBits ); + } + else if( *tc_subfr == 3*L_SUBFR ) + { + if( nBits == 9 ) + { + index = abs_pit_enc( 4, 0, *T0, *T0_frac ); + } + else + { + index = abs_pit_enc( 2, 0, *T0, *T0_frac ); + } + + push_indice( st, IND_PITCH, index, nBits ); + + limit_T0( L_FRAME, 8, 0, 0, *T0, 0, T0_min, T0_max ); + } + else + { + if( nBits == 6 ) + { + index = delta_pit_enc( 2, *T0, *T0_frac, PIT_MIN-1 ); + push_indice( st, IND_PITCH, index, nBits ); + } + else + { + index = delta_pit_enc( 0, *T0, *T0_frac, PIT_MIN-1 ); + push_indice( st, IND_PITCH, index, nBits ); + } + } + } + } + else /* L_frame == L_FRAME16k */ + { + if( nBits == 10 ) + { + pit16k_Q_enc( st, nBits, 1, *T0, *T0_frac, T0_min, T0_max ); + } + else if( nBits == 6 ) + { + index = 2*(*T0 - PIT16k_MIN) + *T0_frac/2; + push_indice( st, IND_PITCH, index, nBits ); + } + } + + push_indice( st, IND_TC_IMP_SHAPE, imp_shape, 3 ); + push_indice( st, IND_TC_IMP_POS, imp_pos, 6 ); + push_indice( st, IND_TC_IMP_SIGN, imp_sign, 1 ); + push_indice( st, IND_TC_IMP_GAIN, imp_gain, 3 ); + + *position = imp_pos + i_subfr; + + 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( + float *gain_trans, /* i/o: gain for TC */ + float exc[], /* i/o: glottal codebook contribution */ + short *quant_index, /* o : index of quantized gain_trans */ + short *quant_sign /* o : sign of quantized gain_trans */ +) +{ + short i; + + + if( *gain_trans < 0 ) + { + *gain_trans *= -1; + *quant_sign = 0; + } + else + { + *quant_sign = 1; + } + + *quant_index = N_GAIN_TC-1; + + for( i=0; i +#include + + + +void bg_music_decision(T_CldfbVadState *st, + int *music_backgound_f, /*(i) background music flag*/ + float frame_energy /*(i) current frame energy 1*/ + ) +{ + int music_background_frame=0; + float *sp_center = st->sp_center; + float *ltd_stable_rate = st->ltd_stable_rate; + float *sSFM = st->sfm; + float *f_tonality_rate = st->f_tonality_rate; + + + if((f_tonality_rate[1]>0.60)||(f_tonality_rate[0]>0.86)) + { + if(ltd_stable_rate[0]<0.072&& sp_center[0]>1.2&&(sSFM[0]<0.76|| sSFM[1]<0.88|| sSFM[2]<0.96)) + { + music_background_frame = 1; + } + } + if(music_background_frame&&(4.6*st->fg_energy_count*frame_energy>st->fg_energy)&&(st->fg_energy_est_start==1)) + { + st->music_background_rate = st->music_background_rate*0.975f + 0.025f; + } + else if(music_background_frame) + { + st->music_background_rate = st->music_background_rate*0.998f + 0.002f; + } + else + { + st->music_background_rate = st->music_background_rate*0.997f; + } + if(st->music_background_rate>0.5) + { + *music_backgound_f = 1; + } + else + { + *music_backgound_f = 0; + } +} + +int update_decision(T_CldfbVadState *st, + float snr, /*(i) frequency domain SNR */ + float tsnr, /*(i) time domain SNR */ + float frame_energy, /*(i) current frame energy*/ + float high_eng, /*(i) current frame high frequency energy*/ + int vad_flag, + int music_backgound_f /*(i) background music flag*/ + ) +{ + float g_high_eng_sacle = 0.0f; + float sp_center3_diff; + int update_flag = 1; + int tonality_flag = 0; + int frameloop = st->frameloop; + int bw = st->bw_index; + float *sp_center = st->sp_center; + float *ltd_stable_rate = st->ltd_stable_rate; + float *sSFM = st->sfm; + float *f_tonality_rate = st->f_tonality_rate; + float tmpout = frame_energy - 4*st->frame_energy_smooth; + + + g_high_eng_sacle = high_eng/(st->lt_bg_highf_eng + FLT_MIN); + sp_center3_diff = sp_center[3] - st->lt_noise_sp_center3; + if(frameloop>50) + { + + if(ltd_stable_rate[0]>0.12) + { + update_flag=0; + } + + if((bw == CLDFBVAD_WB_ID || bw == CLDFBVAD_SWB_ID) && st->frame_energy_smooth < 4*frame_energy) + { + if(g_high_eng_sacle > 3.0f && (sp_center3_diff > 0.4)) + { + update_flag = 0; + } + if((sp_center[3]>2.8f)&&(ltd_stable_rate[0]>0.02f)) + { + update_flag = 0; + } + } + } + + + + if((f_tonality_rate[1] > 0.50) && (ltd_stable_rate[0]>0.1)) + { + update_flag = 0; + } + if(sSFM[1] < 0.92 && sSFM[0] < 0.92 && sSFM[2] < 0.92) + { + update_flag=0; + } + if(sSFM[0] < 0.80 || sSFM[1] < 0.78|| sSFM[2] < 0.80) + { + update_flag=0; + } + + if(frame_energy > 32*st->frame_energy_smooth) + { + update_flag = 0; + } + if((4.6*st->fg_energy_count*frame_energy>st->fg_energy)&&(st->fg_energy_est_start==1)&&(frame_energy>3)) + { + update_flag = 0; + } + if((f_tonality_rate[1]>0.60)||(f_tonality_rate[0]>0.86)) + { + update_flag = 0; + tonality_flag = 1; + } + + + if(tonality_flag) + { + st->tonality_rate3 = st->tonality_rate3*0.983f + 0.017f; + } + else + { + st->tonality_rate3 = st->tonality_rate3*0.983f; + } + + if(st->tonality_rate3>0.5) + { + update_flag = 0; + } + + + if((sp_center[0] > 4.0f) && ltd_stable_rate[0]>0.04) + { + update_flag = 0; + } + if((f_tonality_rate[1] > 0.46) && ((sSFM[1] > 0.93)||(ltd_stable_rate[0]>0.09))) + { + update_flag = 0; + + } + if((sSFM[1] < 0.93 && sSFM[0] < 0.92 && sSFM[2] < 0.97) && (f_tonality_rate[1] > 0.5)) + { + update_flag = 0; + } + if((f_tonality_rate[1] > 0.43)&&(sSFM[0] < 0.95)&&(sp_center[1] > 1.94f)) + { + update_flag = 0; + } + + if(update_flag) + { + if(st->update_count < 1000) + { + st->update_count = st->update_count + 1; + } + + } + + + if(update_flag) + { + st->lt_noise_sp_center3 = 0.9f*st->lt_noise_sp_center3 + 0.1f*sp_center[3]; + } + if((tmpout>0)&&(frameloop<100)&&(f_tonality_rate[1]<0.56)&&((sp_center[0]<1.36)|| ltd_stable_rate[0]<0.03)) + { + update_flag = 1; + } + if(snr<0.3 && tmpout < 0 + && tsnr<1.2&& vad_flag==0&& f_tonality_rate[1]<0.5 + &&(music_backgound_f==0)&& ltd_stable_rate[3]<0.1) + + { + update_flag = 1; + } + if(vad_flag && (snr > 1.0) && bw == CLDFBVAD_SWB_ID && tmpout > 0) + { + update_flag = 0; + } + + if(vad_flag && (snr > 1.5) && bw != CLDFBVAD_SWB_ID && tmpout > 0) + { + update_flag = 0; + } + + + if(update_flag == 0) + { + st->update_num_with_snr = 0; + } + else + { + + if(vad_flag && (snr > 3.0) && st->update_num_with_snr < 10) + { + update_flag = 0; + st->update_num_with_snr++; + } + } + + + + if(vad_flag==0|| update_flag == 1) + { + float tmpp =(float)fabs(st->sp_center[2]-st->lt_noise_sp_center0); + if(tmpp>2.5) + { + tmpp = 2.5f; + } + st->lt_noise_sp_center_diff_sum +=tmpp; + st->lt_noise_sp_center_diff_counter++; + if(st->lt_noise_sp_center_diff_counter==128) + { + st->lt_noise_sp_center_diff_sum = st->lt_noise_sp_center_diff_sum*0.75f; + st->lt_noise_sp_center_diff_counter = 96; + } + if(fabs(sp_center[0]-st->lt_noise_sp_center0) >2.4 ) + { + st->lt_noise_sp_center0 = 0.996f*st->lt_noise_sp_center0 + 0.004f*sp_center[0]; + } + else if(fabs(sp_center[0]-st->lt_noise_sp_center0) >1.0 ) + { + st->lt_noise_sp_center0 = 0.99f*st->lt_noise_sp_center0 + 0.01f*sp_center[0]; + } + else + { + st->lt_noise_sp_center0 = 0.96f*st->lt_noise_sp_center0 + 0.04f*sp_center[0]; + } + } + + if((fabs(sp_center[2]-st->lt_noise_sp_center0) > (6*(st->lt_noise_sp_center_diff_sum/st->lt_noise_sp_center_diff_counter)+0.3))&& st->frameloop>200) + { + update_flag = 0; + } + + + return update_flag; +} diff --git a/lib_enc/updt_enc.c b/lib_enc/updt_enc.c new file mode 100644 index 000000000..df59182ab --- /dev/null +++ b/lib_enc/updt_enc.c @@ -0,0 +1,234 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "cnst.h" +#include "rom_com.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * updt_enc() + * + * Common updates (all frame types) + *-------------------------------------------------------------------*/ + +void updt_enc( + Encoder_State *st, /* i/o: state structure */ + const short L_frame, /* i : length of the frame */ + const short coder_type, /* i : speech coder type */ + const float *old_exc, /* i : buffer of excitation */ + const float *pitch_buf, /* i : floating pitch for each subframe */ + const float Es_pred, /* i : predicited scaled innovation energy */ + const float *Aq, /* i : A(z) quantized for all subframes */ + const float *lsf_new, /* i : current frame LSF vector */ + const float *lsp_new, /* i : current frame LSP vector */ + const float *old_bwe_exc /* i : buffer of excitation */ +) +{ + short i; + + /* update old excitation buffer */ + mvr2r( &old_exc[L_frame], st->LPDmem.old_exc, L_EXC_MEM ); + if( !st->Opt_AMR_WB ) + { + mvr2r( &old_bwe_exc[L_FRAME32k], st->old_bwe_exc, PIT16k_MAX * 2 ); + } + + /* update old LSP and LSF vector */ + mvr2r( lsp_new, st->lsp_old, M ); + mvr2r( lsf_new, st->lsf_old, M ); + + /* update last coder type */ + st->last_coder_type = coder_type; + if ( coder_type == INACTIVE || (st->bpf_off == 1 && coder_type != AUDIO && coder_type != TRANSITION) ) + { + st->last_coder_type = UNVOICED; + } + + /* this ensures that st->last_coder_type is never set to INACTIVE in case of AVQ inactive because the FEC does not distinguish between GSC inactive and AVQ inactive */ + if ( coder_type == INACTIVE && st->total_brate > ACELP_24k40 ) + { + st->last_coder_type = GENERIC; + } + + if( st->Opt_AMR_WB && coder_type == INACTIVE && st->core_brate != SID_1k75 && st->core_brate != FRAME_NO_DATA ) + { + /* overwrite previous coding type to help FEC */ + st->last_coder_type = UNVOICED; + } + + /* AC mode (GSC) - in speech we can consider that the last pitch band reached the max */ + if ( coder_type != AUDIO && coder_type != INACTIVE ) + { + st->mem_last_pit_band = 10 + BAND1k2; + st->past_dyn_dec = NOISE_LEVEL_SP0-1; /* tends to speech */ + st->noise_lev = NOISE_LEVEL_SP0-1; /* tends to speech */ + st->mid_dyn = 40.0f * 0.5f + st->mid_dyn * 0.5f; + } + + /* convert old LSP vector from 12kHz domain to 16kHz domain (needed in case of ACELP@12k8 <-> ACELP@16kHz switching) */ + if( L_frame == L_FRAME ) + { + mvr2r( st->lsp_old, st->lsp_old16k, M ); + + st->rate_switching_reset_16kHz=lsp_convert_poly( st->lsp_old16k, L_FRAME16k, st->Opt_AMR_WB ); + } + + /* update buffer of old subframe pitch values */ + if( st->last_L_frame != L_frame ) + { + if( L_frame == L_FRAME ) + { + for( i=0; iold_pitch_buf[NB_SUBFR+i] = 0.8f * st->old_pitch_buf[NB_SUBFR+i+1]; + } + } + else + { + for( i=NB_SUBFR; i>0; i-- ) + { + st->old_pitch_buf[NB_SUBFR+i] = 1.25f * st->old_pitch_buf[NB_SUBFR+i-1]; + } + st->old_pitch_buf[2*NB_SUBFR16k-1] = st->old_pitch_buf[2*NB_SUBFR16k-2]; + } + } + + mvr2r( &st->old_pitch_buf[L_frame/L_SUBFR], st->old_pitch_buf, L_frame/L_SUBFR ); + mvr2r( pitch_buf, &st->old_pitch_buf[L_frame/L_SUBFR], L_frame/L_SUBFR ); + + /* SC-VBR */ + st->last_Opt_SC_VBR = st->Opt_SC_VBR; + st->last_last_ppp_mode = st->last_ppp_mode; + st->last_ppp_mode = st->ppp_mode; + st->last_nelp_mode = st->nelp_mode; + + /* core switching updates */ + mvr2r( &Aq[(st->L_frame/L_SUBFR-1)*(M+1)], st->old_Aq_12_8, M+1 ); + st->old_Es_pred = Es_pred; + + return; +} + +/*-------------------------------------------------------------------* + * updt_IO_switch() + * + * Common updates for AMR-WB IO mode and EVS primary mode switching + *-------------------------------------------------------------------*/ + +void updt_IO_switch_enc( + Encoder_State *st, /* i/o: state structure */ + const short input_frame /* i : input frame length */ +) +{ + float xsp_tmp[M]; + + if( st->last_core == AMR_WB_CORE ) /* switching to EVS primary mode */ + { + /* reset onset detection counter */ + st->tc_cnt = -1; + + /* force safety-net LSFQ in the first frames after the switching */ + st->Nb_ACELP_frames = 0; + + /* AMR-WB IO mode uses ISF(ISP), but EVS primary mode LSF(LSP) */ + mvr2r( stable_LSP, xsp_tmp, M ); + isf2lsf( st->lsf_old, st->lsf_old, xsp_tmp, M, INT_FS_12k8 ); + mvr2r( stable_LSP, xsp_tmp, M ); + isp2lsp( st->lsp_old, st->lsp_old, xsp_tmp, M ); + isp2lsp( st->lsp_old1, st->lsp_old1, xsp_tmp, M ); + + mvr2r( stable_LSP, xsp_tmp, M ); + isp2lsp( st->lspCNG, st->lspCNG, xsp_tmp, M ); + if( st->old_enr_index >= 0 ) + { + st->old_enr_index = min( (short)((float)st->old_enr_index / STEP_AMR_WB_SID * STEP_SID), 127 ); + } + /* Perform preemphasis of the old input signal @16kHz */ + st->mem_preemph16k = 0; + preemph( st->old_inp_16k, PREEMPH_FAC_16k, L_INP_MEM, &(st->mem_preemph16k) ); + + /* reset TD BWE buffers */ + set_f( st->old_speech_shb, 0.0f, L_LOOK_16k + L_SUBFR16k ); + set_f( st->old_speech_wb, 0.0f, (L_LOOK_12k8 + L_SUBFR) * 5/16 ); + set_f( st->old_bwe_exc, 0.0f, PIT16k_MAX * 2 ); + set_f( st->old_bwe_exc_extended, 0.0f, NL_BUFF_OFFSET ); + + st->bwe_non_lin_prev_scale = 0.0; + set_f( st->decim_state1, 0.0f, (2*ALLPASSSECTIONS_STEEP+1) ); + set_f( st->decim_state2, 0.0f, (2*ALLPASSSECTIONS_STEEP+1) ); + set_f( st->old_wtda_swb, 0, L_FRAME16k ); + set_f( st->old_input_wb, 0, NS2SA(16000, DELAY_FD_BWE_ENC_NS) ); + + wb_tbe_extras_reset( st->mem_genSHBexc_filt_down_wb2, st->mem_genSHBexc_filt_down_wb3 ); + if( input_frame >= L_FRAME32k ) + { + swb_tbe_reset( st->mem_csfilt, st->mem_genSHBexc_filt_down_shb, st->state_lpc_syn, + st->syn_overlap, st->state_syn_shbexc, &(st->tbe_demph),&(st->tbe_premph), st->mem_stp_swb, &(st->gain_prec_swb) ); + } + + if( input_frame == L_FRAME48k ) + { + set_f( st->fb_state_lpc_syn, 0, LPC_SHB_ORDER ); + st->fb_tbe_demph = 0; + fb_tbe_reset_enc( st->elliptic_bpf_2_48k_mem, &st->prev_fb_energy ); + } + + /* reset FD BWE buffers */ + st->prev_mode = NORMAL; + + /* reset the unvoiced/audio signal improvement memories */ + st->seed_tcx = 15687; + + st->use_acelp_preq = 0; + + } + else /* switching to AMR-WB IO mode */ + { + set_f( st->mem_MA, 0, M ); + + /* AMR-WB IO mode uses ISF(ISP), but EVS primary mode LSF(LSP) */ + mvr2r( stable_ISP, xsp_tmp, M ); + lsf2isf( st->lsf_old, st->lsf_old, xsp_tmp, M, INT_FS_12k8 ); + mvr2r( stable_ISP, xsp_tmp, M ); + lsp2isp( st->lsp_old, st->lsp_old, xsp_tmp, M ); + mvr2r( st->lsp_old, st->lsp_old1, M ); + lsp2isp( st->lsp_old1, st->lsp_old1, xsp_tmp, M ); + mvr2r( stable_ISP, xsp_tmp, M ); + lsp2isp( st->lspCNG, st->lspCNG, xsp_tmp, M ); + if( st->old_enr_index >= 0 ) + { + st->old_enr_index = min( (short)((float)st->old_enr_index / STEP_SID * STEP_AMR_WB_SID), 63 ); + } + + /* gain quantization memory */ + set_f(st->past_qua_en, -14.0f, GAIN_PRED_ORDER ); + + /* reset VBR signalling */ + st->ppp_mode = 0; + st->nelp_mode = 0; + + /* reset the unvoiced/audio signal improvement memories */ + st->seed_tcx = 15687; + } + + /* Force SID in case of AMR-WB IO mode/EVS primary mode switching */ + st->cnt_SID = 0; + + /* CNG - reset */ + st->cng_cnt = 0; + st->ho_hist_size = 0; + st->burst_ho_cnt = 0; + + /* LP memories */ + mvr2r( UVWB_Ave, st->mem_AR, M ); + + /* FEC - update adaptive LSF mean vector */ + mvr2r( st->lsf_old, st->lsfoldbfi0, M ); + mvr2r( st->lsf_old, st->lsfoldbfi1, M ); + mvr2r( st->lsf_old, st->lsf_adaptive_mean, M ); + + return; +} diff --git a/lib_enc/updt_tar.c b/lib_enc/updt_tar.c new file mode 100644 index 000000000..d7ba73829 --- /dev/null +++ b/lib_enc/updt_tar.c @@ -0,0 +1,29 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "wmc_auto.h" +#include "prot.h" + +/*----------------------------------------------------------------------------------* + * procedure updt_tar: + * + * Update the target vector for codebook search. + *----------------------------------------------------------------------------------*/ +void updt_tar( + const float *x, /* i : old target (for pitch search) */ + float *x2, /* o : new target (for codebook search) */ + const float *y, /* i : filtered adaptive codebook vector */ + const float gain, /* i : adaptive codebook gain */ + const short L /* i : subframe size */ +) +{ + short i; + + + for (i = 0; i < L; i++) + { + x2[i] = x[i] - gain*y[i]; + } +} diff --git a/lib_enc/vad.c b/lib_enc/vad.c new file mode 100644 index 000000000..13be30834 --- /dev/null +++ b/lib_enc/vad.c @@ -0,0 +1,1010 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_enc.h" + + +/*-----------------------------------------------------------------* + * Local constants + *-----------------------------------------------------------------*/ + +#define HANGOVER_LONG 10 /* Hangover for CNG */ +#define HANGOVER_LONG_HE 20 /* Hangover of CNG */ +#define HANGOVER_LONG_MUSIC 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 */ + +#define TH16_2 35.0f /* long-term SNR that separates the curves for clean speech and noisy speech */ +#define TH8_1 20.0f /* long-term SNR that separates the curves for clean speech and noisy speech */ +#define TH16_2_NFLAG 35.0f +#define TH8_1_NFLAG 35.0f + + +#define SNR_OUTLIER_WGHT_1 1.00f +#define SNR_OUTLIER_WGHT_2 1.01f +#define SNR_OUTLIER_WGHT_3 1.02f +#define OUTLIER_THR_1 10.0f +#define OUTLIER_THR_2 6.0f +#define MAX_SNR_OUTLIER_IND 17 +#define MAX_SNR_OUTLIER_1 10.0f +#define MAX_SNR_OUTLIER_2 25.0f +#define MAX_SNR_OUTLIER_3 50.0f + +/*---------------------------------------------------------------------* + * wb_vad_init() + * + * VAD initializations + *---------------------------------------------------------------------*/ + +void wb_vad_init( + short *nb_active_frames, /* o : nb of consecutive active speech frames */ + short *hangover_cnt, + float *lp_speech, /* o : long-term active speech level */ + short *nb_active_frames_he, /* o : nb of consecutive active speech frames */ + short *hangover_cnt_he, + float *bcg_flux, /* o : background noise fluctuation */ + short *soft_hangover, /* o : soft hangover counter */ + short *voiced_burst, /* o : consecutive voiced speech counter */ + short *bcg_flux_init, /* o : initialization period for noise fluctuation estimation */ + short *nb_active_frames_he1, /* o : nb of consecutive active speech frames 1 */ + short *hangover_cnt_he1, + long *vad_flag_reg_H, + long *vad_flag_reg_L, + long *vad_prim_reg, + short *vad_flag_cnt_50, + short *vad_prim_cnt_16, + short *hangover_cnt_dtx, + short *flag_noisy_speech_snr + ,short *hangover_cnt_music /* o : counter of VAD DTX Music hangover frames */ +) +{ + *hangover_cnt = 0; /* Hangover counter initialized to 0 */ + *nb_active_frames = ACTIVE_FRAMES; /* The counter of SPEECH frames necessary to trigger HO */ + /* is set to max (-> start with hangover) */ + *lp_speech = 45.0f; /* Initialize the long-term active speech level in dB */ + *flag_noisy_speech_snr=0; + + *vad_flag_reg_H = 0L; + *vad_flag_reg_L = 0L; + *vad_prim_reg = 0L; + *vad_flag_cnt_50 = 0; + *vad_prim_cnt_16 = 0; + + /* By default one should not start with a hangover */ + *hangover_cnt_dtx = HANGOVER_LONG; /* hangover for DTX */ + *hangover_cnt_music = HANGOVER_LONG_MUSIC; /* hangover for DTX */ + + *hangover_cnt_he = 0; /* Hangover counter initialized to 0 */ + *nb_active_frames_he = ACTIVE_FRAMES; /* The counter of SPEECH frames necessary to trigger HO */ + *bcg_flux = 70; + *soft_hangover = 0; + *voiced_burst = 0; + *bcg_flux_init = 50; + *nb_active_frames_he1 = ACTIVE_FRAMES; + *hangover_cnt_he1 = 0; + + return; +} + +/*-----------------------------------------------------------------* + * sing_thr_snr_acc() + * + * accumulate snr_sum with significance thresholds + *-----------------------------------------------------------------*/ + +static void sign_thr_snr_acc( + float *snr_sum, + float snr, + float sign_thr, + float min_snr +) +{ + if( snr >= sign_thr ) + { + *snr_sum = *snr_sum + snr; + } + else + { + *snr_sum = *snr_sum + min_snr; + } + + return; +} + +/*-----------------------------------------------------------------* + * dtx_hangover_addition() + * + * accumulate snr_sum with significance thresholds + *-----------------------------------------------------------------*/ + +short dtx_hangover_addition( + Encoder_State *st, /* i/o: encoder state structure */ + const short localVAD, + const short vad_flag, + const float lp_snr, + const short cldfb_subtraction, + short *vad_hover_flag +) +{ + short hangover_short_dtx, flag_dtx; + short ho_limit_clean; + + flag_dtx = 0; + + /* Determine initial hangover length */ + hangover_short_dtx = 2; /* was 1 */ + if ( ( lp_snr < 16.0f && st->input_bwidth != NB ) || + st->prim_act_he > 0.95f ) + { + hangover_short_dtx = 3; /* was 2 */ + } + + /* Adjust hangover according to activity history */ + if (st->vad_prim_cnt_16 > 12 ) /* 12 requires roughly > 80% primary activity */ + { + hangover_short_dtx = hangover_short_dtx + 2; + } + + if (st->vad_flag_cnt_50 >40 ) /* 40 requires roughtly > 80% flag activity */ + { + hangover_short_dtx = hangover_short_dtx + 5; + } + + /* Keep hangover_short lower than maximum hangover count */ + if (hangover_short_dtx > HANGOVER_LONG-1) + { + hangover_short_dtx = HANGOVER_LONG-1; + } + + /* Only allow short HO if not sufficient active frames */ + ho_limit_clean = 3; + if (st->core == AMR_WB_CORE ) + { + ho_limit_clean = 2; + } + + if ( st->input_bwidth != NB && st->core != AMR_WB_CORE && lp_snr > 25.0f ) + { + ho_limit_clean = 2; + } + + if ( ho_limit_clean != 0 ) + { + if ( (hangover_short_dtx > ho_limit_clean) && ( ( st->vad_prim_cnt_16 < 7 ) || ( lp_snr > 16 && st->prim_act_he < 0.85 ) ) ) + { + hangover_short_dtx = ho_limit_clean; + } + } + + + /* hangover adjustment from combined FFT + CLDFBVAD */ + if (st->core != AMR_WB_CORE) + { + hangover_short_dtx = hangover_short_dtx - cldfb_subtraction; + if( hangover_short_dtx < 0 ) + { + hangover_short_dtx = 0; + } + } + if ( vad_flag == 1 ) /* Speech present */ + { + flag_dtx = 1; + + /* Add hangover after sufficient # of active frames or sufficient activity during last second */ + if (st->nb_active_frames >= ACTIVE_FRAMES || st->vad_flag_cnt_50 >45 ) /* 45 requires roughtly > 90% flag activity */ + { + st->hangover_cnt_dtx = 0; + } + + /* inside HO period */ + if( st->hangover_cnt_dtx < HANGOVER_LONG && st->hangover_cnt_dtx != 0 ) + { + st->hangover_cnt_dtx++; + } + + st->hangover_terminate_flag = 0; + + /* Music hangover when music detected */ + if( st->prim_act_he > 0.98f && st->Etot_lp > 40 && st->vad_prim_cnt_16 > 14 && st->vad_flag_cnt_50 > 48 ) + { + st->hangover_cnt_music = 0; + } + + /* inside music HO period */ + if (st->hangover_cnt_music < HANGOVER_LONG_MUSIC && st->hangover_cnt_music != 0 ) + { + st->hangover_cnt_music++; + } + } + else + { + /* Reset the counter of speech frames necessary to start hangover algorithm */ + if(st->hangover_cnt_dtx < HANGOVER_LONG ) /* inside HO period */ + { + st->hangover_cnt_dtx++; + } + if(st->hangover_cnt_music < HANGOVER_LONG_MUSIC ) /* inside music HO period */ + { + st->hangover_cnt_music++; + } + /* fast terminate DTX hangover if st->hangover_terminate_flag is set */ + if ( st->hangover_terminate_flag == 1 ) + { + st->hangover_cnt = HANGOVER_LONG; + st->hangover_cnt_dtx = HANGOVER_LONG; + st->hangover_terminate_flag = 0; + /* only shorten music hangover when low energy frames */ + if ( st->Etot_lp < 20.0f ) + { + st->hangover_cnt_music = HANGOVER_LONG_MUSIC; + } + } + + if( st->hangover_cnt_dtx <= hangover_short_dtx ) /* "hard" hangover */ + { + flag_dtx = 1; + } + + if( st->hangover_cnt_music <= 15 ) /* "hard" hangover */ + { + flag_dtx = 1; + } + + } + + + if ( flag_dtx != 0 && localVAD == 0 ) + { + *vad_hover_flag = 1; + } + + return flag_dtx ; +} + + +/*-----------------------------------------------------------------* + * wb_vad() + * + * Voice Activity Detector + *-----------------------------------------------------------------*/ + +short wb_vad( + Encoder_State *st, /* i/o: encoder state structure */ + const float fr_bands[], /* i : per band input energy (contains 2 vectors) */ + short *localVAD, + short *noisy_speech_HO, /* o : SC-VBR noisy speech HO flag */ + short *clean_speech_HO, /* o : SC-VBR clean speech HO flag */ + short *NB_speech_HO, /* o : SC-VBR NB speech HO flag */ + float *snr_sum_he, /* o : Output snr_sum as weighted spectral measure */ + short *localVAD_HE_SAD, /* o : HE_SAD decision without hangovers */ + short *flag_noisy_speech_snr /* o: */ +) +{ + short i, j, flag, hangover_short; + float snr[NB_BANDS], snr_sum, thr1, thr2, lp_snr, nk, nc, th_clean; + const float *pt1, *pt2, *pt3; + float min_snr, sign_thr; + float fr_enr; + float ftmp, ftmp1; + float mssnr = 0; + float snr_sumt; + float vad_thr; + short hangover_hd; + short snr_idx; + float delta1, delta2, delta3; + short flag_he1; + float mssnr_hov; + short stmp; + float msnr; + float snr_outlier; + short snr_outlier_index; + float accum_ener_L, accum_ener_H; + float delta4; + float snr18=1.0f, snr19=1.0f; + short nb_sig_snr; + float nv; + float snr_sum_HE_SAD; + float sign_thr_HE_SAD,min_snr_HE_SAD; + float nv_ofs; + float thr1_ol; + float snr_sum_ol; + snr_outlier = 0; + snr_outlier_index = 0; + accum_ener_L = 0; + accum_ener_H = 0; + + if( st->input_bwidth == NB ) + { + st->min_band = 1; + st->max_band = 16; + } + else + { + st->min_band = 0; + st->max_band = 19; + } + + /*---------------------------------------------------------------------* + * set SNR thresholds depending on the input rate + *---------------------------------------------------------------------*/ + + if(st->max_band == 19 ) /* WB input */ + { + nk = 0.1f; + nc = 16.1f; + nv = 2.05f; + nv_ofs = 1.65f; + th_clean = TH16_2; + if ( st->input_bwidth == WB ) + { + sign_thr = 1.3f; + min_snr = 0.8f; + } + else + { + sign_thr = 1.75f; + min_snr = 0.25f; + } + sign_thr_HE_SAD = 2.5f; + min_snr_HE_SAD = 0.2f; + } + else /* NB input */ + { + nk = 0.10f; + nc = 16.0f; + nv = 4.00f; /* Was 4.5f but trunkated to 4.00 used when converted to short */ + nv_ofs = 1.15f; + th_clean = TH8_1; + sign_thr = 1.75f; + min_snr = 0.25f; + + sign_thr_HE_SAD = 2.65f; + min_snr_HE_SAD = 0.05f; + } + + hangover_short = 0; + + + if( st->Opt_SC_VBR ) + { + *noisy_speech_HO = 0; + *clean_speech_HO = 0; + *NB_speech_HO = 0; + } + + /*---------------------------------------------------------------------* + * compute SNR for each band & total + *---------------------------------------------------------------------*/ + + pt1 = fr_bands; + pt2 = fr_bands + NB_BANDS; + snr_sum = 0.0f; + *snr_sum_he = 0.0f; + snr_sumt = 0; + mssnr_hov = 0; + snr_sum_HE_SAD = 0.0f; + lp_snr = st->lp_speech - st->lp_noise; + + if ( lp_snr > 24.0f ) + { + snr_idx = 0; + } + else if ( lp_snr > 18 ) + { + snr_idx = 1; + } + else + { + snr_idx = 2; + } + + if ( snr_idx == 0 ) + { + stmp = 6; + delta1 = 0.0f; + delta2 = 0.0f; + delta3 = 0.0f; + delta4 = 0.0f; + vad_thr = 2.4f*lp_snr - 42.2f; + vad_thr = min(vad_thr, 80); + } + else if ( snr_idx == 1) + { + stmp = 6; + delta1 = 0.1f; + delta2 = 0.2f; + delta3 = 0.2f; + delta4 = 0.2f; + vad_thr = 2.4f*lp_snr - 40.2f; + vad_thr = min(vad_thr, 80); + } + else + { + stmp = 9; + delta1 = 0.2f; + delta2 = 0.4f; + delta3 = 0.3f; + delta4 = 0.4f; + vad_thr = 2.5f*lp_snr - 10.0f; + vad_thr = max(vad_thr, 1); + } + pt3 = st->bckr; + nb_sig_snr = 20; + + for( i=st->min_band; i<=st->max_band; i++ ) + { + ftmp = *pt1++; + ftmp1 = *pt2++; + fr_enr = ( 0.2f * st->enrO[i] + 0.4f * ftmp + 0.4f * ftmp1 ); + + if (ftmp > ftmp1) + { + snr[i] = ( 0.2f * st->enrO[i] + 0.4f * ftmp + 0.4f * ftmp1 ) / *pt3++; + } + else + { + snr[i] = ( 0.2f * st->enrO[i] + 0.3f * ftmp + 0.5f * ftmp1 ) / *pt3++; + } + + if ( snr[i] < 2.0f ) + { + nb_sig_snr--; + } + + if ( snr[i] < 1 ) + { + snr[i] = 1; + } + + snr[i] = (float)log10(snr[i]); + snr_sumt += snr[i]; + if (i < 2) + { + ftmp = snr[i] + delta1; + } + else if (i < 7) + { + ftmp = snr[i] + delta2; + } + else if (i <18) + { + ftmp = snr[i] + delta3; + } + else + { + ftmp = snr[i] + delta4; + } + ftmp1 = ftmp; + if ( i < 7 ) + { + ftmp1 = ftmp + 0.4f; + } + ftmp = min(ftmp, 2.0f); + ftmp1 = min(ftmp1, 2.0f); + msnr = 1; + for (j=0; jbckr[i]; + + sign_thr_snr_acc( &snr_sum_HE_SAD, snr[i], sign_thr_HE_SAD, min_snr_HE_SAD ); + sign_thr_snr_acc( &snr_sum,snr[i], sign_thr, min_snr ); + + /* To make snr[] compatible with older versions where snr[i] >= 1 + also this could be removed if this no longer is a requriement */ + if( snr[i] < 1.0f ) + { + snr[i] = 1.0f; + } + /* accumulate background noise energy in bands [0-2] and in bands [3-19]*/ + if( i < 3 ) + { + accum_ener_L = accum_ener_L + st->bckr[i]; + } + else + { + accum_ener_H = accum_ener_H + st->bckr[i]; + } + + /* identify the outlier band */ + if( snr[i] > snr_outlier ) + { + snr_outlier = snr[i]; + snr_outlier_index = i; + } + } + + if ( (st->max_band == 19) && (snr[18] > 5.0f) && (snr[19] > 5.0f) ) + { + ftmp = (mssnr + 3*(snr18 + snr19)) * 0.77f; + if ( ftmp > mssnr ) + { + mssnr = ftmp; + } + } + else if ( snr_idx != 0 && nb_sig_snr > 13 ) + { + if ( 2.5f*lp_snr - 15.5f > 0 ) + { + mssnr += 2.5f*lp_snr - 15.5f; + } + } + + + /* Separate SNR_SUM modification to */ + snr_sum_ol = snr_sum; + if(st->max_band == 19 && snr_outlier < MAX_SNR_OUTLIER_3 && snr_outlier_index > 3 && snr_outlier_index < MAX_SNR_OUTLIER_IND) /* Update the total SNR only for WB signals */ + { + 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); + } + } + + st->snr_sum_vad = 0.5f * st->snr_sum_vad + 0.5f * snr_sum_ol; + + snr_sum_ol = 10.0f * (float)log10( snr_sum_ol ); + snr_sum = snr_sum_ol; /* for NB no outlier modification */ + + snr_sum_HE_SAD = 10.0f * (float)log10( snr_sum_HE_SAD ); + *snr_sum_he=snr_sum_HE_SAD; + + /*---------------------------------------------------------------------* + * compute thr1 for SAD decision + *---------------------------------------------------------------------*/ + + lp_snr = st->lp_speech - st->lp_noise; /* long-term SNR */ + + if (lp_snr < st->sign_dyn_lp) + { + lp_snr +=1; + + if (lp_snr > st->sign_dyn_lp) + { + lp_snr = st->sign_dyn_lp; + } + } + + thr1 = nk * lp_snr + nc + nv * ( st->Etot_v_h2 - nv_ofs); /* Linear function for noisy speech */ + + if (lp_snr > 20.0f ) + { + thr1 = thr1 + 0.3f * (lp_snr - 20.0f); + if ( st->max_band==16 && lp_snr > 40 && thr1 > 24.1f && st->lp_speech < 45.0f ) + { + thr1 = 24.1f; + } + } + + /*---------------------------------------------------------------------* + * WB input + * SNR threshold computing + * Hangover control & final VAD decision + *---------------------------------------------------------------------*/ + + if( st->input_bwidth != NB ) + { + /* Outlier Detection first calculates thr1_ol and snr_sum_ol instead of + thr1 and snr_sum */ + + thr1_ol = thr1; + if( lp_snr < th_clean ) + { + hangover_short = 4; + if( ( snr_outlier_index <= 4 && (st->last_coder_type > UNVOICED) && !st->Opt_SC_VBR ) || + ( snr_outlier_index <= 4 && (st->last_7k2_coder_type > UNVOICED) && st->Opt_SC_VBR ) ) + { + thr1_ol = thr1 - 1.0f ; + snr_sum_ol = 10.0f * (float)log10( st->snr_sum_vad ); + } + else if ( ( (st->last_coder_type <= UNVOICED) && (snr_outlier < MAX_SNR_OUTLIER_2) && !st->Opt_SC_VBR ) || + ( (st->last_7k2_coder_type <= UNVOICED) && (snr_outlier < MAX_SNR_OUTLIER_2) && st->Opt_SC_VBR ) ) + + { + thr1_ol = thr1 + (float)(1.0f - 0.04f * snr_outlier); + } + else + { + thr1_ol = thr1 + max(0, (float)(0.6f - 0.01f * snr_outlier)); + } + } + else + { + if( st->Opt_SC_VBR ) + { + hangover_short = 3; + } + else + { + hangover_short = 3; + } + } + + /* The use of outlier detection had been removed by accident at some point */ + snr_sum = snr_sum_ol; + thr1 = thr1_ol; + + /* DTX HANGOVER ADDITION MOVED TO pre_proc() */ + + flag_he1 = 0; + *localVAD = 0; + if ( mssnr > vad_thr ) + { + *localVAD = 1; /* he1 primary decision */ + flag_he1 = 1; + st->nb_active_frames_he1++; /* Counter of consecutive active speech frames */ + if ( st->nb_active_frames_he1 >= ACTIVE_FRAMES ) + { + st->nb_active_frames_he1 = ACTIVE_FRAMES; + st->hangover_cnt_he1 = 0; /* Reset the counter of hangover frames after at least "active_frames" speech frames */ + } + /* inside HO period */ + if ( st->hangover_cnt_he1 < HANGOVER_LONG_HE && st->hangover_cnt_he1 != 0 ) + { + st->hangover_cnt_he1++; + } + + if ( st->soft_hangover > 0 ) + { + st->soft_hangover--; + } + } + else + { + /* Reset the counter of speech frames necessary to start hangover algorithm */ + st->nb_active_frames_he1 = 0; + } + + + if ( st->voiced_burst > 3 ) + { + if ( st->bcg_flux < 40 ) + { + st->soft_hangover = hangover_sf_tbl[snr_idx+3]; + } + else + { + st->soft_hangover = hangover_sf_tbl[snr_idx]; + } + } + + + hangover_hd = hangover_hd_tbl[snr_idx]; + + if ( st->bcg_flux < 40 ) + { + hangover_hd = (hangover_hd>>1) + 1; + } + + + if ( flag_he1 == 0 && st->soft_hangover > 0 ) + { + if ( mssnr_hov > vad_thr ) + { + flag_he1 = 1; + st->soft_hangover--; + } + else + { + st->soft_hangover = 0; + } + + if ( st->soft_hangover < 0 ) + { + st->soft_hangover = 0; + } + } + + if ( flag_he1 == 0 && st->hangover_cnt_he1 < hangover_hd && st->soft_hangover == 0 ) + { + flag_he1 = 1; + st->hangover_cnt_he1++; + } + + /* Calculate background stationarity */ + if ( flag_he1 == 0 && st->first_noise_updt > 0 ) + { + if ( snr_sumt > st->bcg_flux ) + { + if ( st->bcg_flux_init-- > 0 ) + { + if ( snr_sumt > st->bcg_flux+50 ) + { + st->bcg_flux = 0.9f * st->bcg_flux + (1-0.9f)*(st->bcg_flux+50); + } + else + { + st->bcg_flux = 0.9f * st->bcg_flux + (1-0.9f)*snr_sumt; + } + } + else + { + if ( snr_sumt > st->bcg_flux+10 ) + { + st->bcg_flux = 0.99f * st->bcg_flux + (1-0.99f)*(st->bcg_flux+10); + } + else + { + st->bcg_flux = 0.99f * st->bcg_flux + (1-0.99f)*snr_sumt; + } + } + } + else + { + if ( st->bcg_flux_init-- > 0 ) + { + if ( snr_sumt < st->bcg_flux-30 ) + { + st->bcg_flux = 0.95f * st->bcg_flux + (1-0.95f)*(st->bcg_flux-30); + } + else + { + st->bcg_flux = 0.95f * st->bcg_flux + (1-0.95f)*snr_sumt; + } + } + else + { + if ( snr_sumt < st->bcg_flux-10 ) + { + st->bcg_flux = 0.9992f * st->bcg_flux + (1-0.9992f)*(st->bcg_flux-10); + } + else + { + st->bcg_flux = 0.9992f * st->bcg_flux + (1-0.9992f)*snr_sumt; + } + } + } + + if ( st->bcg_flux_init < 0 ) + { + st->bcg_flux_init = 0; + } + } + + flag = 0; + *localVAD = 0; + + if ( snr_sum > thr1 && flag_he1 == 1 ) /* Speech present */ + { + flag = 1; + *localVAD = 1; + st->nb_active_frames++; /* Counter of consecutive active speech frames */ + if (st->nb_active_frames >= ACTIVE_FRAMES ) + { + st->nb_active_frames = ACTIVE_FRAMES; + st->hangover_cnt = 0; /* Reset the counter of hangover frames after at least "active_frames" speech frames */ + } + + /* inside HO period */ + if(st->hangover_cnt < HANGOVER_LONG && st->hangover_cnt != 0 ) + { + st->hangover_cnt++; + } + } + else + { + /* Reset the counter of speech frames necessary to start hangover algorithm */ + st->nb_active_frames = 0; + if(st->hangover_cnt < HANGOVER_LONG ) /* inside HO period */ + { + st->hangover_cnt++; + } + + if(st->hangover_cnt <= hangover_short ) /* "hard" hangover */ + { + /* send the extra 3 HO frames to NELP */ + if ( (lp_snr < th_clean) && (st->Opt_SC_VBR) && (st->hangover_cnt >= 2) ) + { + *noisy_speech_HO = 1; + } + + if ( (lp_snr >= th_clean) && (st->Opt_SC_VBR) && (st->hangover_cnt >= 2) ) + { + *clean_speech_HO = 1; + } + + flag = 1; + } + + } + + /* localVAD and vad_flag for HE-SAD - in parallel with normal localVAD and vad_flag */ + *localVAD_HE_SAD = 0; + if( snr_sum_HE_SAD > thr1 && (flag_he1 == 1) ) /* Speech present */ + { + *localVAD_HE_SAD = 1; + } + } + + /*---------------------------------------------------------------------* + * 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; + if (snr_sum_HE_SAD > thr1 ) + { + *localVAD_HE_SAD = 1; + } + + *localVAD = 0; /* init needed in NB, otherwise it can be undefined */ + if ( snr_sum > thr1 ) /* Speech present */ + { + st->nb_active_frames++; /* Counter of consecutive active speech frames */ + if (st->nb_active_frames >= ACTIVE_FRAMES ) + { + st->nb_active_frames = ACTIVE_FRAMES; + st->hangover_cnt = 0; /* Reset the counter of hangover frames after at least "active_frames" speech frames */ + } + + *localVAD = 1; + } + else + { + st->nb_active_frames = 0; /* Reset the counter of speech frames necessary to start hangover algorithm */ + } + + if(st->hangover_cnt < HANGOVER_LONG_NB ) + { + st->hangover_cnt++; + if( lp_snr < 19.0f ) /* very low SNR */ + { + thr1 -= 5.2f; + } + else if( lp_snr < 35.0f ) /* low SNR */ + { + thr1 -= 2.0f; + } + } + + if (st->Opt_DTX_ON) + { + if (lp_snr < th_clean) + { + thr2 = thr1 - 1.10f; + + } + else + { + thr2 = thr1 - 1.5f; + } + } + else + { + if (lp_snr < th_clean) + { + thr2 = thr1 - 1.3f; + } + else + { + thr2 = thr1 - 1.5f; + } + } + + flag = 0; + if ( snr_sum > thr1 ) /* Speech present */ + { + flag = 1; + } + + if ( (snr_sum < thr1) && (snr_sum > thr2) ) /* Speech present */ + { + flag = 1; + *localVAD = 0; + *NB_speech_HO = 1; + } + + /* Need to handle the case when switching from WB -> NB */ + } + + + + if( st->input_bwidth != NB ) + { + *flag_noisy_speech_snr = (lp_snr < TH16_2_NFLAG ); /*original threshold: 35dB*/ + } + else + { + *flag_noisy_speech_snr = (lp_snr < TH8_1_NFLAG ); /*original threshold: 20dB, not yet tested!*/ + } + + /* SC-VBR */ + st->vadsnr = snr_sum; + st->vadnoise = thr1; + + /* Updates */ + st->prim_act_quick = 0.2f * (*localVAD) + (1.0f -0.2f)* st->prim_act_quick; + st->prim_act_slow = 0.01f * (*localVAD) + (1.0f-0.01f)* st->prim_act_slow; + if (st->prim_act_quick <= st->prim_act_slow) + { + st->prim_act = 0.1f * st->prim_act_quick + (1.0f-0.1f)* st->prim_act; + } + else + { + st->prim_act = 0.1f * st->prim_act_slow + (1.0f-0.1f)* st->prim_act; + } + + st->prim_act_quick_he = 0.2f * *localVAD_HE_SAD + (1.0f -0.2f)* st->prim_act_quick_he; + st->prim_act_slow_he = 0.01f * *localVAD_HE_SAD + (1.0f-0.01f)* st->prim_act_slow_he; + + if (st->prim_act_quick_he <= st->prim_act_slow_he) + { + st->prim_act_he = 0.1f * st->prim_act_quick_he + (1.0f-0.1f)* st->prim_act_he; + } + else + { + st->prim_act_he = 0.1f * st->prim_act_slow_he + (1.0f-0.1f)* st->prim_act_he; + } + + + if ((st->vad_flag_reg_H & (long) 0x40000L) != 0) /* 0x4000L = 0x01L << 18 */ + { + st->vad_flag_cnt_50 = st->vad_flag_cnt_50-1; + } + + st->vad_flag_reg_H = (st->vad_flag_reg_H & (long) 0x3fffffffL ) << 1; + + if ( ( st->vad_flag_reg_L & (long) 0x40000000L) != 0) + { + st->vad_flag_reg_H = st->vad_flag_reg_H | 0x01L; + } + + st->vad_flag_reg_L = (st->vad_flag_reg_L & (long) 0x3fffffffL ) << 1; + + if ( flag ) /* should not include the extra DTX hangover */ + { + st->vad_flag_reg_L = st->vad_flag_reg_L | 0x01L; + st->vad_flag_cnt_50 = st->vad_flag_cnt_50+1; + } + + if ((st->vad_prim_reg & (long) 0x8000L ) != 0) /* 0x8000L = 1L << 15 */ + { + st->vad_prim_cnt_16 = st->vad_prim_cnt_16-1; + } + + st->vad_prim_reg = (st->vad_prim_reg & (long) 0x3fffffffL ) << 1; + + if(*localVAD) + { + st->vad_prim_reg = st->vad_prim_reg | 0x01L; + st->vad_prim_cnt_16 = st->vad_prim_cnt_16+1; + } + + + + return flag; +} diff --git a/lib_enc/vad_param_updt.c b/lib_enc/vad_param_updt.c new file mode 100644 index 000000000..9540b33a9 --- /dev/null +++ b/lib_enc/vad_param_updt.c @@ -0,0 +1,119 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "options.h" +#include "cnst.h" +#include "prot.h" + +/*-------------------------------------------------------------------* + * vad_param_updt() + * + * Update parameters used by the VAD or DTX + *--------------------------------------------------------------------*/ + +void vad_param_updt( + Encoder_State *st, /* i/o: encoder state structure */ + const short pitch[3], /* i : open loop pitch lag for each half-frame */ + const float voicing[3], /* i : maximum normalized correlation for each half-frame */ + const short old_pitch1, /* i : OL pitch value from last frame */ + const float corr_shift, /* i : correlation shift */ + const float A[] /* i : A(z) unquantized for the 4 subframes */ +) +{ + float refl[M+1]; + short tmp_active_flag; + + + if( !st->Opt_AMR_WB ) + { + /* 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 + */ + tmp_active_flag = 0; + + if( (st->core_brate != SID_2k40) && (st->core_brate != 0) ) /* Note, core_brate_fx can be -1 */ + { + tmp_active_flag = 1; /* requires active coding according to dtx_fx logic */ + } + + if( st->Opt_DTX_ON != 0 && tmp_active_flag == 0 && st->ini_frame > 3) + + { + /* update the counter of consecutive inactive frames in DTX */ + st->consec_inactive++; + if( st->consec_inactive > 5 ) + { + st->consec_inactive = 5; + } + + if( st->consec_inactive == 5 ) + { + /* compute spectral tilt parameter */ + a2rc( &A[1], refl, M ); + + if( st->spectral_tilt_reset == 1 ) + { + st->spectral_tilt_reset = 0; + st->running_avg = refl[0]; + st->ra_deltasum = 0; + } + + st->ra_deltasum += (0.80f * st->running_avg + 0.20f * refl[0]) - st->running_avg; + st->running_avg = 0.80f * st->running_avg + 0.20f * refl[0]; + + if( fabs(st->ra_deltasum) > 0.2f ) + { + st->spectral_tilt_reset = 1; + st->running_avg = 0; + st->ra_deltasum = 0; + st->trigger_SID = 1; + } + } + } + else + { + st->trigger_SID = 0; + st->consec_inactive = 0; + } + + if( st->trigger_SID == 1 ) + { + if( st->cng_cnt >= 8 ) + { + /* Declare SID frame due to spectral tilt changes */ + st->cnt_SID = 1; + st->core_brate = SID_2k40; + st->trigger_SID = 0; + } + else if ( st->core_brate == SID_2k40 ) + { + /* SID fame has already been declared before */ + st->trigger_SID = 0; + } + } + } + + + if( (voicing[0] + voicing[1] + voicing[2]) / 3 + corr_shift > 0.65 && + ( short )(abs( pitch[0] - old_pitch1 ) + abs( pitch[1] - pitch[0] ) + abs( pitch[2] - pitch[1] )) / 3 < 14 ) + { + (st->voiced_burst)++; + } + else + { + st->voiced_burst = 0; + } + + /* Update previous voicing value for next frame use */ + st->voicing_old = (voicing[0] + voicing[1] + voicing[2]) / 3 + corr_shift; + + return; +} diff --git a/lib_enc/vad_proc.c b/lib_enc/vad_proc.c new file mode 100644 index 000000000..67323ee71 --- /dev/null +++ b/lib_enc/vad_proc.c @@ -0,0 +1,264 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include + +#include "prot.h" +#include "rom_enc.h" + + +/*-------------------------------------------------------------------* + * vad_init() + * + * + *-------------------------------------------------------------------*/ + +short vad_init( + T_CldfbVadState *st +) +{ + float sSFM[SFM_NUM]= {0.88f,0.92f,0.92f}; + short i = 0; + + if(st == NULL) + { + return -1; + } + + st->frameloop = 0; + st->lt_snr_org = 1.0f; + st->lf_snr_smooth = 5.0f; + st->l_silence_snr = 0.5f; + st->l_speech_snr = 5.0f; + st->l_silence_snr_count = 1; + st->l_speech_snr_count = 1; + st->fg_energy = 16*(3.0518e-5f); + st->bg_energy = 16*(4.6566e-10f); + st->fg_energy_count = 16; + st->bg_energy_count = 16; + st->tonality_rate3 = 0.46f; + st->music_background_rate = 0.46f; + st->lt_noise_sp_center_diff_sum = 0.4f; + st->lt_noise_sp_center_diff_counter = 4; + st->lt_noise_sp_center0 = 1.8f; + st->lt_noise_sp_center3 = 2.0f; + st->lt_bg_highf_eng = 2.0f; + st->t_bg_energy = 0.01f; + st->t_bg_energy_sum = 0.01f; + st->tbg_energy_count = 1; + st->bg_update_count = 0; + st->frame_energy_smooth = 1.0f; + st->fg_energy_est_start = 0; + st->speech_flag = 0; + st->continuous_noise_num = 0; + st->continuous_speech_num = 0; + st->continuous_speech_num2 = 0; + st->update_num_with_snr = 0; /* the number of the background update with SNR*/ + st->update_count = 0; + st->warm_hang_num = 0; + for(i = 0; i < PRE_SNR_NUM; i++) + { + st->pre_snr[i] = 0.0f; + } + + for(i = 0; i < POWER_NUM; i++) + { + st->frames_power[i] = 0; + } + + for(i = 0; i < SPEC_AMP_NUM; i++) + { + st->smooth_spec_amp[i] = 0; + } + + for(i = 0; i < SFM_NUM; i++) + { + st->sfm[i] = sSFM[i]; + } + + for(i = 0; i < SP_CENTER_NUM; i++) + { + st->sp_center[i] = 1.2f; + } + + for(i = 0; i < STABLE_NUM; i++) + { + st->ltd_stable_rate[i] = 0.07f; + } + + for(i = 0; i < BG_ENG_NUM; i++) + { + st->sb_bg_energy[i] = 0.01f; + st->frame_sb_energy[i] = 0.001f; + } + + for(i = 0; i < TONA_NUM; i++) + { + st->f_tonality_rate[i] = 0.48f; + } + + for(i = 0; i < PRE_SPEC_DIF_NUM; i++) + { + st->pre_spec_low_dif[i] = 1.0f; + } + + + return 0; +} + + +/*-------------------------------------------------------------------* + * UpdateState() + * + * + *-------------------------------------------------------------------*/ + +static void UpdateState( + T_CldfbVadState *st, + float frame_energy, /*(i) current frame energy */ + float high_eng, /*(i) current frame high frequency energy */ + int update_flag, /*(i) current frame update flag */ + int music_backgound_f, /*(i) background music flag */ + int vad_flag + ,float snr +) +{ + st->frame_energy_smooth = st->frame_energy_smooth*0.95f + frame_energy*0.05f; + + if(vad_flag==0) + { + st->lt_bg_highf_eng = st->lt_bg_highf_eng*0.95f + high_eng*0.05f; + } + + if(st->frameloop<1000) + { + st->frameloop++; + } + background_update( st, frame_energy, update_flag, music_backgound_f, snr); + if( vad_flag == 0) + { + st->continuous_speech_num2 = 0; + + if(st->continuous_noise_num > 10) + { + st->continuous_speech_num = 0; + } + else if (st->continuous_speech_num > 9) + { + st->continuous_speech_num = 9; + } + + st->continuous_noise_num++; + + if(st->continuous_noise_num > 2048) + { + st->continuous_noise_num = 2048; + } + } + else + { + st->continuous_noise_num = 0; + st->continuous_speech_num2++; + st->continuous_speech_num++; + + if(st->continuous_speech_num > 2048) + { + st->continuous_speech_num = 2048; + } + + if(st->continuous_speech_num2 > 2048) + { + st->continuous_speech_num2 = 2048; + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * vad_proc() + * + * + *-------------------------------------------------------------------*/ + +short vad_proc( + float realValues[16][60], /* CLDFB real values */ + float imagValues[16][60], /* CLDFB imag values */ + float *sb_power, /* Energy of CLDFB data */ + int numBands, /* number of input bands */ + T_CldfbVadState *vad_st, + short *cldfb_addition, + short vada_flag +) +{ + float frame_energy,frame_energy2; + float spec_amp[8*10]; /* 120 */ + + float snr, tsnr; + int update_flag; + int vad_flag; + int music_backgound_f=0; + float HB_Power=0; + float snr_flux; + float lt_snr; + float lt_snr_org; + float lf_snr; + int bandwidth; + + if(numBands<20) + { + bandwidth = 1; + } + else if(numBands<40) + { + bandwidth = 2; + } + else + { + bandwidth = 3; + } + + vad_st->bw_index = bandwidth; + + assert(numBands>=10); + + /* new optimized structure */ + est_energy(sb_power, vad_st->frame_sb_energy, &frame_energy, &frame_energy2, &HB_Power, bandwidth); + + subband_FFT(realValues,imagValues,spec_amp); + + spec_center(sb_power,vad_st->sp_center,bandwidth); + + ltd_stable(vad_st->frames_power,vad_st->ltd_stable_rate,frame_energy,vad_st->frameloop); + + spec_flatness( spec_amp, vad_st->smooth_spec_amp, vad_st->sfm ); + + frame_spec_dif_cor_rate( spec_amp, vad_st->pre_spec_low_dif, vad_st->f_tonality_rate ); + + bg_music_decision( vad_st, &music_backgound_f, frame_energy ); + + SNR_calc( vad_st->frame_sb_energy, vad_st->sb_bg_energy, vad_st->t_bg_energy, &snr, &tsnr, frame_energy2, bandwidth ); + + calc_snr_flux( tsnr, vad_st->pre_snr, &snr_flux ); + + calc_lt_snr( <_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, snr, tsnr, snr_flux, lt_snr, lt_snr_org, lf_snr, frame_energy2, music_backgound_f, cldfb_addition, vada_flag ); + + update_flag = update_decision( vad_st,snr,tsnr, frame_energy,HB_Power,vad_st->vad_flag_for_bk_update, music_backgound_f ); + UpdateState( vad_st, frame_energy2, HB_Power, update_flag,music_backgound_f, vad_st->vad_flag_for_bk_update,snr); + + + return vad_flag; +} diff --git a/lib_enc/vbr_average_rate.c b/lib_enc/vbr_average_rate.c new file mode 100644 index 000000000..b1c5afb49 --- /dev/null +++ b/lib_enc/vbr_average_rate.c @@ -0,0 +1,167 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include "options.h" +#include "cnst.h" +#include "prot.h" +#include "rom_com.h" + + +/*------------------------------------------------------------------* + * Local constants + *------------------------------------------------------------------*/ + +#define RATEWIN 600 /* length of the rate control window. This is 600 active speech frames. This equals roughly 12s of active speech */ + +/*------------------------------------------------------------------* + * update_average_rate() + * + * SC-VBR update average data rate + *------------------------------------------------------------------*/ + +void update_average_rate( + Encoder_State *st /* i/o: encoder state structure */ +) +{ + float avratetarg; /* target rate for next RATEWIN active frames */ + float target; /* target set by VBR_ADR_MAX_TARGET*RATEWIN*10 */ + + if ( st->numactive == 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 ( st->global_frame_cnt < 1000 ) + { + st->global_frame_cnt++; + st->global_avr_rate = (st->global_avr_rate * (st->global_frame_cnt-1) + st->sum_of_rates) / st->global_frame_cnt; + } + else + { + st->global_avr_rate = 0.01f * st->sum_of_rates + 0.99f * st->global_avr_rate; + } + + if ( st->sum_of_rates == 0 ) + { + st->sum_of_rates = (float) (RATEWIN * VBR_ADR_MAX_TARGET * 10); + } + + target = VBR_ADR_MAX_TARGET * 10 * RATEWIN; + + if ( target < st->global_avr_rate ) /* 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 */ + + if ( st->SNR_THLD < 67 ) /* 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; + } + else if ( st->mode_QQF == 0 && st->sum_of_rates > target ) /* 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->mode_QQF = 1; + } + else if ( st->sum_of_rates > target ) /* 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->rate_control = 1; + + /* 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 ( st->global_avr_rate > (target+420.0f) ) /* Last resort rate control. This is a safer rate control mechanism by increasing NELPS */ + { + st->Last_Resort = 1; /* compute based on a larger window as the last resort */ + } + else + { + st->Last_Resort = 0; + } + } + else if ( st->sum_of_rates < target ) /* 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->Last_Resort = 0; + st->mode_QQF = 1; + st->rate_control = 0; + } + } + else + { + /* floding back to lesser and leser aggresive rate control mechanisms gradually if global rate is under control */ + st->Last_Resort = 0; + + if ( st->rate_control == 1 ) + { + st->rate_control = 0; + } + else if ( st->mode_QQF == 1) /* now rate control is not active and still the global rate is below the target. so go to QFF mode */ + { + st->mode_QQF = 0; + } + else + { + if ( st->SNR_THLD >= 60 ) + { + st->SNR_THLD -= 1.5f; + } + else + { + st->SNR_THLD = 60.0f; + } + } + } + + if ( st->global_avr_rate < target-120 ) /* 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->Q_to_F = 1; + + /* 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); + + /* 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) ); + + if ( st->pattern_m < 0 ) + { + st->pattern_m = 0; /* no bump up will ever happen */ + } + + if ( st->pattern_m > 1000 ) + { + st->pattern_m = 1000; /* 10% of bump ups */ + } + + st->patterncount = 0; + } + else + { + st->Q_to_F = 0; + } + + st->sum_of_rates = 0; + st->numactive = 0; + } + + st->numactive++; + + /* sum the total number of bits (in kbytes) * 10 here */ + st->sum_of_rates += (st->core_brate / 1000.0f) * 10; + + return; +} diff --git a/lib_enc/vlpc_1st_cod.c b/lib_enc/vlpc_1st_cod.c new file mode 100644 index 000000000..33b4618ed --- /dev/null +++ b/lib_enc/vlpc_1st_cod.c @@ -0,0 +1,120 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "cnst.h" +#include "prot.h" + + +extern float const dico_lsf_abs_8b[]; + +/*------------------------------------------------------------------* +* lsf_weight() +* +* outputs only the weightings, doesn't do anything with the lsfq +*------------------------------------------------------------------*/ + +static void lsf_weight( + const float *lsfq, + float *w, + float sr_core +) +{ + int i; + float inv_di0, inv_di1; + float scale = sr_core/INT_FS_12k8; + float freq_max = sr_core/2.f; + + /* Verify, that M is pair, otherwise adapt exit of loop below */ + assert ((M & 1) == 0); + + /* weighting function */ + inv_di0 = scale / lsfq[0]; + for (i=1; i<(M-2); i+=2) + { + inv_di1 = scale / (lsfq[i] - lsfq[i-1]); + w[i-1] = inv_di0 + inv_di1; + + inv_di0 = scale / (lsfq[i+1] - lsfq[i]); + w[i] = inv_di1 + inv_di0; + } + inv_di1 = scale / (lsfq[i] - lsfq[i-1]); + w[i-1] = inv_di0 + inv_di1; + + inv_di0 = scale / (freq_max - lsfq[i]); + w[i] = inv_di1 + inv_di0; + + return; +} + +/*------------------------------------------------------------------* +* vlpc_1st_cod() +* +* +*------------------------------------------------------------------*/ + +int vlpc_1st_cod( /* output: codebook index */ + const float *lsf, /* input: vector to quantize */ + float *lsfq, /* i/o: i:prediction o:quantized lsf */ + float sr_core + ,float *wout /* o: lsf weights */ +) +{ + int i, j, index; + float w[M], x[M]; + float dist_min, dist, temp; + const float *p_dico; + int hit=0; + float scale = sr_core/INT_FS_12k8; + float scaleinv = 1.f / scale; + + /* weighting */ + lsf_weight(lsf, w, sr_core ); + + mvr2r( w, wout, M ); + + /* remove lsf prediction/means */ + + for( i=0; i0); + + return index; +} diff --git a/lib_enc/vlpc_2st_cod.c b/lib_enc/vlpc_2st_cod.c new file mode 100644 index 000000000..5b9d00ee9 --- /dev/null +++ b/lib_enc/vlpc_2st_cod.c @@ -0,0 +1,116 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "cnst.h" +#include "prot.h" + +/*------------------------------------------------------------------* +* vlpc_2st_cod() +* +* +*------------------------------------------------------------------*/ + +int vlpc_2st_cod( /* output: number of allocated bits */ + const float *lsf, /* input: normalized vector to quantize */ + float *lsfq, /* i/o: i:1st stage o:1st+2nd stage */ + int *indx, /* output: index[] (4 bits per words) */ + int mode, /* input: 0=abs, >0=rel */ + float sr_core +) +{ + int i, nbits; + float w[M], x[M], tmp; + int nq, xq[M]; + float scale = sr_core/INT_FS_12k8; + float scaleinv = 1.f / scale; + + /* 0 bit with true weighting: save 0.5 bit */ + + lsf_weight_2st( lsf, w, 1, sr_core ); + + for (i=0; i 6) + { + nbits += nq - 3; /* unary code (Q7=1110, ...) */ + } + else if (nq > 4) + { + nbits += nq - 4; /* Q5=0, Q6=10 */ + } + else if (nq == 0) + { + nbits += 3; /* Q0=110 */ + } + } + + /* reorder */ + v_sort( lsfq, 0, M-1 ); + reorder_lsf( lsfq, LSF_GAP, M, sr_core ); + + return( nbits ); +} diff --git a/lib_enc/voiced_enc.c b/lib_enc/voiced_enc.c new file mode 100644 index 000000000..ab8b78109 --- /dev/null +++ b/lib_enc/voiced_enc.c @@ -0,0 +1,647 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include "prot.h" +#include "cnst.h" +#include "rom_com.h" + + +/*-------------------------------------------------------------------* + * Local functions + *--------------------------------------------------------------------*/ + +static void SynthesisFilter( float *output, float *input, float *coef, float *memory, short order, short length ); + +/*-------------------------------------------------------------------* + * ppp_voiced_encoder() + * + * voiced encoder for SC-VBR + *--------------------------------------------------------------------*/ + +void ppp_voiced_encoder( + Encoder_State *st, /* i/o: state structure */ + float *in, /* i : residual signal */ + float *out, /* o : Quantized residual signal */ + short delay, /* i : open loop pitch */ + float *lpc1, /* i : prev frame de-emphasized LPC */ + float* lpc2, /* i : current frame de-emphasized LPC */ + float *exc, /* i : previous frame quantized excitation */ + float *pitch, /* o : floating pitch values for each subframe */ + float vadsnr /* i : current frame SNR */ +) +{ + short i; + short spike_near_edge = 0; + short flag; + short delta_lag_E = 0, PPP_MODE_E, Q_delta_lag = 0; + short out_of_bound = 0; + float tmp, tmptmp, tmptmp1, res_enratio = 0, sp_enratio = 0; + double tmp2; + int pl, l; + float interp_delay[3], temp_pl, temp_l; + short upper_cut_off_freq_of_interest = 0, upper_cut_off_freq = 0; + float pos_nq, neg_nq, pos_q, neg_q; + float impzi[160]; + float impzo[160]; + float mem[10]; + float energy_impz = 0.0f; + float pos_nq0, neg_nq0, tmpres; + float sp_hb_enratio; + float low_band_en; + + DTFS_STRUCTURE *CURRP_NQ = DTFS_new(); + DTFS_STRUCTURE *TMPDTFS = DTFS_new(); + DTFS_STRUCTURE *TMPDTFS2 = DTFS_new(); + DTFS_STRUCTURE *TMPDTFS3 = DTFS_new(); + DTFS_STRUCTURE *CURRP_Q_E = DTFS_new(); + DTFS_STRUCTURE *dtfs_temp = DTFS_new(); + + if ( st->bwidth == WB ) + { + upper_cut_off_freq_of_interest = 4000; + upper_cut_off_freq = 6400; + } + else if ( st->bwidth == NB ) + { + upper_cut_off_freq_of_interest = 3300; + upper_cut_off_freq = 4000; + } + + /* Initialization */ + if (st->firstTime_voicedenc) + { + st->firstTime_voicedenc = 0; + st->dtfs_enc_lag = 0; + st->dtfs_enc_nH = 0; + st->dtfs_enc_nH_4kHz = 0; + st->dtfs_enc_upper_cut_off_freq_of_interest = 3300.0; + st->dtfs_enc_upper_cut_off_freq = 4000.0; + + set_f(st->dtfs_enc_a, 0, MAXLAG_WI); + set_f(st->dtfs_enc_b, 0, MAXLAG_WI); + } + + /* Figure out the PPP_MODE */ + if ( st->last_ppp_mode == 1 && !st->mode_QQF ) + { + st->bump_up = 1; + + free(CURRP_NQ); + free(TMPDTFS); + free(TMPDTFS2); + free(TMPDTFS3); + free(CURRP_Q_E); + free(dtfs_temp); + + return; + } + + /* Use the aggresive bumpups if there are two consecutive Q frames */ + /* Aggresive bump upsare only used in the second Q frame */ + if ( st->last_ppp_mode == 1 ) + { + st->rate_control = 0; + } + + PPP_MODE_E = 'Q'; + pl = min(MAX_LAG_PIT, (int)rint_new(st->old_pitch_buf[(2*NB_SUBFR)-1])); + l = min(MAX_LAG_PIT, (int)rint_new(delay)); + + /* Bump up if the lag is out_fx of range */ + if ((l-pl)>13 || (l-pl)<-11 || (l < 19) || (pl < 19) ) + { + st->bump_up = 1; + + free(CURRP_NQ); + free(TMPDTFS); + free(TMPDTFS2); + free(TMPDTFS3); + free(CURRP_Q_E); + free(dtfs_temp); + return; + } + + if (st->last_ppp_mode!=1) + { + /* Obtain DTFS of last pl values of past excitation */ + DTFS_to_fs(exc-pl, pl, dtfs_temp, st->bwidth == WB ? (short)16000 : (short)8000, 0 ); + + } + + if( st->last_coder_type_raw == UNVOICED ) + { + pl = l; /* if prev frame was sil/uv */ + } + + /* Use the out array as a temp storage for currp */ + spike_near_edge = ppp_extract_pitch_period(in, out, l, &out_of_bound) ; + + if (out_of_bound == 1) + { + st->bump_up = 1; + + free(CURRP_NQ); + free(TMPDTFS); + free(TMPDTFS2); + free(TMPDTFS3); + free(CURRP_Q_E); + free(dtfs_temp); + + return; + } + + /* Get DTFS of current prototype */ + DTFS_to_fs(out, l, CURRP_NQ, st->bwidth == WB ? (short)16000 : (short)8000, 0); + + /* 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) + { + DTFS_to_fs(in+L_FRAME-l, l, TMPDTFS, st->bwidth == WB ? (short)16000 : (short)8000 ,0); + + tmp = DTFS_alignment_extract(*TMPDTFS, *CURRP_NQ, 0.0, lpc2) ; /* figure out how much to shift currp_nq to align with TMP */ + + DTFS_phaseShift(CURRP_NQ, (float)(PI2*tmp/l)) ; + } + + temp_pl = (float) pl; + temp_l = (float) l; + + for(i = 0; i < NB_SUBFR; i++) + { + /* do the linear pitch interp to drive the nb_post_filt */ + Interpol_delay(interp_delay, &(temp_pl), &(temp_l), i, frac_4sf); + pitch[i] = interp_delay[0]; + } + + + + /* Restoring PPP memories when the last frame is non-PPP */ + if ( st->last_ppp_mode != 1 ) + { + st->ph_offset_E = 0.0 ; + st->prev_cw_en = DTFS_getEngy(*dtfs_temp); + + /* Copy over dtfs_temp into TMPDTFS */ + DTFS_copy(TMPDTFS, *dtfs_temp); + + DTFS_car2pol(TMPDTFS); + + st->lastLgainE = (float) log10(TMPDTFS->lag*DTFS_setEngyHarm(92.0, 1104.5, 0.0, 1104.5, 1.0, TMPDTFS)); + st->lastHgainE = (float) log10(TMPDTFS->lag*DTFS_setEngyHarm(1104.5, upper_cut_off_freq_of_interest, 1104.5, upper_cut_off_freq, 1.0, TMPDTFS)); + + DTFS_to_erb(*TMPDTFS, st->lasterbE); + } + else + { + /* Copy DTFS related parameters from 'st' to 'dtfs_temp' structure */ + dtfs_temp->lag = st->dtfs_enc_lag; + dtfs_temp->nH = st->dtfs_enc_nH; + dtfs_temp->nH_4kHz = st->dtfs_enc_nH_4kHz; + dtfs_temp->upper_cut_off_freq_of_interest = st->dtfs_enc_upper_cut_off_freq_of_interest; + dtfs_temp->upper_cut_off_freq = st->dtfs_enc_upper_cut_off_freq; + + mvr2r(st->dtfs_enc_a, dtfs_temp->a, MAXLAG_WI); + mvr2r(st->dtfs_enc_b, dtfs_temp->b, MAXLAG_WI); + } + + /*-----Open-loop Bump-Up-------- */ + + /* Energy ratio calculation in residual and speech domain */ + /* Also, compute correlation between the previous and the */ + /* current prototype */ + res_enratio = DTFS_getEngy(*CURRP_NQ) / DTFS_getEngy(*dtfs_temp); + + /* Copy over CURRP_NQ into TMPDTFS */ + DTFS_copy(TMPDTFS, *CURRP_NQ); + + /* Copy over dtfs_temp into TMPDTFS2 */ + DTFS_copy(TMPDTFS2, *dtfs_temp); + + tmptmp = DTFS_alignment_full(*TMPDTFS2, *TMPDTFS, TMPDTFS->lag*2); /* align of prev_cw wrt curr_cw, new method */ + + tmptmp1 = TMPDTFS->lag-tmptmp; + tmp = tmptmp1; + + DTFS_phaseShift(TMPDTFS, (float)(-PI2*tmp/TMPDTFS->lag)); /* fixed bug , phase shift by tmp computed in TMP.lag domain (above) */ + tmpres = (float)(DTFS_freq_corr(*TMPDTFS, *TMPDTFS2, 100.0f, 3700.0f)); + + DTFS_poleFilter(TMPDTFS, lpc2, M+1); + + DTFS_adjustLag(TMPDTFS2, TMPDTFS->lag); /* operate in CL domain */ + + DTFS_poleFilter(TMPDTFS2, lpc1, M+1); + + tmp = (float)(DTFS_freq_corr(*TMPDTFS, *TMPDTFS2, 100.0f, 3700.0f)); + + if ( DTFS_getEngy(*TMPDTFS2) > 0 ) + { + sp_enratio = DTFS_getEngy(*TMPDTFS)/DTFS_getEngy(*TMPDTFS2); + } + else + { + sp_enratio = 0.0f; + } + + if (PPP_MODE_E == 'Q') + { + /* Bump up if the lag is out of range */ + if (((l-pl)>13) ||((l-pl)<-11)) + { + PPP_MODE_E = 'B' ; + } + else + { + delta_lag_E=(short) (l-pl); + } + + /* Bump up if big change between the previous and the current CWs */ + if ( vadsnr < st->SNR_THLD ) + { + if ( res_enratio > 5.0 && tmp < 0.65 ) + { + PPP_MODE_E = 'B'; + } + } + else + { + if ( res_enratio > 3.0 && tmp < 1.2 ) + { + PPP_MODE_E = 'B'; + } + } + } + + /* Rapid rampdown frame where time resolution is important */ + /* Not a suitable PPP frame -> Bump to CELP */ + if ( vadsnr < st->SNR_THLD ) + { + if (res_enratio < 0.025) + { + st->bump_up = 1; + + free(CURRP_NQ); + free(TMPDTFS); + free(TMPDTFS2); + free(TMPDTFS3); + free(CURRP_Q_E); + free(dtfs_temp); + + return; + } + } + else + { + if ( res_enratio < 0.092f ) + { + st->bump_up = 1; + } + } + + if ( min(res_enratio, sp_enratio) < 0.075f && tmp < -0.5f ) + { + st->bump_up = 1; + } + + /* Rapid rampup frame where time resolution is important */ + /* Not a suitable PPP frame -> Bump to CELP */ + if ( vadsnr < st->SNR_THLD ) + { + if (res_enratio > 14.5) + { + st->bump_up = 1; + + free(CURRP_NQ); + free(TMPDTFS); + free(TMPDTFS2); + free(TMPDTFS3); + free(CURRP_Q_E); + free(dtfs_temp); + + return; + } + } + else + { + if (res_enratio > 7.0) + { + st->bump_up = 1; + } + } + + if ( st->bump_up == 1 ) + { + + free(CURRP_NQ); + free(TMPDTFS); + free(TMPDTFS2); + free(TMPDTFS3); + free(CURRP_Q_E); + free(dtfs_temp); + + return; + } + + /* Bump up when the previous frame is an unvoiced or a silent frame */ + if( st->last_coder_type_raw == UNVOICED ) + { + st->bump_up=1; + + free(CURRP_NQ); + free(TMPDTFS); + free(TMPDTFS2); + free(TMPDTFS3); + free(CURRP_Q_E); + free(dtfs_temp); + + return; + } + /* -----End Open-loop Bump-Up */ + + /* PPP-WI Quantization */ + if (PPP_MODE_E == 'Q') + { + flag = 1; + if (PPP_MODE_E == 'Q') + { + flag = ppp_quarter_encoder( st, CURRP_Q_E, TMPDTFS, dtfs_temp->lag, *CURRP_NQ, lpc2, &(st->lastLgainE), &(st->lastHgainE), &(st->lasterbE[0]), *dtfs_temp ); + } + + 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 speech dom */ + + /* ----- Closed-loop Bump-Up ---------- */ + DTFS_peaktoaverage(*TMPDTFS, &pos_nq, &neg_nq); + DTFS_peaktoaverage(*CURRP_Q_E, &pos_q, &neg_q); + + /* Before we perform the peak-to-average ratio comparison, we have to */ + /* ensure that the energy is not decaying and also the pitch 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 ( CURRP_Q_E->upper_cut_off_freq > 4000 ) + { + /* Use this bumup only for WB signals */ + if ( DTFS_getEngy_band_wb(*CURRP_Q_E, 0.0, 2000.0) > 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); + } + else + { + sp_hb_enratio = 0; + } + + low_band_en = (float)DTFS_getEngy_band_wb(*CURRP_Q_E, 0.0, 2000.0); + + if ( low_band_en < 25.0f && sp_hb_enratio < 1.6f ) + { + PPP_MODE_E = 'B'; + } + } + + if ( vadsnr < st->SNR_THLD ) + { + if ( DTFS_getEngy(*CURRP_NQ) > 0.8f * st->prev_cw_en && max(pos_nq, neg_nq) > 3.0f && st->rate_control ) + { + if ( pos_nq > neg_nq && pos_nq > 2.0f * pos_q ) + { + PPP_MODE_E = 'B'; + } + + if ( pos_nq < neg_nq && neg_nq > 2.0f * neg_q ) + { + PPP_MODE_E = 'B'; + } + } + } + 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))) + { + 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))) + { + PPP_MODE_E='B'; + } + + 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))) + { + PPP_MODE_E='B'; + } + } + + if ( st->rate_control ) + { + DTFS_peaktoaverage(*CURRP_NQ, &pos_nq0,&neg_nq0); + + for (impzi[0]=1.0,i=1; i<160; i++) + { + impzi[i]=0.0; + } + + for (i=0; i<160; i++) + { + impzo[i]=0.0; + } + + for (i=0; i<10; i++) + { + mem[i]=0.0; + } + + SynthesisFilter(&impzo[0],&impzi[0],lpc2,&mem[0],10,160); + + for (i=0; i<160; i++) + { + energy_impz+=(impzo[i]*impzo[i]); + } + + energy_impz = (float)(10*log10((float)energy_impz)); + + if ((DTFS_getEngy(*CURRP_Q_E) > st->prev_cw_en)&&(max(pos_q,neg_q)>3.5)&& energy_impz>15.0&& tmpres>0.7) + { + if ((pos_q > neg_q) && ((pos_q>3.0*pos_nq0) || ((pos_q > 1.5*pos_nq0) && (neg_q < 1.5*neg_q)))) + { + PPP_MODE_E='B'; + } + + if ((pos_q <= neg_q) && ((neg_q>3.0*neg_nq0)|| ((neg_q > 1.5*neg_nq0) && (pos_q < 1.5*pos_q)))) + { + PPP_MODE_E='B'; + } + } + } + } + + DTFS_copy(TMPDTFS2,*CURRP_Q_E); + + DTFS_poleFilter(TMPDTFS,lpc2,M+1); + DTFS_poleFilter(TMPDTFS2,lpc2,M+1); + + *TMPDTFS3 = DTFS_sub(*TMPDTFS,*TMPDTFS2); + + /* operate in ADR mode only the rate control is active. This adds some bumpups to improve the speech quality */ + tmp2 = DTFS_getEngy_band(*TMPDTFS, 1500.0, upper_cut_off_freq_of_interest)/DTFS_getEngy(*TMPDTFS); + if (tmp2==0.0) + { + tmp2=0.001; + } + if ((tmp2> 0.05)&&(!st->rate_control)) + { + tmp2=DTFS_getEngy_band(*TMPDTFS,1500.0,upper_cut_off_freq_of_interest)/DTFS_getEngy_band(*TMPDTFS3,1500.0,upper_cut_off_freq_of_interest); + if (tmp2==0.0) + { + tmp2=0.001; + } + if (10.0*log10(tmp2) < 0.1) + { + if (res_enratio > 0.8) + { + PPP_MODE_E = 'B'; + } + } + } + + /* To increase bump up, raise first threshold, lower second */ + tmp = (float)(10.0*log10(DTFS_getEngy(*TMPDTFS)/DTFS_getEngy(*TMPDTFS3))); + + if ((tmp <= 0)&&(!st->rate_control)) + { + PPP_MODE_E = 'B'; + } + + if ( vadsnr < st->SNR_THLD ) + { + 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))) + { + PPP_MODE_E = 'B'; + } + } + 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))) + { + PPP_MODE_E = 'B'; + } + } + /* -----End closed-loop Bump-Up */ + } + else + { + PPP_MODE_E = 'B' ; /* Amplitude quantization is failing */ + } + } + else + { + } + + if (PPP_MODE_E == 'B') + { + st->bump_up = 1; + + free(CURRP_NQ); + free(TMPDTFS); + free(TMPDTFS2); + free(TMPDTFS3); + free(CURRP_Q_E); + free(dtfs_temp); + + return; + } + + if ( st->Q_to_F ) + { + st->patterncount += st->pattern_m; + + if (st->patterncount >= 1000) + { + st->patterncount -= 1000; + PPP_MODE_E = 'B'; + st->bump_up = 1; + + free(CURRP_NQ); + free(TMPDTFS); + free(TMPDTFS2); + free(TMPDTFS3); + free(CURRP_Q_E); + free(dtfs_temp); + + return; + } + } + + /* packetization of the delta lag in PPP */ + if (PPP_MODE_E == 'Q') + { + Q_delta_lag = delta_lag_E+11; /* to make it positive always */ + push_indice( st, IND_DELTALAG, Q_delta_lag, 5 ); + } + + WIsyn(*dtfs_temp, CURRP_Q_E, lpc2, &(st->ph_offset_E), out, L_FRAME, 0); + + DTFS_copy(dtfs_temp, *CURRP_Q_E); + st->prev_cw_en = DTFS_getEngy(*CURRP_NQ); + + /* Copy DTFS related parameters from 'dtfs_temp' to 'st' structure */ + st->dtfs_enc_lag = dtfs_temp->lag; + st->dtfs_enc_nH = dtfs_temp->nH; + st->dtfs_enc_nH_4kHz = dtfs_temp->nH_4kHz; + st->dtfs_enc_upper_cut_off_freq_of_interest = dtfs_temp->upper_cut_off_freq_of_interest; + st->dtfs_enc_upper_cut_off_freq = dtfs_temp->upper_cut_off_freq; + + mvr2r(dtfs_temp->a, st->dtfs_enc_a, MAXLAG_WI); + mvr2r(dtfs_temp->b, st->dtfs_enc_b, MAXLAG_WI); + + free(CURRP_NQ); + free(TMPDTFS); + free(TMPDTFS2); + free(TMPDTFS3); + free(CURRP_Q_E); + free(dtfs_temp); + + return; +} + +static void SynthesisFilter( + float *output, + float *input, + float *coef, + float *memory, + short order, + short length +) +{ + short i, j; + float acc; + + /* IIR filter for each subframe */ + for (i=0; i0; j-- ) + { + acc -= coef[j] * memory[j]; + memory[j] = memory[j - 1]; + } + + acc -= coef[0] * memory[0]; + *output++ = acc; + memory[0] = acc; + } + + return; +} diff --git a/lib_enc/waveadjust_fec_cod.c b/lib_enc/waveadjust_fec_cod.c new file mode 100644 index 000000000..746af4d78 --- /dev/null +++ b/lib_enc/waveadjust_fec_cod.c @@ -0,0 +1,44 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0 + ====================================================================================*/ + +#include +#include "wmc_auto.h" +#include +#include +#include +#include "prot.h" + + +/*-------------------------------------------------------------------* + * SFM_Cal() + * + * + *--------------------------------------------------------------------*/ + +float SFM_Cal( + float const fcoef[], + int n +) +{ + int i, k; + double geoMean = 0, arithMean = 0, SFM; + double tmp[4] = {1, 1, 1, 1}; + + for (k = 0; k < 4; k++) + { + + for (i = k*(n>>2); i < (k+1)*(n>>2); i++) + { + tmp[k] *= (fabs(fcoef[i]) + EPSILON); + arithMean += fabs(fcoef[i]); + } + } + geoMean = log(tmp[0])+log(tmp[1])+log(tmp[2])+log(tmp[3]); + geoMean = geoMean/n; + geoMean = exp(geoMean); + arithMean /= n; + SFM = (geoMean+EPSILON)/(arithMean+EPSILON); + + return (float)SFM; +} -- GitLab